Repository navigation
feat(zdr): support zero data retention via CMD_ZDR and provider headers - #194
Conversation
|
Thanks for contributing this! ZDR support is a useful addition. Lint, formatting, all 250 unit tests, typechecking, and the local package check passed. Review found a few things to address before approval: 1. Header casingIn Please check existing header names case-insensitively before adding the default, and add mixed-case regression tests. 2. Config fallbackWith Please preserve valid settings or reject invalid config rather than silently disabling ZDR. Add coverage through both plugin hooks. 3. SDK enforcementThe SDK calls Please establish that endpoint’s ZDR support and test enforcement, or limit the SDK claims to sending the header until support is confirmed. 4. Live-test cancellationTest timeouts don’t cancel the underlying requests, so paid probes may continue afterward. Please add request cancellation and stop scheduling probes when the deadline expires. Small cleanup and CI
We haven’t verified live ZDR enforcement or real OpenCode V1/V2 requests yet. Happy to help with the remaining changes if useful. Thanks again for the contribution! |
|
We have now checked real requests using the local PR code at Both versions used the free
This confirms header propagation and the API’s refusal behavior for the tested Chat Completions path on both generations. Thanks for adding this! The fixes in the main review still apply. SDK |
Add a zero-data-retention opt-in that sends `x-cmd-zdr: 1` on every Command Code request. Enable it with env `CMD_ZDR=1` (1/true/yes/on) or `zdr: true` in the plugin config file. V1 merges the header into provider options.headers, V2 registers it on the commandcode provider, and createCommandCode honors CMD_ZDR. Explicit user headers always win, and custom npm transports are left untouched.
Match x-cmd-zdr case-insensitively and collapse every spelling into the lowercase key, so a user X-Cmd-Zdr: 0 is kept instead of being sent as "1, 0". Fall back per field in PluginFileConfigSchema so an invalid sibling no longer discards a valid zdr opt-in; a present but invalid zdr value fails safe to on. createCommandCode calls /alpha/generate, which the ZDR docs do not cover, so languageModel() now throws when ZDR is requested instead of sending the header; an explicit x-cmd-zdr: 0 opts out of CMD_ZDR.
Tie every live request to an AbortSignal that fires before the test timeout, so a timed-out run cancels in-flight paid probes and schedules no new ones. Drop the live SDK test (the SDK now fails closed) and the log-only skip test.
Scope ZDR to /provider/v1/*, describe case-insensitive header handling, per-field config fallback, and the SDK fail-closed behavior, and limit the Messages/Responses claim to what has been verified live.
OpenCode's plugin loader calls only default.server for this package, so it never invokes createCommandCode. The guard lives in languageModel() because every caller, a direct import or the create* lookup for a provider npm set to this package, resolves a model there before it can send a request.
|
@BrainerVirus Thank you for the review. Below are the respective changes.
Fixed in 85e9414.
Regression tests:
Fixed in 85e9414. I went with "keep the valid settings":
Coverage:
I couldn’t establish that
Fixed in 5a64a57.
|
BrainerVirus
left a comment
There was a problem hiding this comment.
LGTM — verification details in the review comment.
|
Thanks for contributing this, @mohemohe. Re-checked the head ( Build + suite — 1. Header casing — confirmed. Case-insensitive lookup, every spelling folded into one lowercase key with the user's value kept, no mutation. Plant (case-sensitive lookup) fails 2 tests in 2. Config fallback — confirmed. Per-field 3. SDK enforcement — confirmed. 4. Live-test cancellation — the budget AbortSignal and the drop-at-deadline behaviour are right; the local delayed-server check is a valid proof. Live verification (real API, temporary key, free/cheap models)
This does not audit server-side retention and does not re-claim |
|
🎉 This PR is included in version 0.12.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
Adds opt-in zero data retention (ZDR) for the Command Code provider: with
CMD_ZDR=1(orzdr: truein the pluginconfig) every request carries
x-cmd-zdr: 1, the same opt-in the Command Code CLI exposes.Reference: Provider API — Zero data retention
The plugin talks to the Provider API directly (
/provider/v1/...), so the CLI-onlyCMD_ZDRvariable had no effect here before. The header routes the request through ZDR-capable upstreams only and fails with422 cmd_zdr_no_providersinstead of falling back to a non-ZDR provider, so it is worth making it explicitly configurable.Changes
src/zdr.ts(new) — single implementation of the ZDR decision and headerCMD_ZDRcounts as on for1/true/yes/on(trimmed, case-insensitive)zdrEnabled()= configzdr: trueOR the env varwithZdrHeaders()mergesx-cmd-zdr: 1without discarding existing headers, and never creates aheaderskeywhen ZDR is off
plugin.tsserver(): writes the header intoprovider.commandcode.options.headers. V1 merges provideroptionsintoevery model of the provider, whichever
provider.npma model overrides, so one map reaches the Chat Completions,Messages, and Responses routes. Custom npm transports keep owning their options and are left untouched
setup(): writes the header into the registered provider'sinfo.headerson add, and merges it into theexisting provider on update
index.ts— thecreateCommandCodeSDK factory honorsCMD_ZDRtoo (an explicitheadersvalue wins)src/schemas.ts—PluginFileConfigSchemagainszdr: z.boolean().default(false)README.md(config table + ZDR section) anddocs/specs/2026-10-14-zdr-request-header.md(new spec)tests/unit/zdr.test.ts(new) plus V1/V2/SDK/schema unit additions, andtests/integration/zdr.integration.test.ts(new, live)Behavior
"x-cmd-zdr": "0"stays as-is), and other headers in the same mapsurvive untouched. With ZDR off the generated config is identical to before
422 cmd_zdr_no_providersrather than falling back. The upstream can change, so cost can change with it/messagesare already zero-data-retention at the account level; the header is accepted therefor parity and does not change routing
CMD_ZDR=1 opencode, or{ "zdr": true }in~/.config/opencode/opencode-commandcode.jsonVerification
Unit gate (offline, runs in CI):
bun run check # 250 pass / 0 fail (oxlint --deny-warnings + oxfmt --check + bun test tests/unit/ + tsc --noEmit)Live verification (manual, outside bun run check; skipped when COMMANDCODE_API_KEY is unset):
COMMANDCODE_API_KEY=... bun run test:integrationObserved while preparing this PR (command-code@1.82.1, live Provider API):