@deepseek-ai/dsh-terminal-bash 0.1.7-rc.2 → 0.2.0-rc.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/README.i18n.yaml CHANGED
@@ -24,11 +24,11 @@
24
24
  en: 71449ef1985b2f1b
25
25
  zh: 562e9b5ef73cd5e1
26
26
  /deepseek-ai-dsh-terminal-bash/use-this-package/configuration:
27
- en: 229375735e02e80a
28
- zh: 347c617ae312643a
27
+ en: 2a10fc681cee698d
28
+ zh: ac60c8918bae3c85
29
29
  /deepseek-ai-dsh-terminal-bash/use-this-package/shell-dialects-and-readiness:
30
- en: bab340c3347f1794
31
- zh: a4c32b651fea000d
30
+ en: 2cab01d85f524e3d
31
+ zh: 0d00b3e399a935b1
32
32
  /deepseek-ai-dsh-terminal-bash/use-this-package/sandboxing-and-safe-operation:
33
33
  en: 39e0f0b429b024a7
34
34
  zh: 440171193664d13b
package/README.md CHANGED
@@ -57,11 +57,11 @@ Mount the terminal service, a subprocess provider, the sandbox and policy servic
57
57
  | `timeoutMs` | `30000` | Absolute bound on one send wait |
58
58
  | `disposeGraceMs` | `3000` | Grace before teardown escalates to `SIGKILL` |
59
59
 
60
- The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-terminal-bash) is the exhaustive source for every field, including the readiness timings (`pollIntervalMs`, `exactProbeAfterMs`, `idleSilenceMs`, `handoffGraceMs`), terminal size (`rows`, `cols`), and scrollback bounds (`scrollbackLines`, `scrollbackMaxBytes`).
60
+ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-terminal-bash) is the exhaustive source for every field, including the readiness timings (`pollIntervalMs`, `exactProbeAfterMs`, `idleSilenceMs`, `handoffGraceMs`, `promptTailGraceMs`), terminal size (`rows`, `cols`), and scrollback bounds (`scrollbackLines`, `scrollbackMaxBytes`).
61
61
 
62
62
  ### Shell dialects and readiness
63
63
 
64
- Both dialects expose the same readiness contract, so consumers are dialect-agnostic. A send settles when the shell is ready again: after the controlled prompt is verified, after the foreground process group provably waits on stdin (Linux), after output silence (`inferred_idle`), or at the absolute `timeoutMs`. An `inferred_idle` or `timeout` result does not prove the foreground command exited.
64
+ Both dialects expose the same readiness contract, so consumers are dialect-agnostic. A send settles when the shell is ready again: after the controlled prompt is verified, after the foreground process group provably waits on stdin (Linux), after output silence (`inferred_idle`), or at the absolute `timeoutMs`. A prompt marker whose printable tail has not arrived yet holds the send on the exact path for `promptTailGraceMs` beyond `idleSilenceMs + handoffGraceMs`, because the marker and its tail are written by the same prompt render. An `inferred_idle` or `timeout` result does not prove the foreground command exited.
65
65
 
66
66
  ### Sandboxing and safe operation
67
67
 
package/README.zh.md CHANGED
@@ -57,11 +57,11 @@ kind: "package-reference"
57
57
  | `timeoutMs` | `30000` | 一次发送等待的绝对上限 |
58
58
  | `disposeGraceMs` | `3000` | 清理升级到 `SIGKILL` 前的宽限时间 |
59
59
 
60
- 生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-terminal-bash)是每个字段的穷尽式真源,包括就绪计时(`pollIntervalMs`、`exactProbeAfterMs`、`idleSilenceMs`、`handoffGraceMs`)、终端尺寸(`rows`、`cols`)与 scrollback 上限(`scrollbackLines`、`scrollbackMaxBytes`)。
60
+ 生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-terminal-bash)是每个字段的穷尽式真源,包括就绪计时(`pollIntervalMs`、`exactProbeAfterMs`、`idleSilenceMs`、`handoffGraceMs`、`promptTailGraceMs`)、终端尺寸(`rows`、`cols`)与 scrollback 上限(`scrollbackLines`、`scrollbackMaxBytes`)。
61
61
 
62
62
  ### shell 方言与就绪
63
63
 
64
- 两种方言暴露相同的就绪约定,因此消费方与方言无关。当 shell 再次就绪时发送即结算:受控提示符被验证之后、前台进程组被证明在等待 stdin(Linux)之后、输出静默(`inferred_idle`)之后,或到达绝对 `timeoutMs`。`inferred_idle` 或 `timeout` 结果并不证明前台命令已退出。
64
+ 两种方言暴露相同的就绪约定,因此消费方与方言无关。当 shell 再次就绪时发送即结算:受控提示符被验证之后、前台进程组被证明在等待 stdin(Linux)之后、输出静默(`inferred_idle`)之后,或到达绝对 `timeoutMs`。若提示符标记已到达而其可打印尾部尚未到达,send 会在 `idleSilenceMs + handoffGraceMs` 之外继续等待 `promptTailGraceMs`,因为标记与尾部由同一次提示符渲染写出。`inferred_idle` 或 `timeout` 结果并不证明前台命令已退出。
65
65
 
