@deepseek-ai/dsh-terminal-bash 0.1.5-rc.2 → 0.1.6-alpha.2

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
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/terminal/terminal-bash/README.md
5
- README.md: 5dc66b97f550581df18efba55771d30057ab9aa0
6
- README.zh.md: 85a132ee1cc940fa90a53b91ea399ae48d3fdc2b
5
+ README.md: 466a42f46844d16b85d8754df0bd910361e2e401
6
+ README.zh.md: 7ca41883f6c807102c75b25e531187a7ab148cbf
package/README.md CHANGED
@@ -44,7 +44,7 @@ Mount the terminal service, a subprocess provider, the sandbox and policy servic
44
44
  - name: '@deepseek-ai/dsh-tool-terminal'
45
45
  ```
46
46
 
47
- `danger-full-access` starts the shell directly. Confined modes require a same-world `ctx.sandbox` provider: without one, the spawn fails before the shell starts.
47
+ `danger-full-access` starts the shell directly. Confined modes require a same-world `ctx.sandbox` provider: without one, the spawn fails before the shell starts. Confinement preparation receives the opening signal; cancellation prevents terminal allocation even if the provider returns later.
48
48
 
49
49
  ### Configuration
50
50
 
@@ -85,6 +85,8 @@ This section explains the design behind the backend and points at the code that
85
85
 
86
86
  One backend serves both dialects: bash and pwsh share the same session machinery — sanitizer, bounded buffers, readiness polling, cancellation, and teardown — and differ only in argv, environment, and prompt installation. Bash receives a private marker through `PS1` plus `PROMPT_COMMAND`. Pwsh writes a prompt function, pins UTF-8 console encoding, and publishes startup only after the backend reports `stdin_read`; echoed setup text cannot publish the shell. A zero-scrollback `@xterm/headless` instance consumes raw PTY data and returns terminal-protocol replies through the same handle, while the line sanitizer remains the only output projection.
87
87
 
88
+ Scrollback and unread send output retain independently owned strings with incremental byte and newline counts, so sanitized slices cannot retain discarded control sequences. Appending and evicting text takes amortized time proportional to incoming text; reads assemble the retained chunks. Retention preserves code-point boundaries and counts the empty line after a trailing newline. The [retention decision](../../../.agents/notes/implemented/bug-fix/2026-09-11-incremental-terminal-retention.md) owns the complexity and measurement rationale.
89
+
88
90
  ### Source map
89
91
 
90
92
  | File | Role |
package/README.zh.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "持久终端会话的随附 shell 后端:在共享沙箱策略下启动交互式 bash 或 pwsh,带就绪检测与有界逐行输出。"
2
+ description: "持久终端会话的随产品交付的 shell 后端:在共享沙箱策略下启动交互式 bash 或 pwsh,带就绪检测与有界逐行输出。"
3
3
  kind: "package-reference"
4
4
  ---
5
5
 
@@ -29,7 +29,7 @@ kind: "package-reference"
29
29
 
30
30
  ### 何时选择
31
31
 
32
- 当工作需要状态持续存在的交互式 shell 或 REPL 时选择此后端:逐步调试 gdb、在 Python 或 Node REPL 中探索,或中断前台命令后回到 shell。对于应当一次调用即开始并结束的有界命令,请选择单次 bash 工具。bash 方言面向 POSIX;pwsh 方言面向 `dsh-pwsh-local` 能解析出 pwsh 可执行文件的 Windows 主机。
32
+ 当工作需要状态持续存在的交互式 shell 或 REPL 时选择此后端:在调试器中单步执行、在 Python 或 Node REPL 中探索,或中断前台命令后回到 shell。对于应当一次调用即开始并结束的有界命令,请选择单次 bash 工具。bash 方言面向 POSIX;pwsh 方言面向 `dsh-pwsh-local` 能解析出 pwsh 可执行文件的 Windows 主机。
33
33
 
34
34
  ### 组合方式
35
35
 
@@ -44,7 +44,7 @@ kind: "package-reference"
44
44
  - name: '@deepseek-ai/dsh-tool-terminal'
45
45
  ```
46
46
 
47
- `danger-full-access` 直接启动 shell。受限模式要求同一执行世界中存在 `ctx.sandbox` 提供方:缺少时,spawn 会在 shell 启动前失败。
47
+ `danger-full-access` 直接启动 shell。受限模式要求同一执行世界中存在 `ctx.sandbox` 提供方:缺少时,spawn 会在 shell 启动前失败。限制准备过程接收打开操作的取消信号;即使提供方稍后返回,取消仍会阻止终端分配。
48
48
 
