Dashboard › opencode › Distillation
38a97a74-c651-482f-b3a8-eeec3354c9c9["lore_tm_v1_CiSZBhXEK6WCyCfDUfT1o4n2i62F6y6pUEWocWvh8SE","lore_tm_v1_JFPZ_2mvGudCG0v1hjCdcPTWl1sjFVo-PSK2fJldJyY","lore_tm_v1_vM3QNMUkdtKneGPDHGAs5a2nYBDacl6NUygcyeTqtyg","lore_tm_v1_j-TExqZC07n_-iob1Hf5SSCTy0WF_OwFbeXrzYNhvPg","lore_tm_v1_Da6g5_jnMxFhRiVjDlScCAICCCxNCwbwwbrgy_dlpVU","lore_tm_v1_m1G4zYJhOw58WyFnRQ4jJ9HNEPyV2jzhD6b-CckGmgc","lore_tm_v1_wBgTt7o280lEOjq-AzHu8bpl4EPCBlVRHYT_UtOSTsU","lore_tm_v1_UEEbYEMKV75UJgP3YDrfHx00e19F1IEAXMLGLdnxilg","lore_tm_v1_CCn0fJm_W6lbTwS7T-RbUxvrtsaV_1ALVQto8ylLWoI","lore_tm_v1_YVQ-aImDQDi00CtW-Nob3J5hXrdB_IsnMucCji07PXE","lore_tm_v1_MULTiRuY5xSqEEu4blHInSndH2YUv9qSKFvZp3RxJWA","lore_tm_v1_HZtN_vcHwJ9Ev0jJifXV7ot0PJELWGXWZpwlCxqusME","lore_tm_v1_uOJiDAXKjITHIb8hwAvQIXitw2Hom7SXH-b5C3Fdi4A","lore_tm_v1_GHNoPjUcgRwwQPA92WufeuliUurPjupJKRX4oGhbcHY","lore_tm_v1_TlOZPKJoO6osqwH9TzNSUcnw3kMJqY3OImhm84aDS4U","lore_tm_v1_uySQ7sqWlrbwPWV746XhK2os7MWRPJhRtMosfnvtbDg","lore_tm_v1_q4zT6Tx7plPgpdaA2K7KLoT4-n1UrIjEw1RP9UnQoGg","lore_tm_v1_zSlom_pYmVJEUzm6am1i0NmWfnSSLDMun0JV_frTMd4","lore_tm_v1_ltr64XHDNRQFPUfd8tWKycIGMy9hdvykN2fMvNrhmtY","lore_tm_v1_P0kn5HO-oQL-GqapPsli-_QtcU44X-ReWyfT-tiFRZQ","lore_tm_v1_5JPuI4q2u5JhaUw_WhA52RrZZ6SG2NP-RXnnuEI1nCY","lore_tm_v1_zluXfOQqLB9VaRL3w7k4q9uEQ2ub7i7hu0bkOgnptA8","lore_tm_v1_TJmqaq8SJrv6bZnhmLiCU5zy0IwUSATqzQ8RZUbAIdA","lore_tm_v1_pjbR038d_JPtLDe62NbwJS7z5SmfEumtIXgBEOqEDLQ","lore_tm_v1_pG4TeIEH5ng_tlCw4YJdiCtseQKLPbc_kNFiQoisSus","lore_tm_v1_L37PFNn-Dr0bdg6s_Q5FCGl4nPTskUfKuecJVWOabQk","lore_tm_v1_nqt347dbHvGSz6csqhCyGHnsEC_H1t4tIrjNG_c8Jcc","lore_tm_v1_PiGKHBH9pSiFZlw58APPHmAp9jyfXA5GxM4u1xBt2NE","lore_tm_v1_ZuXaUpMnuWp_otH2G2EngdiNfOZHcAs5UwpTSRY6moY"]
/home/byk/Code/opencode-v2-pilot/packages/core/src/plugin/agent.ts configures built-in agents compaction, title, and summary as mode: "primary" and hidden: true; title uses PROMPT_TITLE, summary uses PROMPT_SUMMARY, and both receive a deny-all permission { action: "*", resource: "*", effect: "deny" }.packages/opencode/src/index.ts, the chat.headers hook adds gateway access headers, x-lore-session-id, x-lore-agent, optional x-parent-session-id, project-specific x-lore-project, optional project-specific x-lore-git-remote, runtime provider ID as x-lore-provider, and provider-specific LORE_UPSTREAM_<PROVIDER> as x-lore-upstream-url.packages/opencode/src/index.ts converts a provider ID to its upstream environment-variable name with providerID.toUpperCase().replace(/-/g, "_"), and only sets x-lore-upstream-url when that header is not already present.packages/opencode/src/index.ts parses LORE_UPSTREAM_EXTRA_HEADERS and forwards only headers accepted by shouldForwardUpstreamExtraHeader(name), avoiding headers managed by the gateway.packages/core/src/git.ts function getGitRemote(path: string): string | null immediately returns null in hosted mode; otherwise it caches results per unique path for the process lifetime and runs git remote -v at most once per path using execSync with cwd: path, encoding: "utf-8", timeout: 5000, and stdio: ["pipe", "pipe", "pipe"].getGitRemote() parses fetch remotes only, prefers origin, then upstream, then any other remote. origin is deliberately preferred because unrelated repositories may share a template upstream, and falsely merging distinct projects is considered worse than failing to unify a genuine fork with its source.getGitRemote() normalizes the selected URL with normalizeRemoteUrl(url) and caches null when the path is not a repository, no remote exists, Git is unavailable, the subprocess times out, or another exception occurs.packages/gateway/src/cli/start.ts, in-process callers such as the OpenCode plugin and Pi extension use quiet: true because any stdout/stderr write can corrupt the hostβs full-screen TUI; quiet notifications go through file-based log.warn(msg), while normal lore start CLI notifications use console.error(\[lore] ${msg}`)`.packages/core/src/fetch-interceptor.ts function shouldIntercept(url, gatewayBase) only intercepts known LLM API paths on remote hosts. It returns false for URLs beginning with gatewayBase, local hosts localhost, 127.0.0.1, 0.0.0.0, ::1, and [::1], malformed URLs, and non-LLM paths.mayBeLLMRequest(url) performs a fast prefilter for URLs containing /messages, /completions, or /responses.rewriteRequest() and rewriteRequestForProtocol() never read the request body on known paths; unknown paths pass through unchanged unless a supplied/detected BodyProtocol supports routing. Direct-gateway requests remain the same Request but have their headers observed through onRequestHeaders.x-lore-upstream-url, a valid absolute x-lore-upstream-path, and dynamic X-Lore-* headers only when those headers are not already present. Failures in either dynamic getHeaders() or onRequestHeaders() are logged and do not propagate.installFetchInterceptor() uses process-global Symbol.for("lore.fetchInterceptor.originalFetch") as a cross-bundle double-install guard. This prevents stacked interceptors and the gateway-to-interceptor infinite loop from issue #1027, including when @loreai/core is bundled into the in-process gateway.installFetchInterceptor() call returns a no-op cleanup when the shared original-fetch slot is occupied; normal cleanup restores the captured globalThis.fetch and resets the shared slot to null.${host}${pathname} for an LLM-looking unknown endpoint, preserves extra properties such as fetch.preconnect with Object.assign(interceptor, originalFetch), and supports body-protocol detection only when an unknown path looks LLM-like and has an extractable string body.packages/core/test/fetch-interceptor-request.test.ts verifies routing https://openrouter.ai/api/v1/chat/completions?stream=true&trace=abc to https://gateway.example.com/v1/chat/completions?stream=true&trace=abc while preserving POST, body, authorization: Bearer sk-test, x-api-key: api-key-test, query parameters, x-lore-project: /home/me/project, and x-lore-session-id: session-123; it adds upstream base https://openrouter.ai/api and upstream path /api/v1/chat/completions without consuming the original body.x-lore-session-id: request-session to take precedence over dynamic x-lore-session-id: session-123.https://gateway.example.com/v1/messages to remain object-identical, receive no dynamic x-lore-project, and still invoke the header observer once with the original headers.http://localhost:8000/v1/messages, http://127.0.0.1:8000/v1/messages, http://0.0.0.0:8000/v1/messages, and http://[::1]:8000/v1/messages to remain unchanged.https://registry.npmjs.org/package to remain unchanged.https://api.anthropic.com/v1/messages to route to ${GATEWAY}/v1/messages without consuming the original request body; the routed request must still yield "stream body".https://api.example.com/v2/chat/completions?stream=true to remain unchanged and unread, even when its JSON includes {"model":"gpt-5","messages":[]}.true for three lookalikes: host https://gateway.example.com.evil with /v1/messages, alternate port https://gateway.example.com:444 with /v1/messages, and actual gateway host https://gateway.example.com with /v11/messages.packages/opencode/test/server-runtime.test.ts requires acquireServerRuntime("/project", ...) to stay inactive and avoid gateway resolution when LORE_DISABLED is either "1" or "true"./workspace/one and /workspace/two retain separate projectPath/gitRemote values, resolveGateway runs once, shutdown does not occur after the first release, occurs once after the second, and an additional release is idempotent.gitRemote() throws "identity failed", acquireServerRuntime() rejects with that error and shuts down the newly acquired gateway exactly once./workspace/two while /workspace/one is closing does not call resolveGateway again until shutdown finishes; the subsequent runtime may resolve to http://127.0.0.1:5673 after the original http://127.0.0.1:3207.buildServerHeaders() must include attribution/routing values x-lore-access, x-lore-session-id, x-parent-session-id, x-lore-agent, x-lore-project, x-lore-git-remote, x-lore-provider, x-lore-upstream-url, and approved extra headers such as x-team: platform.buildServerHeaders() must not forward credentials or forged Lore headers from LORE_UPSTREAM_EXTRA_HEADERS; tested exclusions are authorization: Bearer secret, x-api-key: secret, and x-lore-forged: bad.packages/gateway/src/config.ts limits x-lore-git-remote to MAX_GIT_REMOTE_LENGTH = 512; extractGitRemoteHeader() removes control characters [\x00-\x1f\x7f], trims whitespace, rejects absent, empty, or overlength values, and canonicalizes valid SSH/HTTPS/git:// variants using normalizeRemoteUrl().packages/opencode/src/index.ts, startup output must go through log rather than raw stderr because OpenCode owns a full-screen TUI and any stray byte can corrupt it; startup logs include active: ${projectPath}, routing through ${gatewayBase}, and dashboard: ${gatewayBase}/ui, visible through lore logs.getHeaders() emits gateway access headers plus x-lore-project and only the git remote paired with that same current project path, preventing a remote left over from another plugin call.log.error(\init failed: ${detail}`)` before rethrowing because the plugin loader may catch and swallow the error; the error remains available through file logging and Sentry even when stderr is silenced.packages/opencode/src/index.ts warns against adding exports because the legacy OpenCode plugin loader invokes every function export as a plugin and throws on non-function exports.packages/opencode/test/server.test.ts requires the V2 plugin definition to have plugin.id === "lore" and a function plugin.setup, while preserving the legacy entrypoint exports exactly as ["LorePlugin", "default"] with legacy.default === legacy.LorePlugin./home/byk/Code/opencode-v2-pilot/packages/core/test/session-model-request-hooks.test.ts requires both session/http.request and session/http.response hooks to receive every SessionRequestKind, preserving kind and agent ID Agent.ID.make("build"); expected observations are ordered request then response for each kind in KINDS./home/byk/Code/opencode-v2-pilot/packages/core/src/session/title.ts prepares title generation with kind: "title", the selected title agentβs ID and model, optional agent system prompt, one user message containing the title input text, and contextHooks: false./home/byk/Code/opencode-v2-pilot/packages/core/src/session/generate.ts prepares generation with kind: "generate", selected session, selected agent ID, model and tools; its transcript consists of the base system/messages, optional Message.system(history.instructionUpdate), then Message.user(input.prompt)./home/byk/Code/opencode-v2-pilot/packages/core/src/session/compaction.ts prepares compaction with kind: "compaction", agentID: Agent.ID.make("compaction"), the original active agent as contextAgentID, and the current session, model, and tools.