66
66
  ### 沙箱与安全运行
67
67
 
package/lib/index.js CHANGED
@@ -48,11 +48,14 @@ const Config = z.object({
48
48
  exactProbeAfterMs: z.number().default(150),
49
49
  idleSilenceMs: z.number().default(3e3),
50
50
  handoffGraceMs: z.number().default(500),
51
+ promptTailGraceMs: z.number().default(0),
51
52
  timeoutMs: z.number().default(3e4),
52
53
  disposeGraceMs: z.number().default(3e3)
53
54
  });
54
55
  /**
55
- * Assert every effective numeric config field is a positive safe integer and bounds compose.
56
+ * Assert every effective numeric config field is a positive safe integer — except
57
+ * `promptTailGraceMs`, whose zero is the documented "no extension" value — and that bounds
58
+ * compose.
56
59
  * @param config - Schemastery-resolved plugin configuration.
57
60
  * @returns Narrows the input to the fully resolved configuration.
58
61
  */
@@ -60,9 +63,14 @@ function validateConfig(config) {
60
63
  const resolved = config;
61
64
  if (resolved.backendType.length === 0) throw new Error("terminal-bash: backendType must be non-empty");
62
65
  if (resolved.shellPath.length === 0) throw new Error("terminal-bash: shellPath must be non-empty");
63
- for (const [name, value] of Object.entries(resolved)) if (typeof value === "number" && (!Number.isSafeInteger(value) || value <= 0)) throw new Error(`terminal-bash: ${name} must be a positive safe integer`);
66
+ for (const [name, value] of Object.entries(resolved)) {
67
+ if (name === "promptTailGraceMs") continue;
68
+ if (typeof value === "number" && (!Number.isSafeInteger(value) || value <= 0)) throw new Error(`terminal-bash: ${name} must be a positive safe integer`);
69
+ }
70
+ if (typeof resolved.promptTailGraceMs === "number" && (!Number.isSafeInteger(resolved.promptTailGraceMs) || resolved.promptTailGraceMs < 0)) throw new Error("terminal-bash: promptTailGraceMs must be a non-negative safe integer");
64
71
  if (resolved.maxReadBytes > resolved.scrollbackMaxBytes) throw new Error("terminal-bash: maxReadBytes must not exceed scrollbackMaxBytes");
65
72
  if (resolved.handoffGraceMs < resolved.pollIntervalMs) throw new Error("terminal-bash: handoffGraceMs must be at least pollIntervalMs so one readiness poll runs inside the grace window");
73
+ if (resolved.promptTailGraceMs !== 0 && resolved.promptTailGraceMs < resolved.pollIntervalMs) throw new Error("terminal-bash: promptTailGraceMs must be zero or at least pollIntervalMs so a nonzero tolerance contains one readiness poll");
66
74
  }
67
75
  /** Exact printable prompt emitted after the private marker. */
68
76
  const CONTROLLED_PROMPT = "dsh> ";
@@ -714,7 +722,8 @@ var LocalPtySession = class {
714
722
  return;
715
723
  }
716
724
  const handoffGrace = this.promptSeen ? this.config.handoffGraceMs : 0;
