Skip to content

feat(*): add deepseek as a web search and fetch provider - #1125

Merged
LivXue merged 10 commits into
mainfrom
feat/deepseek_web_tool_provider
Oct 30, 2026
Merged

LivXue merged 10 commits into
mainfrom
feat/deepseek_web_tool_provider

Conversation

@LivXue

@LivXue LivXue commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Add DeepSeek's first-party Search and Fetch endpoints as selectable backends for web_search and web_fetch.

  • Search posts query and count only (no page bodies) and renders the vendor's summary field -- the one its reference designates for the model -- in the snippet slot.
  • Queries longer than DeepSeek's 128-character limit are refused before the request, with the limit and the query's length in the error; the research mirror enforces the same bound.
  • Fetch posts a single URL and reads the Markdown content and title. Every endpoint is a literal in the tool, so no apiBase or compatibility gateway is involved.
  • tools.web.providers.deepseek.apiKey is optional. An empty slot borrows the key provider_connection resolves for providers.deepseek, resolved live so a rotation reaches the next call; only a section that resolves to DeepSeek's own host lends it (a gateway, another host, or an endpoints entry elsewhere does not, and an endpoint's key replaces the flat one it supersedes). raven doctor reports "borrowed: providers.deepseek.apiKey" and the Tools page follows the same address rule.
  • The same rule is carried by the research product (including its own-LLM-key branch), the PPT launcher's vendor inheritance, and the sub-agent fetch lane, whose vendor and key are now resolved per call like the main loop's.
  • The onboarding wizard reads the effective key instead of only the vendor slot.
  • Fetch's 403 means a policy-refused URL, and it is deliberately not in the refusal pause set, matching the existing reader semantics; 401 and 402 pause as for every vendor.

Type

  • Fix
  • Feature
  • Docs
  • CI / tooling
  • Refactor
  • Other

Verification

  • Relevant tests pass locally
  • Relevant lint / type checks pass locally
  • User-facing docs or screenshots are updated when needed

Ran uv sync --frozen --all-extras --python 3.12, then in that worktree venv:

  • pytest -q: 36935 passed, 8 failed, 256 skipped, 2 xfailed. The 8 are this box's known baseline (5 ambient-proxy tests, 1 soffice conversion, 1 npm/PATH leak, 1 root-readable test); they fail identically on a clean origin/main checkout, so this branch introduces 0 failures. The 8 oncall shared-ledger xdist flakes seen in earlier runs did not reproduce here.
  • Targeted: test_agent_tools_web_providers, test_config_live, test_tool_capabilities, test_agent_tools_web_fetch, test_subagent_manager, test_agents_research_tools, test_agents_research_launcher, test_agents_ppt_launcher, test_cli_onboard_commands, test_rpc_console -- all pass.
  • vitest run src/features/settings/pages/Tools.test.tsx src/features/settings/SetupBodies.test.tsx: 42 passed.
  • vitest run --no-file-parallelism scripts/gates: 239 passed.
  • tsc --noEmit -p tsconfig.json and eslint on the changed settings files: clean.
  • node scripts/gen-i18n.mjs --check: up to date after regenerating the TUI catalog.
  • Diff coverage: the seven newly added lines the coverage gate reported are covered by three cases (malformed provider sections in both borrowed-key readers, and a DeepSeek 200 with no page text).
  • The live borrow keeps the last admitted key across a rejected provider edit; both launchers are exercised with the borrow helper removed; the zh onboarding entry is pinned by a catalogue test.
  • scripts/check_commit_messages.py origin/main..HEAD, scripts/check_large_files.py origin/main..HEAD, scripts/check_source_language.py origin/main..HEAD: exit 0. commitlint: exit 0. lint-imports: 10 kept, 0 broken.
  • Not run: tests/integration (excluded from CI) and Windows-only checks.

