@deepseek-ai/dsh-tool-present 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,11 +15,11 @@
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
17
  /deepseek-ai-dsh-tool-present/use-this-package:
18
- en: f2726b49d9f4d5b3
19
- zh: 10428317260e5cf1
18
+ en: 3bb0413b8aa3bd10
19
+ zh: ab753bb651a62209
20
20
  /deepseek-ai-dsh-tool-present/understand-the-implementation:
21
- en: 3ae69eb991942c18
22
- zh: 6824644dc0cee1ae
21
+ en: 6e73ca41dddc096e
22
+ zh: b59fdfa3f3cc47e1
23
23
  /deepseek-ai-dsh-tool-present/further-exploration:
24
24
  en: 66269384f8c0d0f7
25
25
  zh: b3d694d2f0ae588a
package/README.md CHANGED
@@ -25,6 +25,8 @@ Use `present` to declare final files accessible through the Session filesystem,
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
+ `present` validates paths against the Session's current working directory and records absolute paths, so later directory changes do not redirect delivered files.
29
+
28
30
  The `standard`, `ptc`, and `cordis` agent presets mount this plugin. Call `present` with `files: [{ path, description? }]` after creating the files. Files must be regular files accessible through the Session filesystem. Relative paths resolve against the Session working directory; absolute paths may name files outside it, including `/tmp` or Downloads. Missing files, directories, final symbolic links, and provider-denied paths fail the call. Files in a shell sandbox’s private `/tmp` must first be written somewhere the Session filesystem can access.
29
31
 
30
32
  Mount it in an agent's Cordis composition with `tools`, `fs`, and the `turnBoundary` Session projection available:
@@ -51,7 +53,7 @@ The file-count limit is validated at mount. The tool requires an agent Session w
51
53
 
52
54
  The tool resolves paths through the configured filesystem provider and checks regular-file metadata without reading contents. Successful final `tools/result` notifications append `deliverables/presented`, including nested calls. A later enclosing program failure does not revoke an already completed declaration. Blocked results publish none. Each plugin instance records only calls it executed; scoped tools with the same name cannot publish through another instance.
53
55
 
54
- The pure `./types` entry declares `PresentedFile` and the Session event without importing Host runtime code. The Web consumer validates persisted declarations before displaying or opening them. The event stores no Session ID, so forked history resolves relative paths against the viewed Session's workspace.
56
+ The pure `./types` entry declares `PresentedFile` and the Session event without importing Host runtime code. The Web consumer validates persisted declarations before displaying or opening them. New declarations store absolute paths. Legacy relative declarations retain the viewed Session's original workspace as their base.
55
57
 
56
58
  </details>
57
59
 
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
+ `present` 按 Session 的当前工作目录校验路径并记录绝对路径,因此后续目录切换不会让已交付文件指向其他位置。
29
+
28
30
  `standard`、`ptc` 与 `cordis` Agent preset 挂载本插件。创建文件后,以 `files: [{ path, description? }]` 调用 `present`。文件必须是 Session 文件系统可访问的普通文件。相对路径按 Session 工作目录解析;绝对路径可以指向工作区外的文件,包括 `/tmp` 或 Downloads。文件缺失、为目录、最终路径为符号链接或提供方拒绝访问时,调用失败。Shell 沙箱私有 `/tmp` 中的文件需要先写入 Session 文件系统可访问的位置。
29
31
 
30
32
  在 Agent 的 Cordis 组合中挂载,并提供 `tools`、`fs` 和 `turnBoundary` Session 投影:
@@ -51,7 +53,7 @@ kind: "package-reference"
51
53
 
52
54
  工具通过配置的文件系统提供方解析路径,检查普通文件元数据,不读取内容。成功的最终 `tools/result` 通知追加 `deliverables/presented`,嵌套调用也适用。外层程序随后失败不会撤销已完成的声明。被阻止的结果不发布声明。每个插件实例只记录其实际执行的调用;同名作用域工具不能通过其他实例发布交付。
53
55
 
54
- 纯 `./types` 入口声明 `PresentedFile` 与 Session 事件,不导入 Host 运行时代码。Web 消费方在展示或打开文件前校验持久声明。事件不保存 Session ID,因此 fork 历史中的相对路径按当前查看的 Session 工作区解析。
56
+ 纯 `./types` 入口声明 `PresentedFile` 与 Session 事件,不导入 Host 运行时代码。Web 消费方在展示或打开文件前校验持久声明。新声明保存绝对路径。历史相对路径声明继续以当前查看的 Session 原始工作区作为基准。
55
57
 
56
58
  </details>
57
59
 
package/lib/index.js CHANGED
@@ -10,7 +10,8 @@ const Config = z.object({ maxFiles: z.number().default(8) });
10
10
  const inject = [
11
11
  "tools",
12
12
  "fs",
13
- "sessionProjections"
13
+ "sessionProjections",
14
+ "workingDirectory"
14
15
  ];
