summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/context/global-sync/bootstrap.ts
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-03-24 18:49:02 -0500
committerAdam <[email protected]>2026-03-25 05:59:05 -0500
commit0dbfefa08088270a000496cfe94e11b5bf3ce821 (patch)
tree022df9271b5825e7c8e1192f240d31de79904075 /packages/app/src/context/global-sync/bootstrap.ts
parentd1c49ba210315900b7d21a7d4926b739d8021c6e (diff)
downloadopencode-0dbfefa08088270a000496cfe94e11b5bf3ce821.tar.gz
opencode-0dbfefa08088270a000496cfe94e11b5bf3ce821.zip
Reapply "fix(app): startup efficiency (#18854)"
This reverts commit a379eb38673aad097e1f178307865ec40a5ac3ea.
Diffstat (limited to 'packages/app/src/context/global-sync/bootstrap.ts')
-rw-r--r--packages/app/src/context/global-sync/bootstrap.ts189
1 files changed, 98 insertions, 91 deletions
diff --git a/packages/app/src/context/global-sync/bootstrap.ts b/packages/app/src/context/global-sync/bootstrap.ts
index 13494b7ad..c795ab471 100644
--- a/packages/app/src/context/global-sync/bootstrap.ts
+++ b/packages/app/src/context/global-sync/bootstrap.ts
@@ -33,27 +33,11 @@ type GlobalStore = {
export async function bootstrapGlobal(input: {
globalSDK: OpencodeClient
- connectErrorTitle: string
- connectErrorDescription: string
requestFailedTitle: string
translate: (key: string, vars?: Record<string, string | number>) => string
formatMoreCount: (count: number) => string
setGlobalStore: SetStoreFunction<GlobalStore>
}) {
- const health = await input.globalSDK.global
- .health()
- .then((x) => x.data)
- .catch(() => undefined)
- if (!health?.healthy) {
- showToast({
- variant: "error",
- title: input.connectErrorTitle,
- description: input.connectErrorDescription,
- })
- input.setGlobalStore("ready", true)
- return
- }
-
const tasks = [
retry(() =>
input.globalSDK.path.get().then((x) => {
@@ -80,11 +64,6 @@ export async function bootstrapGlobal(input: {
input.setGlobalStore("provider", normalizeProviderList(x.data!))
}),
),
- retry(() =>
- input.globalSDK.provider.auth().then((x) => {
- input.setGlobalStore("provider_auth", x.data ?? {})
- }),
- ),
]
const results = await Promise.allSettled(tasks)
@@ -111,6 +90,10 @@ function groupBySession<T extends { id: string; sessionID: string }>(input: T[])
}, {})
}
+function projectID(directory: string, projects: Project[]) {
+ return projects.find((project) => project.worktree === directory || project.sandboxes?.includes(directory))?.id
+}
+
export async function bootstrapDirectory(input: {
directory: string
sdk: OpencodeClient
@@ -119,88 +102,112 @@ export async function bootstrapDirectory(input: {
vcsCache: VcsCache
loadSessions: (directory: string) => Promise<void> | void
translate: (key: string, vars?: Record<string, string | number>) => string
+ global: {
+ config: Config
+ project: Project[]
+ provider: ProviderListResponse
+ }
}) {
- if (input.store.status !== "complete") input.setStore("status", "loading")
+ const loading = input.store.status !== "complete"
+ const seededProject = projectID(input.directory, input.global.project)
+ if (seededProject) input.setStore("project", seededProject)
+ if (input.store.provider.all.length === 0 && input.global.provider.all.length > 0) {
+ input.setStore("provider", input.global.provider)
+ }
+ if (Object.keys(input.store.config).length === 0 && Object.keys(input.global.config).length > 0) {
+ input.setStore("config", input.global.config)
+ }
+ if (loading) input.setStore("status", "partial")
- const blockingRequests = {
- project: () => input.sdk.project.current().then((x) => input.setStore("project", x.data!.id)),
- provider: () =>
+ const results = await Promise.allSettled([
+ seededProject
+ ? Promise.resolve()
+ : retry(() => input.sdk.project.current()).then((x) => input.setStore("project", x.data!.id)),
+ retry(() =>
input.sdk.provider.list().then((x) => {
input.setStore("provider", normalizeProviderList(x.data!))
}),
- agent: () => input.sdk.app.agents().then((x) => input.setStore("agent", x.data ?? [])),
- config: () => input.sdk.config.get().then((x) => input.setStore("config", x.data!)),
- }
+ ),
+ retry(() => input.sdk.app.agents().then((x) => input.setStore("agent", x.data ?? []))),
+ retry(() => input.sdk.config.get().then((x) => input.setStore("config", x.data!))),
+ retry(() =>
+ input.sdk.path.get().then((x) => {
+ input.setStore("path", x.data!)
+ const next = projectID(x.data?.directory ?? input.directory, input.global.project)
+ if (next) input.setStore("project", next)
+ }),
+ ),
+ retry(() => input.sdk.command.list().then((x) => input.setStore("command", x.data ?? []))),
+ retry(() => input.sdk.session.status().then((x) => input.setStore("session_status", x.data!))),
+ input.loadSessions(input.directory),
+ retry(() => input.sdk.mcp.status().then((x) => input.setStore("mcp", x.data!))),
+ retry(() => input.sdk.lsp.status().then((x) => input.setStore("lsp", x.data!))),
+ retry(() =>
+ input.sdk.vcs.get().then((x) => {
+ const next = x.data ?? input.store.vcs
+ input.setStore("vcs", next)
+ if (next?.branch) input.vcsCache.setStore("value", next)
+ }),
+ ),
+ retry(() =>
+ input.sdk.permission.list().then((x) => {
+ const grouped = groupBySession(
+ (x.data ?? []).filter((perm): perm is PermissionRequest => !!perm?.id && !!perm.sessionID),
+ )
+ batch(() => {
+ for (const sessionID of Object.keys(input.store.permission)) {
+ if (grouped[sessionID]) continue
+ input.setStore("permission", sessionID, [])
+ }
+ for (const [sessionID, permissions] of Object.entries(grouped)) {
+ input.setStore(
+ "permission",
+ sessionID,
+ reconcile(
+ permissions.filter((p) => !!p?.id).sort((a, b) => cmp(a.id, b.id)),
+ { key: "id" },
+ ),
+ )
+ }
+ })
+ }),
+ ),
+ retry(() =>
+ input.sdk.question.list().then((x) => {
+ const grouped = groupBySession((x.data ?? []).filter((q): q is QuestionRequest => !!q?.id && !!q.sessionID))
+ batch(() => {
+ for (const sessionID of Object.keys(input.store.question)) {
+ if (grouped[sessionID]) continue
+ input.setStore("question", sessionID, [])
+ }
+ for (const [sessionID, questions] of Object.entries(grouped)) {
+ input.setStore(
+ "question",
+ sessionID,
+ reconcile(
+ questions.filter((q) => !!q?.id).sort((a, b) => cmp(a.id, b.id)),
+ { key: "id" },
+ ),
+ )
+ }
+ })
+ }),
+ ),
+ ])
- try {
- await Promise.all(Object.values(blockingRequests).map((p) => retry(p)))
- } catch (err) {
- console.error("Failed to bootstrap instance", err)
+ const errors = results
+ .filter((item): item is PromiseRejectedResult => item.status === "rejected")
+ .map((item) => item.reason)
+ if (errors.length > 0) {
+ console.error("Failed to bootstrap instance", errors[0])
const project = getFilename(input.directory)
showToast({
variant: "error",
title: input.translate("toast.project.reloadFailed.title", { project }),
- description: formatServerError(err, input.translate),
+ description: formatServerError(errors[0], input.translate),
})
- input.setStore("status", "partial")
return
}
- if (input.store.status !== "complete") input.setStore("status", "partial")
-
- Promise.all([
- input.sdk.path.get().then((x) => input.setStore("path", x.data!)),
- input.sdk.command.list().then((x) => input.setStore("command", x.data ?? [])),
- input.sdk.session.status().then((x) => input.setStore("session_status", x.data!)),
- input.loadSessions(input.directory),
- input.sdk.mcp.status().then((x) => input.setStore("mcp", x.data!)),
- input.sdk.lsp.status().then((x) => input.setStore("lsp", x.data!)),
- input.sdk.vcs.get().then((x) => {
- const next = x.data ?? input.store.vcs
- input.setStore("vcs", next)
- if (next?.branch) input.vcsCache.setStore("value", next)
- }),
- input.sdk.permission.list().then((x) => {
- const grouped = groupBySession(
- (x.data ?? []).filter((perm): perm is PermissionRequest => !!perm?.id && !!perm.sessionID),
- )
- batch(() => {
- for (const sessionID of Object.keys(input.store.permission)) {
- if (grouped[sessionID]) continue
- input.setStore("permission", sessionID, [])
- }
- for (const [sessionID, permissions] of Object.entries(grouped)) {
- input.setStore(
- "permission",
- sessionID,
- reconcile(
- permissions.filter((p) => !!p?.id).sort((a, b) => cmp(a.id, b.id)),
- { key: "id" },
- ),
- )
- }
- })
- }),
- input.sdk.question.list().then((x) => {
- const grouped = groupBySession((x.data ?? []).filter((q): q is QuestionRequest => !!q?.id && !!q.sessionID))
- batch(() => {
- for (const sessionID of Object.keys(input.store.question)) {
- if (grouped[sessionID]) continue
- input.setStore("question", sessionID, [])
- }
- for (const [sessionID, questions] of Object.entries(grouped)) {
- input.setStore(
- "question",
- sessionID,
- reconcile(
- questions.filter((q) => !!q?.id).sort((a, b) => cmp(a.id, b.id)),
- { key: "id" },
- ),
- )
- }
- })
- }),
- ]).then(() => {
- input.setStore("status", "complete")
- })
+ if (loading) input.setStore("status", "complete")
}