Risk

  • Security impact considered

  • Backward compatibility considered

  • Rollback path is clear for risky changes

  • The borrowed credential is a server-side stored key and travels only to the hardcoded api.deepseek.com endpoints; no caller chooses the destination.

  • DEEPSEEK_API_KEY is the vendor's env var, the same name the LLM provider uses. ~/.raven/env exports it only when the web slot is set, and clearing that slot retires only Raven's own export (marker-guarded), so a user's own export survives.

  • A PPT product whose host web slot is empty has the borrowed key written into its own web slot (the rendered product config is 0600); a product with its own LLM key still searches.

  • The research launcher now also reads the host's providers.deepseek.apiKey on its own-LLM-key branch.

  • No schema migration. Selecting Serper or Jina again restores the previous behavior.

  • A DeepSeek search query over 128 characters is now refused before the request, with the limit and the query's length in the error; the other vendors' queries are unchanged.

  • A borrowed web key now travels only to DeepSeek's own host; a gateway address or a foreign endpoint lends nothing, and an endpoint's key replaces the flat one it supersedes.

  • Both product launchers look the borrow helper up at call time, so a stamped launcher on an older raven loads and borrows nothing instead of failing its import.

  • A rejected providers.deepseek edit keeps the last admitted borrowed key serving; removing the provider section falls back to boot.

  • The zh onboarding step-5 sentence is translated again and pinned to the catalogue.

  • Known gap: raven-code and raven-oncall do not inherit the host's web selection at all (pre-existing), so they never select DeepSeek today.

  • The endpoints were exercised against recorded wire shapes, not the live API; the live instance runs this branch for manual testing.

Related Issues

Fixes #1105

@LivXue
LivXue requested review from 0xKT and gloryfromca October 27, 2026 08:14

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: enforce DeepSeek's 128-character search-query limit in both adapters.

I found one contract failure, marked inline. I covered the complete diff, the runtime and research request paths, credential borrowing and live revocation, sub-agent and product-launcher callers, Web UI/RPC boundaries, branch history, backward compatibility for the existing vendor and legacy-key paths, repository rules and canonical terms, and whether tests were weakened. The first-party endpoint and response shapes otherwise match DeepSeek's documentation.

Verification:

  • uv run pytest tests/test_agent_tools_web_fetch.py tests/test_agent_tools_web_providers.py tests/test_agents_ppt_launcher.py tests/test_agents_research_launcher.py tests/test_agents_research_tools.py tests/test_cli_onboard_commands.py tests/test_config_live.py tests/test_rpc_console.py tests/test_subagent_manager.py tests/test_tool_capabilities.py -x: 1,507 passed, 23 warnings. The initial attempt lacked the repository's dev extra; after uv sync --extra dev, the stated run passed.
  • npm test -- --run src/features/settings/SetupBodies.test.tsx src/features/settings/pages/Tools.test.tsx: 41 passed.
  • npm run type-check: passed.
  • uv run python scripts/check_source_language.py github/main...HEAD: passed.
  • git diff --check github/main...HEAD: passed.

Comment thread raven/agent/tools/web.py Resolved
@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member Author

Windows compatibility review — PR #1125 @ 8c6c6adbab87b1196164644f634aad6a016d6f83