49
49
  ### 配置
50
50
 
@@ -83,7 +83,9 @@ shell 在整个生命周期内运行在有效的沙箱边界之下。当所有
83
83
 
84
84
  ### 设计理念
85
85
 
86
- 一个后端服务两种方言:bash 与 pwsh 共享同一套会话机制——清理器、有界缓冲区、就绪轮询、取消与关闭——只在 argv、环境与提示符安装方式上不同。bash 通过 `PS1` 加 `PROMPT_COMMAND` 接收私有标记。pwsh 会写入提示符函数、钉住 UTF-8 控制台编码,并只在后端报告 `stdin_read` 后发布启动;回显的设置文本不能发布 shell。一个不保留 scrollback 的 `@xterm/headless` 实例会消费原始 PTY 数据,并通过同一句柄返回终端协议响应;逐行 sanitizer 仍是唯一输出投影。
86
+ 一个后端服务两种方言:bash 与 pwsh 共享同一套会话机制——清理器、有界缓冲区、就绪轮询、取消与关闭——只在 argv、环境与提示符安装方式上不同。bash 通过 `PS1` 加 `PROMPT_COMMAND` 接收私有标记。pwsh 会写入提示符函数、固定 UTF-8 控制台编码,并只在后端报告 `stdin_read` 后发布启动;回显的设置文本不能发布 shell。一个不保留 scrollback 的 `@xterm/headless` 实例会消费原始 PTY 数据,并通过同一句柄返回终端协议响应;逐行 sanitizer 仍是唯一输出投影。
87
+
88
+ Scrollback 和尚未读取的发送输出保留独立拥有的字符串,并增量维护字节数与换行符数,因此清理后的切片不会保留已丢弃的控制序列。追加与淘汰文本的摊还耗时与输入文本量成正比;读取时才拼接保留的分片。保留策略维持码点边界,并将末尾换行符之后的空行计入行数。[保留策略决策](../../../.agents/notes/implemented/bug-fix/2026-09-11-incremental-terminal-retention.zh.md)记录复杂度与测量依据。
87
89
 
88
90
  ### 源码地图
89
91
 
@@ -96,7 +98,7 @@ shell 在整个生命周期内运行在有效的沙箱边界之下。当所有
96
98
 
97
99
  ### 就绪模型
98
100
 
99
- 三个有界档位结算一次发送:来自子进程提供方的精确 stdin 等待证据(仅 Linux)、带精确可打印尾部的受控私有提示符标记,以及输出静默(`inferred_idle`);绝对超时始终限制等待。pwsh 启动的完整设置循环共用一条 deadline,因此 `inferred_idle` 后续发送不会重新计时。提供方写入前收集的证据会在写入边界丢弃,早于写入的 stdin 等待不算写入后就绪,未知的前台状态绝不是精确空闲的正向信号。
101
+ 三个有界档位结算一次发送:来自子进程提供方的精确 stdin 等待证据(仅 Linux)、带精确可打印尾部的受控私有提示符标记,以及输出静默(`inferred_idle`);绝对超时始终限制等待。pwsh 启动的完整设置循环共用同一个截止时间,因此 `inferred_idle` 后续发送不会重新计时。提供方写入前收集的证据会在写入边界丢弃,早于写入的 stdin 等待不算写入后就绪,未知的前台状态绝不是精确空闲的正向信号。
100
102
 
101
103
  ### 发送取消与关闭
102
104
 
@@ -115,7 +117,7 @@ shell 在整个生命周期内运行在有效的沙箱边界之下。当所有
115
117
 
116
118
  当包级约定不够用时阅读以下页面。它们从共享终端模型进入服务、工具与执行世界基底。
117
119
 
118
- - [终端子系统参考](../../../docs/subsystems/terminal.zh.md)——此后端实现的服务器约定与生成的 `ctx.terminals` 接口面。
120
+ - [终端子系统参考](../../../docs/subsystems/terminal.zh.md)——此后端实现的服务约定与生成的 `ctx.terminals` 接口面。
119
121
  - [terminal 服务](../terminal/README.zh.md)——后端注册、所有者限制与清理语义。
120
122
  - [tool-terminal 工具](../tool-terminal/README.zh.md)——操作会话的面向模型工具。
