Repository navigation
fix(scout): say yes to DeepSeek models, name both paths, and point OpenCode at its guide - #2347
Conversation
…enCode at its guide A new person asked Scout whether DeepSeek Harness could connect and heard that DeepSeek models could not be used here. They left within two minutes. Hosted agents already run on DeepSeek V4 Flash, and OpenCode on a DeepSeek model was walked end to end the same day. - The hosted offer's description names the model a hosted turn runs on, built from the same default the runtime uses (LITELLM_CHAT_MODEL), so it follows the deployment the way the limits line does. Scout names it only when asked about models or runtime. - Scout says yes to DeepSeek models two ways (Run it here, or OpenCode on DeepSeek's API through docs/cli/opencode.md), says dsh itself can't connect yet without promising when, and stops claiming the only tools are Claude Code and Codex. Qwen Code and pi are named as not ready. - Gemini stays "can't join yet". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wkz5axAzCvoLEFkZ5KtkKG
lilyshen0722
left a comment
There was a problem hiding this comment.
Written by Sprint Review, a Commonly agent — code gate at 071bdbefff9bc783663a4de330f4d9542693e9b0 (TASK-311 / Scout), requested by lily-shen in pod message 79209.
Both halves of the stated property hold. BASE and RESTORED both 2 suites / 22 passed. Every claim below is checked against code or against a dated walk, not against the PR body's table.
The model reaches Scout only from the deployment — and it is enforced, not merely unexposed
The plumbing is tighter than the row claims, and the stronger fact is worth having on the record. At nativeRuntimeService.ts:1311-1314 a hosted-native turn replaces the config outright:
const cfg = hostedNative
? normalizeConfig(hostedNativeRunConfig(installation, hostedTurnsPerDay, {...}))
: installedCfg;The stored installedCfg is discarded for hosted turns, and hostedNativeRunConfig returns no model key (0 occurrences). So cfg.model is undefined on every hosted turn and :1607's String(cfg.model || DEFAULT_MODEL) resolves to DEFAULT_MODEL unconditionally. "The person cannot choose another model today" is true by construction — even a stored install carrying a model could not change it, so the claim does not rest on the absence of a UI control.
DEFAULT_MODEL is process.env.LITELLM_CHAT_MODEL || 'deepseek-v4-flash' (:87), and the live backend deployment declares LITELLM_CHAT_MODEL = deepseek-v4-flash, so the sentence Scout will actually speak in production today is the true one rather than a coincidence of the fallback.
| mutation (needle asserted at 1) | red |
|---|---|
HOSTED_MODEL_NAME becomes the literal 'DeepSeek V4 Flash' |
follows LITELLM_CHAT_MODEL when the deployment changes it |
MODEL_DISPLAY_NAMES emptied (falls back to the raw id) |
names DeepSeek V4 Flash for the default model, and says it cannot be changed |
| the model name copied into the prompt | names Codex as the GPT path… — via expect(prompt).not.toMatch(/v4[ -]?flash/i) |
| the dsh caveat turned into a promise | says yes to DeepSeek models and names both paths, without promising dsh |
Do not claim any other tool connects removed |
connects OpenCode through its guide, never through the connect card |
The third row is the one that matters most for this PR's shape: the prompt is held to naming no model, so the only route is the tool description. Both directions are pinned — the description must follow the env, and the prompt must not duplicate it.
The last row also answers a question the diff raises. The old guard line "The listener runs Claude Code or Codex. Do not claim it runs any other tool" is removed, which on its face loosens Scout. It does not: the replacement carries Do not claim any other tool connects in a wider frame (own-agent paths rather than listener-only), and removing that sentence reds a test. The guard survived the rewrite with a reader attached.
The product claims, one at a time
- DeepSeek hosted — true: hosted turns run on
DEFAULT_MODEL, live valuedeepseek-v4-flash. - DeepSeek through OpenCode — the guide Scout names exists at this head (
docs/cli/opencode.md, 128 lines) and actually describes the thing claimed: a chosen provider with your own key,provider.id/baseURL/keyFileinenvironment.json, with a DeepSeek example. It also says in its own text that Linux and Windows have not been walked, matching Scout's "walked on a Mac only". The suite now asserts the file exists, so the citation cannot rot silently. - dsh cannot connect — true by absence of any path: a word-boundary search for
dshacrosscli/andbackend/(excluding tests) returns exactly one hit, Scout's own sentence. There is no adapter, no route, nothing to connect with. - OpenCode never through the connect card — true: the page types the listener adapter
'claude' | 'codex'(4 occurrences inV2AgentBYO.tsx) andADAPTERS_WITH_GRANT_BROKERis exactly{claude, codex}(default-environment.js:51), soserverAdapterBindingRefusalrefusesopencodeon a Connect-page key. - Gemini unchanged — correct, and now the best-evidenced claim in the set: TASK-291's 10-19 walk returned NO, with the cause one layer above anything the route check could see (Gemini 3 requires
thought_signatureechoed on everyfunctionCall, which@ai-sdk/openai-compatibledoes not carry). - Qwen Code and pi "not ready for outside use" — this is the one I can only partly verify, and I would rather say so than imply a check I did not run. What I confirmed: neither is in the broker set, neither is offered by the page, and
host-check.jsrecords that pi refuses a declared sandbox by design ("confining pi belongs to pi's own sandbox work"). That supports not offered and not confined. "Not ready" is a product judgement on top of that, and nothing in the code contradicts it.
Notes, neither blocking
MODEL_DISPLAY_NAMESholds one entry, so any other deployment value is spoken as its raw id — "A hosted agent runs ondeepseek-v4-flash-0711". Accurate but unpolished, and the fallback has its own arm, so this is a deliberate trade rather than a gap.docsSiteFacts.test.jsstill asserts the docs-site quickstart and connect pages contain no--adapter (qwen|opencode|pi), while Scout now points at a repo guide that necessarily does. Those are different surfaces and the comment was updated to say so, so there is no conflict today — but the two now encode opposite expectations about the same adapter name, and a future reader moving the guide's content onto the docs site would trip the assertion. Worth a line in the test naming which surface the ban applies to.
CI at this exact head: 14 pass, 0 pending or failing, including Test & Coverage, E2E Tests and Service Tests (Tier 1 — real DBs). merge-tree clean against main 0c3d25c8e — re-fetched and re-read rather than reusing the sha from my previous gate, after misnaming it on #2337 earlier today. Head unchanged from the one requested.
No defects.
GATE: PASS
What happened
On 10-19 a new person asked Scout whether DeepSeek Harness (dsh) could connect. Scout told them only Claude Code or Codex agents can join and that DeepSeek models can't be chosen here. They left within two minutes. Two of the last three outside signups who typed something asked for a non-Claude model.
Both of Scout's claims were wrong:
What changes
Scout's prompt (
backend/config/native-agents/scout.ts):docs/cli/opencode.md.The hosted model, without a copy in the prompt (
backend/services/nativeRuntimeService.ts):commonly_offer_hosted_agentdescription now says a hosted agent runs onHOSTED_MODEL_NAMEand that the person can't choose another model today.HOSTED_MODEL_NAMEis built fromDEFAULT_MODEL, the same value a hosted turn runs on, becausehostedNativeRunConfigleavesmodelunset. So it followsLITELLM_CHAT_MODELthe way the limits line does (feat(hosted): the plan line — 30 hosted turns a day free, 200 on Pro (TASK-268) #2237).Tests
nativeAgents.scoutKnowledge.test.js:LITELLM_CHAT_MODEL=some-other-modelit follows the deployment. A mutation that hard-codes the name turns that arm red.docsSiteFacts.test.js: a comment corrected; no assertion changed.Behaviour check
The new prompt and tool list were sent to the live model from the backend pod. The key stayed in the pod env.
After deploy
Each person's Scout keeps the prompt from signup. After the deploy, run
node dist/scripts/refresh-native-agent-configs.js --app scoutin the backend pod: a dry run first, then--apply. Report the count.Focused suites: 26/26 on Node 22 locally.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Wkz5axAzCvoLEFkZ5KtkKG