Scope: full base 26352da0 → this head (32 files, +644/−74): DeepSeek as a web_search/web_fetch vendor (fixed https://api.deepseek.com/v1/tools/{search,fetch} endpoints), the optional web key borrowed live from providers.deepseek.apiKey, config schema/live/self-surface plumbing, onboarding and settings UI, i18n, and the tests.

Result: no Windows-specific issue.

  • The transport is httpx.AsyncClient to a literal HTTPS URL with JSON headers — no path, filesystem, subprocess, signal, encoding, or platform primitive is introduced.
  • live_vendor_key gains one more source (the borrowed provider key), still pure config-dict logic.

Verification (native Windows 11, CPython 3.12.13, isolated worktrees D:\tmp\rv-1125 and D:\tmp\rv-1125-main, scratch HOME/USERPROFILE, PYTHONUTF8=1):

pytest tests/test_agent_tools_web_fetch.py tests/test_agent_tools_web_providers.py \
       tests/test_config_live.py tests/test_tool_capabilities.py \
       tests/test_cli_onboard_commands.py tests/test_agents_research_tools.py -q
→ 3 failed, 901 passed in 27.58s

The three failures are the inherited POSIX-assumption onboarding tests — test_onboard_writes_the_a2a_token_owner_only and test_env_file_carries_both_keys_owner_only (chmod 0600) and test_the_login_shell_capture_actually_sees_the_keys (POSIX login shell). All three fail identically on main 26352da0 (re-run there: 3 failed), so this PR introduces none.

Limitations: no live DeepSeek endpoint was called; the settings UI was not exercised in a browser.

@LivXue
LivXue force-pushed the feat/deepseek_web_tool_provider branch from 8c6c6ad to 5b9f46e Compare October 27, 2026 09:16
@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member Author

@0xKT the blocking item from the review is fixed at 262fb54 (the fix and the coverage tests are in the latest push). A re-review would be welcome when you have a moment.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

The reported DeepSeek query-limit defect is fixed in both adapters with boundary and no-request coverage, and I resolved the original thread. I reviewed the current full PR diff, the delta and range-diff from the previously reviewed revision, request-path callers, backward compatibility, repository rules and domain terms, architecture boundaries, history, and test changes; the three original commits are unchanged after the rebase, and I found no new issue.

Verification:

  • uv run pytest tests/test_agent_tools_web_fetch.py tests/test_agent_tools_web_providers.py tests/test_agents_research_tools.py tests/test_config_live.py -x: 495 passed, 24 warnings.
  • uv run pytest tests/test_agents_ppt_launcher.py tests/test_agents_research_launcher.py tests/test_cli_onboard_commands.py tests/test_rpc_console.py tests/test_subagent_manager.py tests/test_tool_capabilities.py -x: 1,017 passed.
  • uv run python scripts/check_source_language.py github/main...HEAD: passed.
  • git diff --check github/main...HEAD: passed.

@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member Author

Windows compatibility re-review — PR #1125 @ 5b9f46e96b645087cf8d401ed86c1962815a1eef

Scope: the head moved from the previously reviewed 8c6c6adb. Against the new main tip 984d47d4, the PR's own change is the same DeepSeek provider work plus one new guard in raven/agent/tools/web.py: DEEPSEEK_SEARCH_QUERY_MAX_CHARS = 128 and a pre-request length check that returns an actionable message instead of the vendor's bare 400. The rest of the raw delta is main's merge (#1124's settings Add-button work).

Result: no Windows-specific issue. The delta is a string-length check and an error message; the DeepSeek transport is unchanged (httpx to a literal HTTPS URL).

Verification (native Windows 11, CPython 3.12.13, isolated worktree D:\tmp\rv-1125-n at this head, scratch HOME/USERPROFILE, PYTHONUTF8=1):

pytest tests/test_agent_tools_web_providers.py tests/test_agent_tools_web_fetch.py \
       tests/test_config_live.py tests/test_tool_capabilities.py -q
→ 440 passed in 10.55s

Limitations: no live DeepSeek endpoint; the settings UI was not exercised in a browser.

Comment thread raven/config/schema.py Resolved
Comment thread agents/raven-ppt/run.py Resolved
@0xKT

0xKT commented Oct 27, 2026

Copy link
Copy Markdown
Member

Not a blocker -- smaller points from the same pass, separate from the two blocking threads. All changed test files pass on this head merged onto main (2540 passed, isolated tree).

Severity of this one finding, not a verdict on the pull request. Any blocking findings from this pass are review threads on the changed files; GitHub renders those collapsed, as a file name with no text.

  1. The DeepSeek web env fallback is DEEPSEEK_API_KEY, the same variable raven's own LLM client reads. Clearing providers.deepseek.apiKey therefore does not revoke web search when that variable is set in the environment, so the two features cannot be revoked separately.
  2. A rejected providers.deepseek edit (one the schema refuses) rolls the live web key back to the boot value or revokes it, instead of keeping the last admitted key the way the other live key readers do (_admit).
  3. zh onboarding: the step-5 web explanation falls back to English; the old catalog entry is orphaned.
  4. Nits:
    • The self-configuration catalog still tells the agent that web_search runs only once the vendor's own key is set.
    • capabilities.py:312's borrowed-key branch has no test.
    • An empty providers.deepseek.apiKey with no web slot is not tested as a revocation.
    • The DeepSeek fetch could drop the proxy unnoticed, a gap shared with the other vendors.

