Dashboard › opencode › Distillation
c060c6de-92d4-4173-aa9b-df228dda29a2["lore_tm_v1_l-U735T4P2XD5oUY5WB_QwilimtsT2D2OLrifvSw4nQ","lore_tm_v1_RBbh1npn6HiilqVzviPGlhhsqaLAZzpMl_eZlqTzVdc","lore_tm_v1_XA6kiV5d2wo647sXcGziOBRgIU1UFFZHTFF_2EphCxk","lore_tm_v1_uJWWhVgM9HXo28FcUdDggswxzalOy6oLWqNfAjPTRbM","lore_tm_v1_rBvLjVTa81W1WkryKK3sMeCgqXbYrKenFeJDKZMJDs0","lore_tm_v1_wlyCy5TJGKUr3dpKiNsQ-OcpbyP-aZvSCjv7OogIJ-E","lore_tm_v1_XkveEyRol1W0xJZnK9JHQrUAEYyALbWq8p4xhKNTF10","lore_tm_v1_INtjvFLe1NQYnAjtRPidmm5wgNuNUthBFUjU5ulMsIc","lore_tm_v1_Vij07VR9_vX3pZSbgypmp29egEAX3F5AvVcAkvBuht8","lore_tm_v1_ui2wDlK5CXZvJSn1YPqANBNC4FpBrXuoM732_q5R4e0","lore_tm_v1_OAAB0SYZYczrSYelZSf7YzeLaarwcr9Oy_ZJcPLpwaM","lore_tm_v1_LxC-typ-Ishi-OEFVWI8BKrJsqOXceNt-0rTtUGD-Rg"]
/home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/plugin.ts: Plugin has readonly id: string and setup(context) returning Promise<Cleanup | void> | Cleanup | void; Cleanup is () => Promise<void> | void; define(plugin: Plugin) returns the plugin unchanged.Context exposes app, location, options, agent, aisdk, catalog, command, event, integration, mcp, generate, permission, plugin, reference, rpc, session, shell, skill, storage, tool, vcs, websearch, and worktree; experimental.terminal is restricted to Pick<OpenCodeClient["experimental"]["persistentPty"], "read">, while plugin is restricted to Pick<PluginApi, "list">./home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/session.ts includes prompt, context, "model.request", "http.request", "http.response", and retry.SessionContext has mutable system: Array<SystemPart>, messages: Array<Message>, tools, generation, and providerOptions; generation contains request overrides where unset fields retain route and model defaults.SessionRequestKind values, in order, are "primary", "compaction", "title", and "generate"; auxiliary requests share the Session hook identity but are distinguished from the agent loop by this kind.SessionModelRequest exposes mutable baseURL?: string and headers: Record<string, string> alongside readonly sessionID, agent, model, and kind.SessionHttpRequest exposes the final mutable web-standard request: Request; SessionHttpResponse exposes readonly request: Request and mutable response: Response.SessionRetryDecision is { retry: false } | { retry: true; delay: number }; SessionRetry supplies error, attempt, and a mutable decision.SessionDomain includes create, get, switchAgent, switchModel, prompt, generate, command, synthetic, interrupt, rename, move, wait, and context, plus hook: ModelHooks<SessionHooks>."http.request" hook’s final mutable Request is the correct routing seam because it avoids a process-global fetch patch; planned to reuse one canonical routing implementation and return complete cleanup rather than duplicate URL/header logic.packages/core/src/fetch-interceptor.ts recognize /v1/{messages,chat/completions,responses}, /api/v1/{messages,chat/completions,responses}, /api/{messages,chat/completions,responses}, /(openai|anthropic)/v1/{messages,chat/completions,responses}, and /codex/responses, each permitting a trailing suffix."/codex/responses" to "/v1/codex/responses"; protocol gateway paths map anthropic → "/v1/messages", openai → "/v1/chat/completions", and "openai-responses" → "/v1/responses"."/chat/completions"; 2. "/codex/responses"; 3. "/responses"; 4. "/messages"; longest/specific suffixes are checked first.model; OpenAI Responses is detected first by array-valued input, max_output_tokens, or previous_response_id; Anthropic is detected by top-level system plus array-valued messages; remaining array-valued messages are treated as OpenAI Chat.system; it embeds system messages inside the messages array.RequestInit: strings, ArrayBuffer, and typed-array views decoded as UTF-8; it does not read streaming bodies or bodies available only on a Request, and returns undefined on failure.gatewayUrl, upstreamBase, and the client’s original full upstreamPath; the gateway uses x-lore-upstream-path to forward the exact intended endpoint rather than synthesizing /v1/..., including GitHub Copilot’s /chat/completions and provider-specific prefixes."/v1/" occurrence: the gateway receives that suffix plus the original query string, while upstreamBase is the origin and preceding path prefix; body-detected rewriting chooses a canonical gateway endpoint but preserves the original pathname and derives the upstream base by stripping a recognized endpoint suffix.localhost, 127.0.0.1, 0.0.0.0, ::1, and [::1]; bracketed IPv6 loopback is handled because URL.hostname retains brackets in the observed runtime.buildGatewayHeaders() behavior preserves original headers, sets x-lore-upstream-url, conditionally sets x-lore-upstream-path only for a sane absolute path beginning with /, and injects dynamic context headers only when the request does not already contain that header.buildGatewayHeaders() so header handling can never drift between them.getHeaders() and onRequestHeaders() are logged rather than propagated./messages, /completions, or /responses; 2. parse URL once; 3. bypass/observe direct gateway requests; 4. bypass local hosts; 5. route recognized URL patterns; 6. otherwise attempt body-shape detection for LLM-looking paths; 7. warn once per ${host}${pathname} if an LLM-looking request cannot be recognized; 8. pass through unchanged.Symbol.for("lore.fetchInterceptor.originalFetch") as a cross-copy double-install guard; subsequent installs return a no-op cleanup to avoid stacked interceptors and the gateway→interceptor→gateway infinite-loop shape from issue #1027.Object.assign(interceptor, originalFetch); cleanup restores globalThis.fetch and sets the shared original-fetch slot back to null./home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/registration.ts: every Registration has dispose: () => Promise<void>; Hooks<Spec> and ModelHooks<Spec> asynchronously register callbacks and return Promise<Registration>; model hooks may be scoped with ModelHookOptions.providerID; Transform<Input> also returns Promise<Registration>.packages/opencode/src/internal.ts: helpers must remain outside ./index.ts because the legacy loader invokes every exported function as a plugin; exporting applyLoreProviderConfig() caused undefined to enter the host hooks array and later crash with undefined is not an object (evaluating 'A.event').gatewayAccessHeadersForRemote() injects GATEWAY_AUTH_HEADER only when normalized LORE_REMOTE_URL exactly matches the normalized selected gatewayBase and LORE_GATEWAY_AUTH_TOKEN exists.shouldForwardUpstreamExtraHeader(name): reject all x-lore-* headers plus x-api-key, x-goog-api-key, and authorization; provider and Lore credentials are applied by the gateway, never by this hop.applyLoreProviderConfig() pins every configured provider’s options.baseURL to ${gatewayBase}/v1, deep-merges existing provider/options fields, forces headerTimeout: false for openai and openai-codex, and creates an openai provider with those options if absent.http://host/messages without /v1, while the gateway routes /v1/messages and the interceptor bypasses 127.0.0.1; additionally, resolveSDK() passes options.baseURL, preventing AI SDK environment-variable fallback, and many providers have no base-URL environment variable.probeGateway(baseURL, timeoutMs = 1500) checks ${baseURL}/health; loopback URLs use Node http/https, remote URLs use fetch, only HTTP 2xx is success, timeout uses AbortController, failures return false, and the timer is always cleared.surfaceGatewayUnavailable() logs the error and fire-and-forgets client.tui.showToast({ body: { title: "Lore", message, variant: "error" } }); synchronous throws and promise rejections are swallowed so notification failure cannot crash a degraded session./home/byk/Code/opencode-v2-pilot/packages/core/src/session/model-request.ts applies "session.model.request" hooks before dispatch, allowing hooks to rewrite route baseURL and HTTP headers while retaining request body and query.httpMiddleware converts the outbound request to a web-standard Request, triggers "session.http.request", reconstructs the internal request from the possibly replaced Request, clones and restores a present body as Uint8Array, invokes the handler, then triggers "session.http.response" with a web-standard Response.204, 205, and 304; other response streams are converted with Stream.toReadableStreamEffect(), and non-Error failures are wrapped as new Error(String(cause))."x-session-affinity", "X-Session-Id", optional "x-parent-session-id", "User-Agent", "x-opencode-project", "x-opencode-session", and "x-opencode-client".package.json uses pnpm@10.28.0, Volta Node 24.16.0, Volta pnpm 10.28.0, TypeScript ^5.8.0, Vitest ^4.1.7, fast-check ^4.5.3, oxlint 1.73.0, and oxfmt 0.58.0.typecheck: pnpm -r run typecheck, test: vitest run with pretest: pnpm --filter @loreai/gateway run bundle, lint: oxlint --type-aware, and format:check: oxfmt --check; mutation testing uses premutation: pnpm --filter @loreai/gateway run bundle and mutation: stryker run.main and "." export set to ./packages/opencode/src/index.ts, workspaces packages/*, repository git+https://github.com/BYK/loreai.git, and author BYK."@opencode/plugin": "workspace:*": root package.json, plus packages/sdk, packages/plugin-browser, packages/latex, packages/tui, packages/simulation, packages/server, packages/plugin, packages/merman, packages/core, and packages/cli.packages/core/test/fetch-interceptor-body.test.ts, packages/core/test/fetch-interceptor-install.test.ts, packages/core/test/fetch-interceptor-global.test.ts, and packages/core/test/fetch-interceptor-paths.test.ts.