* fix(web-search-deepseek): disable thinking for auxiliary search requests
The provider discards the generated text of the auxiliary Messages turn,
so reasoning tokens have no consumer. DeepSeek enables thinking by default,
which adds latency and output tokens to every search.
Fixes#6099.
* feat(web): add opt-in traditional Search and Fetch APIs
* test(web): verify API settings persistence and refresh Session evidence
* fix(web): require an explicit Search API base with its route prefix
* docs(web): document direct Search and Fetch API decisions
* fix(web): keep Messages search default behind the new Web Search API switch
- Rename useTraditionalApi/traditionalBaseURL to useSearchApi/searchApiBaseURL and
label the switch "Use the new Web Search API"; Messages search stays the default.
- Default the Search / Fetch API base to https://api.deepseek.com/v1/tools.
- Authenticate the Search API with an API key only: DeepSeek Account tokens
returned an empty HTTP 404 on /v1/tools/* when probed on 2026-10-16.
- Remove the count setting, which tool-web's maxResults always overrides, and
the undocumented DeepSeek-API-Version header.
- Name the active API's base URL field and the current settings path in
endpoint guidance; re-record the endpoint guidance Session.
- Keep WebFetchResult.statusCode required: DeepSeek Fetch reports HTTP 200 and
drops the page title, so the fetch-metadata widening and its upgrade guide
are removed.
* fix(web): accept account sign-in on the live Search API
The public Search and Fetch routes went live on 2026-10-16 and accept the
DeepSeek Account token, so account-route Sessions send it to the Search API
as they do for Messages search, and the settings copy no longer says account
sign-in does not apply.
Record the live behavior in the README and Agent Note: summaries of
1,000-2,300 characters, an HTTP 500 for an unresolvable Fetch target, and
migration notes for gateways without /v1/tools routes. Test doubles now use
the live response fields and RFC 3339 offsets.
* feat(web): configure Search API result count and send the triggering question
- Add web-search-deepseek.count (1-50, default 10, the service default) and
show it as "Results per search" in Search API mode, where "Max searches per
request" applies only to Messages; a smaller request maxResults still wins.
- Send the initiating Session's latest human prompt as ori_question, with
whitespace collapsed and cut to the API's 128-character limit; blank or
absent prompts omit it, and sendOriginalQuestion: false disables it. The
settings hint states that the question is sent.
- Match the web search double on the request's query field, since
ori_question now carries every query in the prompt.
* fix(client): unify web search endpoint override controls
* feat(web): configure registered search and fetch providers through shared settings
* feat(web): include Exa and Perplexity in provider settings
* test(web): cover provider settings branches and refresh plugin snapshots
* revert(web): drop the provider dropdown, schema-driven form, and Exa/Perplexity settings
Revert aed8c5cb609, d88c47dcd80, and 036a5a337d3. The Web search settings
page returns to the DeepSeek toggle; the DeepSeek Search and Fetch API split
is reintroduced as one plugin in the following commit.
* feat(web): move the DeepSeek Search and Fetch APIs into web-deepseek-api
The new web-deepseek-api plugin registers deepseek-search-api and
deepseek-fetch-api over one credential and API base, and exports the
authentication and redirect-rejecting transport that web-search-deepseek now
reuses for Messages search only. The web service reads searchProvider and
fetchProvider for each operation, so the Web search settings switch selects
both APIs together on save and restores Messages search with local HTTP fetch
when turned off. The switch hint links to the DeepSeek search and fetch guide.
* refactor(client): keep the web search endpoint fields on the shared override controls
Drop the always-visible reset and the inherited-address placeholder from the
Web search page, restoring ui-primitives to its base. Each endpoint field shows
the selected section's effective value and offers Reset to default only for an
override, like every other settings field.
* refactor(web): keep Messages search independent of web-deepseek-api
Restore dsh-web-search-deepseek to its own credential and transport code,
keeping only the disabled-thinking request and the current settings guidance,
so the Messages plugin no longer depends on the Search and Fetch API package.
dsh-web-deepseek-api keeps its transport internal; the regions that repeat the
Messages helpers carry jscpd:ignore markers, with the rationale recorded in the
Search and Fetch API Agent Note.
* refactor(web): keep the web-deepseek-api request type module-private
---------
Co-authored-by: LegGasai <[email protected]>
The packer images the web template bundles, every optional bundle, and an installation manifest instead of a dumped composition, and the Worker boots that profile through app-boot like dsh web. Package-local lazy client chunks move into content-addressed archives that the VFS fetches on first asynchronous read; client-modules reads chunks asynchronously.
The Worker replaces node-addon-require-builtin with Node v24.18.0 internal-module interfaces and reports Node 24, so plugin metadata, the Cordis Loader, and HMR reach one cascaded loader backed by the Worker loader. Resolution failures carry Node error codes, the empty load cache lets HMR apply profile changes, and every optional bundle switches on and off live. Platform stubs throw ERR_FEATURE_UNAVAILABLE_ON_PLATFORM.
Generate a validated format-1 plugin market index from a list of npm package
names and https Git repository URLs, without running package code.
- List every non-deprecated npm bundle version, and Git versions at release
tags and the default branch, each with its engines.dsh range.
- Read display fields, keywords, homepage, and icons the way DSH reads
installed plugins; inline small icons up to the format's 32 KiB limit.
- Cache results per immutable input and rewrite output only when it changes.
Read configured plugin market indexes on the Host, search them with fuzzy
multilingual matching, and install a chosen version from the Plugins page.
- dsh-plugin-market-index validates format-1 indexes and builds install
arguments; inline icons are capped at 32 KiB.
- The pluginMarket service fetches configured http(s) URLs, parses bodies in
a Worker Thread, caches documents, and pages filtered, ordered results with
installation status and engines.dsh compatibility.
- Discover is an opt-in experimental bundle; the Plugins page gains a
plugins.tab slot and confirmed installs.
- The plugin_market tool lists indexes, plugins, and versions for Creator mode.
- Plugin compatibility reads engines.dsh before DSH peer dependencies.
verify-package-dependencies now covers every packages/*/* manifest, experimental included, and reads each package's tsdown build entries so Worker and child-process entries count as Host runtime sources. Experimental Client packages no longer declare browser and type relationships as peers.
Package modules that other code imports must not suspend evaluation at module scope. A syntax-aware gate scans packages/*/*/src and excludes only executables (a shebang or a package bin target). The SenseVoice worker, the SSH helper entry, and the Inspector worker entry now run an explicit main().
Plugin Manager hardcodes feature previews by package name, like its
experimental bundle lists, instead of reading a package manifest field.
The DSH badge skill bundle shows an English or Chinese illustration
below its description. Client bundles embed imported SVG, PNG, and
WebP files as data URLs through the shared tsdown preset, which
replaces the account package's own asset loader.
Co-authored-by: ZiyaZhang <[email protected]>
With HMR, installing, enabling, disabling and removing bundles take effect live. Each profile recomposition compares
the loaded modules below the profile directory and its linked targets with disk, stops the plugins whose files
changed, and recomposes the profile through app-boot's recomposeProfile(): the rows the next generation drops are
removed first, the latest runtime resolution is published once, and the generation is applied and judged. Afterwards
HMR evicts the modules below the mappings the recomposition dropped.
- app-boot: recomposeProfile(); PluginPackages.resolution; ResolutionRestartRequired; the resolver accepts in-place
version changes and relinks, and relocates Node's cached link real paths.
- plugin-manager: with HMR, installBundle refuses an installed package (already-installed), so an upgrade is a
removal and an installation; every restart-required result carries a restartReason; removal uses the registry the
package was installed from.
- ui-plugin-manager: the Official Update removes and then installs; restart prompts name their reason.
The caller-connection work — forwarded-event opt-in, physical socket
ownership, and the Node/MCP artifact-only consumer fixture — moves to a
stacked PR on top of this one. This branch now changes only how Remote
definitions are generated (Typert artifacts, lazy method info,
consumer-selected input strictness, tool-schema projection) and how the
existing Registry consumes them.