@gloryfromca

Copy link
Copy Markdown
Member

Blocking: the two newly raised compatibility findings need resolution.

The unchanged revision now has open blocker threads covering credential borrowing across custom/endpoints routing and product-launcher compatibility with older Raven schemas. They were raised by another reviewer, so I am not re-grading or resolving those threads. This supersedes my earlier clean stance until their author closes or downgrades them.

@LivXue
LivXue force-pushed the feat/deepseek_web_tool_provider branch from 5b9f46e to e81f041 Compare October 27, 2026 12:49
@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member Author

Non-blocking items from the same pass:

  • N2 (shared DEEPSEEK_API_KEY): leaving as designed. The env fallback is the rule every vendor uses, Raven's own ~/.raven/env export is marker-guarded and follows the web slot, and a user's own export is intentionally not cleared by Raven. The Risk section states the sharing; a web-only variable would break the vendor-to-env-var mapping.
  • N3 (rejected edit keeps last-good): fixed through the live reader's _admit memory; an absent provider still falls back to boot.
  • N4 (zh onboarding): fixed; the sentence is a shared constant with a zh entry, the orphan removed, and a catalogue test added.
  • N5 (nits): (a) self-surface wording fixed; (b) the borrowed branch now asserts has_credential; (c) the no-web-slot revocation case added; (d) the reader's configured proxy is pinned for DeepSeek (the gap was shared by every vendor).

@gloryfromca the two blocking threads are answered; could you re-check once 0xKT has had a look?

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking: the two open compatibility threads still need their originating reviewer's confirmation.

Reviewed e81f041e9536 against github/main, including the revision delta/range-diff, repository rules and domain constraints, affected callers and history, backward compatibility, test changes, and the provider/launcher architecture. I found no additional defect.

The new implementation matches both reported failure modes: borrowed DeepSeek credentials now come from the resolved address/key pair and are withheld for non-DeepSeek hosts, while both launchers look up the newer borrowing helper at call time and tolerate older Raven schemas. The added regressions cover custom bases, endpoints-only and stale flat keys, live last-good behavior, and missing-helper launchers.

Verification:

  • uv run pytest tests/test_agent_tools_web_fetch.py tests/test_agent_tools_web_providers.py tests/test_agents_ppt_launcher.py tests/test_agents_research_launcher.py tests/test_agents_research_tools.py tests/test_cli_onboard_commands.py tests/test_config_live.py tests/test_rpc_console.py tests/test_subagent_manager.py tests/test_tool_capabilities.py -x: 1523 passed, 26 warnings
  • focused web settings tests: 42 passed
  • web UI type-check: passed
  • uv run python scripts/check_source_language.py github/main...HEAD: passed
  • git diff --check github/main...HEAD: passed

I cannot close or re-grade the two blocker threads opened by @0xKT; both remain unresolved, so the whole-record stance stays blocking pending that reviewer's response.

@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member Author

Windows compatibility re-review — PR #1125 @ e81f041e9536e8cc07934aa0fb456ca158573646

Scope: the head moved from the previously reviewed 5b9f46e9. Against main 06509f8e, the PR's own change grew to 10 files under raven/ (+267/−32): DeepSeek was added to the vendor enums and self-surface catalogue, onboarding now reads a borrowing vendor's key through live_vendor_key (so the model-provider key shows as configured), and the 128-character search guard remains; the raw delta also contains main's merges (#1121's ACP outcome work, #1126's context reading), which are not this PR's.

Result: no Windows-specific issue. The additions are config-dict/enumeration and onboarding text logic; the transport is still httpx to a literal HTTPS URL, and no path, filesystem, subprocess, signal, encoding, or platform primitive is introduced. (The onboarding bash rc-file code is pre-existing and untouched apart from key lookup.)

