@deepseek-ai/dsh-tool-bash 0.2.1-alpha.1 → 0.2.1-alpha.3

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
@@ -15,8 +15,8 @@
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
17
  /deepseek-ai-dsh-tool-bash/use-this-package:
18
- en: e20abe0ff6964f16
19
- zh: 143d7c17499b2247
18
+ en: b38c1a304e18185c
19
+ zh: 05275ff8d127c9c0
20
20
  /deepseek-ai-dsh-tool-bash/use-this-package/minimal-configuration:
21
21
  en: 9a16909fc013c6e5
22
22
  zh: ba740dbce3cd2e93
@@ -36,8 +36,8 @@
36
36
  en: cc9a6cc87468d73a
37
37
  zh: aaa94162ef9de2f0
38
38
  /deepseek-ai-dsh-tool-bash/understand-the-implementation:
39
- en: 8d94a7381bca3fa9
40
- zh: f4bd2866fff6fa8d
39
+ en: 165313776a851b51
40
+ zh: 828f48807036aff0
41
41
  /deepseek-ai-dsh-tool-bash/understand-the-implementation/design-philosophy:
42
42
  en: 9332353fda6ac7be
43
43
  zh: 45c17e5e83478032
@@ -45,8 +45,8 @@
45
45
  en: 0547d68864628d08
46
46
  zh: 5adb79f945b17a0d
47
47
  /deepseek-ai-dsh-tool-bash/understand-the-implementation/request-resolution:
48
- en: b03c1d84aa4b5cd4
49
- zh: 111eba387b7082ae
48
+ en: 56dae7757fab0a79
49
+ zh: 7930235dc0490c73
50
50
  /deepseek-ai-dsh-tool-bash/understand-the-implementation/rendering-story:
51
51
  en: 167c045d6a6278cc
52
52
  zh: 3f17ee8d31e0bbad
package/README.md CHANGED
@@ -25,6 +25,8 @@ English | [中文](README.zh.md)
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
+ New commands start in the Session's current working directory. Relative `workdir` values resolve from that directory; per-call overrides and background jobs do not change it.
29
+
28
30
  Load this plugin in any composition where the agent should run bash commands: it registers the `bash` tool once an executor provider and the `dsh-shell-env` registry are mounted, and stays pending until the `tools`, `shell`, `systemPrompt`, and `shellEnv` services exist.
29
31
 
30
32
  ### Minimal configuration
@@ -79,6 +81,8 @@ A composition with no executor provider never activates the tool. Background cal
79
81
  <details>
80
82
  <summary>Implementation internals — click to expand</summary>
81
83
 
