@klarkxy/dsh-dev-index 0.2.5 → 0.2.7
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/README.md +4 -3
- package/README.zh-CN.md +7 -6
- package/client.js +3 -3
- package/dsh.plugin.json +1 -1
- package/lib/gh.js +2 -2
- package/lib/github.d.ts +3 -1
- package/lib/github.js +32 -15
- package/package.json +17 -11
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[简体中文](README.zh-CN.md)
|
|
6
6
|
|
|
7
|
-
Read the official DeepSeek Harness
|
|
7
|
+
Read the official DeepSeek Harness docs without leaving DSH, and give Creator mode tools to look up docs and check plugins before installing them.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
@@ -17,14 +17,15 @@ Replace `web` with your profile name and restart the profile.
|
|
|
17
17
|
## Use
|
|
18
18
|
|
|
19
19
|
- **Plugins → DSH Docs** shows the [official documentation site](https://deepseek-harness.github.io/deepseek-harness/) inside DSH, with a Chinese / English switch.
|
|
20
|
-
- In Creator mode the agent gets five read-only tools: `dsh_docs_search` and `dsh_docs_fetch` to find and read official docs
|
|
20
|
+
- In Creator mode the agent gets five read-only tools: `dsh_docs_search` and `dsh_docs_fetch` to find and read official docs; `dsh_plugins_search` and `dsh_plugins_fetch` to check a plugin's npm information before installing it (search sources: catalog, npm or GitHub repositories); and `dsh_github_fetch` to inspect a GitHub plugin repository and pin its branch to an exact commit. Creator mode is also reminded to verify runtime interfaces with `cordis_inspect_list` and `cordis_inspect_query`.
|
|
21
21
|
|
|
22
22
|
## Limits
|
|
23
23
|
|
|
24
24
|
- The tools only read; they never install anything. Installing stays with the DSH plugin manager.
|
|
25
25
|
- The website follows the latest DSH release, which may differ from the version you run.
|
|
26
26
|
- npm metadata is not proof that a plugin works with your DSH.
|
|
27
|
-
- GitHub data comes from your local signed-in gh CLI or anonymous API access (a small hourly quota); the plugin stores no GitHub credentials. Manifest-based code search
|
|
27
|
+
- GitHub data comes from your local signed-in gh CLI or anonymous API access (a small hourly quota); the plugin stores no GitHub credentials. Manifest-based code search works only when gh is signed in.
|
|
28
|
+
- Cancelling the last request using a GitHub CLI check waits for that check to stop; unloading the plugin waits for its active GitHub requests and CLI processes to finish.
|
|
28
29
|
|
|
29
30
|
## Install from GitHub
|
|
30
31
|
|
package/README.zh-CN.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[English](README.md)
|
|
6
6
|
|
|
7
|
-
不离开 DSH 就能阅读 DeepSeek Harness
|
|
7
|
+
不离开 DSH 就能阅读 DeepSeek Harness 官方文档;创造模式还会获得查文档、安装前核对插件的工具。
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
10
10
|
|
|
@@ -16,15 +16,16 @@ dsh plugin --profile web add @klarkxy/dsh-dev-index
|
|
|
16
16
|
|
|
17
17
|
## 使用
|
|
18
18
|
|
|
19
|
-
- 「插件 → DSH
|
|
20
|
-
- 创造模式下,智能体获得五个只读工具:`dsh_docs_search` 和 `dsh_docs_fetch`
|
|
19
|
+
- 「插件 → DSH 文档」在 DSH 内显示[官方文档站](https://deepseek-harness.github.io/deepseek-harness/),可切换中文 / English。
|
|
20
|
+
- 创造模式下,智能体获得五个只读工具:`dsh_docs_search` 和 `dsh_docs_fetch` 用于查找和阅读官方文档;`dsh_plugins_search` 和 `dsh_plugins_fetch` 用于在安装前查看插件的 npm 信息(搜索源可选 catalog、npm 或 GitHub 仓库);`dsh_github_fetch` 用于查看 GitHub 插件仓库的元数据并把分支解析成可锁定的 commit。创造模式还会被提醒用 `cordis_inspect_list` 和 `cordis_inspect_query` 核对运行时接口。
|
|
21
21
|
|
|
22
22
|
## 限制
|
|
23
23
|
|
|
24
|
-
-
|
|
24
|
+
- 这些工具只读,不安装任何东西;安装仍由 DSH 插件管理器负责。
|
|
25
25
|
- 官网对应最新发布的 DSH,可能与你正在使用的版本不同。
|
|
26
26
|
- npm 元数据不能证明插件与你的 DSH 兼容。
|
|
27
|
-
- GitHub 数据来自本机已登录的 gh CLI 或匿名 API(匿名额度有限,约每小时几十次请求);插件不保存任何 GitHub 凭据。按 `dsh.plugin.json`
|
|
27
|
+
- GitHub 数据来自本机已登录的 gh CLI 或匿名 API(匿名额度有限,约每小时几十次请求);插件不保存任何 GitHub 凭据。按 `dsh.plugin.json` 清单的代码搜索仅在 gh 已登录时可用。
|
|
28
|
+
- 取消最后一个使用 GitHub CLI 检查的请求时,会等待该检查停止;卸载插件会等待正在进行的 GitHub 请求和 CLI 进程结束。
|
|
28
29
|
|
|
29
30
|
## 从 GitHub 安装
|
|
30
31
|
|
|
@@ -32,7 +33,7 @@ dsh plugin --profile web add @klarkxy/dsh-dev-index
|
|
|
32
33
|
dsh plugin --profile web add "github:klarkxy/dsh-plugins#path:/plugins/dsh-dev-index"
|
|
33
34
|
```
|
|
34
35
|
|
|
35
|
-
从 GitHub 安装会在本机构建插件,pnpm 会先要求你允许。把下面内容加入 `$DSH_HOME/profiles/web/pnpm-workspace.yaml`
|
|
36
|
+
从 GitHub 安装会在本机构建插件,pnpm 会先要求你允许。把下面内容加入 `$DSH_HOME/profiles/web/pnpm-workspace.yaml` 后,再执行一次安装命令:
|
|
36
37
|
|
|
37
38
|
```yaml
|
|
38
39
|
allowBuilds:
|
package/client.js
CHANGED
|
@@ -26,7 +26,7 @@ const css = `
|
|
|
26
26
|
& *, & *::before, & *::after { box-sizing: border-box; }
|
|
27
27
|
& h1, & h2, & h3, & h4, & p, & figure { margin: 0; }
|
|
28
28
|
/* Keyboard focus only: pointer input keeps the native resting appearance. */
|
|
29
|
-
& :focus-visible { outline: var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); outline-offset: 2px;
|
|
29
|
+
& :focus-visible { outline: var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); outline-offset: 2px; }
|
|
30
30
|
& [hidden] { display: none !important; }
|
|
31
31
|
|
|
32
32
|
/* --- Type tiers. The same 14/22 and 12/18 steps the primitives use. --- */
|
|
@@ -36,7 +36,7 @@ const css = `
|
|
|
36
36
|
/* --- Layout scaffolding. Each recipe also matches the root itself, because
|
|
37
37
|
* this plugin's one surface carries the root class and the stack on the same
|
|
38
38
|
* element; a descendant-only rule would leave it unstyled. --- */
|
|
39
|
-
&.dsh-ui-
|
|
39
|
+
&.dsh-ui-page, & .dsh-ui-page { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 760px; min-width: 0; }
|
|
40
40
|
&.dsh-ui-row-wrap, & .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
|
|
41
41
|
&.dsh-ui-spacer, & .dsh-ui-spacer { flex: 1; min-width: 0; }
|
|
42
42
|
|
|
@@ -116,7 +116,7 @@ const css = `
|
|
|
116
116
|
|
|
117
117
|
return h('section', {
|
|
118
118
|
'aria-label': chinese ? 'DSH 文档浏览器' : 'DSH documentation browser',
|
|
119
|
-
className: 'dsh-di-root dsh-ui-
|
|
119
|
+
className: 'dsh-di-root dsh-ui-page',
|
|
120
120
|
},
|
|
121
121
|
h('style', null, css),
|
|
122
122
|
h('div', { className: 'dsh-ui-row-wrap' },
|
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "@klarkxy/dsh-dev-index",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "DSH Docs: read the official DSH documentation in the Plugins page; Creator mode searches docs and checks plugin metadata on npm and GitHub with native tools.",
|
|
6
6
|
"engines": {
|
package/lib/gh.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { access } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { delimiter, join } from "node:path";
|
|
4
|
-
import { runCli } from "@klarkxy/dsh-plugin-kit/cli-process";
|
|
4
|
+
import { cliEnvironment, runCli } from "@klarkxy/dsh-plugin-kit/cli-process";
|
|
5
5
|
// gh api and gh auth status are long-stable subcommands; the floor only rejects
|
|
6
6
|
// truly ancient binaries.
|
|
7
7
|
export const MIN_GH_VERSION = [2, 0, 0];
|
|
@@ -28,7 +28,7 @@ export async function findGh(deps = {}) {
|
|
|
28
28
|
const candidate = join(dir, file);
|
|
29
29
|
try {
|
|
30
30
|
await access(candidate);
|
|
31
|
-
return { command: candidate, displayPath: candidate };
|
|
31
|
+
return { command: candidate, displayPath: candidate, env: cliEnvironment(process.env, ["GH_TOKEN", "GITHUB_TOKEN", "GH_ENTERPRISE_TOKEN", "GITHUB_ENTERPRISE_TOKEN", "GH_HOST", "GH_CONFIG_DIR"]) };
|
|
32
32
|
}
|
|
33
33
|
catch { /* keep looking */ }
|
|
34
34
|
}
|
package/lib/github.d.ts
CHANGED
|
@@ -37,7 +37,9 @@ export declare class GitHubClient {
|
|
|
37
37
|
private readonly run;
|
|
38
38
|
private readonly discoverProbe;
|
|
39
39
|
constructor(deps?: GitHubDeps);
|
|
40
|
-
|
|
40
|
+
private readonly work;
|
|
41
|
+
private track;
|
|
42
|
+
dispose(): Promise<void>;
|
|
41
43
|
private abandonProbe;
|
|
42
44
|
private ghBroken;
|
|
43
45
|
private merged;
|
package/lib/github.js
CHANGED
|
@@ -262,9 +262,19 @@ export class GitHubClient {
|
|
|
262
262
|
this.run = deps.run ?? runCli;
|
|
263
263
|
this.discoverProbe = deps.discover ?? ((signal) => probeGh({ run: this.run }, signal));
|
|
264
264
|
}
|
|
265
|
-
|
|
265
|
+
work = new Set();
|
|
266
|
+
track(work) {
|
|
267
|
+
this.work.add(work);
|
|
268
|
+
void work.then(() => this.work.delete(work), () => this.work.delete(work));
|
|
269
|
+
return work;
|
|
270
|
+
}
|
|
271
|
+
async dispose() {
|
|
266
272
|
this.lifetime.abort();
|
|
273
|
+
this.confirmedProbe = undefined;
|
|
267
274
|
this.abandonProbe(this.pendingProbe);
|
|
275
|
+
// Includes abandoned probes: their caller may already have stopped waiting.
|
|
276
|
+
while (this.work.size)
|
|
277
|
+
await Promise.allSettled([...this.work]);
|
|
268
278
|
}
|
|
269
279
|
// Detach and cancel a probe nobody wants any more, releasing its listener. Its
|
|
270
280
|
// late resolution is rejected by the publish gate in startProbe.
|
|
@@ -288,8 +298,8 @@ export class GitHubClient {
|
|
|
288
298
|
merged(signal) {
|
|
289
299
|
return AbortSignal.any([this.lifetime.signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS), ...(signal ? [signal] : [])]);
|
|
290
300
|
}
|
|
291
|
-
// Resolve gh for one caller:
|
|
292
|
-
//
|
|
301
|
+
// Resolve gh for one caller: a peer can keep the shared probe alive, while
|
|
302
|
+
// the final cancelled waiter must await cleanup. An already-aborted caller
|
|
293
303
|
// never spawns discovery. The throw runs inside the promise so no caller can
|
|
294
304
|
// observe a partially started probe.
|
|
295
305
|
probe(signal) {
|
|
@@ -298,8 +308,9 @@ export class GitHubClient {
|
|
|
298
308
|
if (this.confirmedProbe)
|
|
299
309
|
return this.confirmedProbe;
|
|
300
310
|
const pending = this.pendingProbe ?? this.startProbe();
|
|
301
|
-
|
|
302
|
-
|
|
311
|
+
const waiter = { signal };
|
|
312
|
+
pending.waiters.add(waiter);
|
|
313
|
+
return this.awaitProbe(pending, waiter);
|
|
303
314
|
});
|
|
304
315
|
}
|
|
305
316
|
startProbe() {
|
|
@@ -309,7 +320,7 @@ export class GitHubClient {
|
|
|
309
320
|
// probes do not accumulate listeners on the lifetime signal.
|
|
310
321
|
this.lifetime.signal.addEventListener("abort", onLifetimeAbort, { once: true });
|
|
311
322
|
const probe = {
|
|
312
|
-
controller, waiters:
|
|
323
|
+
controller, waiters: new Set(), promise: Promise.resolve(null), onLifetimeAbort,
|
|
313
324
|
};
|
|
314
325
|
// Discovery runs inside the promise chain so a synchronous throw is folded
|
|
315
326
|
// into the same catch/finally: the listener is always released, pendingProbe
|
|
@@ -322,7 +333,8 @@ export class GitHubClient {
|
|
|
322
333
|
.then((found) => {
|
|
323
334
|
// Publish only from the current, live probe: an abandoned, cancelled or
|
|
324
335
|
// disposed probe may still resolve late and must not overwrite the cache.
|
|
325
|
-
if (found && this.pendingProbe === probe && !controller.signal.aborted && !this.lifetime.signal.aborted
|
|
336
|
+
if (found && this.pendingProbe === probe && !controller.signal.aborted && !this.lifetime.signal.aborted
|
|
337
|
+
&& [...probe.waiters].some(waiter => !waiter.signal.aborted)) {
|
|
326
338
|
this.confirmedProbe = found;
|
|
327
339
|
}
|
|
328
340
|
return found;
|
|
@@ -334,12 +346,14 @@ export class GitHubClient {
|
|
|
334
346
|
this.pendingProbe = undefined;
|
|
335
347
|
});
|
|
336
348
|
this.pendingProbe = probe;
|
|
349
|
+
this.track(probe.promise);
|
|
337
350
|
return probe;
|
|
338
351
|
}
|
|
339
352
|
// Race the shared probe against this caller's cancellation. A null result falls
|
|
340
|
-
// through to anonymous access as before.
|
|
341
|
-
//
|
|
342
|
-
async awaitProbe(probe,
|
|
353
|
+
// through to anonymous access as before. The last cancelled waiter abandons
|
|
354
|
+
// and drains the probe, while a peer keeps it alive.
|
|
355
|
+
async awaitProbe(probe, waiter) {
|
|
356
|
+
const { signal } = waiter;
|
|
343
357
|
let onAbort;
|
|
344
358
|
let settled = false;
|
|
345
359
|
try {
|
|
@@ -357,9 +371,11 @@ export class GitHubClient {
|
|
|
357
371
|
finally {
|
|
358
372
|
if (onAbort)
|
|
359
373
|
signal.removeEventListener("abort", onAbort);
|
|
360
|
-
probe.waiters
|
|
361
|
-
if (!settled && probe.waiters
|
|
374
|
+
probe.waiters.delete(waiter);
|
|
375
|
+
if (!settled && probe.waiters.size === 0) {
|
|
362
376
|
this.abandonProbe(probe);
|
|
377
|
+
await probe.promise;
|
|
378
|
+
}
|
|
363
379
|
}
|
|
364
380
|
}
|
|
365
381
|
async request(path, signal) {
|
|
@@ -369,14 +385,14 @@ export class GitHubClient {
|
|
|
369
385
|
merged.throwIfAborted();
|
|
370
386
|
if (probe) {
|
|
371
387
|
try {
|
|
372
|
-
return { data: await this.viaGh(probe.executable, path, signal), transport: "gh" };
|
|
388
|
+
return { data: await this.track(this.viaGh(probe.executable, path, signal)), transport: "gh" };
|
|
373
389
|
}
|
|
374
390
|
catch (error) {
|
|
375
391
|
if (!this.ghBroken(error))
|
|
376
392
|
throw error;
|
|
377
393
|
}
|
|
378
394
|
}
|
|
379
|
-
return { data: await this.viaHttp(path, signal), transport: "anonymous" };
|
|
395
|
+
return { data: await this.track(this.viaHttp(path, signal)), transport: "anonymous" };
|
|
380
396
|
}
|
|
381
397
|
async viaGh(executable, path, signal) {
|
|
382
398
|
const merged = this.merged(signal);
|
|
@@ -393,6 +409,7 @@ export class GitHubClient {
|
|
|
393
409
|
}
|
|
394
410
|
throw error;
|
|
395
411
|
}
|
|
412
|
+
merged.throwIfAborted();
|
|
396
413
|
if (result.exitCode !== 0)
|
|
397
414
|
throw classifyGhFailure(result.stderr);
|
|
398
415
|
try {
|
|
@@ -521,7 +538,7 @@ export class GitHubClient {
|
|
|
521
538
|
const path = `search/code?q=${encodeURIComponent(query)}&per_page=${PER_PAGE}&page=${page}`;
|
|
522
539
|
let data;
|
|
523
540
|
try {
|
|
524
|
-
data = await this.viaGh(probe.executable, path, signal);
|
|
541
|
+
data = await this.track(this.viaGh(probe.executable, path, signal));
|
|
525
542
|
}
|
|
526
543
|
catch (error) {
|
|
527
544
|
this.ghBroken(error); // code search has no anonymous lane, but the next call re-probes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@klarkxy/dsh-dev-index",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "DSH Docs: read the official DSH documentation in the Plugins page; Creator mode searches docs and checks plugin metadata on npm and GitHub with native tools.",
|
|
5
5
|
"icon": "./icon.svg",
|
|
6
6
|
"keywords": [
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"url": "https://github.com/klarkxy"
|
|
25
25
|
},
|
|
26
26
|
"type": "module",
|
|
27
|
-
"packageManager": "pnpm@
|
|
27
|
+
"packageManager": "pnpm@11.28.5",
|
|
28
28
|
"main": "lib/index.js",
|
|
29
29
|
"types": "lib/index.d.ts",
|
|
30
30
|
"exports": {
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"@deepseek-ai/dsh-tools": ">=0.2.0-rc.2"
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"@klarkxy/dsh-plugin-kit": "0.
|
|
83
|
+
"@klarkxy/dsh-plugin-kit": "0.5.0"
|
|
84
84
|
},
|
|
85
85
|
"peerDependenciesMeta": {
|
|
86
86
|
"@deepseek-ai/dsh-agent-preset-registry": {
|
|
@@ -91,22 +91,28 @@
|
|
|
91
91
|
},
|
|
92
92
|
"@deepseek-ai/dsh-tools": {
|
|
93
93
|
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@deepseek-ai/cordis": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@deepseek-ai/schemastery": {
|
|
99
|
+
"optional": true
|
|
94
100
|
}
|
|
95
101
|
},
|
|
96
102
|
"devDependencies": {
|
|
97
|
-
"@deepseek-ai/cordis": "4.0.
|
|
98
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
99
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.2.
|
|
100
|
-
"@deepseek-ai/dsh-agent-preset-registry": "0.2.
|
|
101
|
-
"@deepseek-ai/dsh-system-prompt": "0.2.
|
|
102
|
-
"@deepseek-ai/dsh-tools": "0.2.
|
|
103
|
-
"@deepseek-ai/dsh-scope": "0.2.
|
|
103
|
+
"@deepseek-ai/cordis": "4.0.5",
|
|
104
|
+
"@deepseek-ai/schemastery": "3.18.5",
|
|
105
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.1",
|
|
106
|
+
"@deepseek-ai/dsh-agent-preset-registry": "0.2.1-rc.1",
|
|
107
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-tools": "0.2.1-rc.1",
|
|
109
|
+
"@deepseek-ai/dsh-scope": "0.2.1-rc.1"
|
|
104
110
|
},
|
|
105
111
|
"publishConfig": {
|
|
106
112
|
"access": "public",
|
|
107
113
|
"registry": "https://registry.npmjs.org/"
|
|
108
114
|
},
|
|
109
115
|
"dshRelease": {
|
|
110
|
-
"contentHash": "
|
|
116
|
+
"contentHash": "a2daf4a6e10ea93df0733a844d8e8eee52a8d946908b0efec797b1dec2467896"
|
|
111
117
|
}
|
|
112
118
|
}
|