Verification (native Windows 11, CPython 3.12.13, isolated worktree D:\tmp\rv-1125-n2 at this head, scratch HOME/USERPROFILE, PYTHONUTF8=1):

pytest tests/test_agent_tools_web_providers.py tests/test_agent_tools_web_fetch.py \
       tests/test_config_live.py tests/test_tool_capabilities.py \
       tests/test_cli_onboard_commands.py -q
→ 3 failed, 801 passed in 24.59s

The three failures are the inherited POSIX onboarding tests (..._owner_only chmod checks and test_the_login_shell_capture_actually_sees_the_keys), which fail identically on main; they are unrelated to this PR's code paths.

Limitations: no live DeepSeek endpoint; the settings UI was not exercised in a browser.

@LivXue
LivXue force-pushed the feat/deepseek_web_tool_provider branch from e81f041 to e1a11da Compare October 28, 2026 08:09

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

Reviewed e1a11da291ea against github/main. The range-diff confirms all nine PR commits are patch-identical to the previously reviewed revision; this head only rebases them onto the newer main. I covered the repository rules and domain constraints, the diff and revision history, affected callers, backward compatibility, test changes, and the provider/launcher architecture.

The originating reviewer re-verified both compatibility fixes and resolved both threads. The earlier query-limit thread is also resolved, so no review thread remains open and the previous blocker stance is superseded.

Verification:

  • focused Python suites: 1531 passed, 26 warnings
  • focused web settings suites: 42 passed
  • web UI type-check: passed
  • source-language check: passed
  • git diff --check github/main...HEAD: passed

@LivXue

LivXue commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

Windows compatibility re-review — PR #1125 @ e1a11da291eadd06fa01454cd213a1a4c597c681

Scope: the branch is rebased onto current main; the PR's own diff at this head is 959cd0a9..e1a11da2 (33 files, +1010/−79). git range-diff 06509f8e..e81f041e 959cd0a9..e1a11da2 reports all nine PR commits content-identical to the previously reviewed head e81f041e — the new head is the rebase, with no changed or added PR behaviour. Re-ran the affected suites on Windows.

Result: no Windows-specific defect. The feature is a DeepSeek web search/fetch provider with config plumbing, onboarding key borrowing, and settings UI; the launcher change is an import guard, and the web calls are HTTP with no path, subprocess, permission, or encoding surface.

Verification on native Windows 11, detached worktree D:\tmp\rv-1125 at the reviewed head (venv from the same lock), scratch HOME/USERPROFILE, PYTHONUTF8=1, PYTHONPATH pinned:

  • pytest tests/test_agent_tools_web_fetch.py tests/test_agent_tools_web_providers.py tests/test_agents_ppt_launcher.py tests/test_agents_research_launcher.py tests/test_agents_research_tools.py tests/test_cli_onboard_commands.py tests/test_config_live.py tests/test_rpc_console.py tests/test_subagent_manager.py tests/test_tool_capabilities.py -q → 18 failed, 1510 passed, 3 skipped
  • the same ten files at the new base 959cd0a9 → 18 failed, 1455 passed, 3 skipped
  • failing-ID sets are identical (inherited Windows login-shell, path-listing and subagent cases); the 55 added tests pass.
  • ui-web: vitest run src/features/settings/pages/Tools.test.tsx src/features/settings/SetupBodies.test.tsx → 2 passed, 42 passed.

Coverage gaps: the full suite was not rerun; no live call to the DeepSeek endpoints was made.

@LivXue

LivXue commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

Rebased onto main 959cd0a and pushed e1a11da; the diff against main is unchanged in content (the four upstream commits are unrelated) and CI is re-running on the new head.

@0xKT could you give this an approving review when you have a moment? You re-verified both blocking fixes at e81f041 and both threads are resolved.
@gloryfromca your 20:52 review found no additional defect on the same code; 0xKT's re-verification satisfies the condition your 19:26 record-level note set. Could you confirm that block is lifted as well?

@LivXue
LivXue requested a review from 0xKT October 28, 2026 11:00
@gloryfromca