84
+ Structured foreground and background results expose `cwd`, the executor-resolved launch directory. Persisted presentation metadata carries the same value so settled cards retain the directory used by that call. A command’s own `cd` does not change this launch value; native result text remains stdout, stderr, and status markers.
85
+
82
86
  This section explains the design decisions behind the tool and points at the code that realizes them; the observable behavior is fully covered in [Use this package](#use-this-package).
83
87
 
84
88
  ### Design philosophy
@@ -98,7 +102,7 @@ This section explains the design decisions behind the tool and points at the cod
98
102
 
99
103
  ### Request resolution
100
104
 
101
- The tool resolves the workdir before `ctx.shell.resolve()` runs: an explicit relative `workdir` is resolved against the session cwd, and a sandbox policy's canonical workspace root wins so confinement and launch use the same identity. Sandbox policy resolves per call through `ctx.sandboxPolicy`; an escalation request goes through `ctx.approval` before anything executes, and the tool fails at load if the executor confines but no policy service is mounted.
105
+ The tool resolves the workdir before `ctx.shell.resolve()` runs: an explicit relative `workdir` is resolved against the Session's current directory, independently of the sandbox permission root. Sandbox policy resolves per call through `ctx.sandboxPolicy`; an escalation request goes through `ctx.approval` before anything executes, and the tool fails at load if the executor confines but no policy service is mounted.
102
106
 
103
107
  ### Rendering story
104
108
 
package/README.zh.md CHANGED
@@ -25,6 +25,8 @@ kind: "package-reference"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
+ 新命令从 Session 的当前工作目录启动。相对 `workdir` 从该目录解析;单次调用的覆盖值与后台任务不会改变该目录。
29
+
28
30
  在 agent 需要运行 bash 命令的任何组合中加载本插件:一旦挂载执行器提供方与 `dsh-shell-env` 注册表,它就注册 `bash` 工具,并在 `tools`、`shell`、`systemPrompt` 与 `shellEnv` 服务就绪之前保持等待。
29
31
 
30
32
  ### 最小配置
@@ -79,6 +81,8 @@ kind: "package-reference"
79
81
  <details>
80
82
  <summary>实现细节——点击展开</summary>
81
83
 
84
+ 前台与后台的结构化结果均包含 `cwd`,即执行器解析后的启动目录。持久化展示元数据携带同一值,使已结束的调用卡片保留该次调用使用的目录。命令内部的 `cd` 不会改变这个启动值;原生结果文本仍由 stdout、stderr 与状态标记组成。
85
+
82
86
  本节解释工具背后的设计决策,并指出实现它们的代码位置;可观察行为已在[使用本包](#use-this-package)中完整说明。
83
87
 
84
88
  ### 设计理念
@@ -98,7 +102,7 @@ kind: "package-reference"
98
102
 
99
103
  ### 请求解析
100
104
 
101
- 工具在 `ctx.shell.resolve()` 运行前解析 workdir:显式的相对 `workdir` 相对会话 cwd 解析,沙箱策略的规范化 workspace root 优先,使约束与启动使用同一身份。沙箱策略通过 `ctx.sandboxPolicy` 按调用解析;升权请求在任何执行前经由 `ctx.approval`,若执行器会约束命令却没有挂载策略服务,工具在加载时失败。
105
+ 工具在 `ctx.shell.resolve()` 运行前解析 workdir:显式的相对 `workdir` 相对 Session 当前目录解析,与沙箱权限根目录独立。沙箱策略通过 `ctx.sandboxPolicy` 按调用解析;升权请求在任何执行前经由 `ctx.approval`,若执行器会约束命令却没有挂载策略服务,工具在加载时失败。
102
106
 
103
107
  ### 渲染故事
104
108
 
package/lib/index.js CHANGED
@@ -224,7 +224,8 @@ const inject = [
224
224
  "tools",
225
225
  "shell",
226
226
  "systemPrompt",
227
- "shellEnv"
227
+ "shellEnv",
228
+ "workingDirectory"
228
229
  ];
229
230
  /** Runtime configuration schema for the bash tool plugin. */
230
231
  const Config = z.object({
@@ -284,27 +285,21 @@ function presentBashResult(args, result) {
284
285
  ...exit
285
286
  };
286
287
  }
287
- /**
288
- * Resolve an explicit workdir first, making a relative one session-workspace-relative;
289
- * otherwise use the filesystem identity of the session cwd and leave executor
290
- * defaulting as the fallback. A resolved sandbox-policy root wins so workdir
291
- * and confinement use the exact same per-call identity.
292
- */
293
- function resolveWorkdir(modelWorkdir, exec, policyWorkspaceRoot) {
294
- const headerCwd = exec.agent?.session.header.cwd;
295
- const sessionCwd = policyWorkspaceRoot ?? headerCwd;
288
+ /** Resolve a relative per-call override against the Session's current directory. */
289
+ function resolveWorkdir(modelWorkdir, sessionCwd) {
296
290
  if (modelWorkdir === void 0) return sessionCwd;
297
291
  if (sessionCwd !== void 0 && !isAbsolute(modelWorkdir)) return `${sessionCwd}${sep}${modelWorkdir}`;
298
292
  return modelWorkdir;
299
293
  }
300
294
  /** Detach the executor DTO from readonly Service Definition types into plain JSON data. */
301
- function canonicalBashResult(result) {
295
+ function canonicalBashResult(result, cwd) {
302
296
  const output = (stream) => ({
303
297
  text: stream.text,
304
298
  truncated: stream.truncated,
305
299
  ...stream.spillPath !== void 0 ? { spillPath: stream.spillPath } : {}
306
300
  });
307
301
  return {
302
+ cwd,
308
303
  exitCode: result.exitCode,
309
304
  signal: result.signal,
310
305
  timedOut: result.timedOut,
@@ -336,6 +331,10 @@ const BACKGROUND_OUTPUT_PROPERTIES = {
336
331
  jobId: {
337
332
  type: "string",
338
333
  required: true
334
+ },
335
+ cwd: {
336
+ type: "string",
337
+ required: true
339
338
  }
340
339
  };
341
340
  function apply(ctx, config = {}) {
@@ -395,6 +394,10 @@ function apply(ctx, config = {}) {
395
394
  id: registry.start({
396
395
  kind: "bash",
397
396
  label: args.command,
397
+ toolCall: {
398
+ callId: exec.callId,
399
+ rootCallId: exec.rootCallId
400
+ },
398
401
  ...exec.agent ? { owner: exec.agent.id } : {},
399
402
  output: processSources(() => proc),
400
403
  run: () => {
@@ -445,6 +448,7 @@ function apply(ctx, config = {}) {
445
448
  await stop("timed out during preparation");
446
449
  return {
447
450
  kind: "foreground",
451
+ cwd: spec.workdir,
448
452
  exitCode: null,
449
453
  signal: null,
450
454
  timedOut: true,
@@ -468,6 +472,7 @@ function apply(ctx, config = {}) {
468
472
  const read = registry.read(attached.id, owner);
469
473
  return {
470
474
  kind: "promoted",
475
+ cwd: spec.workdir,
471
476
  jobId: attached.id,
472
477
  timeoutMs,
473
478
  output: renderJobRead(ringDelta(read.chunks), read.lossy, read.job.output.spillPaths ?? [], attached.process()?.sandbox, escalationModes)
@@ -480,7 +485,7 @@ function apply(ctx, config = {}) {
480
485
  const stopped = attached.stopped();
481
486
  return {
482
487
  kind: "foreground",
483
- ...canonicalBashResult(result),
488
+ ...canonicalBashResult(result, spec.workdir),
484
489
  ...stopped !== void 0 ? { stopped } : {}
485
490
  };
486
491
  };
@@ -538,6 +543,10 @@ function apply(ctx, config = {}) {
538
543
  required: true,
539
544
  const: "promoted"
540
545
  },
546
+ cwd: {
547
+ type: "string",
548
+ required: true
549
+ },
541
550
  jobId: {
542
551
  type: "string",
543
552
  required: true
@@ -561,6 +570,10 @@ function apply(ctx, config = {}) {
561
570
  required: true,
562
571
  const: "foreground"
563
572
  },
573
+ cwd: {
574
+ type: "string",
575
+ required: true
576
+ },
564
577
  exitCode: {
565
578
  required: true,
566
579
  oneOf: [{ type: "integer" }, { type: "null" }]
@@ -636,7 +649,8 @@ function apply(ctx, config = {}) {
636
649
  render: (_args, value) => [{
637
650
  type: "text",
638
651
  text: value.kind === "background" ? `started background job ${value.jobId}` : value.kind === "promoted" ? renderPromoted(value) : renderResult(value, escalationModes)
639
- }]
652
+ }],
653
+ presentationMeta: (_args, value) => ({ cwd: value.cwd })
640
654
  },
641
655
  async execute(args, exec) {
642
656
  const standingPolicy = resolveSandboxPolicy(exec);
@@ -646,7 +660,8 @@ function apply(ctx, config = {}) {
646
660
  ...standingPolicy,
647
661
  mode: approvedMode
648
662
  };
649
- const workdir = resolveWorkdir(args.workdir, exec, standingPolicy?.workspaceRoot);
663
+ const cwd = exec.agent === void 0 ? void 0 : await ctx.workingDirectory.ensure(exec.agent, exec.signal);
664
+ const workdir = resolveWorkdir(args.workdir, cwd);
650
665
  const dshEnv = ctx.shellEnv.collect(exec);
651
666
  const request = {
652
667
  command: args.command,
@@ -659,12 +674,14 @@ function apply(ctx, config = {}) {
659
674
  if (!backgroundEnabled) throw new Error("run_in_background is disabled for this deployment (enableRunInBackground: false)");
660
675
  if (jobs === void 0) throw new Error("background jobs unavailable: load @deepseek-ai/dsh-jobs and @deepseek-ai/dsh-tool-jobs");
661
676
  if (exec.signal.aborted) throw toolAborted();
677
+ const spec = ctx.shell.resolve({
678
+ ...request,
679
+ onExpiry: "none"
680
+ });
662
681
  return {
663
682
  kind: "background",
664
- jobId: startJob(jobs, args, exec, ctx.shell.resolve({
665
- ...request,
666
- onExpiry: "none"
667
- })).id
683
+ jobId: startJob(jobs, args, exec, spec).id,
684
+ cwd: spec.workdir
668
685
  };
669
686
  }
670
687
  if (jobs !== void 0 && promote) {
@@ -680,14 +697,15 @@ function apply(ctx, config = {}) {
680
697
  }
681
698
  if (attached !== void 0) return waitOnJob(jobs, attached, exec, spec);
682
699
  }
683
- const result = await (await ctx.shell.execute(ctx.shell.resolve({
700
+ const spec = ctx.shell.resolve({
684
701
  ...request,
685
702
  signal: exec.signal
686
- }))).result();
703
+ });
704
+ const result = await (await ctx.shell.execute(spec)).result();
687
705
  if (result.aborted) throw toolAborted();
688
706
  return {
689
707
  kind: "foreground",
690
- ...canonicalBashResult(result)
708
+ ...canonicalBashResult(result, spec.workdir)
691
709
  };
692
710
  },
693
711
  presentCall: presentBashCall,
package/locale/en.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "meta": {
3
+ "title": "tool-bash"
4
+ }
5
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "Bash 命令工具",
4
+ "description": "让 AI 执行 Bash 命令,并按配置管理后台运行和权限申请。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-tool-bash",
3
3
  "description": "Model-facing bash tool with optional generic background-job and sandbox-escalation support",
4
- "version": "0.2.1-alpha.1",
4
+ "version": "0.2.1-alpha.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -19,49 +19,54 @@
19
19
  "default": "./lib/index.js"
20
20
  },
21
21
  "./src/*": "./src/*",
22
- "./package.json": "./package.json"
22
+ "./package.json": "./package.json",
23
+ "./locale/*.json": "./locale/*.json"
23
24
  },
24
25
  "files": [
26
+ "locale/*.json",
25
27
  "lib/index.js",
26
28
  "lib/types/**/*.d.ts"
27
29
  ],
28
30
  "license": "MIT",
29
31
  "peerDependencies": {
30
- "@deepseek-ai/dsh-shell": "0.2.1-alpha.1",
31
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
32
- "@deepseek-ai/dsh-sandbox": "0.2.1-alpha.1",
33
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
34
- "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.1",
35
- "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.1",
36
- "@deepseek-ai/dsh-jobs": "0.2.1-alpha.1",
37
- "@deepseek-ai/dsh-tools": "0.2.1-alpha.1",
38
- "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
39
- "@deepseek-ai/cordis": "~4.0.5-alpha.1",
40
- "@deepseek-ai/dsh-user-approval": "0.2.1-alpha.1"
32
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.3",
33
+ "@deepseek-ai/dsh-shell": "0.2.1-alpha.3",
34
+ "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.3",
35
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.3",
36
+ "@deepseek-ai/dsh-sandbox": "0.2.1-alpha.3",
37
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.3",
38
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.3",
39
+ "@deepseek-ai/dsh-jobs": "0.2.1-alpha.3",
40
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.3",
41
+ "@deepseek-ai/dsh-user-approval": "0.2.1-alpha.3",
42
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2",
43
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.3"
41
44
  },
42
45
  "dependencies": {
43
- "@deepseek-ai/schemastery": "~3.18.5-alpha.1"
46
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.2"
44
47
  },
45
48
  "devDependencies": {
46
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
47
- "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.1",
48
- "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.1",
49
- "@deepseek-ai/dsh-shell": "0.2.1-alpha.1",
50
- "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.1",
51
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
52
- "@deepseek-ai/dsh-subprocess-local": "0.2.1-alpha.1",
53
- "@deepseek-ai/dsh-sandbox": "0.2.1-alpha.1",
54
- "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.1",
55
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
56
- "@deepseek-ai/dsh-session-persistence-jsonl": "0.2.1-alpha.1",
57
- "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
58
- "@deepseek-ai/dsh-jobs": "0.2.1-alpha.1",
59
- "@deepseek-ai/dsh-bash-local": "0.2.1-alpha.1",
60
- "@deepseek-ai/dsh-tool-jobs": "0.2.1-alpha.1",
61
- "@deepseek-ai/dsh-tools": "0.2.1-alpha.1",
62
- "@deepseek-ai/dsh-user-approval": "0.2.1-alpha.1",
63
- "@deepseek-ai/cordis": "~4.0.5-alpha.1",
64
- "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
65
- "@deepseek-ai/dsh-jobs-local": "0.2.1-alpha.1"
49
+ "@deepseek-ai/dsh-ptc-runtime": "0.2.1-alpha.3",
50
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.3",
51
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.3",
52
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.3",
53
+ "@deepseek-ai/dsh-shell": "0.2.1-alpha.3",
54
+ "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.3",
55
+ "@deepseek-ai/dsh-bash-local": "0.2.1-alpha.3",
56
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.3",
57
+ "@deepseek-ai/dsh-subprocess-local": "0.2.1-alpha.3",
58
+ "@deepseek-ai/dsh-sandbox": "0.2.1-alpha.3",
59
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.3",
60
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.3",
61
+ "@deepseek-ai/dsh-session-persistence-jsonl": "0.2.1-alpha.3",
62
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.3",
63
+ "@deepseek-ai/dsh-jobs": "0.2.1-alpha.3",
64
+ "@deepseek-ai/dsh-jobs-local": "0.2.1-alpha.3",
65
+ "@deepseek-ai/dsh-tool-jobs": "0.2.1-alpha.3",
66
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.3",
67
+ "@deepseek-ai/dsh-user-approval": "0.2.1-alpha.3",
68
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2",
69
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.3",
70
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.3"
66
71
  }
67
72
  }