717
- if (startupHasOutput && idleFor >= this.config.idleSilenceMs + handoffGrace) this.settleActive("inferred_idle");
725
+ const tailGrace = this.promptSeen && !this.promptTextSeen && "dsh> ".startsWith(this.promptTail) ? this.config.promptTailGraceMs : 0;
726
+ if (startupHasOutput && idleFor >= this.config.idleSilenceMs + handoffGrace + tailGrace) this.settleActive("inferred_idle");
718
727
  } catch (error) {
719
728
  if (this.protocolWorkPending()) await this.drainTerminalProtocol();
720
729
  if (this.active === operation && !this.closing && this.interrupting !== operation) this.failActive(error);
@@ -33,6 +33,15 @@ export interface Config {
33
33
  * regain the foreground before `inferred_idle` settles; at least one `pollIntervalMs`.
34
34
  */
35
35
  handoffGraceMs?: number;
36
+ /**
37
+ * Extra wait beyond `idleSilenceMs` and `handoffGraceMs`, once a prompt marker was seen but
38
+ * its printable tail has not arrived, before `inferred_idle` settles. The marker is written
39
+ * by the shell's own prompt function and the tail by the same render, so a missing tail is a
40
+ * delivery delay on a contended host rather than an absent prompt. Zero keeps the bound at
41
+ * `idleSilenceMs + handoffGraceMs`; any other value covers at least one `pollIntervalMs`, so a
42
+ * nonzero tolerance always contains a readiness poll.
43
+ */
44
+ promptTailGraceMs?: number;
36
45
  /** Absolute bound for one send and the complete pwsh startup sequence. */
37
46
  timeoutMs?: number;
38
47
  /** Grace before teardown escalates to `SIGKILL`. */
@@ -63,7 +72,9 @@ export declare function resolveConfig(config: Config): ResolvedConfig;
63
72
  /** Schemastery config exposed by the plugin. */
64
73
  export declare const Config: z<Config>;
65
74
  /**
66
- * Assert every effective numeric config field is a positive safe integer and bounds compose.
75
+ * Assert every effective numeric config field is a positive safe integer — except
76
+ * `promptTailGraceMs`, whose zero is the documented "no extension" value — and that bounds
77
+ * compose.
67
78
  * @param config - Schemastery-resolved plugin configuration.
68
79
  * @returns Narrows the input to the fully resolved configuration.
69
80
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-terminal-bash",
3
3
  "description": "Persistent shell PTY backend over the DeepSeek Harness subprocess terminal primitive",
4
- "version": "0.1.7-rc.2",
4
+ "version": "0.2.0-rc.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,30 +27,30 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "peerDependencies": {
30
- "@deepseek-ai/dsh-agent": "0.1.7-rc.2",
31
- "@deepseek-ai/dsh-terminal": "0.1.7-rc.2",
32
- "@deepseek-ai/dsh-sandbox": "0.1.7-rc.2",
33
- "@deepseek-ai/dsh-sandbox-policy": "0.1.7-rc.2",
34
- "@deepseek-ai/dsh-session": "0.1.7-rc.2",
35
- "@deepseek-ai/dsh-subprocess": "0.1.7-rc.2",
36
- "@deepseek-ai/cordis": "~4.0.4",
37
- "@deepseek-ai/dsh-session-projection": "0.1.7-rc.2"
30
+ "@deepseek-ai/dsh-agent": "0.2.0-rc.1",
31
+ "@deepseek-ai/dsh-terminal": "0.2.0-rc.1",
32
+ "@deepseek-ai/dsh-sandbox": "0.2.0-rc.1",
33
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.1",
34
+ "@deepseek-ai/dsh-session": "0.2.0-rc.1",
35
+ "@deepseek-ai/dsh-subprocess": "0.2.0-rc.1",
36
+ "@deepseek-ai/dsh-session-projection": "0.2.0-rc.1",
37
+ "@deepseek-ai/cordis": "~4.0.4"
38
38
  },
39
39
  "dependencies": {
40
40
  "@xterm/headless": "^6.0.0",
41
- "@deepseek-ai/dsh-lazy-require": "0.1.7-rc.2",
42
- "@deepseek-ai/dsh-pwsh-local": "0.1.7-rc.2",
41
+ "@deepseek-ai/dsh-lazy-require": "0.2.0-rc.1",
42
+ "@deepseek-ai/dsh-pwsh-local": "0.2.0-rc.1",
43
43
  "@deepseek-ai/schemastery": "~3.18.4"
44
44
  },
45
45
  "devDependencies": {
46
- "@deepseek-ai/dsh-agent": "0.1.7-rc.2",
47
- "@deepseek-ai/dsh-agent-loop-testkit": "0.1.7-rc.2",
48
- "@deepseek-ai/dsh-terminal": "0.1.7-rc.2",
49
- "@deepseek-ai/dsh-sandbox-policy": "0.1.7-rc.2",
50
- "@deepseek-ai/dsh-session": "0.1.7-rc.2",
51
- "@deepseek-ai/dsh-sandbox": "0.1.7-rc.2",
52
- "@deepseek-ai/dsh-subprocess": "0.1.7-rc.2",
53
- "@deepseek-ai/dsh-subprocess-local": "0.1.7-rc.2",
46
+ "@deepseek-ai/dsh-agent": "0.2.0-rc.1",
47
+ "@deepseek-ai/dsh-terminal": "0.2.0-rc.1",
48
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.0-rc.1",
49
+ "@deepseek-ai/dsh-sandbox": "0.2.0-rc.1",
50
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.1",
51
+ "@deepseek-ai/dsh-session": "0.2.0-rc.1",
52
+ "@deepseek-ai/dsh-subprocess-local": "0.2.0-rc.1",
53
+ "@deepseek-ai/dsh-subprocess": "0.2.0-rc.1",
54
54
  "@deepseek-ai/cordis": "~4.0.4"
55
55
  }
56
56
  }