dsh-web-search-plugin 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  本项目的重要变更都记录在此。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.4.0] - 2026-09-02
6
+
7
+ ### 变更
8
+
9
+ - **适配 DeepSeek Harness 最新 main(`0.1.2-alpha.4`)**:`@deepseek-ai/dsh-settings` 已移除顶层 `installSettingsSection` / `settingsNamespace`,Host 侧改为在 `ctx.inject(['settings'])` 后调用 `settingsCtx.settings.installSection(ctx, ...)`;settings namespace 直接使用普通字符串。
10
+ - **浏览器端移除对 `@deepseek-ai/dsh-client-runtime` / 旧 `connection` 的依赖**:该包已不在最新 Harness workspace / 客户端模块表中。`createSnapshotStore` 改从平台常驻模块 `@deepseek-ai/dsh-client-store` 导入;`dsh.client.inject` 与客户端 `inject` 对齐为 `slots` / `locale` / `remote` / `settingsScope`。
11
+ - **凭据远端接口迁移到 `ctx.remote`**:`credentials.describe(refs[])` / `set(ref, value)` 使用最新 Remote 参数与响应形状(`{ ok, value }`);凭据变更事件从 `credentials/updated` 改为 `credentials/reference-updated`;不再经旧 `connection.api` 调用。
12
+ - peerDependencies 中 dsh 包版本从 `0.1.0-rc.7` 提升到 `0.1.2-alpha.4`;`@deepseek-ai/cordis` / `@deepseek-ai/schemastery` 分别对齐 `^4.0.2` / `^3.18.2`;版本号升至 `0.4.0`,`User-Agent` 同步。
13
+
5
14
  ## [0.3.1] - 2026-08-30
6
15
 
7
16
  ### 修复
@@ -99,7 +108,7 @@
99
108
 
100
109
  ### 修复
101
110
 
102
- - **客户端 bundle 缺少 `exports.inject`**(`lib/client.js`)。浏览器插件原先只导出 `apply`,cordis 的 `fiber.inject` 为空,访问 `ctx.locale` 等服务会抛 `cannot get property "locale" without inject`。现在导出 `inject = ["slots", "locale", "connection", "remote", "settingsScope"]`。
111
+ - **客户端 bundle 缺少 `exports.inject`**(`lib/client.js`)。浏览器插件原先只导出 `apply`,cordis 的 `fiber.inject` 为空,访问 `ctx.locale` 等服务会抛 `cannot get property "locale" without inject`。现在导出 `inject = ["slots", "locale", "remote", "settingsScope"]`。
103
112
  - **插件卡片的 slot 注册**(`lib/client.js`)。卡片按 rc.6 的 `id`/`order` 形状注册进 `settings.plugin.item`;该 slot 从 rc.6+ 起是 keyed 的,必须带 `key: "dsh-web-search-plugin"`。
104
113
  - **`CardForm.field("apiKey")` 崩溃**(`lib/client.js`)。只写凭据字段没有 section spec,对 `undefined` 调用 `spec.format(...)` 会在卡片投影时抛 `Cannot read properties of undefined (reading 'format')`。已加上 secret 字段分支(对齐官方 `CardForm`)。
105
114
  - **`dsh.client.inject` 补上 `@deepseek-ai/dsh-client-ui-slots`**(`package.json`),与社区插件的加载集合一致。
package/README.md CHANGED
@@ -17,19 +17,19 @@
17
17
 
18
18
  ## 特性
19
19
 
20
- - 与官方 `@deepseek-ai/dsh-web-search-deepseek` 相同的提供方约定:`inject: ['web']` + `installSettingsSection` + `ctx.web.registerSearchProvider`。
20
+ - 与官方 `@deepseek-ai/dsh-web-search-deepseek` 相同的提供方约定:`inject: ['web']` + `ctx.settings.installSection` + `ctx.web.registerSearchProvider`。
21
21
  - 顶层 **设置 → 网页搜索** 分区:两列布局、未保存草稿、保存 toast;结果数量为 1–20 下拉。
22
22
  - **默认引擎为 DeepSeek(官方)**:新装 / 未显式改动时,搜索直接走 `deepseek-official`,不再依赖 keyless 的 Tavily。
