dsh-plugin-scout 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +137 -2
- package/README.zh.md +136 -0
- package/cordis.patch.yml +6 -0
- package/icon.svg +11 -0
- package/lib/client.js +1024 -0
- package/lib/host.js +2996 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +84 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fegnze
|
|
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,138 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DSH Plugin Scout
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
[](https://github.com/fegnze/dsh-plugin-scout/actions/workflows/ci.yml) · MIT
|
|
6
|
+
|
|
7
|
+
Discover and verify DeepSeek Harness plugins published under the GitHub topic `dsh-plugin`, from inside DSH. Plugins are grouped by purpose, ranked by trust score, and checked against the official peer-compatibility rule. Supports DSH **0.2.x** (`>=0.2.0-rc.2 <0.3.0`); tested on desktop 0.2.0-rc.2.
|
|
8
|
+
|
|
9
|
+
> The in-app UI is currently Chinese only. The plugin's title and description in the official Plugins page are localized (`locale/en.json`, `locale/zh.json`).
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
Open the official **Plugins** page → **Add plugin**, and enter one of:
|
|
14
|
+
|
|
15
|
+
| Spec | Notes |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `dsh-plugin-scout` | Recommended. Prebuilt npm package with provenance; no install scripts, no build approval needed |
|
|
18
|
+
| Absolute path of `dsh-plugin-scout-<version>.tgz` downloaded from a GitHub Release | Bypasses the npm registry |
|
|
19
|
+
|
|
20
|
+
From the CLI: `dsh plugin --profile <profile> add dsh-plugin-scout`. Enable it on the Plugins page; a **发现插件** (Discover plugins) entry appears in the sidebar.
|
|
21
|
+
|
|
22
|
+
Do not install from `github:fegnze/dsh-plugin-scout`: a git install fetches source without `lib/`, and this repository deliberately ships no `prepare` script.
|
|
23
|
+
|
|
24
|
+
## One-click install, through the official installer
|
|
25
|
+
|
|
26
|
+
The **Install** button in the details drawer takes the same path as the official **Add plugin**: `inspect` first, then `installBundle(spec, {enabled: false, requestId, registry})`. Installed plugins start **disabled**; **Enable** is a separate click (`setBundleEnabled`).
|
|
27
|
+
|
|
28
|
+
- Plugins with install hooks, or whose DSH peers do not cover the running version, need a second click to install.
|
|
29
|
+
- When the official installer blocks dependency build scripts (`pendingBuilds`), they are listed by name; a double click on **Allow and reinstall** retries with `approvedBuilds`.
|
|
30
|
+
- **Cancel install** calls `cancelInstall` with the same `requestId`; a lost reply is recovered with `waitForInstall`. On failure the official installer restores `package.json` and the lockfile.
|
|
31
|
+
- **Uninstalling and version exemptions stay on the official Plugins page.** Scout never calls `removeBundle`; the tests fail if it does. Without the official `pluginManager`, the Install button is hidden and the drawer falls back to "copy pinned spec + open the Plugins page".
|
|
32
|
+
|
|
33
|
+
## Data sources (first-party only)
|
|
34
|
+
|
|
35
|
+
| Source | Used for |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| GitHub GraphQL `search(topic:dsh-plugin)` | Repository metadata, root `package.json`, `cordis.patch.yml` text (never evaluated) |
|
|
38
|
+
| `registry.npmjs.org/<name>/latest` | The manifest that would actually be installed: peers, install hooks, `repository`, provenance |
|
|
39
|
+
| Official `pluginManager.listBundles` / `inspect` | Installed state; the official pre-install check (resolves only, runs no code) |
|
|
40
|
+
| Official `pluginManager.installBundle` / `waitForInstall` / `cancelInstall` / `setBundleEnabled` | One-click install (disabled by default), cancel, separate enable; progress from `plugin-manager/install-state` and `install-log` events |
|
|
41
|
+
|
|
42
|
+
No third-party marketplace or aggregator is used.
|
|
43
|
+
|
|
44
|
+
**Crawling, measured (2026-10):** the topic holds about 19,000 repositories, 12,700 of them created in August, many of them same-name copies. GitHub search returns at most 1,000 results per query, so Scout bisects time windows adaptively (≤900 results per window, 60 s minimum window). Pages are 50 items: 100-item pages return 502 in dense windows, so on 502 the page size steps down to 25, then 10, resuming from the same cursor. Later runs crawl incrementally by `pushed`.
|
|
45
|
+
|
|
46
|
+
**Refresh is streaming and pays only for what changed:**
|
|
47
|
+
- **Newest first.** Windows are seeded geometrically (last 6 h / 1 d / 3 d / 1 w / 1 mo / 3 mo / older) and paged from the newest. Window counting and paging overlap (3 workers).
|
|
48
|
+
- **Publish while crawling.** Each page is merged into the record set immediately and published every 1.5 s; the UI reloads the list when `status.rev` changes. The previous index stays usable throughout. A checkpoint is written every 30 s.
|
|
49
|
+
- **Pay for change.** With an existing index, a light query fetches metadata only (100 per page, no blobs). Repositories whose `pushedAt` is unchanged keep their facts and only refresh stars and similar metadata; changed ones fetch `package.json` and the patch by node id in batches of 50.
|
|
50
|
+
- **npm in parallel.** npm lookups run alongside the GitHub crawl (8 workers), only for repositories with new pushes, missing entries, or entries older than one day. Entries older than 7 days are refreshed oldest first, at most 800 per run.
|
|
51
|
+
- **Activation does not wait for the index.** The ~30 MB index loads in the background; the UI first sees `loaded: false` and polls.
|
|
52
|
+
|
|
53
|
+
Measured on 2026-10-14 over a real network:
|
|
54
|
+
|
|
55
|
+
| Scenario | First results | Total | Notes |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| Incremental, 1,082 repos pushed | 4.5 s | 38 s | 125 refetched blobs, 963 metadata-only, 70 npm lookups |
|
|
58
|
+
| Cold full crawl | 6.7 s | — | ~1,000 plugins browsable within 60 s; the rest fill in the background |
|
|
59
|
+
|
|
60
|
+
## Checks and trust score
|
|
61
|
+
|
|
62
|
+
| Check | Rule | Points |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| V1 | Root `package.json` declares `dsh.bundle` / `dsh.client` (otherwise not a plugin) | 20 |
|
|
65
|
+
| V2 | Official peer rule: only `@deepseek-ai/dsh` and `@deepseek-ai/dsh-*`, `semver.satisfies(runtime, range, {includePrerelease})`, `workspace:*` means the running version. Inside the App, Scout calls `dsh-app-boot.evaluatePluginCompatibility` directly | covered 30 · no peers 10 · not covered 5 |
|
|
66
|
+
| V3 | Install hooks: preinstall / install / postinstall / prepare | none +15 · present −15 |
|
|
67
|
+
| V4 | Source chain: the same-name npm package's `repository` points back to this repo | match +15 · mismatch −20 · unpublished 0 |
|
|
68
|
+
| V5 | npm provenance | +10 |
|
|
69
|
+
| V6 | Activity: archived, pushed within 90 days, version drift (V6b) | +5 / −10 |
|
|
70
|
+
| V9 | Uses the `@deepseek-ai/` scope but the repo is not owned by deepseek-ai | −30 |
|
|
71
|
+
| V10 | Fork | note only |
|
|
72
|
+
| — | Stars: `min(5, round(log10(1+s)·2))` | ≤5 |
|
|
73
|
+
|
|
74
|
+
The total is clamped to 0–100. Any ✕ marks the plugin as **risky**: copying its spec or installing it takes two clicks, and its badge shows ✕. Repositories sharing a package name collapse under one representative, chosen by: matching source chain > score > stars > earliest creation. The rest are listed as copies, hidden by default.
|
|
75
|
+
|
|
76
|
+
Ten purpose categories: UI, session, memory, agent, tools, models, security, development, bridges, domain. A category is scored from the official packages a plugin depends on (highest weight), topics/keywords (3), and text (2); a plugin is categorized only with a score of at least 2. On 41 hand-labelled plugins, the top-1 category is correct for at least 35.
|
|
77
|
+
|
|
78
|
+
## UI and integration points
|
|
79
|
+
|
|
80
|
+
- **Discover page:** sidebar **发现插件** → `main` panel with search, filters (compatibility, risk, kind, installed state, copies), category chips, sorting and paging.
|
|
81
|
+
- **Details drawer:** checklist, score breakdown, category evidence, source chain and copies, surface (cordis inserts, `client.inject`, peers), and the official pre-install check. Footer:
|
|
82
|
+
- **Install / Enable / Cancel install**, as described above.
|
|
83
|
+
- **Copy pinned spec:** copies `name@npmVersion`, or `github:owner/repo` when unpublished.
|
|
84
|
+
- **Open in Plugins page / Add on Plugins page:** installed plugins open their official details via `pluginNavigation.openBundle`; others switch to the official Plugins page.
|
|
85
|
+
- **Official Plugins page:** `plugins.detail.badge` (trust score) and `plugins.detail.section` (checklist plus a link back to Scout). Packages missing from the index render `null`, taking no space.
|
|
86
|
+
|
|
87
|
+
## Development
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
npm install --ignore-scripts
|
|
91
|
+
npm test # builds lib/, then runs the core / host / client / manifest suites
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Local debugging: add this directory's absolute path on the Plugins page (a link install; do not move the directory). Host changes need a full App restart; client-only changes need a window reload.
|
|
95
|
+
|
|
96
|
+
**GitHub token**, in order: `DSH_SCOUT_GITHUB_TOKEN` / `GITHUB_TOKEN` / `GH_TOKEN`, or `gh auth token` run through the DSH subprocess service. The token stays in process memory: never written to disk, never sent to the browser. Without one, the page asks you to run `gh auth login`.
|
|
97
|
+
|
|
98
|
+
## Data and configuration
|
|
99
|
+
|
|
100
|
+
- Index: `~/.dsh/dsh-plugin-scout/index.json` stores facts only (repo metadata, slimmed manifests, npm cache) and is re-judged against the current runtime on every load, so compatibility verdicts follow DSH upgrades automatically.
|
|
101
|
+
- Auto refresh: an in-process timer checks 45 s after start and runs an incremental crawl when the index is older than `autoRefreshHours` (default 24; 0 disables). No LaunchAgent or external scheduler.
|
|
102
|
+
- Optional config: `dataDir`, `topic`, `runtimeVersion` (overrides runtime detection), `autoRefreshHours`.
|
|
103
|
+
|
|
104
|
+
## Security boundaries
|
|
105
|
+
|
|
106
|
+
- Routes live on DSH's own webServer (`/dsh-plugin-scout/api/*`). Every request must carry the custom header `x-dsh-plugin-scout: 1` and pass DSH `connection.admit` (Host/Origin fence plus browser auth). Without the `connection` service, requests are refused (fail closed).
|
|
107
|
+
- `cordis.patch.yml` is scanned for `name:` with a regex; YAML tags are never parsed. Crawled code is never executed and tarballs are never downloaded.
|
|
108
|
+
- Style tags carry `data-plugin` / `data-plugin-css` before entering the DOM. Only `--dsw-alias-*` tokens are used; class names avoid substrings that host skins target; the drawer does not use `role="dialog"`.
|
|
109
|
+
|
|
110
|
+
## Layout
|
|
111
|
+
|
|
112
|
+
- `src/core/`: `classify.mjs` (categories), `verify.mjs` (checks and score), `crawl.mjs` (GraphQL, windows, npm), `store.mjs` (fact index, queries).
|
|
113
|
+
- `src/host.mjs`: runtime and token detection, refresh state machine, same-origin routes, in-process timer.
|
|
114
|
+
- `src/client/`: Discover page, drawer, installer, official-page badge/section, styles.
|
|
115
|
+
- `scripts/build.mjs`: esbuild bundling; both artifacts are **executed** after writing, as the gate.
|
|
116
|
+
- `test/`: `core` (real GraphQL page, 41 labelled samples), `host` (fake-fetch end-to-end refresh, route auth), `client` (Happy DOM loading the built artifact), `manifest` (official packaging conventions).
|
|
117
|
+
|
|
118
|
+
After a DSH upgrade, re-check the official Plugins page slot names, the `pluginManager` methods, and the `dsh-app-boot` exports before re-accepting.
|
|
119
|
+
|
|
120
|
+
## Official conventions followed
|
|
121
|
+
|
|
122
|
+
Based on the official repository's `docs/user/develop/basic/publish`, `docs/cookbook/adding-a-package` §5, and the `@deepseek-ai/dsh-package-manifest` types; `test/manifest.test.mjs` asserts each one.
|
|
123
|
+
|
|
124
|
+
| Convention | This package |
|
|
125
|
+
| --- | --- |
|
|
126
|
+
| Bundle: `dsh.bundle.patch`; patch rows reference the package **by name** | `./cordis.patch.yml` → `name: 'dsh-plugin-scout'` |
|
|
127
|
+
| Only public author fields under `dsh` | `manifestVersion: 1`, `bundle`, `client` (`platform: web`) |
|
|
128
|
+
| Display metadata: `locale/en.json` is the entry, other languages use the same fields; export `./locale/*.json` and `./package.json`, and ship them | `meta.title` / `meta.description` in `en.json` and `zh.json` |
|
|
129
|
+
| Icon: relative path inside the package, ≤256 KiB, self-contained | `./icon.svg` |
|
|
130
|
+
| Packages sharing host instances are peers; the version gate reads only `@deepseek-ai/dsh*` peers | `@deepseek-ai/cordis ~4.0.4`; `@deepseek-ai/dsh-app-boot >=0.2.0-rc.2 <0.3.0` (optional, declares the range for the official gate) |
|
|
131
|
+
| `engines.dsh` is declarative | `>=0.2.0-rc.2 <0.3.0` |
|
|
132
|
+
| Ship prebuilt artifacts; never ask users to approve builds | Published to npm with `--provenance`; no `prepare` or other install hooks |
|
|
133
|
+
|
|
134
|
+
## Releasing
|
|
135
|
+
|
|
136
|
+
1. Bump `version` in `package.json` and commit.
|
|
137
|
+
2. `git tag v<version> && git push --tags`. The `release` workflow runs the tests, runs `npm publish --provenance`, and attaches the same tgz to a GitHub Release. npm authenticates the workflow through Trusted Publishing (OIDC), so no npm token is stored in the repository; provenance is attached automatically. One-time setup on npmjs.com → package Settings → Trusted Publisher (GitHub Actions, workflow `release.yml`), or: `npx npm@latest trust github dsh-plugin-scout --file release.yml --repo fegnze/dsh-plugin-scout --allow-publish`.
|
|
138
|
+
3. Keep the repository public with the `dsh-plugin` topic so it appears on https://github.com/topics/dsh-plugin and in Scout itself.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# DSH Plugin Scout · 发现插件
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
[](https://github.com/fegnze/dsh-plugin-scout/actions/workflows/ci.yml) · MIT
|
|
6
|
+
|
|
7
|
+
在 DeepSeek Harness 里发现并核验 GitHub `topic:dsh-plugin` 上的插件:按用途分类、按可信度排序、套用官方的 peer 兼容规则。适用 DSH **0.2.x**(`>=0.2.0-rc.2 <0.3.0`),实测版本为桌面版 0.2.0-rc.2。
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
官方「插件」页 → 添加插件,填入以下任一规格:
|
|
12
|
+
|
|
13
|
+
| 规格 | 说明 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| `dsh-plugin-scout` | 推荐。npm 预构建产物带 provenance,无安装脚本,不需要批准构建 |
|
|
16
|
+
| 下载 Release 里的 `dsh-plugin-scout-<版本>.tgz`,填它的绝对路径 | 不经 npm 注册表 |
|
|
17
|
+
|
|
18
|
+
命令行:`dsh plugin --profile <profile> add dsh-plugin-scout`。装好后在插件页启用,侧栏会出现「发现插件」。
|
|
19
|
+
|
|
20
|
+
不要用 `github:fegnze/dsh-plugin-scout` 安装:git 安装拿到的是源码,没有 `lib/`,本仓库也不提供 `prepare` 脚本。
|
|
21
|
+
|
|
22
|
+
## 一键安装,走官方安装器
|
|
23
|
+
|
|
24
|
+
抽屉里的「安装」与官方「添加插件」走同一条路径:先 `inspect` 预检,再 `installBundle(spec, {enabled:false, requestId, registry})`。插件**装好后默认不启用**,「启用」是单独一次点击(`setBundleEnabled`)。
|
|
25
|
+
|
|
26
|
+
- 有安装钩子或 peer 不覆盖当前版本的插件,「安装」要点两次才执行。
|
|
27
|
+
- 依赖的构建脚本被官方安装器拦下时(`pendingBuilds`),会逐个列出;双击「允许并重装」后才带 `approvedBuilds` 重装。
|
|
28
|
+
- 安装中可「取消安装」(`cancelInstall`,同一 `requestId`);回复丢失时用 `waitForInstall` 取回结果。失败时官方安装器自动回滚 `package.json` 和锁文件。
|
|
29
|
+
- **卸载、版本豁免仍只在官方「插件」页做**:本插件不调用 `removeBundle`,测试中一调用就失败。没有官方 pluginManager 时不显示「安装」按钮,退回「复制锁定规格 + 去插件页添加」。
|
|
30
|
+
|
|
31
|
+
## 数据来源(只用一手来源)
|
|
32
|
+
|
|
33
|
+
| 来源 | 用途 |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| GitHub GraphQL `search(topic:dsh-plugin)` | 仓库元数据、根 `package.json`、`cordis.patch.yml` 的文本(不求值) |
|
|
36
|
+
| `registry.npmjs.org/<name>/latest` | 实际会被安装的清单:peer、安装钩子、`repository`、provenance |
|
|
37
|
+
| 官方 `pluginManager.listBundles` / `inspect` | 已安装状态;添加前的官方预检(只解析,不执行代码) |
|
|
38
|
+
| 官方 `pluginManager.installBundle` / `waitForInstall` / `cancelInstall` / `setBundleEnabled` | 一键安装(默认不启用)、取消、单独启用;进度来自 `plugin-manager/install-state` 与 `install-log` 事件 |
|
|
39
|
+
|
|
40
|
+
不使用任何第三方插件市场或聚合站。
|
|
41
|
+
|
|
42
|
+
**抓取实测(2026-10)**:topic 下约有 1.9 万个仓库,其中 8 月集中出现 1.27 万个,大量是同名副本。GitHub 搜索单次查询最多返回 1000 条结果,所以按时间窗口自适应二分,每个窗口不超过 900 条,最小窗口 60 秒。每页 50 条:密集窗口里每页 100 条会返回 502,遇到 502 时依次降到 25、10,并从同一游标续翻。之后按 `pushed` 字段做增量抓取。
|
|
43
|
+
|
|
44
|
+
**刷新是流式、按变化量计费的**:
|
|
45
|
+
- **最新的先出。** 时间窗先按几何间隔播种(近 6 小时 / 1 天 / 3 天 / 1 周 / 1 月 / 3 月 / 更早),从最新一段开始翻。切窗计数与翻页并行跑(3 路)。
|
|
46
|
+
- **边抓边发布。** 每页结果立即并入记录集,每 1.5 秒发布一次,界面随 `status.rev` 变化重拉列表;刷新期间旧索引一直可用。每 30 秒落一次断点。
|
|
47
|
+
- **只为变化付费。** 已有索引时先走轻查询:只取元数据,每页 100 条,不读 blob。`pushedAt` 没变的仓库沿用已有事实,只刷新 star 等元数据;变动过的仓库才按 node id 每 50 个一批补取 `package.json` 和 patch。
|
|
48
|
+
- **npm 并行。** npm 查询与 GitHub 抓取同时进行(8 路)。只有仓库有新推送、npm 条目缺失或超过 1 天时才重查;超过 7 天的过期条目按最旧优先,每轮最多补 800 个。
|
|
49
|
+
- **激活不等索引。** 激活时不等待约 30 MB 的索引读完,界面先拿到 `loaded:false`,随后自行轮询。
|
|
50
|
+
|
|
51
|
+
实测(2026-10-14,真实网络):
|
|
52
|
+
|
|
53
|
+
| 场景 | 首批可见 | 总耗时 | 说明 |
|
|
54
|
+
|---|---|---|---|
|
|
55
|
+
| 增量,1082 个仓库有推送 | 4.5 s | 38 s | 125 个补 blob,963 个只刷新元数据,70 次 npm 查询 |
|
|
56
|
+
| 冷启动全量 | 6.7 s | — | 60 s 内已可浏览约 1000 个插件,其余在后台补齐 |
|
|
57
|
+
|
|
58
|
+
## 核验项与可信度
|
|
59
|
+
|
|
60
|
+
| 项 | 判定 | 分值 |
|
|
61
|
+
| --- | --- | --- |
|
|
62
|
+
| V1 | 根 `package.json` 声明 `dsh.bundle` / `dsh.client`(不满足的不算插件) | 20 |
|
|
63
|
+
| V2 | 官方 peer 规则:只看 `@deepseek-ai/dsh` 和 `@deepseek-ai/dsh-*`,`semver.satisfies(runtime, range, {includePrerelease})`,`workspace:*` 视为当前版本。在 App 内直接调用 `dsh-app-boot.evaluatePluginCompatibility` | 覆盖 30 · 无 peer 10 · 不覆盖 5 |
|
|
64
|
+
| V3 | 安装钩子:preinstall / install / postinstall / prepare | 无 +15 · 有 −15 |
|
|
65
|
+
| V4 | 来源链:npm 同名包的 `repository` 指回本仓库 | 一致 +15 · 不一致 −20 · 未发布 0 |
|
|
66
|
+
| V5 | npm provenance | +10 |
|
|
67
|
+
| V6 | 活跃度:归档、90 天内推送、版本漂移(V6b) | +5 / −10 |
|
|
68
|
+
| V9 | 用了 `@deepseek-ai/` 作用域,但仓库不属于 deepseek-ai | −30 |
|
|
69
|
+
| V10 | fork | 仅提示 |
|
|
70
|
+
| — | stars:`min(5, round(log10(1+s)·2))` | ≤5 |
|
|
71
|
+
|
|
72
|
+
总分截断到 0–100。任何一项为 ✕ 都记为「有风险」:复制规格要点两次,徽章上带 ✕。同名的多个仓库会折叠到同一个代表仓库下,选择顺序是:来源链一致 > 分数 > stars > 创建最早;其余仓库记为副本,默认隐藏。
|
|
73
|
+
|
|
74
|
+
用途分类共 10 类:界面、会话、记忆、Agent、工具、模型、安全、开发、桥接、领域。分类依据是依赖的官方包(权重最高)、topics/keywords(3 分)和文本(2 分),总分不低于 2 才归类。在 41 个人工标注样本上,第一类命中率不低于 35/41。
|
|
75
|
+
|
|
76
|
+
## 界面与接缝
|
|
77
|
+
|
|
78
|
+
- **发现页**:侧栏「发现插件」→ `main` 面板,内容包括搜索、筛选(兼容、风险、形态、安装状态、副本)、分类条、排序和分页。
|
|
79
|
+
- **详情抽屉**:核验清单、评分构成、分类依据、来源链与副本、作用面(cordis 插入、`client.inject`、peer),以及官方预检。底部按钮:
|
|
80
|
+
- **安装 / 启用 / 取消安装**:见上文。
|
|
81
|
+
- **复制锁定规格**:复制 `name@npmVersion`;未发布的复制 `github:owner/repo`。
|
|
82
|
+
- **在插件页打开 / 去插件页添加**:已安装的通过官方 `pluginNavigation.openBundle` 直达详情;未安装的切到官方插件页,粘贴规格即可添加。
|
|
83
|
+
- **官方插件页**:`plugins.detail.badge`(可信度分数)、`plugins.detail.section`(核验清单,以及「在发现页查看 →」)。索引里没有的包返回 `null`,不占位。
|
|
84
|
+
|
|
85
|
+
## 开发
|
|
86
|
+
|
|
87
|
+
```sh
|
|
88
|
+
npm install --ignore-scripts
|
|
89
|
+
npm test # 先构建 lib/,再跑 core / host / client / manifest 四组测试
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
本地调试:在插件页添加本目录的绝对路径(link 安装,源目录不能移动)。Host 侧有改动时需要完整重启 App;只改了 Client 时刷新窗口即可。
|
|
93
|
+
|
|
94
|
+
**GitHub token** 依次从这些地方取:环境变量 `DSH_SCOUT_GITHUB_TOKEN` / `GITHUB_TOKEN` / `GH_TOKEN`,或通过 DSH subprocess 服务执行 `gh auth token`。token 只在本进程内存里使用,不落盘、不回传给前端。没有 token 时页面会提示执行 `gh auth login`。
|
|
95
|
+
|
|
96
|
+
## 数据与配置
|
|
97
|
+
|
|
98
|
+
- 索引:`~/.dsh/dsh-plugin-scout/index.json`,只存事实(仓库元数据、精简清单、npm 缓存),每次加载按当前运行时重新判定。所以升级 DSH 后,兼容结论会自动更新。
|
|
99
|
+
- 自动刷新:App 运行期间由进程内定时器执行,启动 45 秒后检查一次,超过 `autoRefreshHours`(默认 24,设为 0 关闭)就做增量抓取。不使用 LaunchAgent 或外部调度器。
|
|
100
|
+
- 可选配置:`dataDir`、`topic`、`runtimeVersion`(覆盖运行时探测)、`autoRefreshHours`。
|
|
101
|
+
|
|
102
|
+
## 安全边界
|
|
103
|
+
|
|
104
|
+
- 接口挂在 DSH 自己的 webServer 上(`/dsh-plugin-scout/api/*`)。每个请求都要带自定义头 `x-dsh-plugin-scout: 1`,并通过 DSH `connection.admit`(Host/Origin 栅栏 + 浏览器认证)。拿不到 `connection` 服务时拒绝请求(fail closed)。
|
|
105
|
+
- `cordis.patch.yml` 只用正则提取 `name:`,从不解析 YAML 标签。抓取到的代码不执行,也不下载 tarball。
|
|
106
|
+
- 样式标签在插入 DOM 之前就打上 `data-plugin` / `data-plugin-css`。只使用 `--dsw-alias-*` 令牌;类名避开宿主皮肤会匹配的子串;抽屉不用 `role="dialog"`。
|
|
107
|
+
|
|
108
|
+
## 结构
|
|
109
|
+
|
|
110
|
+
- `src/core/`:`classify.mjs`(用途分类)、`verify.mjs`(核验与评分)、`crawl.mjs`(GraphQL、切窗、npm)、`store.mjs`(事实索引、查询)。
|
|
111
|
+
- `src/host.mjs`:运行时与 token 探测、刷新状态机、同源路由、进程内定时。
|
|
112
|
+
- `src/client/`:发现页、抽屉、安装器、官方页徽章/区块、样式。
|
|
113
|
+
- `scripts/build.mjs`:esbuild 打包,打包后**实际执行**两份产物来把关。
|
|
114
|
+
- `test/`:`core`(真实 GraphQL 页、41 个标注样本)、`host`(假 fetch 端到端刷新、路由鉴权)、`client`(Happy DOM 加载构建产物)、`manifest`(官方发布约定)。
|
|
115
|
+
|
|
116
|
+
升级 DSH 后,先核对官方插件页的 Slot 名、`pluginManager` 方法和 `dsh-app-boot` 导出,再重新验收。
|
|
117
|
+
|
|
118
|
+
## 对齐的官方约定
|
|
119
|
+
|
|
120
|
+
依据官方仓库的 `docs/user/develop/basic/publish`、`docs/cookbook/adding-a-package` §5 和 `@deepseek-ai/dsh-package-manifest` 类型;`test/manifest.test.mjs` 逐条断言。
|
|
121
|
+
|
|
122
|
+
| 约定 | 本包 |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| 组合包:`dsh.bundle.patch`,patch 行按**包名**引用 | `./cordis.patch.yml` → `name: 'dsh-plugin-scout'` |
|
|
125
|
+
| `dsh` 下只放公共作者字段 | `manifestVersion: 1`、`bundle`、`client`(`platform: web`) |
|
|
126
|
+
| 展示元信息:`locale/en.json` 为入口,其他语言同字段;导出 `./locale/*.json`、`./package.json` 并发布 | `en.json` / `zh.json` 的 `meta.title`、`meta.description` |
|
|
127
|
+
| 图标:包内相对路径,≤256 KiB,自包含 | `./icon.svg` |
|
|
128
|
+
| 需要与宿主共享实例的包写进 peer;版本门禁只看 `@deepseek-ai/dsh*` peer | `@deepseek-ai/cordis ~4.0.4`;`@deepseek-ai/dsh-app-boot >=0.2.0-rc.2 <0.3.0`(optional,作为官方门禁的版本声明) |
|
|
129
|
+
| `engines.dsh` 只是声明 | `>=0.2.0-rc.2 <0.3.0` |
|
|
130
|
+
| 发预构建产物,不让用户批准构建 | npm `--provenance` 发布,无 `prepare` 及其他安装钩子 |
|
|
131
|
+
|
|
132
|
+
## 发布
|
|
133
|
+
|
|
134
|
+
1. 改 `package.json` 的 `version`,提交。
|
|
135
|
+
2. `git tag v<version> && git push --tags`。`release` 工作流会跑测试,执行 `npm publish --provenance`,并把同一个 tgz 挂到 GitHub Release。npm 通过可信发布(Trusted Publishing,OIDC)认证工作流,仓库里不存 npm token,provenance 自动附带。一次性配置:npmjs.com → 包 Settings → Trusted Publisher(GitHub Actions,工作流 `release.yml`),或:`npx npm@latest trust github dsh-plugin-scout --file release.yml --repo fegnze/dsh-plugin-scout --allow-publish`。
|
|
136
|
+
3. 仓库保持 public,并带 topic `dsh-plugin`,这样才会出现在 https://github.com/topics/dsh-plugin,也能被 Scout 自己收录。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bundle layer for DSH Plugin Scout: mounts the host routes and the browser half.
|
|
2
|
+
# Installing goes through the official pluginManager (installBundle, disabled by
|
|
3
|
+
# default); uninstalling and version exemptions stay on the official Plugins page.
|
|
4
|
+
- insert:
|
|
5
|
+
- id: dsh-plugin-scout
|
|
6
|
+
name: 'dsh-plugin-scout'
|
package/icon.svg
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="scout-g" x1="7" y1="7" x2="29" y2="29" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#58BCC8"/>
|
|
5
|
+
<stop offset="0.55" stop-color="#658EFF"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<circle cx="16" cy="16" r="8.2" stroke="url(#scout-g)" stroke-width="2.2"/>
|
|
9
|
+
<path d="M22.2 22.2L28.4 28.4" stroke="url(#scout-g)" stroke-width="2.6" stroke-linecap="round"/>
|
|
10
|
+
<path d="M13.2 12.6h5.6v2.1a1.3 1.3 0 1 1 0 2.6v2.1h-5.6v-2.1a1.3 1.3 0 1 0 0-2.6z" fill="url(#scout-g)"/>
|
|
11
|
+
</svg>
|