121
123
  - [子进程 seam](../../../docs/subsystems/subprocess.zh.md)——负责 PTY 分配与进程树清理的终端原语。
@@ -164,7 +166,7 @@ shell 在整个生命周期内运行在有效的沙箱边界之下。当所有
164
166
 
165
167
  - **仅逐行输出**——headless xterm 只为终端协议响应维护控制序列状态。返回输出仍按行规范化;不支持全屏备用缓冲区交互。
166
168
  - **没有精确档时,就绪是启发式的**——精确 stdin 等待检测取决于已挂载的子进程提供方;无法证明该状态的提供方(macOS、Windows)按提示符标记与静默/超时就绪结算。
167
- - **受限沙箱中的 pwsh 引导**——提示符函数与 UTF-8 钉通过 `[Console]::` 写入,Windows ACL 沙箱的只读模式可能拒绝。若因此无法获得 marker 就绪,启动会在 `timeoutMs` 到期时拒绝,而不会发布不完整的 shell。
169
+ - **受限沙箱中的 pwsh 引导**——提示符函数与 UTF-8 编码固定操作通过 `[Console]::` 写入,Windows ACL 沙箱的只读模式可能拒绝。若因此无法获得标记就绪状态,启动会在 `timeoutMs` 到期时拒绝,而不会发布不完整的 shell。
168
170
  - **清理保证属于提供方**——进程树清理是 `SubprocessTerminalHandle` 的约定,而不是此后端的。
169
171
  - **会话不随进程退出存活**——harness 重启会销毁所有会话。
170
172
 
@@ -178,4 +180,4 @@ shell 在整个生命周期内运行在有效的沙箱边界之下。当所有
178
180
 
179
181
  </details>
180
182
 
181
- **运行时不变式:** 不发布伴生入口。readiness、terminal buffer 与 process-tree state 都是按 Session 的私有实现状态,backend 不发布独立 lifecycle stream 或 snapshot。
183
+ **运行时不变式:** 不发布伴生入口。就绪状态、终端缓冲区与进程树状态都是各会话私有的实现状态,后端不发布独立的生命周期流或快照。
package/lib/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { createRequire } from "node:module";
2
1
  import { TerminalBackendCleanupError, TerminalError } from "@deepseek-ai/dsh-terminal";
3
2
  import { ENCODING_PREAMBLE, resolvePwshPath } from "@deepseek-ai/dsh-pwsh-local";
4
3
  import z from "@deepseek-ai/schemastery";
5
4
  import { Buffer } from "node:buffer";
5
+ import { createLazyRequire } from "@deepseek-ai/dsh-lazy-require";
6
6
  //#region lib/types/config.js
7
7
  /** Validated configuration for the local PTY backend. */
8
8
  /** Bash dialect default executable. */
