dsh-search-tools 0.0.0-stage → 0.1.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.
Files changed (99) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/LICENSE +21 -0
  3. package/README.md +113 -2
  4. package/README.zh.md +92 -0
  5. package/SECURITY.md +20 -0
  6. package/THIRD_PARTY_NOTICES.md +17 -0
  7. package/cordis.patch.yml +16 -0
  8. package/icon.svg +6 -0
  9. package/lib/client.js +3047 -0
  10. package/lib/client.js.map +1 -0
  11. package/lib/index.js +2221 -0
  12. package/lib/index.js.map +1 -0
  13. package/lib/types/client/ActivationHint.d.ts +6 -0
  14. package/lib/types/client/ActivationHint.d.ts.map +1 -0
  15. package/lib/types/client/ResearchCard.d.ts +7 -0
  16. package/lib/types/client/ResearchCard.d.ts.map +1 -0
  17. package/lib/types/client/SettingsPage.d.ts +65 -0
  18. package/lib/types/client/SettingsPage.d.ts.map +1 -0
  19. package/lib/types/client/TakeoverWarning.d.ts +12 -0
  20. package/lib/types/client/TakeoverWarning.d.ts.map +1 -0
  21. package/lib/types/client/api.d.ts +43 -0
  22. package/lib/types/client/api.d.ts.map +1 -0
  23. package/lib/types/client/components/Field.d.ts +36 -0
  24. package/lib/types/client/components/Field.d.ts.map +1 -0
  25. package/lib/types/client/diagnostic-text.d.ts +4 -0
  26. package/lib/types/client/diagnostic-text.d.ts.map +1 -0
  27. package/lib/types/client/index.d.ts +14 -0
  28. package/lib/types/client/index.d.ts.map +1 -0
  29. package/lib/types/client/issue-text.d.ts +5 -0
  30. package/lib/types/client/issue-text.d.ts.map +1 -0
  31. package/lib/types/client/locales.d.ts +185 -0
  32. package/lib/types/client/locales.d.ts.map +1 -0
  33. package/lib/types/client/styles.d.ts +3 -0
  34. package/lib/types/client/styles.d.ts.map +1 -0
  35. package/lib/types/config.d.ts +20 -0
  36. package/lib/types/config.d.ts.map +1 -0
  37. package/lib/types/core/diagnostics.d.ts +9 -0
  38. package/lib/types/core/diagnostics.d.ts.map +1 -0
  39. package/lib/types/core/dispatchers.d.ts +61 -0
  40. package/lib/types/core/dispatchers.d.ts.map +1 -0
  41. package/lib/types/core/host-types.d.ts +37 -0
  42. package/lib/types/core/host-types.d.ts.map +1 -0
  43. package/lib/types/core/service.d.ts +40 -0
  44. package/lib/types/core/service.d.ts.map +1 -0
  45. package/lib/types/core/types.d.ts +197 -0
  46. package/lib/types/core/types.d.ts.map +1 -0
  47. package/lib/types/fetch/adapters/readable-http/adapter.d.ts +3 -0
  48. package/lib/types/fetch/adapters/readable-http/adapter.d.ts.map +1 -0
  49. package/lib/types/fetch/adapters/readable-http/manifest.d.ts +4 -0
  50. package/lib/types/fetch/adapters/readable-http/manifest.d.ts.map +1 -0
  51. package/lib/types/fetch/adapters/readable-http/provider.d.ts +13 -0
  52. package/lib/types/fetch/adapters/readable-http/provider.d.ts.map +1 -0
  53. package/lib/types/fetch/adapters/readable-http/readability.d.ts +28 -0
  54. package/lib/types/fetch/adapters/readable-http/readability.d.ts.map +1 -0
  55. package/lib/types/fetch/adapters/readable-http/schema.d.ts +18 -0
  56. package/lib/types/fetch/adapters/readable-http/schema.d.ts.map +1 -0
  57. package/lib/types/host/routes.d.ts +18 -0
  58. package/lib/types/host/routes.d.ts.map +1 -0
  59. package/lib/types/index.d.ts +12 -0
  60. package/lib/types/index.d.ts.map +1 -0
  61. package/lib/types/research/pipeline.d.ts +26 -0
  62. package/lib/types/research/pipeline.d.ts.map +1 -0
  63. package/lib/types/research/prompt.d.ts +43 -0
  64. package/lib/types/research/prompt.d.ts.map +1 -0
  65. package/lib/types/research/render.d.ts +4 -0
  66. package/lib/types/research/render.d.ts.map +1 -0
  67. package/lib/types/research/tool.d.ts +7 -0
  68. package/lib/types/research/tool.d.ts.map +1 -0
  69. package/lib/types/search/adapters/searxng/adapter.d.ts +3 -0
  70. package/lib/types/search/adapters/searxng/adapter.d.ts.map +1 -0
  71. package/lib/types/search/adapters/searxng/client.d.ts +31 -0
  72. package/lib/types/search/adapters/searxng/client.d.ts.map +1 -0
  73. package/lib/types/search/adapters/searxng/manifest.d.ts +4 -0
  74. package/lib/types/search/adapters/searxng/manifest.d.ts.map +1 -0
  75. package/lib/types/search/adapters/searxng/parse-html.d.ts +5 -0
  76. package/lib/types/search/adapters/searxng/parse-html.d.ts.map +1 -0
  77. package/lib/types/search/adapters/searxng/parse-json.d.ts +21 -0
  78. package/lib/types/search/adapters/searxng/parse-json.d.ts.map +1 -0
  79. package/lib/types/search/adapters/searxng/schema.d.ts +43 -0
  80. package/lib/types/search/adapters/searxng/schema.d.ts.map +1 -0
  81. package/lib/types/shared/defaults.d.ts +44 -0
  82. package/lib/types/shared/defaults.d.ts.map +1 -0
  83. package/lib/types/shared/diff.d.ts +23 -0
  84. package/lib/types/shared/diff.d.ts.map +1 -0
  85. package/lib/types/shared/errors.d.ts +14 -0
  86. package/lib/types/shared/errors.d.ts.map +1 -0
  87. package/lib/types/shared/limit.d.ts +8 -0
  88. package/lib/types/shared/limit.d.ts.map +1 -0
  89. package/lib/types/shared/localized.d.ts +5 -0
  90. package/lib/types/shared/localized.d.ts.map +1 -0
  91. package/lib/types/shared/path.d.ts +7 -0
  92. package/lib/types/shared/path.d.ts.map +1 -0
  93. package/lib/types/shared/url.d.ts +18 -0
  94. package/lib/types/shared/url.d.ts.map +1 -0
  95. package/lib/types/shared/validation.d.ts +17 -0
  96. package/lib/types/shared/validation.d.ts.map +1 -0
  97. package/locale/en.json +6 -0
  98. package/locale/zh.json +6 -0
  99. package/package.json +149 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,149 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 — 2026-10-22