15
16
  /**
16
17
  * Register present with durable file references in its tool result.
@@ -79,8 +80,7 @@ function apply(ctx, config) {
79
80
  const boundary = ctx.sessionProjections.stateOf(exec.agent.session, "turnBoundary");
80
81
  if (boundary === void 0 || boundary.openTurnStartSeq === null) throw new Error("present requires an open turn");
81
82
  if (args.files.length === 0 || args.files.length > config.maxFiles) throw new Error(`present accepts 1 to ${config.maxFiles} files`);
82
- const cwd = exec.agent.session.header.cwd;
83
- if (cwd === void 0) throw new Error("present requires a workspace");
83
+ const cwd = await ctx.workingDirectory.ensure(exec.agent, exec.signal);
84
84
  const options = {
85
85
  cwd,
86
86
  signal: exec.signal
@@ -94,7 +94,10 @@ function apply(ctx, config) {
94
94
  const info = await ctx.fs.stat(target, exec.signal);
95
95
  if (info === void 0) throw new FsError(`Cannot present ${file.path}: file not found. Check the path, create the file if needed, and retry.`, "FS_NOT_FOUND");
96
96
  if (info.type !== "file") throw new Error(`Cannot present ${file.path}: not a regular file`);
97
- files.push({ ...file });
97
+ files.push({
98
+ ...file,
99
+ path: ctx.fs.processPath(target)
100
+ });
98
101
  }
99
102
  exec.signal.throwIfAborted();
100
103
  pending.set(exec, {
@@ -1,4 +1,3 @@
1
- /** Scoped tool that declares filesystem deliveries in their owning Session. */
2
1
  import type { Context } from '@deepseek-ai/cordis';
3
2
  import z from '@deepseek-ai/schemastery';
4
3
  /** Stable Loader identity. */
@@ -8,7 +8,7 @@ export const Config = z.object({
8
8
  maxFiles: z.number().default(8),
9
9
  });
10
10
  /** Services used by the scoped delivery tool. */
11
- export const inject = ['tools', 'fs', 'sessionProjections'];
11
+ export const inject = ['tools', 'fs', 'sessionProjections', 'workingDirectory'];
12
12
  /**
13
13
  * Register present with durable file references in its tool result.
14
14
  * @param ctx - agent-scoped services.
@@ -65,9 +65,7 @@ export function apply(ctx, config) {
65
65
  throw new Error('present requires an open turn');
66
66
  if (args.files.length === 0 || args.files.length > config.maxFiles)
67
67
  throw new Error(`present accepts 1 to ${config.maxFiles} files`);
68
- const cwd = exec.agent.session.header.cwd;
69
- if (cwd === undefined)
70
- throw new Error('present requires a workspace');
68
+ const cwd = await ctx.workingDirectory.ensure(exec.agent, exec.signal);
71
69
  const options = { cwd, signal: exec.signal };
72
70
  const files = [];
73
71
  for (const file of args.files) {
@@ -82,7 +80,7 @@ export function apply(ctx, config) {
82
80
  throw new FsError(`Cannot present ${file.path}: file not found. Check the path, create the file if needed, and retry.`, 'FS_NOT_FOUND');
83
81
  if (info.type !== 'file')
84
82
  throw new Error(`Cannot present ${file.path}: not a regular file`);
85
- files.push({ ...file });
83
+ files.push({ ...file, path: ctx.fs.processPath(target) });
86
84
  }
87
85
  exec.signal.throwIfAborted();
88
86
  pending.set(exec, { session: exec.agent.session, turn: boundary.lastTurn, files });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-tool-present",
3
3
  "description": "Explicit workspace file delivery declarations for the DeepSeek Harness",
4
- "version": "0.2.1-alpha.1",
4
+ "version": "0.2.1-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -36,25 +36,27 @@
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@deepseek-ai/cordis": "~4.0.5-alpha.1",
39
- "@deepseek-ai/dsh-fs": "0.2.1-alpha.1",
40
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
41
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
42
- "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
43
- "@deepseek-ai/dsh-tools": "0.2.1-alpha.1",
44
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1"
39
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
40
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.2",
41
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
42
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
43
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
44
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
45
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.2"
45
46
  },
46
47
  "devDependencies": {
47
- "@deepseek-ai/dsh-agent": "0.2.1-alpha.1",
48
- "@deepseek-ai/dsh-fs": "0.2.1-alpha.1",
49
- "@deepseek-ai/dsh-llm": "0.2.1-alpha.1",
50
- "@deepseek-ai/dsh-session": "0.2.1-alpha.1",
51
48
  "@deepseek-ai/cordis": "~4.0.5-alpha.1",
52
- "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.1",
53
- "@deepseek-ai/dsh-tools": "0.2.1-alpha.1",
54
- "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.1",
55
- "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.1",
56
- "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.1",
57
- "@deepseek-ai/dsh-scope": "0.2.1-alpha.1",
58
- "@deepseek-ai/dsh-fs-local": "0.2.1-alpha.1"
49
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
50
+ "@deepseek-ai/dsh-fs": "0.2.1-alpha.2",
51
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
52
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
53
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
54
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
55
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.2",
56
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.2",
57
+ "@deepseek-ai/dsh-fs-local": "0.2.1-alpha.2",
58
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.2",
59
+ "@deepseek-ai/dsh-scope": "0.2.1-alpha.2",
60
+ "@deepseek-ai/dsh-working-directory": "0.2.1-alpha.2"
59
61
  }
60
62
  }