diff --git a/README.md b/README.md index 3c668cb..a69acb9 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,17 @@ The log captures the request (model id, body byte length), each HTTP attempt (st wait, elapsed ms), every stream event payload, and the terminal finish reason + usage. It is useful for diagnosing model selection, retry, tool-call, and finish-reason issues. +## ZDR header toggle + +The `x-cmd-zdr: 1` request header is **omitted by default** because it is rejected by some +models. Set `COMMANDCODE_ZDR=1` (or `true`/`yes`) when launching opencode to opt back in. The +value is read once at provider load, so restart opencode after changing it. Per-provider +overrides still win: `headers: { "x-cmd-zdr": "..." }` in `opencode.json` takes precedence over +the environment variable. + +With `COMMANDCODE_DEBUG` enabled, the trace logs a `zdr on|off` line per request so the toggle +state is observable. + ## Features | Capability | Status | diff --git a/src/model.ts b/src/model.ts index 35578c0..9519337 100644 --- a/src/model.ts +++ b/src/model.ts @@ -23,6 +23,10 @@ import { redact } from "./redact.js"; import { transform } from "./transform.js"; import { finishReasonFrom, usageFromFinish, type FinishEvent } from "./usage.js"; +// x-cmd-zdr breaks some models; off by default (server.py never sends it). +// COMMANDCODE_ZDR=1|true|yes opts back in. Read at load, like COMMANDCODE_DEBUG. +const ZDR_ENABLED = /^(1|true|yes)$/i.test(process.env["COMMANDCODE_ZDR"] ?? ""); + export type CommandCodeOptions = { name?: string; apiKey?: string; @@ -139,9 +143,10 @@ class CommandCodeLanguageModel implements LanguageModelV3 { "x-project-slug": "project", "x-taste-learning": "true", "x-co-flag": "false", - "x-cmd-zdr": "1", + ...(ZDR_ENABLED ? { "x-cmd-zdr": "1" } : {}), ...this.opts.headers, }; + debug("fetch", "zdr", ZDR_ENABLED ? "on" : "off"); const auth = bearer(this.opts.apiKey); if (auth) headers["Authorization"] = auth; for (const [k, v] of Object.entries(extra ?? {})) if (v !== undefined) headers[k] = v;