23
23
  - 纯 REST 后端由**静态元数据表 + 通用后端**驱动,新增 provider 即"表里加一行 + 官方跳转链接",无定制执行代码。
24
24
  - Tavily keyless 无需密钥即可用;Brave 需要订阅 token(若本机已有 `BRAVE_API_KEY` 凭据,可直接复用)。
25
25
  - Tavily keyed / Brave 在设置卡展示额度进度条(DeepSeek 官方与 Tavily keyless / 其余 REST 后端不展示)。
26
26
  - 各引擎结果都规范化为接缝的 `WebSearchResult`(可选 `content` + `sources[]`),按 URL 去重。
27
- - 设置段 `dsh-web-search-plugin` 通过 rc.7 的 `settings.describe()` 动态暴露,不需要宿主白名单补丁,也不需要自建回环 settings 桥。
27
+ - 设置段 `dsh-web-search-plugin` 通过 dsh 的 `settings.installSection` 注册、由 `settings.describe()` 动态暴露,不需要宿主白名单补丁,也不需要自建回环 settings 桥。
28
28
  - 错误映射为 `WEB_PROVIDER_ERROR` / `WEB_ABORTED` / `WEB_PROVIDER_CREDENTIAL_MISSING`。
29
29
 
30
30
  ## 运行要求
31
31
 
32
- - DeepSeek Harness `0.1.0-rc.7` 或更新
32
+ - DeepSeek Harness `0.1.2-alpha.4`(最新 main)或更新
33
33
  - pnpm,用于通过 `dsh plugin` 把插件装进 profile
34
34
 
35
35
  ## 安装
@@ -189,7 +189,7 @@ dsh plugin --profile web remove @dsh-ltctfer/dsh-web-search-brave
189
189
  npm run check
