stop the CoS runner rebuilding OpenCode's config from an identity-only provider view - #6140
Merged
Merged
Conversation
…y provider view
PortOS composes a CLI child-env delta from the full provider record and POSTs it
to the CoS runner alongside cliProviderAuthDescriptor's non-secret identity
({ id, command, ollamaBacked }). The runner then re-ran composeProviderEnv with
that partial view as `provider` — and every generative layer there sits ABOVE
`before`, so the rebuild overwrote the complete value it was layered onto.
For an OpenCode wrapper that meant a config with an EMPTY models map replacing
the good one: `--model ollama/<id>` stopped resolving, and OpenCode silently fell
back to the first model in its own catalog (a hosted OpenCode Zen model) rather
than failing. Every runner-owned OpenCode agent ran on a model nobody chose.
Mark the descriptor `authOnly` and short-circuit composeProviderEnv on it, so an
identity-only view contributes no env at all. buildSafeCliBaseEnv still receives
it — selecting that provider's ambient-auth allowlist is why it is POSTed — but
it can no longer generate config. Guarding the seam rather than the OpenCode
builder also covers the next layer added to composeProviderEnv.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every runner-owned OpenCode agent was silently running on a hosted OpenCode Zen model instead of the local model it was dispatched with. Reported against
agent-eac37dd4, which was launched onopencode-ollama-tui/qwen3-coder:30band ran on Zen's default.The cause is a second, non-idempotent env-composition pass over a partial provider view:
before, alongsidecliProviderAuthDescriptor's identity-only view —{ id, command, ollamaBacked }, noenvVars, nomodels, nodefaultModel.buildCliChildEnvwith that partial view asprovider. Every generative layer incomposeProviderEnvsits abovebefore, so the rebuild overwrote the complete value it was layered onto.OPENCODE_CONFIG_CONTENTrebuilt with an empty models map.--model ollama/<id>then resolved to nothing, and OpenCode fell back to the first model in its own catalog rather than failing — so the run looked healthy while answering from the wrong model.Reproduced directly: with the good config,
opencode modelslists the tenollama/*ids; with the rebuilt one it lists only the hostedopencode/*catalog.The fix is at the seam, not in the OpenCode builder.
cliProviderAuthDescriptornow stampsauthOnly: true, andcomposeProviderEnvshort-circuits on it — an identity-only view contributes no env at all.buildSafeCliBaseEnvstill receives the descriptor, since selecting that provider's ambient-auth allowlist is the whole reason it is POSTed. Guarding here rather than insidebuildOpencodeEnvVarsalso covers the next generative layer added tocomposeProviderEnv, instead of special-casing the one symptom that surfaced.Both runner call sites (
/spawnand/spawn-tui) are fixed by the same change, so headless runner-CLI OpenCode agents were affected too, not just the TUI path.Test plan
cliChildEnv.test.jscase drives the real two-hop shape — compose from the full record, then re-layer with the descriptor — and asserts the whole composed env equals the POSTed delta (plusPATH/PWD), so a future generative layer is covered rather than justOPENCODE_CONFIG_CONTENT. Verified it fails without the fix.