fix(web): offer DeepSeek web tools whenever a credential exists

The DeepSeek search and Search/Fetch API providers now report readiness
from credential presence alone, on any model route: the account token
first on the deepseek-account route, then a literal apiKey or a
configured apiKeyEnv reference. A conversation on another provider's
model keeps web_search and web_fetch while a DeepSeek key is configured,
as on master, so the route refusal WEB_PROVIDER_ROUTE_DISABLED and its
upgrade guide are removed.

The pi-ai-conversation-updates and deepseek-messages-system-prompt
snapshots replay their master recordings again, the headless keyless
smoke points its search key reference at an unset variable, and the
readiness Agent Note records the rejected route and endpoint rules.
This commit is contained in:
Yichen Jiang committed 2026-10-22 15:38:16 +08:00
1 parent a19aabc8ba
commit fb378dacf2
34 files changed
+171 -2198

No files matched your search

@@ -41,3 +41,9 @@
config:
mode: !!js process.env.DSH_PERMISSION_MODE ?? 'workspace-write'
workspaceRoot: !!js process.cwd()
# A search key reference no runner sets: the turn runs as a deployment without
# web search credentials, whatever the launching environment exports.
- id: web-search-deepseek
config:
apiKeyEnv: DSH_KEYLESS_SMOKE_SEARCH_KEY
@@ -61,7 +61,7 @@ describe('headless-agent keyless smoke', () => {
expect(String(result?.['output'])).toContain('CLI_TOOL_ROUND_TRIP')
expect(persistedHeader).toMatchObject({ type: 'session' })
expect(persistedToolNames).toEqual(expect.arrayContaining(['read', 'write', 'edit', 'web_fetch']))
// DeepSeek web search serves only DeepSeek model routes, and this turn runs on the cli-mock route.
// Search has no key in this composition, so the model request does not offer it.
expect(persistedToolNames).not.toContain('web_search')
expect(persistedToolNames).not.toContain('str_replace_editor')
}, PRODUCTION_PROFILE_TEST_TIMEOUT_MS)