dsh-deeptutor 0.1.6 → 0.1.8

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/cordis.patch.yml CHANGED
@@ -1,17 +1,17 @@
1
- # dsh-deeptutor bundle patch: inserts the DeepTutor bridge plugin.
2
- #
3
- # Mount into a profile either by adding "dsh-deeptutor" to the profile's
4
- # `dsh.profile.bundles` list (recommended), or by inserting the same row
5
- # through a user patch layer:
6
- #
7
- # - insert:
8
- # - id: dsh-deeptutor
9
- # name: 'dsh-deeptutor'
10
- #
11
- # The `name` is the npm package itself; the loader resolves it from the
12
- # profile's node_modules (installed via `dsh plugin` or the profile's own
13
- # package manager).
14
-
15
- - insert:
16
- - id: dsh-deeptutor
17
- name: 'dsh-deeptutor'
1
+ # dsh-deeptutor bundle patch: inserts the DeepTutor bridge plugin.
2
+ #
3
+ # Mount into a profile either by adding "dsh-deeptutor" to the profile's
4
+ # `dsh.profile.bundles` list (recommended), or by inserting the same row
5
+ # through a user patch layer:
6
+ #
7
+ # - insert:
8
+ # - id: dsh-deeptutor
9
+ # name: 'dsh-deeptutor'
10
+ #
11
+ # The `name` is the npm package itself; the loader resolves it from the
12
+ # profile's node_modules (installed via `dsh plugin` or the profile's own
13
+ # package manager).
14
+
15
+ - insert:
16
+ - id: dsh-deeptutor
17
+ name: 'dsh-deeptutor'
package/lib/config.js CHANGED
@@ -44,6 +44,7 @@ export function configGuide() {
44
44
  ' export DEEPTUTOR_REMOTE_HOME="remote-DEEPTUTOR_HOME-workspace"\n' +
45
45
  " Verify serve is running on the server (ssh to it: curl http://127.0.0.1:8001/api/v1/system/status)\n" +
46
46
  " Verify passwordless SSH login works (ssh alias + BatchMode)\n" +
47
+ 'PowerShell users: use $env:VAR="value" instead of export VAR=value.\n' +
47
48
  "Restart the agent after configuring.\n");
48
49
  }