Copy link
Copy Markdown
Member

No blockers; this can merge as far as I am concerned.

Confirmed on e1a11da291ea: @0xKT re-verified both fixes and resolved both blocker threads, satisfying the condition in my earlier record-level note. My review of this rebased head found the nine PR commits patch-identical, with 1531 focused Python tests and 42 focused UI tests passing along with UI type-check and repository policy checks. My stance on this revision is clean.

@LivXue
LivXue force-pushed the feat/deepseek_web_tool_provider branch from e1a11da to f2efa9f Compare October 28, 2026 11:02

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

Reviewed f2efa9f82eb9 against the refreshed github/main. This revision rebases the same nine PR commits over upstream PR #1102; the only integration adjustment uses that upstream change's separate search/fetch keyless-hint keys while preserving the borrowed-key notices. I found no new defect.

Covered the repository rules and domain constraints, the diff and range-diff, affected callers and history, backward compatibility, test changes, and the provider/launcher architecture. All three review threads remain resolved.

Verification:

  • focused Python suites: 1531 passed, 26 warnings
  • focused web settings suites: 44 passed
  • web UI type-check: passed
  • source-language check: passed
  • git diff --check github/main...HEAD: passed

@LivXue

LivXue commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

Windows compatibility re-review — PR #1125 @ f2efa9f82eb9f07b568a7f145212563c79145cec

Scope: the branch is rebased onto current main, which now includes #1102; the PR's own diff at this head is 855a412fa..f2efa9f8 (33 files, +1010/−79). git range-diff 959cd0a9..e1a11da2 855a412fa..f2efa9f8 shows the nine commits content-identical to the previously reviewed head e1a11da2, except the first, which now reads #1102's split search_keyless_hint/fetch_keyless_hint keys. Re-ran the affected suites on Windows.

Result: no Windows-specific defect. The feature is unchanged — the DeepSeek web search/fetch provider with its config plumbing, onboarding key borrowing, and settings UI — and the rebase adaptation is two i18n key names. No path, subprocess, signal, socket, permission, or encoding surface is involved.

Verification on native Windows 11, detached worktree D:\tmp\rv-1125b at the reviewed head, offline venv (uv sync --frozen --offline --all-extras --no-extra segmenter --dev), scratch HOME/USERPROFILE, PYTHONUTF8=1, PYTHONPATH pinned:

  • uv run --no-sync pytest tests/test_agent_tools_web_fetch.py tests/test_agent_tools_web_providers.py tests/test_agents_ppt_launcher.py tests/test_agents_research_launcher.py tests/test_agents_research_tools.py tests/test_cli_onboard_commands.py tests/test_config_live.py tests/test_rpc_console.py tests/test_subagent_manager.py tests/test_tool_capabilities.py -q → 18 failed, 1510 passed, 3 skipped
  • the same ten files at the new base 855a412fa → 18 failed, 1455 passed, 3 skipped
  • failing-ID sets are identical in both directions (inherited Windows login-shell, path-listing and subagent cases); the 55 added tests pass.
  • ui-web: vitest run src/features/settings/SetupBodies.test.tsx src/features/settings/pages/Tools.test.tsx → 2 passed files, 44 passed tests

Coverage gaps: the full suite was not rerun for this rebase; no live call to the DeepSeek endpoints was made.

Add DeepSeek's first-party /v1/tools/search and /v1/tools/fetch endpoints as providers for web_search and web_fetch. Search renders the vendor's summary field; the tools never ask for page bodies.

The DeepSeek web credential is optional: an empty tools.web.providers.deepseek.apiKey borrows providers.deepseek.apiKey, resolved live and reported by raven doctor as borrowed. The research product, the PPT launcher and the sub-agent fetch lane carry the same rule, and the settings page treats a borrowed key as configured.