@@ -232,7 +232,7 @@ function normalizeTerminalText(text) {
232
232
  //#endregion
233
233
  //#region lib/types/session.js
234
234
  /** Persistent PTY session with bounded output, readiness, and terminal-protocol replies. */
235
- const { Terminal: HeadlessTerminal } = createRequire(import.meta.url)("@xterm/headless");
235
+ const requireHeadless = createLazyRequire("@xterm/headless", import.meta.url);
236
236
  function utf8Tail(text, maxBytes) {
237
237
  if (Buffer.byteLength(text) <= maxBytes) return {
238
238
  text,
@@ -252,33 +252,83 @@ function utf8Tail(text, maxBytes) {
252
252
  truncated: true
253
253
  };
254
254
  }
255
+ const COALESCED_CHUNK_UNITS = 4096;
256
+ /** Retention work is amortized over appended text; reads assemble the retained chunks. */
255
257
  var BoundedTextBuffer = class {
256
258
  maxBytes;
257
259
  maxLines;
258
- value = "";
260
+ head;
261
+ tail;
262
+ bytes = 0;
263
+ newlines = 0;
264
+ lastCodeUnit = 0;
259
265
  dropped = false;
260
266
  constructor(maxBytes, maxLines) {
261
267
  this.maxBytes = maxBytes;
262
268
  this.maxLines = maxLines;
263
269
  }
270
+ get truncated() {
271
+ return this.dropped;
272
+ }
273
+ get isEmpty() {
274
+ return this.head === void 0;
275
+ }
264
276
  append(text) {
265
277
  if (text.length === 0) return;
266
- this.value += text;
267
- if (this.maxLines !== void 0) {
268
- const lines = this.value.split("\n");
269
- if (lines.length > this.maxLines) {
270
- this.value = lines.slice(lines.length - this.maxLines).join("\n");
271
- this.dropped = true;
272
- }
278
+ text = Buffer.from(text, "utf16le").toString("utf16le");
279
+ this.bytes += Buffer.byteLength(text);
280
+ const tail = this.tail;
281
+ if (tail !== void 0) {
282
+ const last = this.lastCodeUnit;
283
+ const first = text.charCodeAt(0);
284
+ if (last >= 55296 && last <= 56319 && first >= 56320 && first <= 57343) this.bytes -= 2;
285
+ }
286
+ for (let index = text.indexOf("\n"); index !== -1; index = text.indexOf("\n", index + 1)) this.newlines += 1;
287
+ this.lastCodeUnit = text.charCodeAt(text.length - 1);
288
+ if (tail !== void 0 && tail !== this.head && tail.text.length + text.length <= COALESCED_CHUNK_UNITS) tail.text += text;
289
+ else {
290
+ if (tail !== void 0 && tail.text.length <= COALESCED_CHUNK_UNITS) tail.text = Buffer.from(tail.text, "utf16le").toString("utf16le");
291
+ const chunk = {
292
+ text,
293
+ start: 0,
294
+ next: void 0
295
+ };
296
+ if (tail === void 0) this.head = chunk;
297
+ else tail.next = chunk;
298
+ this.tail = chunk;
299
+ }
300
+ while (this.head !== void 0 && (this.bytes > this.maxBytes || this.maxLines !== void 0 && this.newlines >= this.maxLines)) {
301
+ const head = this.head;
302
+ const first = head.text.charCodeAt(head.start);
303
+ const second = head.start + 1 < head.text.length ? head.text.charCodeAt(head.start + 1) : head.next?.text.charCodeAt(0);
304
+ const paired = first >= 55296 && first <= 56319 && second !== void 0 && second >= 56320 && second <= 57343;
305
+ this.bytes -= paired ? 4 : first < 128 ? 1 : first < 2048 ? 2 : 3;
306
+ if (first === 10) this.newlines -= 1;
307
+ this.advance(paired ? 2 : 1);
308
+ this.dropped = true;
309
+ }
310
+ const head = this.head;
311
+ if (head !== void 0 && head.start >= head.text.length / 2) {
312
+ head.text = Buffer.from(head.text.slice(head.start), "utf16le").toString("utf16le");
313
+ head.start = 0;
314
+ }
315
+ }
316
+ advance(units) {
317
+ while (units > 0 && this.head !== void 0) {
318
+ const head = this.head;
319
+ const count = Math.min(units, head.text.length - head.start);
320
+ head.start += count;
321
+ units -= count;
322
+ if (head.start === head.text.length) this.head = head.next;
273
323
  }
274
- const tail = utf8Tail(this.value, this.maxBytes);
275
- this.value = tail.text;
276
- this.dropped ||= tail.truncated;
324
+ if (this.head === void 0) this.tail = void 0;
277
325
  }
278
326
  consume() {
279
- const delta = this.value;
280
- const truncated = this.dropped;
281
- this.value = "";
327
+ const { text: delta, truncated } = this.snapshot();
328
+ this.head = void 0;
329
+ this.tail = void 0;
330
+ this.bytes = 0;
331
+ this.newlines = 0;
282
332
  this.dropped = false;
283
333
  return {
284
334
  delta,
@@ -286,8 +336,10 @@ var BoundedTextBuffer = class {
286
336
  };
287
337
  }
288
338
  snapshot() {
339
+ const chunks = [];
340
+ for (let chunk = this.head; chunk !== void 0; chunk = chunk.next) chunks.push(chunk.text.slice(chunk.start));
289
341
  return {
290
- text: this.value,
342
+ text: chunks.join(""),
291
343
  truncated: this.dropped
292
344
  };
293
345
  }
@@ -398,6 +450,7 @@ var LocalPtySession = class {
398
450
  this.terminal = terminal;
399
451
  this.config = config;
400
452
  this.pid = terminal.pid;
453
+ const { Terminal: HeadlessTerminal } = requireHeadless();
401
454
  this.emulator = new HeadlessTerminal({
402
455
  cols: config.cols,
403
456
  rows: config.rows,
@@ -654,7 +707,7 @@ var LocalPtySession = class {
654
707
  return;
655
708
  }
656
709
  const elapsed = Date.now() - operation.startedAt;
657
- const startupHasOutput = !this.initializing || this.scrollback.snapshot().text.length > 0;
710
+ const startupHasOutput = !this.initializing || !this.scrollback.isEmpty;
658
711
  const acceptsStdinWait = startupHasOutput && foreground !== void 0 && operation.acceptsStdinWait(foreground.processGroupId, foreground.inputWaiting);
659
712
  if (elapsed >= this.config.exactProbeAfterMs && acceptsStdinWait) {
660
713
  this.settleActive("stdin_read");
@@ -759,7 +812,7 @@ var LocalPtySession = class {
759
812
  settleActive(waitReason, retainOwnership = false) {
760
813
  const operation = this.active;
761
814
  if (operation === void 0) return;
762
- const scrollbackTruncated = this.scrollback.snapshot().truncated;
815
+ const scrollbackTruncated = this.scrollback.truncated;
763
816
  if (retainOwnership) {
764
817
  this.stopPolling();
765
818
  this.activeAbort?.();
@@ -898,15 +951,15 @@ function childEnvironment(spec, dialect) {
898
951
  * input are unreliable under PSReadLine.
899
952
  */
900
953
  const PWSH_PROMPT_SETUP = "function prompt { [Console]::Write([char]27 + ']133;D;' + [int]$LASTEXITCODE + [char]7); 'dsh> ' }";
901
- function spawnArgv(ctx, config, policy) {
954
+ async function spawnArgv(ctx, config, policy, signal) {
902
955
  const argv = [config.shellPath, ...config.shellArgs];
903
956
  if (policy.mode === "danger-full-access") return argv;
904
957
  const sandbox = ctx.get("sandbox");
905
958
  if (sandbox === void 0) throw new Error(`terminal-bash: sandbox mode "${policy.mode}" requires a ctx.sandbox provider in the execution world`);
906
- return sandbox.confine(argv, {
959
+ return (await sandbox.confine(argv, {
907
960
  ...policy,
908
961
  mode: policy.mode
909
- }).argv;
962
+ }, signal)).argv;
910
963
  }
911
964
  async function startupSession(session, dialect, timeoutMs, signal) {
912
965
  let startupOperation;
@@ -958,6 +1011,15 @@ async function startupSession(session, dialect, timeoutMs, signal) {
958
1011
  if (signal !== void 0 && onAbort !== void 0) signal.removeEventListener("abort", onAbort);
959
1012
  }
960
1013
  }
1014
+ /** Reject a failed startup only after its unpublished resources reach quiescence. */
1015
+ async function rejectAfterStartupCleanup(error, cleanup) {
1016
+ try {
1017
+ await cleanup();
1018
+ } catch (cleanupError) {
1019
+ throw new TerminalBackendCleanupError(error, cleanupError);
1020
+ }
1021
+ throw error;
1022
+ }
961
1023
  /** Local shell backend registered under the configured type. */
962
1024
  var BashTerminalBackend = class {
963
1025
  ctx;
@@ -976,7 +1038,8 @@ var BashTerminalBackend = class {
976
1038
  spec.signal?.throwIfAborted();
977
1039
  ensureSandboxModeFence(this.ctx, spec.owner);
978
1040
  const policy = this.ctx.sandboxPolicy.resolve({ session: spec.owner.session });
979
- const argv = spawnArgv(this.ctx, this.config, policy);
1041
+ const argv = await spawnArgv(this.ctx, this.config, policy, spec.signal);
1042
+ spec.signal?.throwIfAborted();
980
1043
  if (argv[0] === void 0) throw new Error("terminal-bash: sandbox returned empty argv");
981
1044
  const terminal = await this.spawnTerminal({
982
1045
  argv,
@@ -984,20 +1047,21 @@ var BashTerminalBackend = class {
984
1047
  env: childEnvironment(spec, this.config.shellDialect),
985
1048
  rows: this.config.rows,
986
1049
  cols: this.config.cols,
1050
+ terminalType: "dumb",
987
1051
  graceMs: this.config.disposeGraceMs,
988
1052
  signal: spec.signal
989
1053
  });
990
- const session = this.createSession(terminal, this.config);
1054
+ let session;
1055
+ try {
1056
+ session = this.createSession(terminal, this.config);
1057
+ } catch (error) {
1058
+ return rejectAfterStartupCleanup(error, () => terminal.terminate());
1059
+ }
991
1060
  try {
992
1061
  await startupSession(session, this.config.shellDialect, this.config.timeoutMs, spec.signal);
993
1062
  return session;
994
1063
  } catch (error) {
995
- try {
996
- await session.close("PTY startup failed");
997
- } catch (closeError) {
998
- throw new TerminalBackendCleanupError(error, closeError);
999
- }
1000
- throw error;
1064
+ return rejectAfterStartupCleanup(error, () => session.close("PTY startup failed"));
1001
1065
  }
1002
1066
  }
1003
1067
  };
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.5-rc.2",
4
+ "version": "0.1.6-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,29 +27,30 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "peerDependencies": {
30
- "@deepseek-ai/dsh-agent": "^0.1.5-rc.2",
31
- "@deepseek-ai/dsh-terminal": "^0.1.5-rc.2",
32
- "@deepseek-ai/dsh-session": "^0.1.5-rc.2",
33
- "@deepseek-ai/dsh-subprocess": "^0.1.5-rc.2",
30
+ "@deepseek-ai/dsh-agent": "^0.1.6-alpha.2",
31
+ "@deepseek-ai/dsh-terminal": "^0.1.6-alpha.2",
32
+ "@deepseek-ai/dsh-sandbox": "^0.1.6-alpha.2",
33
+ "@deepseek-ai/dsh-session": "^0.1.6-alpha.2",
34
+ "@deepseek-ai/dsh-subprocess": "^0.1.6-alpha.2",
34
35
  "@deepseek-ai/cordis": "^4.0.2",
35
- "@deepseek-ai/dsh-sandbox-policy": "^0.1.5-rc.2",
36
- "@deepseek-ai/dsh-sandbox": "^0.1.5-rc.2",
37
- "@deepseek-ai/dsh-session-projection": "^0.1.5-rc.2"
36
+ "@deepseek-ai/dsh-sandbox-policy": "^0.1.6-alpha.2",
37
+ "@deepseek-ai/dsh-session-projection": "^0.1.6-alpha.2"
38
38
  },
39
39
  "dependencies": {
40
40
  "@xterm/headless": "^6.0.0",
41
- "@deepseek-ai/schemastery": "^3.18.2",
42
- "@deepseek-ai/dsh-pwsh-local": "^0.1.5-rc.2"
41
+ "@deepseek-ai/dsh-lazy-require": "^0.1.6-alpha.2",
42
+ "@deepseek-ai/dsh-pwsh-local": "^0.1.6-alpha.2",
43
+ "@deepseek-ai/schemastery": "^3.18.2"
43
44
  },
44
45
  "devDependencies": {
45
- "@deepseek-ai/dsh-agent-loop-testkit": "^0.1.5-rc.2",
46
- "@deepseek-ai/dsh-terminal": "^0.1.5-rc.2",
47
- "@deepseek-ai/dsh-sandbox": "^0.1.5-rc.2",
48
- "@deepseek-ai/dsh-agent": "^0.1.5-rc.2",
49
- "@deepseek-ai/dsh-sandbox-policy": "^0.1.5-rc.2",
50
- "@deepseek-ai/dsh-session": "^0.1.5-rc.2",
51
- "@deepseek-ai/dsh-subprocess-local": "^0.1.5-rc.2",
52
- "@deepseek-ai/cordis": "^4.0.2",
53
- "@deepseek-ai/dsh-subprocess": "^0.1.5-rc.2"
46
+ "@deepseek-ai/dsh-agent": "^0.1.6-alpha.2",
47
+ "@deepseek-ai/dsh-agent-loop-testkit": "^0.1.6-alpha.2",
48
+ "@deepseek-ai/dsh-terminal": "^0.1.6-alpha.2",
49
+ "@deepseek-ai/dsh-sandbox": "^0.1.6-alpha.2",
50
+ "@deepseek-ai/dsh-sandbox-policy": "^0.1.6-alpha.2",
51
+ "@deepseek-ai/dsh-session": "^0.1.6-alpha.2",
52
+ "@deepseek-ai/dsh-subprocess-local": "^0.1.6-alpha.2",
53
+ "@deepseek-ai/dsh-subprocess": "^0.1.6-alpha.2",
54
+ "@deepseek-ai/cordis": "^4.0.2"
54
55
  }
55
56
  }