4
+
5
+ ### Added
6
+
7
+ - Adapter-first core: `ctx.searchTools` registry, stable search/fetch dispatchers,
8
+ manifest-driven settings metadata.
9
+ - SearXNG search adapter skeleton: config validation, JSON/HTML parsing, auth
10
+ lookup, failover, pagination, cache, probe.
11
+ - Readability HTTP fetch adapter skeleton: DSH safe fetch, lazily imported
12
+ linkedom/Readability, fail-open extraction.
13
+ - `web_research` tool and conversation card.
14
+ - Settings section registration (`settings.section`) and authenticated host
15
+ routes for status, adapters, probe, search preview, fetch preview, cache clear.
16
+ - YAML-backed config through DSH settings; credentials-backed secrets.
17
+ - Project skeleton: TypeScript, tsdown host/client builds, Vitest, CI/release
18
+ workflows, bilingual README, MIT license.
19
+ - Component tests for the settings page and `web_research` card
20
+ (`tests/settings-page.spec.tsx`, `tests/research-card.spec.tsx`), with jsdom
21
+ as a dev-only test environment.
22
+ - Code-based adapter issue messages, localized for `zh` / `en`; the settings
23
+ page falls back to the English message when no code is present.
24
+ - Generic manifest validation for external adapters, so a new adapter's required
25
+ fields and numeric bounds are checked before saving without importing its code
26
+ into the browser.
27
+ - The research card only turns `http(s)` source URLs into links and drops
28
+ malformed presentation-meta entries instead of rendering empty rows.
29
+ - `web_research` pipeline integration test: real HTML extraction, per-page
30
+ failure isolation, text clipping, total-budget accounting, disabled mode, and
31
+ presentation-meta projection.
32
+ - The research card reports successful fetches separately when some pages fail
33
+ (`1/2 fetched`) instead of counting attempts as successes.
34
+ - Search and Fetch tabs now have inline test panels. Results are structured:
35
+ elapsed time, safe `http(s)` source links, snippets, and fetch metadata/content,
36
+ instead of the previous single text blob. Tests refuse to run while the draft
37
+ has validation errors.
38
+ - Advanced diagnostics can copy a credential-free summary and clear the in-memory
39
+ error ring (`POST /api/dsh-search-tools/diagnostics/clear`).
40
+ - Search and Fetch validation is section-scoped: a broken search draft no longer
41
+ blocks a fetch test, and fetch errors no longer attach to search fields that
42
+ happen to share a key.
43
+ - Tab semantics (`role=tablist/tab/tabpanel`, arrow/Home/End navigation),
44
+ `aria-invalid` on invalid fields, an aria-live save/diagnostic status, and
45
+ `Cmd/Ctrl+S` save.
46
+ - The active-takeover instance rule is driven by the selected manifest's
47
+ `instances` field rather than a hard-coded SearXNG check. External adapters
48
+ without instances no longer produce a false save error.
49
+ - `/status` lists credential refs declared by every registered adapter manifest,
50
+ not just SearXNG's two refs.
51
+ - The settings footer is no longer sticky, so it cannot cover a long test result
52
+ in the 800px settings pane. Overview cards use `auto-fit` columns to avoid
53
+ label overlap at that width.
54
+ - Activation-hint and takeover-warning cards use token fallbacks, so they render
55
+ with a real border/background outside the settings theme scope.
56
+ - Adapter picker shows the selected manifest's description/capabilities and keeps
57
+ a visible “not installed” option for orphaned config.
58
+ - Adapter picker is now a radio-card group with per-adapter
59
+ configured/needs-setup/needs-attention status, a “not installed” orphan card,
60
+ and a Refresh adapters action.
61
+ - Research tab previews the model-facing `web_research` description and parameter
62
+ bounds from the current draft. The contract lives in `src/research/prompt.ts`
63
+ and is shared with the registered tool, so the preview cannot drift from the
64
+ tool description.
65
+ - Instance rows stack the URL/label fields and their actions in the 800px
66
+ settings pane, and show a visible “Enabled” label next to the switch. This
67
+ fixes a 4px-wide URL input caused by the action row consuming the grid.
68
+ - SearXNG's `unresponsive_engines` are surfaced as `Search notes` in the settings
69
+ preview, so an empty result caused by suspended engines is distinguishable from
70
+ a genuinely empty search.
71
+
72
+ ### Changed
73
+
74
+ - `pnpm release` now uses a narrow publint policy that ignores only the known
75
+ `FILE_INVALID_FORMAT` verdict for `lib/client.js` (a DSH browser CJS factory)
76
+ and reports every other diagnostic. The same check runs in CI.
77
+ - Package metadata now includes search keywords, `publishConfig.access: public`,
78
+ and publishes `CHANGELOG.md` / `SECURITY.md` in the tarball.
79
+
80
+ ### Verified
81
+
82
+ - M0 on DSH `0.2.1-rc.2`: Settings → Search Tools renders; Save writes
83
+ `cordis.patch.yml`; authenticated routes return 401 without the browser
84
+ cookie and 200 with it; probe/search-preview work against a mock SearXNG;
85
+ search/fetch takeover and restore work; secret write stays out of YAML.
86
+ Details: `docs/m0-verification.md`.
87
+ - A scripted model drove `web_research` through the real DSH agent loop and Web
88
+ GUI: the tool executed against a mock SearXNG, fetched two public pages, wrote
89
+ a `tool/result` with presentation meta, and rendered the card in the
90
+ conversation (`2 sources`, `2 fetched`, source links, fetched details).
91
+ - 65 tests across 13 files, including settings-page, activation-hint,
92
+ research-card, takeover-warning, diagnostics text, publint policy, and
93
+ `web_research` pipeline tests (`pnpm test`).
94
+ - A live Web GUI pass on the new form UX: inline search test rendered two
95
+ structured sources, the footer no longer covered the result, the zero-instance
96
+ empty state and one-column Overview layout rendered correctly, `Copy
97
+ diagnostics`/`diagnostics/clear` worked, and the activation hint rendered as a
98
+ bordered card after disabling/re-enabling the bundle. Dark theme and a 700px
99
+ narrow viewport also rendered correctly; tabs wrap instead of clipping.
100
+ - A live Web GUI pass on the product-polish surface: the picker rendered as a
101
+ one-card radiogroup with `Configured`, `Refresh adapters` reported success, the
102
+ research prompt rendered at 530×272 with current bounds, and at 700px the prompt
103
+ reflowed to 382px without horizontal overflow. The same pass caught and fixed a
104
+ 4px-wide instance URL input caused by the action row consuming the instance
105
+ grid; URL/label now render full width with actions below.
106
+ - A real authenticated SearXNG instance was probed and searched through the
107
+ settings page: JSON API and Basic auth worked, 10 real sources rendered, and
108
+ credentials stayed out of YAML (`Source: env`). With the instance's default
109
+ engines suspended, the preview showed `Search notes`; selecting `bing` returned
110
+ real results. Details: `docs/m0-verification.md`.
111
+ - A real OpenAI-compatible model (`agnes-3.0-flash`) called `web_research`,
112
+ built-in `web_search`, and built-in `web_fetch` through the live Web GUI. The
113
+ research turn returned 8 real SearXNG sources and fetched 2 pages (1,792 and
114
+ 868 chars); `web_search` used the taken-over provider; `web_fetch` returned
115
+ HTTP 200 for example.com. The provider key stayed in the process environment,
116
+ with no secret in YAML, the repository, or the three test-session logs (the
117
+ chat transcript that supplied it is separate and should be treated as exposed).
118
+ Details: `docs/m0-verification.md`.
119
+ - Final v0.1.0 gate: `pnpm release` passed with 65 tests / 13 files, host/client/
120
+ type builds, a pack dry run, and no publint issues after the documented
121
+ client-bundle exemption. `npm publish --dry-run` accepted the 99-file, 158.4 kB
122
+ tarball, including `CHANGELOG.md` / `SECURITY.md`; publication itself remains
123
+ pending npm authentication and a reachable repository remote.
124
+
125
+ ### Fixed during M0
126
+
127
+ - Resolve credentials per request instead of capturing them at plugin apply.
128
+ - Read the `{ ok, value }` envelope from `remote.credentials.describe`.
129
+ - Render write-only secret fields from `manifest.secretRefs`.
130
+ - Require a passing search test before search takeover and restore the previous
131
+ provider on disable.
132
+ - Allow an empty instance list when takeover is off.
133
+ - Localize page copy and adapter manifests for `zh` / `en`.
134
+ - Rebuild the LRU when cache bounds change; wire `undici.ProxyAgent`.
135
+ - Validate a missing `userAgent` against the adapter default.
136
+ - Use linkedom instead of jsdom for Readability: jsdom's `tr46` dependency
137
+ calls `createRequire(...).resolve.paths`, which DSH's profile-resolution hook
138
+ breaks; linkedom is smaller and works inside the Host.
139
+ - Add the `plugins.detail.section` takeover warning with a direct
140
+ “disable takeover” action.
141
+ - Add per-instance probe buttons and an empty-state guide.
142
+ - Add localized adapter manifests so external adapters can ship `en` / `zh`
143
+ labels without changing the page.
144
+ - Drop malformed `web_research` presentation-meta entries instead of rendering
145
+ empty list items or duplicate React keys.
146
+ - Give research number fields real label/id associations, so they are reachable
147
+ by accessible name as well as by mouse.
148
+ - Recognize a scoped package name (`@scope/dsh-search-tools`) in the Plugins-page
149
+ takeover warning instead of requiring the unscoped name verbatim.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ThzxxArt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,114 @@
1
- # Temporary Holding Version
1
+ # dsh-search-tools
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Adapter-first web search and readable page fetching for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).
4
+
5
+ > **Status: v0.1.0 release candidate (2026-10-22).** M0 is verified end to end:
6
+ > the host and client bundles build, Settings → Search Tools renders in the real
7
+ > Web GUI, Save writes YAML, authenticated routes work, search/fetch takeover and
8
+ > restore work, and credentials stay out of YAML. The settings page has inline
9
+ > search/fetch tests, diagnostics copy/clear, keyboard save, a card-based adapter
10
+ > picker, and a live preview of the model-facing `web_research` contract. A real
11
+ > OpenAI-compatible model called `web_research`, built-in `web_search`, and
12
+ > built-in `web_fetch`; search used a real SearXNG instance and the research card
13
+ > rendered. Build, test, pack, and publint checks pass. Publication is the
14
+ > remaining external step; see `docs/release-v0.1.0.md`.
15
+
16
+ ## What it does
17
+
18
+ - Exposes **stable** DSH providers `dsh-search-tools` (search) and
19
+ `dsh-search-tools-fetch` (fetch). The provider ids never change when a backend
20
+ is added or swapped.
21
+ - Ships **SearXNG** as the first search adapter and **Readability HTTP** as the
22
+ first fetch adapter.
23
+ - Adds a `web_research` tool that searches, fetches the top N pages, and returns
24
+ readable content in one call.
25
+ - Registers **Settings → Search Tools** in the Web GUI. Configuration is edited
26
+ there, never by hand.
27
+ - Search and Fetch tabs include inline test panels with structured sources and
28
+ fetch previews; Advanced can copy or clear diagnostics.
29
+ - Stores configuration in the DSH profile's YAML patch
30
+ (`$DSH_HOME/profiles/<profile>/cordis.patch.yml`) through the native settings
31
+ service. Secrets go to DSH credentials, not YAML.
32
+
33
+ ## Adding a backend
34
+
35
+ An adapter package depends on `ctx.searchTools` and registers a manifest plus a
36
+ runtime:
37
+
38
+ ```ts
39
+ export const inject = ['searchTools']
40
+
41
+ export function apply(ctx: Context): void {
42
+ ctx.effect(() => ctx.searchTools.registerSearchAdapter(exaAdapter), 'exa adapter')
43
+ }
44
+ ```
45
+
46
+ The settings page reads adapter manifests from the host route and renders their
47
+ fields generically. No page code changes when a new adapter is registered.
48
+
49
+ ## Development
50
+
51
+ ```sh
52
+ pnpm install --registry=https://registry.npmjs.org
53
+ pnpm typecheck
54
+ pnpm test
55
+ pnpm build
56
+ pnpm pack:check
57
+ ```
58
+
59
+ `pnpm build` emits:
60
+
61
+ ```text
62
+ lib/index.js Host half
63
+ lib/client.js Browser lazy-CJS factory
64
+ lib/types/** Declarations
65
+ ```
66
+
67
+ ## Install in DSH
68
+
69
+ Primary path is the Web UI:
70
+
71
+ 1. Open **Plugins**.
72
+ 2. **Add plugin** → enter `dsh-search-tools`.
73
+ 3. Enable it.
74
+ 4. Open **Settings → Search Tools** and configure a SearXNG instance.
75
+
76
+ Before the npm release, install a packed tarball instead:
77
+
78
+ ```sh
79
+ pnpm pack
80
+ dsh plugin --profile <profile> add ./dsh-search-tools-0.1.0.tgz
81
+ ```
82
+
83
+ For local development, an absolute-path overlay can load `src/index.ts`; use the
84
+ DSH checkout's own docs for the exact `--patch` command.
85
+
86
+ ## Project layout
87
+
88
+ ```text
89
+ src/core/ adapter types, registry, stable dispatchers
90
+ src/search/adapters/ search adapters (searxng first)
91
+ src/fetch/adapters/ fetch adapters (readable-http first)
92
+ src/research/ web_research pipeline, prompt, render, tool
93
+ src/host/ authenticated settings routes
94
+ src/client/ Settings → Search Tools + tool card
95
+ src/shared/ config, validation, diff, URL helpers
96
+ tests/ host units + settings page / research card components
97
+ ```
98
+
99
+ Readability uses `linkedom`, not `jsdom`: jsdom's `tr46` dependency calls
100
+ `createRequire(...).resolve.paths`, which DSH's profile-resolution hook does not
101
+ implement. linkedom is smaller and works inside the Host.
102
+
103
+ ## Security
104
+
105
+ - Settings routes use DSH's `connection.requestRejection` fence.
106
+ - Fetch reuses DSH's SSRF-safe `HttpFetchProvider`.
107
+ - Tokens are read from `ctx.credentials`/environment per request and never enter
108
+ YAML, logs, or error text.
109
+ - SearXNG requests use `redirect: 'error'` so credentials cannot follow a
110
+ cross-origin redirect.
111
+
112
+ ## License
113
+
114
+ MIT. See [LICENSE](LICENSE) and [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
package/README.zh.md ADDED
@@ -0,0 +1,92 @@
1
+ # dsh-search-tools
2
+
3
+ 为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 提供 adapter-first 的网页搜索与正文抓取。
4
+
5
+ > **状态:v0.1.0 发布候选(2026-10-22)。** M0 已端到端验证:Host 与客户端 bundle 可构建,设置里的「搜索工具」在真实 Web GUI 中出现,保存写入 YAML,认证路由可用,搜索/抓取接管与恢复可用,密钥不落 YAML。设置页提供搜索/抓取内联测试、诊断复制/清空、键盘保存、卡片式 adapter picker,以及模型看到的 `web_research` 契约预览。真实 OpenAI 兼容模型已分别调用 `web_research`、内置 `web_search` 和内置 `web_fetch`,搜索走真实 SearXNG,研究卡片正常渲染。构建、测试、打包和 publint 检查均通过。发布是剩余的外部步骤;见 `docs/release-v0.1.0.md`。
6
+
7
+ ## 它做什么
8
+
9
+ - 注册**稳定**的 DSH provider:`dsh-search-tools`(搜索)和 `dsh-search-tools-fetch`(抓取)。新增或切换后端时 provider id 不变。
10
+ - 第一个搜索 adapter 是 **SearXNG**,第一个抓取 adapter 是 **Readability HTTP**。
11
+ - 新增 `web_research` 工具:一次调用完成“搜索 + 抓前 N 条正文”。
12
+ - 在 Web GUI 注册 **设置 → 搜索工具**,所有配置在页面完成,不需要手改文件。
13
+ - 搜索/抓取页签内置测试面板,返回结构化来源和抓取预览;高级页可复制/清空诊断信息。
14
+ - 配置通过 DSH 原生 settings 服务写入 profile 的 YAML patch(`$DSH_HOME/profiles/<profile>/cordis.patch.yml`)。密钥走 DSH credentials,不写入 YAML。
15
+
16
+ ## 新增后端
17
+
18
+ Adapter 包依赖 `ctx.searchTools`,注册 manifest 和 runtime:
19
+
20
+ ```ts
21
+ export const inject = ['searchTools']
22
+
23
+ export function apply(ctx: Context): void {
24
+ ctx.effect(() => ctx.searchTools.registerSearchAdapter(exaAdapter), 'exa adapter')
25
+ }
26
+ ```
27
+
28
+ 设置页从 Host 路由读取 manifest,自动渲染字段;新增 adapter 不需要改页面代码。
29
+
30
+ ## 开发
31
+
32
+ ```sh
33
+ pnpm install --registry=https://registry.npmjs.org
34
+ pnpm typecheck
35
+ pnpm test
36
+ pnpm build
37
+ pnpm pack:check
38
+ ```
39
+
40
+ `pnpm build` 产出:
41
+
42
+ ```text
43
+ lib/index.js Host 半侧
44
+ lib/client.js 浏览器 lazy-CJS factory
45
+ lib/types/** 类型声明
46
+ ```
47
+
48
+ ## 在 DSH 里安装
49
+
50
+ 主路径是 Web UI:
51
+
52
+ 1. 打开 **插件**。
53
+ 2. **添加插件** → 输入 `dsh-search-tools`。
54
+ 3. 启用。
55
+ 4. 打开 **设置 → 搜索工具**,配置 SearXNG 实例。
56
+
57
+ npm 发布前,先用打包产物安装:
58
+
59
+ ```sh
60
+ pnpm pack
61
+ dsh plugin --profile <profile> add ./dsh-search-tools-0.1.0.tgz
62
+ ```
63
+
64
+ 本地开发可以用绝对路径 overlay 加载 `src/index.ts`,具体 `--patch` 命令以 DSH checkout 文档为准。
65
+
66
+ ## 目录
67
+
68
+ ```text
69
+ src/core/ adapter 类型、注册表、稳定 dispatcher
70
+ src/search/adapters/ 搜索 adapter(第一个是 searxng)
71
+ src/fetch/adapters/ 抓取 adapter(第一个是 readable-http)
72
+ src/research/ web_research pipeline、prompt、render、tool
73
+ src/host/ 受认证的设置路由
74
+ src/client/ 设置 → 搜索工具 + 工具卡片
75
+ src/shared/ config、校验、diff、URL 辅助
76
+ tests/ Host 单测 + 设置页/研究卡片组件测试
77
+ ```
78
+
79
+ Readability 使用 `linkedom`,不是 `jsdom`:jsdom 的 `tr46` 依赖会调用
80
+ `createRequire(...).resolve.paths`,而 DSH 的 profile resolution hook 没有实现它。
81
+ linkedom 更小,也能在 Host 内正常工作。
82
+
83
+ ## 安全
84
+
85
+ - 设置路由使用 DSH 的 `connection.requestRejection` 栅栏。
86
+ - 抓取复用 DSH 的 SSRF 安全 `HttpFetchProvider`。
87
+ - token 每次请求从 `ctx.credentials`/环境变量读取,不进 YAML、日志或错误文本。
88
+ - SearXNG 请求使用 `redirect: 'error'`,凭据不会跟随跨源重定向。
89
+
90
+ ## 许可证
91
+
92
+ MIT。见 [LICENSE](LICENSE) 与 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。
package/SECURITY.md ADDED
@@ -0,0 +1,20 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ v0.1.x is the current preview line. DSH itself is preview software; treat this
6
+ plugin as preview too.
7
+
8
+ ## Reporting
9
+
10
+ Please open a private security advisory on GitHub rather than a public issue.
11
+
12
+ ## Design notes
13
+
14
+ - Configuration is written by DSH's settings/config-editor into the profile
15
+ `cordis.patch.yml` (mode 0600) and never contains bearer/basic secrets.
16
+ - Secrets are referenced as `SEARXNG_TOKEN` / `SEARXNG_BASIC_AUTH` and resolved
17
+ per request from DSH credentials or the process environment.
18
+ - The settings routes require DSH's browser authentication and Host/Origin fence.
19
+ - Fetching reuses `@deepseek-ai/dsh-web-fetch-http`, including its SSRF policy.
20
+ - Diagnostics redact URL query strings and never include credentials.
@@ -0,0 +1,17 @@
1
+ # Third-party notices
2
+
3
+ This package is MIT-licensed. It depends on:
4
+
5
+ - `@mozilla/readability` — Apache-2.0
6
+ - `linkedom` — MIT
7
+ - `cheerio` — MIT
8
+ - `lru-cache` — ISC
9
+ - `normalize-url` — MIT
10
+ - `turndown` — MIT
11
+ - `@joplin/turndown-plugin-gfm` — MIT
12
+ - `undici` — MIT
13
+
14
+ DSH packages (`@deepseek-ai/*`) are peer dependencies supplied by the host
15
+ installation; their licenses are those of DeepSeek Harness.
16
+
17
+ See each package's own LICENSE for the authoritative text.
@@ -0,0 +1,16 @@
1
+ # dsh-search-tools bundle layer
2
+ #
3
+ # The row uses the bare package name so the client module system attaches the
4
+ # browser half. The stable provider ids are owned by the Host half; adapters
5
+ # are selected inside this row's config.
6
+ - insert:
7
+ - id: dsh-search-tools
8
+ name: dsh-search-tools
9
+ config:
10
+ search:
11
+ adapter: searxng
12
+ fetch:
13
+ adapter: readable-http
14
+ research:
15
+ enabled: true
16
+ defaultFetchTop: 3
package/icon.svg ADDED
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Search Tools">
2
+ <rect width="64" height="64" rx="14" fill="#1f6feb"/>
3
+ <circle cx="27" cy="27" r="12" fill="none" stroke="#fff" stroke-width="4"/>
4
+ <path d="M36 36l11 11" fill="none" stroke="#fff" stroke-width="4" stroke-linecap="round"/>
5
+ <path d="M20 24h14M20 29h9" fill="none" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/>
6
+ </svg>