Endpoints are literals; no apiBase or compatibility gateway is involved.
The class-namespace gate rejected keyrow-tbox as unprefixed; settings-tbox-wide carries the domain prefix and the rule stays in the settings stylesheet.
The wizard read only tools.web.providers.<vendor>.apiKey, so a DeepSeek deployment with the key under providers.* was asked for a second one and probed with an empty string. Read the effective key (borrow included) and say so in the step's copy.
DeepSeek's Search API accepts 1-128 Unicode characters; a longer query answers HTTP 400, which this tool renders as the bare status, so the model was never told to shorten it. Check the limit before the request in both the host tool and the research mirror, and name the limit and the query's length in the error.
The limit cases pin both adapters: 129 characters sends no request, 128 is still sent. Three further cases cover the seven newly added lines the diff-coverage gate reported -- the two exception paths in borrowed_web_key and live_borrowed_web_key, and DeepSeek answering 200 with no page text.
The web endpoints are literals, so a key borrowed from the model provider must be one that provider issued for its own host: borrow through provider_connection and lend nothing when the section resolves to a gateway, another host, or an endpoint somewhere else. Endpoints are the section's own key/address groups, so an endpoint's key wins over the flat one it replaces, and a key only in endpoints is found.

The live reader now distinguishes a provider the file does not name (boot still answers) from a rejected edit (the last admitted key keeps serving), as every other live reader here does. The Tools page follows the same address rule when it says the key is already set.
Both launchers can outlive the raven they run on, so the helper this PR introduced is looked up at call time: the ppt launcher no longer imports it at module top (an older raven raised ImportError before parsing arguments), and the research launcher's first vendor_key lookup answers no key instead of raising. Each has an outlive case that removes the name.
The step-5 explanation is its own gettext key; rewriting it left the zh catalogue on the old sentence, so the whole screen fell back to English. The text is now a constant the catalogue and the test share, with the new zh entry and the orphaned one removed.
The self-configuration catalogue still told the agent that web_search runs only once the vendor's own key is set. The borrowed-key tests also pin that a borrowed key counts as a credential, that an empty provider key without a web slot revokes, and that the reader dials through the configured proxy.
The research product's .env.example still listed the web vendors without
deepseek, one stanza above the new RESEARCH_DEEPSEEK_API_KEY entry, and its
"a name not on the list refuses to launch" line now read as excluding a
vendor the launcher accepts. Add it to both halves.

The changelog had no entry for the new vendor; add one under Unreleased,
following the Serply and Keenable entries it sits beside.

The settings page's own host table is the fourth copy of the borrow rule and
only the vendor list was pinned to the schema. Pin the host map too, so a
drift cannot make the page claim a key the server refuses.
@LivXue
LivXue force-pushed the feat/deepseek_web_tool_provider branch from f2efa9f to e1f729b Compare October 30, 2026 10:03

@ZuyiZhou ZuyiZhou left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the core of this at e1f729b: the endpoints are literals, the borrowed key is lent only when provider_connection resolves the section to api.deepseek.com (the default section does, via the deepseek base-URL fallback), and provider_connection is still a 3-tuple after the rebase, so the broad except in the borrow helper is not hiding a signature change. The tenth commit is changelog, .env.example and a test only. Earlier rounds from gloryfromca and 0xKT are resolved. CI was still running when I approved (unit shards, ui rpc contract, Windows ACP stdio).

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers; this can merge as far as I am concerned.

Reviewed e1f729be342b against refreshed github/main. The first nine commits are patch-identical to the previously reviewed revision. The new final commit accurately documents DeepSeek in the changelog and research environment example, and adds a passing contract test that keeps the settings host table aligned with the schema. I found no new defect.

Covered repository rules and domain constraints, the diff and range-diff, affected callers and history, backward compatibility, test changes (none weakened), and the provider/launcher architecture. All three review threads remain resolved.

Verification:

  • focused Python suites: 1559 passed, 27 warnings
  • focused web settings suites: 44 passed
  • web UI type-check: passed
  • source-language check: passed
  • git diff --check github/main...HEAD: passed

@LivXue
LivXue merged commit 9d9bec9 into main Oct 30, 2026
25 checks passed
@LivXue
LivXue deleted the feat/deepseek_web_tool_provider branch October 30, 2026 10:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(agent): add DeepSeek Search and Fetch as web tool providers

4 participants