Dashboard › opencode › Distillation
c2d9af9c-f7a1-4973-8966-3706e1496ff8["lore_tm_v1_D-eqGOWFfQWMMT6I_RL2fnN5mGsTHEvEtaaBEezj964","lore_tm_v1_pL-WhHtSOa7kB5qUe4SV8-ZWwniyIbNa9OhpU2uw36k","lore_tm_v1_Td81uS7FDQGjN5q1hFHLkN3Rg2Bq8CruXMDbickdURM","lore_tm_v1_3TnlRDntsAyzxWqotU7ZKRbxa9uqYaipqSCkUM2SW-s","lore_tm_v1_cZM7xWYc1wbQzn7zBpMD5vk2PGEN2gmiEtVXykhOGek","lore_tm_v1_9HsFtere1BMpVpdgF68NYp7vCvdGuURZDakWOror6dA","lore_tm_v1_fbRm74SBN7aF712qcRcGA1r4DyYt6hYO7r9eViGHA3E","lore_tm_v1_0_zjhuuHTatPqtYm9cqyKslhQZLDkki_fVbSyXpkCUE"]
rewriteRequest in /home/byk/Code/opencode-lore-v2: /packages/core/src/index.ts line 357 and /packages/core/src/fetch-interceptor.ts lines 328, 334, 343, and 558./home/byk/Code/opencode-lore-v2/packages/core/src/fetch-interceptor.ts lines 315-320 define mayBeLLMRequest(url) by checking whether the URL includes /messages, /completions, or /responses.rewriteRequest() never reads the request body: known paths can safely carry streaming bodies, while unknown paths always pass through.rewriteRequest(request, gatewayBase, dynamicHeaders, onRequestHeaders?) delegates to rewriteRequestForProtocol(request, gatewayBase, new URL(gatewayBase), dynamicHeaders, onRequestHeaders).rewriteRequestForProtocol() returns the original request when mayBeLLMRequest(request.url) is false; observes headers and returns unchanged when already routed through gatewayBase; and returns unchanged for local hosts.rewriteRequestForProtocol() routes recognized paths with interceptUrl(upstream, gateway), can route protocol-inferred paths with interceptUrlForProtocol(upstream, gateway, protocol), and passes the request through unchanged when neither produces a rewrite.new Request(rewrite.gatewayUrl, request), receives gateway headers through applyGatewayHeaders() using rewrite.upstreamBase, rewrite.upstreamPath, and dynamicHeaders, and is reported through observeRequestHeaders().X-Lore-Upstream-URL and X-Lore-Upstream-Path, and 4. inject dynamic X-Lore-* context headers from getHeaders()./home/byk/Code/opencode-lore-v2/packages/opencode/test/server.test.ts mocks a runtime with gateway http://127.0.0.1:3207, project /workspace/project, git remote github.com/example/project, and headers for session ses_1, agent build, provider openai, and upstream https://api.openai.com.id === "lore" and a setup function, while the legacy entrypoint still exports exactly LorePlugin and default, with legacy.default === legacy.LorePlugin.subagent workers in this exact order: 1. lore-distill — "Lore memory distillation worker"; 2. lore-curator — "Lore knowledge curator worker"; 3. lore-query-expand — "Lore query expansion worker".model.request and http.request hooks and calls acquireServerRuntime("/workspace/project").model.request test resolves parent session ses_parent, calls buildServerHeaders() with sessionID: "ses_1", parentID: "ses_parent", agent: "build", and providerID: "openai", preserves authorization: "Bearer provider", adds x-lore-session-id: "ses_1", and changes baseURL from https://api.openai.com/v1 to http://127.0.0.1:3207/v1.http.request test calls rewriteRequest(original, "http://127.0.0.1:3207", {}) and replaces https://api.openai.com/v1/chat/completions with http://127.0.0.1:3207/v1/chat/completions.release() once.session.hook() throws "registration failed" and disposal throws "dispose failed", setup still rejects with "registration failed", disposes the 1 prior registration once, and calls release() once.session.get() rejects with "unavailable", routing continues without a parentID header and still adds x-lore-session-id: "ses_1"./workspace/a releases only runtime A, runtime B at /workspace/b remains usable for a model.request, and each runtime is released exactly once when its own scope closes.release() only once./home/byk/Code/opencode-lore-v2/packages/opencode/package.json defines @loreai/opencode version 0.40.0, ESM type, FSL-1.1-Apache-2.0 license, and description "Three-tier memory architecture for OpenCode — distillation, not summarization"."." export points to ./src/index.ts, while "./server" uses types from ./src/server.ts and Bun/default runtime exports from ./dist/server.js."typecheck": "tsc --noEmit" and "build": "tsx script/build.ts"; peer dependencies are @opencode-ai/plugin >=1.1.0 and optional @opencode/plugin >=0.0.0.@loreai/core: "workspace:*" and @loreai/gateway: "workspace:*"; dev dependencies are @opencode-ai/plugin: "^1.1.39", @opencode-ai/sdk: "^1.1.39", @opencode/plugin: "0.0.0-beta-19378", and @types/bun: "^1.2.0"./home/byk/Code/opencode-lore-v2/packages/opencode/script/build.ts deletes and recreates dist/, then bundles src/server.ts to dist/server.js with esbuild using format: "esm", platform: "node", target: "esnext", and sourcemap: true.@loreai/core to src/server-core.ts, leaves @opencode/plugin and @loreai/gateway external, and uses logLevel: "info"./home/byk/Code/opencode-lore-v2/packages/opencode/src/server-core.ts re-exports GATEWAY_AUTH_HEADER, rewriteRequest, getGitRemote, and log directly from core source files./home/byk/Code/opencode-lore-v2/packages/opencode/src/internal.ts keeps helper functions outside ./index.ts because OpenCode’s legacy getServerPlugin/getLegacyPlugins loader treats every exported function as a plugin and invokes it.applyLoreProviderConfig caused its undefined return value to enter the host hooks array, after which first hook dispatch crashed with undefined is not an object (evaluating 'A.event'); fix: keep helpers in src/internal.ts so the entry module exposes only the plugin function while tests import helpers directly.isLoopbackUrl() accepts localhost, localhost., ::1, and IPv4 addresses matching /^127(?:\.\d{1,3}){3}$/, stripping IPv6 brackets and lowercasing the hostname; malformed URLs return false.gatewayAccessHeadersForRemote() injects GATEWAY_AUTH_HEADER only when normalized LORE_REMOTE_URL exactly equals normalized gatewayBase and LORE_GATEWAY_AUTH_TOKEN exists.shouldForwardUpstreamExtraHeader() rejects all x-lore-* headers plus x-api-key, x-goog-api-key, and authorization; provider and Lore credentials are applied by the gateway rather than this hop.parseUpstreamExtraHeaders() splits newline-delimited headers at the first :, trims names and values, and ignores absent input, lines without a valid separator, and empty names.options.baseURL to the @ai-sdk factory, so loadOptionalSetting() only reads an environment base URL when the factory receives an undefined baseURL.OPENAI_BASE_URL while stripping /v1, sending requests to http://host/messages; Lore routes only /v1/messages, and the fetch interceptor skips 127.0.0.1 to avoid loops, resulting in a bare /messages 404.OPENAI_BASE_URL and ANTHROPIC_BASE_URL are bypassed by OpenCode’s resolveSDK(), while providers including Google, Mistral, Groq, Cohere, xAI, Perplexity, Together AI, Vercel, Alibaba, DeepInfra, Gateway, OpenRouter, and Cerebras have no base URL environment variable; therefore iterating over cfg.provider is the universal routing lever.applyLoreProviderConfig(cfg, gatewayBase) pins every object-valued provider’s options.baseURL to ${gatewayBase}/v1, deep-merges existing provider fields and options so custom headers/model overrides survive, and does nothing when gatewayBase is empty.applyLoreProviderConfig() forces headerTimeout: false for openai and openai-codex because Lore context preparation can exceed OpenCode Codex’s 10-second header deadline; the gateway owns the foreground request deadline.applyLoreProviderConfig() creates an openai provider with { options: { baseURL: baseUrl, headerTimeout: false } } if one does not already exist.probeGateway(baseURL, timeoutMs = 1500) probes ${baseURL}/health, uses http/https directly for loopback URLs, uses fetch otherwise, accepts only successful responses, returns false on failures, aborts after the timeout, and always clears its timer.surfaceGatewayUnavailable() never writes a raw byte to the terminal: it uses client.tui.showToast() so notification rendering occurs inside the OpenCode TUI render loop rather than via the replaced process.stderr.write.surfaceGatewayUnavailable() logs to file/Sentry with log.error(message) and sends a toast body { title: "Lore", message, variant: "error" }.surfaceGatewayUnavailable() is fire-and-forget, defensively swallows promise rejection through optional .catch(() => {}), and catches synchronous showToast() errors so a missing/headless TUI or older server without /tui/show-toast cannot crash a degraded-but-running session./home/byk/Code/opencode-lore-v2/packages/core/src/log.ts writes all info, warn, and error calls to ~/.local/share/lore/lore.log regardless of LORE_DEBUG, rotates above 5 MB with one .log.1 backup, and disables file logging under NODE_ENV=test.LogSink supports info(), warn(), error(), captureException(), and optional withDbSpan<T>(sql, fn); the latter allows host-owned tracing such as Sentry.startSpan without adding a Sentry dependency to @loreai/core.traceDbQuery<T>(sql, fn) uses sink.withDbSpan(sql, fn) when available; otherwise it is a transparent pass-through that invokes fn() exactly once, returns its value verbatim, and adds no allocation beyond one optional-chain check.LORE_DEBUG equals "1" or case-insensitive "true"; this fixes the prior bug where !!process.env.LORE_DEBUG incorrectly treated "0" and "false" as enabled and emitted [lore] lines into full-screen TUIs.silenceStderr() because any stdout/stderr byte from an in-process gateway can corrupt the full-screen TUI; afterward every logger level, including error and output under LORE_DEBUG=1, goes only to the persistent file and registered sink.globalThis["__loreStderrSilenced"] rather than a module-local variable because the gateway’s Node/CJS dist/index.cjs can contain a second bundled copy of @loreai/core; globalThis shares the state across both core instances in the main thread.silenceStderr(silenced = true) is process-global and idempotent, while standalone Lore/CLI processes retain stderr visibility because they never call it.