@deepseek-ai/dsh-tool-bash 0.2.1-alpha.1 → 0.2.1-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
@@ -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 = {}) {
@@ -445,6 +444,7 @@ function apply(ctx, config = {}) {
445
444
  await stop("timed out during preparation");
446
445
  return {
447
446
  kind: "foreground",
447
+ cwd: spec.workdir,
448
448
  exitCode: null,
449
449
  signal: null,
450
450
  timedOut: true,
@@ -468,6 +468,7 @@ function apply(ctx, config = {}) {
468
468
  const read = registry.read(attached.id, owner);
469
469
  return {
470
470
  kind: "promoted",
471
+ cwd: spec.workdir,
471
472
  jobId: attached.id,
472
473
  timeoutMs,
473
474
  output: renderJobRead(ringDelta(read.chunks), read.lossy, read.job.output.spillPaths ?? [], attached.process()?.sandbox, escalationModes)
@@ -480,7 +481,7 @@ function apply(ctx, config = {}) {
480
481
  const stopped = attached.stopped();
481
482
  return {
482
483
  kind: "foreground",
483
- ...canonicalBashResult(result),
484
+ ...canonicalBashResult(result, spec.workdir),
484
485
  ...stopped !== void 0 ? { stopped } : {}
485
486
  };
486
487
  };
@@ -538,6 +539,10 @@ function apply(ctx, config = {}) {
538
539
  required: true,
539
540
  const: "promoted"
540
541
  },
542
+ cwd: {
543
+ type: "string",
544
+ required: true
545
+ },
541
546
  jobId: {
542
547
  type: "string",
543
548
  required: true
@@ -561,6 +566,10 @@ function apply(ctx, config = {}) {
561
566
  required: true,
562
567
  const: "foreground"
563
568
  },
569
+ cwd: {
570
+ type: "string",
571
+ required: true
572
+ },
564
573
  exitCode: {
565
574
  required: true,
566
575
  oneOf: [{ type: "integer" }, { type: "null" }]
@@ -636,7 +645,8 @@ function apply(ctx, config = {}) {
636
645
  render: (_args, value) => [{
637
646
  type: "text",
638
647
  text: value.kind === "background" ? `started background job ${value.jobId}` : value.kind === "promoted" ? renderPromoted(value) : renderResult(value, escalationModes)
639
- }]
648
+ }],
649
+ presentationMeta: (_args, value) => ({ cwd: value.cwd })
640
650
  },
641
651
  async execute(args, exec) {
642
652
  const standingPolicy = resolveSandboxPolicy(exec);
@@ -646,7 +656,8 @@ function apply(ctx, config = {}) {
646
656
  ...standingPolicy,
647
657
  mode: approvedMode
648
658
  };
649
- const workdir = resolveWorkdir(args.workdir, exec, standingPolicy?.workspaceRoot);
659
+ const cwd = exec.agent === void 0 ? void 0 : await ctx.workingDirectory.ensure(exec.agent, exec.signal);
660
+ const workdir = resolveWorkdir(args.workdir, cwd);
650
661
  const dshEnv = ctx.shellEnv.collect(exec);
651
662
  const request = {
652
663
  command: args.command,
@@ -659,12 +670,14 @@ function apply(ctx, config = {}) {
659
670
  if (!backgroundEnabled) throw new Error("run_in_background is disabled for this deployment (enableRunInBackground: false)");
660
671
  if (jobs === void 0) throw new Error("background jobs unavailable: load @deepseek-ai/dsh-jobs and @deepseek-ai/dsh-tool-jobs");
661
672
  if (exec.signal.aborted) throw toolAborted();
673
+ const spec = ctx.shell.resolve({
674
+ ...request,
675
+ onExpiry: "none"
676
+ });
662
677
  return {
663
678
  kind: "background",
664
- jobId: startJob(jobs, args, exec, ctx.shell.resolve({
665
- ...request,
666
- onExpiry: "none"
667
- })).id
679
+ jobId: startJob(jobs, args, exec, spec).id,
680
+ cwd: spec.workdir
668
681
  };
669
682
  }
670
683
  if (jobs !== void 0 && promote) {
@@ -680,14 +693,15 @@ function apply(ctx, config = {}) {
680
693
  }
681
694
  if (attached !== void 0) return waitOnJob(jobs, attached, exec, spec);
682
695
  }
683
- const result = await (await ctx.shell.execute(ctx.shell.resolve({
696
+ const spec = ctx.shell.resolve({
684
697
  ...request,
685
698
  signal: exec.signal
686
- }))).result();
699
+ });
700
+ const result = await (await ctx.shell.execute(spec)).result();
687
701
  if (result.aborted) throw toolAborted();
688
702
  return {
689
703
  kind: "foreground",
690
- ...canonicalBashResult(result)
704
+ ...canonicalBashResult(result, spec.workdir)
691
705
  };
692
706
  },
693
707
  presentCall: presentBashCall,
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.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,41 +27,44 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "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",
30
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
31
+ "@deepseek-ai/dsh-shell": "0.2.1-alpha.2",
32
+ "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.2",
33
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
34
+ "@deepseek-ai/dsh-sandbox": "0.2.1-alpha.2",
35
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.2",
36
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.2",
37
+ "@deepseek-ai/dsh-jobs": "0.2.1-alpha.2",
38
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
39
+ "@deepseek-ai/dsh-user-approval": "0.2.1-alpha.2",
39
40
  "@deepseek-ai/cordis": "~4.0.5-alpha.1",
40
- "@deepseek-ai/dsh-user-approval": "0.2.1-alpha.1"
41
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.2"
41
42
  },
42
43
  "dependencies": {
43
44
  "@deepseek-ai/schemastery": "~3.18.5-alpha.1"
44
45
  },
45
46
  "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",
47
+ "@deepseek-ai/dsh-ptc-runtime": "0.2.1-alpha.2",
48
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
49
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.2",
50
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.2",
51
+ "@deepseek-ai/dsh-shell": "0.2.1-alpha.2",
52
+ "@deepseek-ai/dsh-shell-env": "0.2.1-alpha.2",
53
+ "@deepseek-ai/dsh-bash-local": "0.2.1-alpha.2",
54
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
55
+ "@deepseek-ai/dsh-subprocess-local": "0.2.1-alpha.2",
56
+ "@deepseek-ai/dsh-sandbox": "0.2.1-alpha.2",
57
+ "@deepseek-ai/dsh-sandbox-policy": "0.2.1-alpha.2",
58
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
59
+ "@deepseek-ai/dsh-session-persistence-jsonl": "0.2.1-alpha.2",
60
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.2",
61
+ "@deepseek-ai/dsh-jobs": "0.2.1-alpha.2",
62
+ "@deepseek-ai/dsh-jobs-local": "0.2.1-alpha.2",
63
+ "@deepseek-ai/dsh-tool-jobs": "0.2.1-alpha.2",
64
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
65
+ "@deepseek-ai/dsh-user-approval": "0.2.1-alpha.2",
63
66
  "@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"
67
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
68
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.2"
66
69
  }
67
70
  }