49
50
  export const CAPABILITIES = [
package/lib/http-api.js CHANGED
@@ -31,6 +31,7 @@ export async function ensureApi() {
31
31
  return true;
32
32
  if (!SSH_HOST)
33
33
  return false; // Local deployment: fall back to local CLI when serve is down, no tunnel needed
34
+ let tunnelDead = false;
34
35
  if (!tunnelProc || tunnelProc.exitCode !== null) {
35
36
  tunnelProc = spawn("ssh", [
36
37
  "-N",
@@ -48,9 +49,17 @@ export async function ensureApi() {
48
49
  "ConnectTimeout=10",
49
50
  SSH_HOST,
50
51
  ], { stdio: "ignore", windowsHide: true });
52
+ // Fast-fail: a tunnel that exits immediately (bad alias, port in use,
53
+ // refused connection) is not going to recover — stop waiting for it.
54
+ tunnelProc.once("exit", () => {
55
+ tunnelDead = true;
56
+ tunnelProc = null;
57
+ });
51
58
  tunnelProc.unref();
52
59
  }
53
60
  for (let i = 0; i < 20; i++) {
61
+ if (tunnelDead)
62
+ return false;
54
63
  if (await apiProbe(1000))
55
64
  return true;
56
65
  await new Promise((r) => setTimeout(r, 500));
@@ -62,7 +71,15 @@ export async function apiJson(path, init, opts = {}) {
62
71
  const controller = new AbortController();
63
72
  const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 60_000);
64
73
  const onAbort = () => controller.abort();
65
- opts.signal?.addEventListener("abort", onAbort, { once: true });
74
+ // An already-aborted signal never fires its "abort" event again — check the
75
+ // flag first so a pre-aborted call fails immediately instead of running to
76
+ // completion against a still-open controller.
77
+ if (opts.signal?.aborted) {
78
+ controller.abort();
79
+ }
80
+ else {
81
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
82
+ }
66
83
  try {
67
84
  const res = await fetch(`${API_BASE}${path}`, { ...init, signal: controller.signal });
68
85
  if (!res.ok)
package/lib/index.js CHANGED
@@ -127,6 +127,10 @@ export function apply(ctx) {
127
127
  });
128
128
  }
129
129
  catch (err) {
130
+ if (exec.signal.aborted) {
131
+ // user cancelled mid-CLI-run: report it as a cancellation, not a failure
132
+ throw new Error("[deeptutor_run cancelled]");
133
+ }
130
134
  throw new Error(configGuide() +
131
135
  `[deeptutor_run failed (HTTP and CLI both unavailable)] ${err?.message ?? String(err)}`);
132
136
  }
package/lib/turn.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { runCli } from "./cli-exec.ts";
1
2
  export interface TurnResult {
2
3
  answer: string;
3
4
  errors: string[];
@@ -19,6 +20,13 @@ export interface RunParams {
19
20
  export declare function collectEvent(state: TurnResult, e: any): void;
20
21
  /** Execute one turn over WebSocket (streaming). */
21
22
  export declare function wsRunTurn(params: RunParams, timeoutMs: number, signal?: AbortSignal): Promise<TurnResult>;
22
- /** Execute one turn via the CLI (local or SSH). */
23
- export declare function cliRunTurn(params: RunParams, timeoutMs: number, signal?: AbortSignal): Promise<TurnResult>;
23
+ /**
24
+ * Build the `deeptutor run` argv for a capability turn (pure, unit-tested).
25
+ * Scalar config values go as repeatable --config k=v; object/array values are
26
+ * collected into --config-json (the CLI's documented form for complex config)
27
+ * instead of being stringified into a k=<json> value that no parser expects.
28
+ */
29
+ export declare function buildRunArgs(params: RunParams): string[];
30
+ /** Execute one turn via the CLI (local or SSH). `run` is injectable for tests. */
31
+ export declare function cliRunTurn(params: RunParams, timeoutMs: number, signal?: AbortSignal, run?: typeof runCli): Promise<TurnResult>;
24
32
  export declare const fmtTurnResult: (capability: string, r: TurnResult, maxChars: number) => string;
package/lib/turn.js CHANGED
@@ -110,8 +110,13 @@ export function wsRunTurn(params, timeoutMs, signal) {
110
110
  };
111
111
  });
112
112
  }
113
- /** Execute one turn via the CLI (local or SSH). */
114
- export async function cliRunTurn(params, timeoutMs, signal) {
113
+ /**
114
+ * Build the `deeptutor run` argv for a capability turn (pure, unit-tested).
115
+ * Scalar config values go as repeatable --config k=v; object/array values are
116
+ * collected into --config-json (the CLI's documented form for complex config)
117
+ * instead of being stringified into a k=<json> value that no parser expects.
118
+ */
119
+ export function buildRunArgs(params) {
115
120
  const argv = ["run", params.capability, params.prompt, "--format", "json"];
116
121
  for (const kb of params.kbs ?? [])
117
122
  argv.push("--kb", kb);
@@ -121,11 +126,26 @@ export async function cliRunTurn(params, timeoutMs, signal) {
121
126
  argv.push("--session", params.session_id);
122
127
  if (params.language)
123
128
  argv.push("--language", params.language);
124
- for (const [k, v] of Object.entries(params.config ?? {}))
125
- argv.push("--config", `${k}=${typeof v === "object" ? JSON.stringify(v) : v}`);
126
- const { stdout, stderr, code, killed } = await runCli(argv, { signal, timeoutMs });
127
- if (killed)
128
- throw new Error(`CLI execution timed out (${Math.round(timeoutMs / 1000)}s)`);
129
+ const complexConfig = {};
130
+ for (const [k, v] of Object.entries(params.config ?? {})) {
131
+ if (typeof v === "object" && v !== null)
132
+ complexConfig[k] = v;
133
+ else
134
+ argv.push("--config", `${k}=${v}`);
135
+ }
136
+ if (Object.keys(complexConfig).length > 0) {
137
+ argv.push("--config-json", JSON.stringify(complexConfig));
138
+ }
139
+ return argv;
140
+ }
141
+ /** Execute one turn via the CLI (local or SSH). `run` is injectable for tests. */
142
+ export async function cliRunTurn(params, timeoutMs, signal, run = runCli) {
143
+ const { stdout, stderr, code, killed } = await run(buildRunArgs(params), { signal, timeoutMs });
144
+ if (killed) {
145
+ // A kill can come from the user cancelling (signal) or from the timeout;
146
+ // report the real reason instead of always blaming the timeout.
147
+ throw new Error(signal?.aborted ? "Aborted" : `CLI execution timed out (${Math.round(timeoutMs / 1000)}s)`);
148
+ }
129
149
  if (code !== 0)
130
150
  throw new Error(`CLI exit=${code}: ${stderr || "(no stderr)"}`);
131
151
  const state = { answer: "", errors: [], toolCalls: [] };
package/package.json CHANGED
@@ -1,62 +1,74 @@
1
- {
2
- "name": "dsh-deeptutor",
3
- "version": "0.1.6",
4
- "description": "DeepTutor bridge bundle for DeepSeek Harness: learning capabilities, knowledge bases, and note archiving (HTTP/WS first, CLI fallback; auto-adapts local/remote deployment).",
5
- "keywords": [
6
- "dsh",
7
- "dsh-plugin",
8
- "dsh-bundle",
9
- "deeptutor",
10
- "tutoring",
11
- "rag",
12
- "agent"
13
- ],
14
- "license": "MIT",
15
- "type": "module",
16
- "main": "./lib/index.js",
17
- "types": "./lib/index.d.ts",
18
- "bin": {
19
- "dsh-deeptutor": "scripts/install-profile.mjs"
20
- },
21
- "exports": {
22
- ".": {
23
- "types": "./lib/index.d.ts",
24
- "default": "./lib/index.js"
25
- },
26
- "./cordis.patch.yml": "./cordis.patch.yml",
27
- "./scripts/*": "./scripts/*",
28
- "./skills/*": "./skills/*",
29
- "./src/*": "./src/*",
30
- "./package.json": "./package.json"
31
- },
32
- "files": [
33
- "lib",
34
- "src",
35
- "scripts",
36
- "skills",
37
- "cordis.patch.yml",
38
- "README.md",
39
- "README.zh.md"
40
- ],
41
- "dsh": {
42
- "bundle": {
43
- "patch": "./cordis.patch.yml"
44
- }
45
- },
46
- "scripts": {
47
- "build": "tsc -p tsconfig.build.json",
48
- "typecheck": "tsc --noEmit",
49
- "prepack": "npm run build && npm run typecheck",
50
- "pack:check": "npm pack --dry-run"
51
- },
52
- "peerDependencies": {
53
- "@deepseek-ai/cordis": "^4.0.1",
54
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6"
55
- },
56
- "devDependencies": {
57
- "@deepseek-ai/cordis": "^4.0.1",
58
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
59
- "@types/node": "^24.0.0",
60
- "typescript": "^5.9.3"
61
- }
62
- }
1
+ {
2
+ "name": "dsh-deeptutor",
3
+ "version": "0.1.8",
4
+ "description": "DeepTutor bridge bundle for DeepSeek Harness: learning capabilities, knowledge bases, and note archiving (HTTP/WS first, CLI fallback; auto-adapts local/remote deployment).",
5
+ "keywords": [
6
+ "dsh",
7
+ "dsh-plugin",
8
+ "dsh-bundle",
9
+ "deeptutor",
10
+ "tutoring",
11
+ "rag",
12
+ "agent"
13
+ ],
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/TecFancy/dsh-deeptutor.git"
18
+ },
19
+ "homepage": "https://github.com/TecFancy/dsh-deeptutor",
20
+ "bugs": {
21
+ "url": "https://github.com/TecFancy/dsh-deeptutor/issues"
22
+ },
23
+ "engines": {
24
+ "node": ">=20.11"
25
+ },
26
+ "type": "module",
27
+ "main": "./lib/index.js",
28
+ "types": "./lib/index.d.ts",
29
+ "bin": {
30
+ "dsh-deeptutor": "scripts/install-profile.mjs"
31
+ },
32
+ "exports": {
33
+ ".": {
34
+ "types": "./lib/index.d.ts",
35
+ "default": "./lib/index.js"
36
+ },
37
+ "./cordis.patch.yml": "./cordis.patch.yml",
38
+ "./scripts/*": "./scripts/*",
39
+ "./skills/*": "./skills/*",
40
+ "./src/*": "./src/*",
41
+ "./package.json": "./package.json"
42
+ },
43
+ "files": [
44
+ "lib",
45
+ "src",
46
+ "scripts",
47
+ "skills",
48
+ "cordis.patch.yml",
49
+ "README.md",
50
+ "README.zh.md"
51
+ ],
52
+ "dsh": {
53
+ "bundle": {
54
+ "patch": "./cordis.patch.yml"
55
+ }
56
+ },
57
+ "scripts": {
58
+ "build": "tsc -p tsconfig.build.json",
59
+ "typecheck": "tsc --noEmit",
60
+ "prepack": "npm run build && npm run typecheck",
61
+ "pack:check": "npm pack --dry-run",
62
+ "test": "node --test --experimental-strip-types"
63
+ },
64
+ "peerDependencies": {
65
+ "@deepseek-ai/cordis": "^4.0.1",
66
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.6"
67
+ },
68
+ "devDependencies": {
69
+ "@deepseek-ai/cordis": "^4.0.1",
70
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
71
+ "@types/node": "^24.0.0",
72
+ "typescript": "^5.9.3"
73
+ }
74
+ }