Dashboard › opencode › Distillation
c319fc01-05ce-41ec-9975-d2b153cd636e["lore_tm_v1_sEuIfaKS-wt0xpicjAel_pANpGYT-EWJohDUFkOJc-0","lore_tm_v1_viHdVVbUFqW4a5BmAtDCub8EKzYeizQ0c7ZCDLy0skY","lore_tm_v1_WyUnjhDq0nGb7BVaUdf4u13WVk1N8CyMXyD-wptdtVs","lore_tm_v1_C_kU-8D4vrROlDCVnTdgEg9k2qeB_w4njIsFBEWVwMA","lore_tm_v1_pFhVH7eZ1HlbuB7kOI2oatmj1n4p_cJx2SSzD_TbriA","lore_tm_v1_O7837IvBVN_BoXacpS_DkW5i8WlkQ9LTs-xKM1ABHVY","lore_tm_v1_rkwgqMrhmoc14BeHLl0LpPafdbZFirzq4an3J0Zosvk","lore_tm_v1_3bbsmj6agPr8x7Zq5rBUNaY-KMulw9dbHlc3Zs8sSj0"]
Date: Sep 14, 2026
OpenApi.fromApi is non-trivial and should be deferred until /doc is requested, so processes that never serve it—CLI and scripts—do not pay the cost at module load.HttpApiBuilder.group(...); handlers should yield stable services once while constructing the handler layer and close over those services in endpoint implementations.HttpRouter.use(...) should be reserved for routes outside the declared API surface, such as a catch-all UI fallback.packages/opencode/src/server/routes/instance/httpapi/server.ts exports routes = createRoutes() and a lazy webHandler that calls HttpRouter.toWebHandler(routes, { disableLogger: true, memoMap, middleware: disposeMiddleware }).packages/opencode/src/server/routes/instance/httpapi/server.ts, Layer.provideMerge(Observability.layer) must remain last because later-provided layers build beneath earlier ones; otherwise eagerly forked fibers such as the ModelsDev background refresh capture Effect’s default stdout logger and corrupt the TUI (#34730).packages/opencode/src/effect/app-node-builder-v1.ts defines bootstrapReplacement = [InstanceStore.bootstrapNode, InstanceBootstrap.node] as const; build<A, E>(root, replacements = []) delegates to AppNodeBuilder.build(root, replacements.concat([bootstrapReplacement])).packages/opencode/src/project/bootstrap.ts builds global InstanceBootstrap.node for Service; dependencies are Config.node, Format.node, LSP.node, Plugin.node, Project.node, ShareNext.node, Snapshot.node, and Vcs.node.InstanceBootstrap yields Config.Service, Format.Service, LSP.Service, Plugin.Service, Project.Service, ShareNext.Service, Snapshot.Service, and Vcs.Service during layer initialization so its returned run effect has R = never; InstanceStore imports only the lightweight tag from bootstrap-service.ts to avoid importing the implementation graph.InstanceBootstrap.run reads InstanceState.context, logs bootstrapping with ctx.directory, eagerly calls config.get(), then calls plugin.init() before other initialization because plugins can mutate configuration.InstanceBootstrap.run initializes [lsp, shareNext, format, vcs, snapshot, project] concurrently with { concurrency: "unbounded", discard: true }; each s.init() failure is caught and logged as init failed, and the work is traced under InstanceBootstrap.init and InstanceBootstrap.packages/opencode/src/project/instance-store.ts defines LoadInput with directory: string, optional worktree?: string, and optional project?: Project.Info; InstanceStore.Interface exposes load, reload, dispose, disposeDirectory, disposeAll, and provide.InstanceStore maintains Map<string, Entry>, where each Entry contains Deferred.Deferred<InstanceContext>; directory keys are normalized through FSUtil.resolve(...).InstanceStore.boot(...) uses a supplied project and worktree when both are present; otherwise it calls project.fromDirectory(input.directory) and maps result.sandbox to worktree and result.project to project. It then runs bootstrap.run with the resulting context provided as InstanceRef.InstanceStore.completeLoad(...) captures the boot(...) exit, removes the cache entry on failure, and completes the entry’s deferred with the exit.InstanceStore.load(...) is protected by Effect.uninterruptibleMask: it returns the existing deferred for duplicate directory loads, or inserts a new deferred, logs creating instance, forks completeLoad(...) into the store scope with { startImmediately: true }, and awaits the deferred interruptibly via restore(...).InstanceStore.reload(...) atomically replaces the directory’s cache entry with a new deferred; its fork logs reloading instance, waits for and ignores the previous deferred’s result, calls runDisposers(directory), emits disposal when a prior entry existed, and then performs completeLoad(...).runDisposers(ctx.directory), then emits a GlobalBus event with type server.instance.disposed, directory, optional project ID, and WorkspaceContext.workspaceID.InstanceStore.disposeEntry(...) checks entry identity both before and after disposeContext(...) to avoid deleting a replacement cache entry; dispose(ctx) also refuses to dispose when the loaded context is not the same object as ctx.InstanceStore.disposeDirectory(...) awaits the cached deferred, removes failed entries, and otherwise disposes the loaded context. disposeAllOnce() traverses a snapshot of all cache entries, logs failed loads as instance dispose failed, and removes or disposes each entry.InstanceStore.disposeAll wraps disposeAllOnce() with Effect.cachedWithTTL(..., Duration.zero) so disposal executes once; it is registered as a layer finalizer with errors ignored.InstanceStore.provide(...) loads an instance and provides its context as InstanceRef to the supplied effect. bootstrapNode is declared as LayerNode.unbound(InstanceBootstrap.Service, Node.tags.values.global), and InstanceStore.node depends on Project.node plus bootstrapNode.packages/opencode/src/server/routes/instance/httpapi/middleware/instance-context.ts defines InstanceContextMiddleware, requiring WorkspaceRouteContext; its decode(...) helper applies decodeURIComponent(...) and returns the original input if decoding throws.provideInstanceContext(...) reads WorkspaceRouteContext, loads the decoded route directory through InstanceStore, and runs the HTTP effect with InstanceRef set to the loaded context and WorkspaceRef set to route.workspaceID; instanceContextLayer captures InstanceStore.Service once when building the middleware layer.packages/opencode/src/server/routes/instance/httpapi/handlers/session.ts, SessionHttpApi.prompt verifies the session with requireSession(...), calls promptSvc.prompt(...), maps failures to HttpApiError.BadRequest, and returns the JSON-serialized message as an application/json streaming response using HttpServerResponse.stream(Stream.make(...).pipe(Stream.encodeText), ...).SessionHttpApi.promptAsync verifies the session, forks promptSvc.prompt(...) into scope with { startImmediately: true }, and returns HttpApiSchema.NoContent; asynchronous failures are logged as prompt_async failed and published through EventV2Bridge as Session.Event.Error with NamedError.Unknown({ message: Cause.pretty(cause) }).toObject().SessionHttpApi.command maps promptSvc.command(...) errors to HttpApiError.BadRequest; SessionHttpApi.shell, SessionHttpApi.revert, and SessionHttpApi.unrevert map busy-state errors through SessionError.mapBusy(...).SessionHttpApi.permissionRespond calls permissionSvc.reply({ requestID, reply }); Permission.NotFoundError becomes PermissionNotFoundError with the exact message Permission request not found: ${error.requestID}.SessionHttpApi.deleteMessage requires the session, enforces runState.assertNotBusy(...) through SessionError.mapBusy, removes the message, and returns true; deletePart requires the session, removes the part, and returns true.SessionHttpApi.updatePart rejects the request with HttpApiError.BadRequest unless payload id, messageID, and sessionID exactly match route parameters partID, messageID, and sessionID; valid payloads are passed to session.updatePart(...).list, 2. status, 3. get, 4. children, 5. todo, 6. diff, 7. messages, 8. message, 9. raw create, 10. remove, 11. update, 12. raw fork, 13. abort, 14. init, 15. share, 16. unshare, 17. summarize, 18. prompt, 19. promptAsync, 20. command, 21. shell, 22. revert, 23. unrevert, 24. permissionRespond, 25. deleteMessage, 26. deletePart, 27. updatePart.