Dashboard › opencode › Distillation
3e91517f-4975-42ce-9806-e4e170085eb3["lore_tm_v1_z0G818q6R_H4fLtzWe8_Ee-PlTZXlRIDhphMMFG41GY","lore_tm_v1_-80P0CozwTKmqaI4NVACvgvYJV4k4dE8TQveWgykFkA","lore_tm_v1_gJzqgl-vcO7Y7tWeKWLjucV63Y3ooWUiQbDHf9rZ414","lore_tm_v1_99fr8HqjbwAepCfgTTyL4cQXLuaihLBlLuJuBBri2To"]
/home/byk/Code/opencode-lore/packages/opencode/src/index.ts lines 374-456: the "chat.headers" hook merges gatewayAccessHeadersForRemote(gatewayBase), sets stable x-lore-session-id from input.sessionID, sets x-lore-agent from input.agent, and conditionally sets x-parent-session-id, x-lore-project, x-lore-git-remote, x-lore-provider, and x-lore-upstream-url."chat.headers" is cached and never blocks or throws on failure; a resolved parent is forwarded as x-parent-session-id so the gateway can size LTM injection for OpenCode Task sub-agents under issue #1300."chat.headers" uses thisProjectPath and thisGitRemote for the current plugin invocation, preventing concurrent sub-agents or sibling projects in one OpenCode process from clobbering one another; fetch-interceptor getHeaders() remains only a fallback for requests bypassing the hook, such as embedding or image generation..id, code casts input.provider to Record<string, unknown>, writes the ID to x-lore-provider, and derives local-provider configuration as LORE_UPSTREAM_${providerID.toUpperCase().replace(/-/g, "_")}; the resulting value is assigned to x-lore-upstream-url only when that header is not already present.LORE_UPSTREAM_EXTRA_HEADERS handling: split on /\r?\n/, trim and skip empty lines, split each valid line at its first colon, trim name/value, reject lines whose colon index is <= 0, and forward only names accepted by shouldForwardUpstreamExtraHeader(name) so gateway-managed headers are not clobbered. These literal headers support corporate proxies, LiteLLM, and Cloudflare AI Gateway auth/team-routing; the gateway applies the same environment variable as a safety net if the plugin is bypassed.log and is NEVER a raw stderr write because OpenCode owns a full-screen TUI and any stray byte corrupts it; startup information remains visible through lore logs.active: ${projectPath}, installs installFetchInterceptor(...), then logs routing through ${gatewayBase} and dashboard: ${gatewayBase}/ui; processInitDone is then set to true.currentProject.path only with the git remote resolved for that path—never a remote left over from a different project’s plugin call.detail as e.stack || e.message for Error instances or String(e) otherwise, calls log.error(\init failed: ${detail}`)` so the full cause survives in file logs and Sentry even when TUI stderr is silenced, and then rethrows because OpenCode’s loader may catch and swallow the error./home/byk/Code/opencode-lore/packages/opencode/src/index.ts: it must export only LorePlugin plus a same-reference default export; OpenCode’s legacy loader invokes every function export as a plugin and throws on any non-function export, dropping the plugin entirely. Helpers must stay in ./internal.ts, and test/index.test.ts guards this as the "plugin entry module export shape" test./home/byk/Code/opencode-lore/packages/gateway/src/cli/start.ts defines EMBED_DRAIN_DEADLINE_MS = Math.max(500, Math.floor(SHUTDOWN_DEADLINE_MS * 0.6)) for graceful shutdown issue #1331; the bound leaves time for subsequent worker resetProvider(), and incomplete embedding work is re-indexed by runStartupBackfill on the next boot./home/byk/Code/opencode-lore/packages/gateway/src/cli/start.ts defines VECTOR_POOL_SHUTDOWN_DEADLINE_MS = Math.max(Math.min(DEFAULT_VECTOR_POOL_SHUTDOWN_DEADLINE_MS, SHUTDOWN_DEADLINE_MS - 500), 500) for issue #1599.TRUNCATE the WAL; otherwise the -wal file remains stranded and forces WAL recovery at the next boot. The deadline is bounded beneath the global shutdown deadline while retaining a 500 ms floor, including with aggressive LORE_SHUTDOWN_TIMEOUT_MS values such as 1000ms, so a stuck worker still leaves room for the writer’s checkpoint and close./home/byk/Code/opencode-lore/packages/gateway/src/cli/start.ts imports lifecycle coordination APIs currentProcessIdentity, inspectProcessGeneration, withoutLifecycleLock, withLifecycleLock, and types LifecycleLock and ProcessInspection from ../lifecycle-lock; shutdown APIs include installSignalShutdown, makeProcessShutdownController, SHUTDOWN_DEADLINE_MS, and ProcessShutdownController./home/byk/Code/opencode/packages/plugin/src/v2/promise/context.ts: PluginContext contains readonly options: PluginOptions; agent: AgentHooks & Reload; aisdk: AISDKHooks; catalog: CatalogHooks & Reload; command: CommandHooks & Reload; integration: IntegrationHooks & Reload; plugin: PluginDomain; reference: ReferenceHooks & Reload; and skill: SkillHooks & Reload./home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/session.ts defines SessionPrompt with readonly sessionID, readonly messageID, mutable prompt: Types.DeepMutable<PromptInput.Prompt>, optional metadata?: Record<string, unknown>, and delivery: SessionInbox.Delivery.SessionContext contains readonly sessionID, readonly agent, readonly model, mutable system: Array<SystemPart>, messages: Array<Message>, tools: Record<string, { description: string; input: JsonSchema.JsonSchema }>, generation: Types.DeepMutable<GenerationOptionsFields>, and providerOptions: Record<string, unknown>; unset generation fields retain route and model defaults.SessionRequestKind = "primary" | "compaction" | "title" | "generate"; auxiliary requests share the Session hook identity but are distinguished from the agent loop by this kind.SessionModelRequest contains readonly sessionID, agent, model, and kind, plus mutable optional baseURL?: string and headers: Record<string, string>.SessionHttpRequest contains readonly sessionID, agent, model, and kind, plus mutable request: Request; SessionHttpResponse contains the same readonly identity fields, readonly request: Request, and mutable response: Response.SessionRetryDecision is the discriminated union { retry: false } | { retry: true; delay: number }; SessionRetry has readonly sessionID, agent, model, error: SessionError.Error, and attempt: number, with mutable decision: SessionRetryDecision.SessionHooks maps hooks in this order: prompt, context, "model.request", "http.request", "http.response", and retry.SessionDomain is Pick<SessionApi, ...> & { readonly hook: ModelHooks<SessionHooks> }, exposing these methods in order: 1. create, 2. get, 3. switchAgent, 4. switchModel, 5. prompt, 6. generate, 7. command, 8. synthetic, 9. interrupt, 10. rename, 11. move, 12. wait, 13. context.