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.
- package/CHANGELOG.md +149 -0
- package/LICENSE +21 -0
- package/README.md +113 -2
- package/README.zh.md +92 -0
- package/SECURITY.md +20 -0
- package/THIRD_PARTY_NOTICES.md +17 -0
- package/cordis.patch.yml +16 -0
- package/icon.svg +6 -0
- package/lib/client.js +3047 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +2221 -0
- package/lib/index.js.map +1 -0
- package/lib/types/client/ActivationHint.d.ts +6 -0
- package/lib/types/client/ActivationHint.d.ts.map +1 -0
- package/lib/types/client/ResearchCard.d.ts +7 -0
- package/lib/types/client/ResearchCard.d.ts.map +1 -0
- package/lib/types/client/SettingsPage.d.ts +65 -0
- package/lib/types/client/SettingsPage.d.ts.map +1 -0
- package/lib/types/client/TakeoverWarning.d.ts +12 -0
- package/lib/types/client/TakeoverWarning.d.ts.map +1 -0
- package/lib/types/client/api.d.ts +43 -0
- package/lib/types/client/api.d.ts.map +1 -0
- package/lib/types/client/components/Field.d.ts +36 -0
- package/lib/types/client/components/Field.d.ts.map +1 -0
- package/lib/types/client/diagnostic-text.d.ts +4 -0
- package/lib/types/client/diagnostic-text.d.ts.map +1 -0
- package/lib/types/client/index.d.ts +14 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/issue-text.d.ts +5 -0
- package/lib/types/client/issue-text.d.ts.map +1 -0
- package/lib/types/client/locales.d.ts +185 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/styles.d.ts +3 -0
- package/lib/types/client/styles.d.ts.map +1 -0
- package/lib/types/config.d.ts +20 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/core/diagnostics.d.ts +9 -0
- package/lib/types/core/diagnostics.d.ts.map +1 -0
- package/lib/types/core/dispatchers.d.ts +61 -0
- package/lib/types/core/dispatchers.d.ts.map +1 -0
- package/lib/types/core/host-types.d.ts +37 -0
- package/lib/types/core/host-types.d.ts.map +1 -0
- package/lib/types/core/service.d.ts +40 -0
- package/lib/types/core/service.d.ts.map +1 -0
- package/lib/types/core/types.d.ts +197 -0
- package/lib/types/core/types.d.ts.map +1 -0
- package/lib/types/fetch/adapters/readable-http/adapter.d.ts +3 -0
- package/lib/types/fetch/adapters/readable-http/adapter.d.ts.map +1 -0
- package/lib/types/fetch/adapters/readable-http/manifest.d.ts +4 -0
- package/lib/types/fetch/adapters/readable-http/manifest.d.ts.map +1 -0
- package/lib/types/fetch/adapters/readable-http/provider.d.ts +13 -0
- package/lib/types/fetch/adapters/readable-http/provider.d.ts.map +1 -0
- package/lib/types/fetch/adapters/readable-http/readability.d.ts +28 -0
- package/lib/types/fetch/adapters/readable-http/readability.d.ts.map +1 -0
- package/lib/types/fetch/adapters/readable-http/schema.d.ts +18 -0
- package/lib/types/fetch/adapters/readable-http/schema.d.ts.map +1 -0
- package/lib/types/host/routes.d.ts +18 -0
- package/lib/types/host/routes.d.ts.map +1 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/research/pipeline.d.ts +26 -0
- package/lib/types/research/pipeline.d.ts.map +1 -0
- package/lib/types/research/prompt.d.ts +43 -0
- package/lib/types/research/prompt.d.ts.map +1 -0
- package/lib/types/research/render.d.ts +4 -0
- package/lib/types/research/render.d.ts.map +1 -0
- package/lib/types/research/tool.d.ts +7 -0
- package/lib/types/research/tool.d.ts.map +1 -0
- package/lib/types/search/adapters/searxng/adapter.d.ts +3 -0
- package/lib/types/search/adapters/searxng/adapter.d.ts.map +1 -0
- package/lib/types/search/adapters/searxng/client.d.ts +31 -0
- package/lib/types/search/adapters/searxng/client.d.ts.map +1 -0
- package/lib/types/search/adapters/searxng/manifest.d.ts +4 -0
- package/lib/types/search/adapters/searxng/manifest.d.ts.map +1 -0
- package/lib/types/search/adapters/searxng/parse-html.d.ts +5 -0
- package/lib/types/search/adapters/searxng/parse-html.d.ts.map +1 -0
- package/lib/types/search/adapters/searxng/parse-json.d.ts +21 -0
- package/lib/types/search/adapters/searxng/parse-json.d.ts.map +1 -0
- package/lib/types/search/adapters/searxng/schema.d.ts +43 -0
- package/lib/types/search/adapters/searxng/schema.d.ts.map +1 -0
- package/lib/types/shared/defaults.d.ts +44 -0
- package/lib/types/shared/defaults.d.ts.map +1 -0
- package/lib/types/shared/diff.d.ts +23 -0
- package/lib/types/shared/diff.d.ts.map +1 -0
- package/lib/types/shared/errors.d.ts +14 -0
- package/lib/types/shared/errors.d.ts.map +1 -0
- package/lib/types/shared/limit.d.ts +8 -0
- package/lib/types/shared/limit.d.ts.map +1 -0
- package/lib/types/shared/localized.d.ts +5 -0
- package/lib/types/shared/localized.d.ts.map +1 -0
- package/lib/types/shared/path.d.ts +7 -0
- package/lib/types/shared/path.d.ts.map +1 -0
- package/lib/types/shared/url.d.ts +18 -0
- package/lib/types/shared/url.d.ts.map +1 -0
- package/lib/types/shared/validation.d.ts +17 -0
- package/lib/types/shared/validation.d.ts.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- 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
|
-
#
|
|
1
|
+
# dsh-search-tools
|
|
2
2
|
|
|
3
|
-
|
|
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.
|
package/cordis.patch.yml
ADDED
|
@@ -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>
|