190
190
  ```
191
191
 
192
- 客户端 bundle 必须保持 `window.__ModuleLoader__.load({ id, factory })` 线格式 — 由 `dsh-client-modules` 加载,不是打包器。必须同时导出 `apply` 和 `inject`(`slots`、`locale`、`connection`、`remote`、`settingsScope`),并把分区注册进 `settings.section`(`id: "web-search"`)。
192
+ 客户端 bundle 必须保持 `window.__ModuleLoader__.load({ id, factory })` 线格式 — 由 `dsh-client-modules` 加载,不是打包器。必须同时导出 `apply` 和 `inject`(`slots`、`locale`、`remote`、`settingsScope`),并把分区注册进 `settings.section`(`id: "web-search"`)。
193
193
 
194
194
  ## 发布
195
195
 
package/lib/client.js CHANGED
@@ -21,7 +21,7 @@ window.__ModuleLoader__.load({
21
21
  var exports = module.exports;
22
22
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
23
23
  let react = require("react");
24
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
24
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
25
25
 
26
26
  /** Settings namespace of this plugin. */
27
27
  const NS = "dsh-web-search-plugin";
@@ -334,9 +334,9 @@ window.__ModuleLoader__.load({
334
334
  * spec and are written through the credentials domain.
335
335
  */
336
336
  var SearchCardForm = class {
337
- constructor(scope, api) {
337
+ constructor(scope, remote) {
338
338
  this.scope = scope;
339
- this.api = api;
339
+ this.remote = remote;
340
340
  this.specs = new Map([
341
341
  choiceField("provider"),
342
342
  choiceField("mode"),
@@ -391,7 +391,7 @@ window.__ModuleLoader__.load({
391
391
  this.readCredential();
392
392
  }
393
393
  bind(project) {
394
- const store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)(project());
394
+ const store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)(project());
395
395
  this.listeners.add(() => {
396
396
  store.set(project());
397
397
  });
@@ -591,12 +591,12 @@ window.__ModuleLoader__.load({
591
591
  }
592
592
  let response;
593
593
  try {
594
- response = await this.api.credentials.describe({ refs: [ref] });
594
+ response = await this.remote.credentials.describe([ref]);
595
595
  } catch (_credentialReadFailure) {
596
596
  return;
597
597
  }
598
- if (!response.result.ok || ref !== this.refOf()) return;
599
- const view = response.result.value.credentials[ref];
598
+ if (!response.ok || ref !== this.refOf()) return;
599
+ const view = response.value[ref];
600
600
  const next = {
601
601
  ref,
602
602
  configured: view?.configured ?? false,
@@ -619,7 +619,8 @@ window.__ModuleLoader__.load({
619
619
  ref = rest !== void 0 ? this.restKeyRef(rest) : this.tavilyRef();
620
620
  }
621
621
  try {
622
- await this.api.credentials.set({ ref, value });
622
+ const response = await this.remote.credentials.set(ref, value);
623
+ if (!response.ok) return false;
623
624
  } catch (_credentialWriteFailure) {}
624
625
  await this.readCredential();
625
626
  return this.credential.ref === ref ? this.credential.configured : true;
@@ -628,10 +629,10 @@ window.__ModuleLoader__.load({
628
629
 
629
630
  /** Bridges the plugin scope and the credentials domain onto the card. */
630
631
  var SearchCardController = class {
631
- constructor(scope, api) {
632
+ constructor(scope, remote) {
632
633
  this.scope = scope;
633
- this.api = api;
634
- this.form = new SearchCardForm(scope, api);
634
+ this.remote = remote;
635
+ this.form = new SearchCardForm(scope, remote);
635
636
  this.store = this.form.bind(() => this.projection());
636
637
  scope.subscribe(() => {
637
638
  this.form.readCredential();
@@ -1150,11 +1151,10 @@ window.__ModuleLoader__.load({
1150
1151
 
1151
1152
  /** Mount the top-level "Web search" settings section. */
1152
1153
  function apply(ctx) {
1153
- const { api } = ctx.get("connection");
1154
1154
  const t = ctx.locale.bind(NS);
1155
1155
  ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-web-search-plugin: card dictionaries");
1156
- const controller = new SearchCardController(ctx.settingsScope.bind({ namespace: NS }), api);
1157
- ctx.effect(() => ctx.remote.$on("credentials/updated", (ref) => {
1156
+ const controller = new SearchCardController(ctx.settingsScope.bind({ namespace: NS }), ctx.remote);
1157
+ ctx.effect(() => ctx.remote.$on("credentials/reference-updated", (ref) => {
1158
1158
  controller.form.refreshCredential(ref);
1159
1159
  }), "dsh-web-search-plugin: credential invalidations");
1160
1160
  ctx.effect(() => usageStore.start(), "dsh-web-search-plugin: usage poll");
@@ -1168,7 +1168,7 @@ window.__ModuleLoader__.load({
1168
1168
  }, makeSection(ctx, controller)));
1169
1169
  }
1170
1170
 
1171
- const inject = ["slots", "locale", "connection", "remote", "settingsScope"];
1171
+ const inject = ["slots", "locale", "remote", "settingsScope"];
1172
1172
 
1173
1173
  exports.apply = apply;
1174
1174
  exports.inject = inject;
package/lib/index.js CHANGED
@@ -17,7 +17,6 @@
17
17
  * @module dsh-web-search-plugin
18
18
  */
19
19
  import z from "@deepseek-ai/schemastery";
20
- import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
21
20
  import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
22
21
  import { MAX_RESULTS_CAP } from "./shared.js";
23
22
  import { TAVILY_DEFAULT_API_KEY_ENV, TAVILY_DEFAULT_BASE_URL, TavilySearchProvider, resolveTavilyOptions } from "./tavily.js";
@@ -34,6 +33,8 @@ const SEARCH_PROVIDER_ID = "dsh-web-search";
34
33
  const name = "dsh-web-search-plugin";
35
34
  /** The web seam this provider registers into. */
36
35
  const inject = ["web"];
36
+ /** Settings namespace carrying this plugin's backend switch and options. */
37
+ const WEB_SEARCH_SETTINGS_NAMESPACE = "dsh-web-search-plugin";
37
38
 
38
39
  /** Plugin config (all optional — `apply` fills defaults). */
39
40
  const Config = z.object({
@@ -117,11 +118,6 @@ const Config = z.object({
117
118
  maxUses: z.number().step(1).min(1).default(5)
118
119
  });
119
120
 
120
- /** Settings namespace carrying this plugin's backend switch and options. */
121
- const WEB_SEARCH_SETTINGS_NAMESPACE = settingsNamespace("dsh-web-search-plugin");
122
- /** @deprecated Use {@link WEB_SEARCH_SETTINGS_NAMESPACE}. */
123
- const WEB_SEARCH_TAVILY_SETTINGS_NAMESPACE = WEB_SEARCH_SETTINGS_NAMESPACE;
124
-
125
121
  /**
126
122
  * One seam-facing provider whose `id` stays `dsh-web-search`. The active
127
123
  * backend is read from the live settings section on every `available` /
@@ -254,11 +250,13 @@ function sendJson(res, statusCode, data) {
254
250
  /** Register the dispatched search provider with `ctx.web`. */
255
251
  function apply(ctx, config) {
256
252
  let current = () => config;
257
- installSettingsSection(ctx, WEB_SEARCH_SETTINGS_NAMESPACE, Config, config, {
258
- setSource: (source) => {
259
- current = source;
260
- },
261
- onChange: () => {}
253
+ ctx.inject(["settings"], (settingsCtx) => {
254
+ settingsCtx.settings.installSection(ctx, WEB_SEARCH_SETTINGS_NAMESPACE, Config, config, {
255
+ setSource: (source) => {
256
+ current = source;
257
+ },
258
+ onChange: () => {}
259
+ });
262
260
  });
263
261
  const live = () => resolveOptions(ctx, current());
264
262
  const usage = new UsageTracker({
@@ -335,7 +333,6 @@ export {
335
333
  TavilySearchProvider,
336
334
  UsageTracker,
337
335
  WEB_SEARCH_SETTINGS_NAMESPACE,
338
- WEB_SEARCH_TAVILY_SETTINGS_NAMESPACE,
339
336
  apply,
340
337
  findProvider,
341
338
  inject,
package/lib/shared.js CHANGED
@@ -7,7 +7,7 @@ import { launchEnvironmentOf } from "@deepseek-ai/dsh-launch-environment";
7
7
  import { WebError } from "@deepseek-ai/dsh-web";
8
8
 
9
9
  /** Attribution header sent on every request. */
10
- export const USER_AGENT = "dsh-web-search-plugin/0.3.1";
10
+ export const USER_AGENT = "dsh-web-search-plugin/0.4.0";
11
11
  /** Shared cap: Tavily `max_results` and Brave `count` both accept 1..20. */
12
12
  export const MAX_RESULTS_CAP = 20;
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-web-search-plugin",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Unified web search for the DeepSeek Harness seam (ctx.web): DeepSeek (official), Tavily, Brave, Serper, SerpApi, Exa, SearXNG, Scavio, and Firecrawl backends",
5
5
  "keywords": [
6
6
  "dsh-plugin",
@@ -43,9 +43,7 @@
43
43
  "client": {
44
44
  "platform": "web",
45
45
  "inject": [
46
- "@deepseek-ai/dsh-client-connection",
47
46
  "@deepseek-ai/dsh-client-locale",
48
- "@deepseek-ai/dsh-client-runtime",
49
47
  "@deepseek-ai/dsh-client-ui-settings",
50
48
  "@deepseek-ai/dsh-client-ui-slots",
51
49
  "@deepseek-ai/dsh-api-remotes"
@@ -59,12 +57,12 @@
59
57
  "undici": "^6.21.0"
60
58
  },
61
59
  "peerDependencies": {
62
- "@deepseek-ai/dsh-web": "^0.1.0-rc.7",
63
- "@deepseek-ai/dsh-credentials": "^0.1.0-rc.7",
64
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.7",
65
- "@deepseek-ai/dsh-launch-environment": "^0.1.0-rc.7",
66
- "@deepseek-ai/schemastery": "^3.18.1",
67
- "@deepseek-ai/cordis": "^4.0.1"
60
+ "@deepseek-ai/dsh-web": "^0.1.2-alpha.4",
61
+ "@deepseek-ai/dsh-credentials": "^0.1.2-alpha.4",
62
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.4",
63
+ "@deepseek-ai/dsh-launch-environment": "^0.1.2-alpha.4",
64
+ "@deepseek-ai/schemastery": "^3.18.2",
65
+ "@deepseek-ai/cordis": "^4.0.2"
68
66
  },
69
67
  "license": "MIT",
70
68
  "repository": {