@qilin-agent/tools 3.1.3 → 3.1.5

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
@@ -5,99 +5,99 @@
5
5
  /:
6
6
  en: 3b12a77945c0d1e9
7
7
  zh: e9af32047e4f658b
8
- /qilin-tools:
9
- en: a4b050d1b91ebf39
10
- zh: 2a5cffff9987575d
11
- /qilin-tools/summary:
8
+ /qilin-agent-tools:
9
+ en: 04bcb1e79c92cad9
10
+ zh: 45acefa225993264
11
+ /qilin-agent-tools/summary:
12
12
  en: 7fb51274d4f721df
13
13
  zh: da9b19633629eefd
14
- /qilin-tools/table-of-contents:
14
+ /qilin-agent-tools/table-of-contents:
15
15
  en: d152484eb41ac6b4
16
16
  zh: 09388d293f9be9cb
17
- /qilin-tools/use-this-package:
18
- en: 5157221ba48c5c22
19
- zh: 0fd32b2fd246495e
20
- /qilin-tools/use-this-package/register-a-tool:
17
+ /qilin-agent-tools/use-this-package:
18
+ en: 6530bbd1b2a98e3f
19
+ zh: c3ec6a876315c08e
20
+ /qilin-agent-tools/use-this-package/register-a-tool:
21
21
  en: 02fce53c21a33d74
22
22
  zh: 01110c4714dfd602
23
- /qilin-tools/use-this-package/configure-the-presentation-mode:
24
- en: 623fcab2e684b719
25
- zh: cde146b5f4cd610d
26
- /qilin-tools/use-this-package/restrict-tools-per-agent:
23
+ /qilin-agent-tools/use-this-package/configure-the-presentation-mode:
24
+ en: 7e438825611cbff6
25
+ zh: 4b85bf913691640d
26
+ /qilin-agent-tools/use-this-package/restrict-tools-per-agent:
27
27
  en: c6f98b2283cc2e47
28
28
  zh: c2cdce5d13473f15
29
- /qilin-tools/use-this-package/enforce-policy-on-calls:
29
+ /qilin-agent-tools/use-this-package/enforce-policy-on-calls:
30
30
  en: 1dd4ee9d8cdd2038
31
31
  zh: aa3e9790641e521f
32
- /qilin-tools/use-this-package/host-presentation-descriptors:
32
+ /qilin-agent-tools/use-this-package/host-presentation-descriptors:
33
33
  en: d9aec6b6a174584a
34
34
  zh: b42039a7015e0364
35
- /qilin-tools/understand-the-implementation:
35
+ /qilin-agent-tools/understand-the-implementation:
36
36
  en: ce7e776e9d516bdb
37
37
  zh: 59d2751743db7795
38
- /qilin-tools/understand-the-implementation/design-concept:
38
+ /qilin-agent-tools/understand-the-implementation/design-concept:
39
39
  en: 92e8af53e6067bad
40
40
  zh: 33c7b99b42c5acac
41
- /qilin-tools/understand-the-implementation/source-map:
41
+ /qilin-agent-tools/understand-the-implementation/source-map:
42
42
  en: c14e20d6a5c4c408
43
43
  zh: ab9dc0fd38006749
44
- /qilin-tools/understand-the-implementation/execution-and-cancellation:
44
+ /qilin-agent-tools/understand-the-implementation/execution-and-cancellation:
45
45
  en: dc44a88997777988
46
46
  zh: 56454aeace1c8b77
47
- /qilin-tools/understand-the-implementation/ptc-mode:
48
- en: 3c9d085b862b98e0
49
- zh: d243755c77c3432d
50
- /qilin-tools/understand-the-implementation/extension-points:
47
+ /qilin-agent-tools/understand-the-implementation/ptc-mode:
48
+ en: 05db4632bd08eb8c
49
+ zh: d1699b7a159eea9b
50
+ /qilin-agent-tools/understand-the-implementation/extension-points:
51
51
  en: c2a14d6f22bc9428
52
52
  zh: 89c1414fca465931
53
- /qilin-tools/further-exploration:
54
- en: 890aed31a2a34950
55
- zh: d1833fc8d1bb8bca
56
- /qilin-tools/model-experience:
53
+ /qilin-agent-tools/further-exploration:
54
+ en: 20c5e038e7b3b0fa
55
+ zh: 18daabad7c1f582a
56
+ /qilin-agent-tools/model-experience:
57
57
  en: 215e7ba838619b7b
58
58
  zh: a311da3843709f90
59
- /qilin-tools/model-experience/normal-tool-schemas:
59
+ /qilin-agent-tools/model-experience/normal-tool-schemas:
60
60
  en: 483b01d9bb2cb49a
61
61
  zh: 1d95095e76fb0996
62
- /qilin-tools/model-experience/normal-tool-schemas/what-the-model-sees:
63
- en: 1978238355b5755a
64
- zh: c65b1c5309ec1831
65
- /qilin-tools/model-experience/normal-tool-schemas/token-effect:
62
+ /qilin-agent-tools/model-experience/normal-tool-schemas/what-the-model-sees:
63
+ en: 53d988bc9af2af86
64
+ zh: a87f2017ee996676
65
+ /qilin-agent-tools/model-experience/normal-tool-schemas/token-effect:
66
66
  en: d594b71ff5e4cc87
67
67
  zh: dcec1ea0dd2a0fa6
68
- /qilin-tools/model-experience/normal-tool-schemas/kv-cache-effect:
68
+ /qilin-agent-tools/model-experience/normal-tool-schemas/kv-cache-effect:
69
69
  en: 7c5e75964e020b2c
70
70
  zh: d50d0402d15232d9
71
- /qilin-tools/model-experience/ptc-mode-schema-and-system-prompt:
71
+ /qilin-agent-tools/model-experience/ptc-mode-schema-and-system-prompt:
72
72
  en: eaefd7303f22977d
73
73
  zh: 9c425f9501128224
74
- /qilin-tools/model-experience/ptc-mode-schema-and-system-prompt/what-the-model-sees:
75
- en: ad6b9ea4c514455f
76
- zh: fe27c64ce8b0f465
77
- /qilin-tools/model-experience/ptc-mode-schema-and-system-prompt/what-the-model-sees/typescript-ptc-mode-sdk-instructions-with-bash:
74
+ /qilin-agent-tools/model-experience/ptc-mode-schema-and-system-prompt/what-the-model-sees:
75
+ en: 2efe3c1c793219e0
76
+ zh: 40be3fbb1dd63d4e
77
+ /qilin-agent-tools/model-experience/ptc-mode-schema-and-system-prompt/what-the-model-sees/typescript-ptc-mode-sdk-instructions-with-bash:
78
78
  en: 3a8df15e4ae32f9e
79
79
  zh: fc4a800ba363e835
80
- /qilin-tools/model-experience/ptc-mode-schema-and-system-prompt/token-effect:
80
+ /qilin-agent-tools/model-experience/ptc-mode-schema-and-system-prompt/token-effect:
81
81
  en: 12296fcafc14562c
82
82
  zh: f8e9351bb8c6437d
83
- /qilin-tools/model-experience/ptc-mode-schema-and-system-prompt/kv-cache-effect:
83
+ /qilin-agent-tools/model-experience/ptc-mode-schema-and-system-prompt/kv-cache-effect:
84
84
  en: 78906628d634441f
85
85
  zh: 492f133aea50cfe3
86
- /qilin-tools/model-experience/tool-call-history-and-results:
86
+ /qilin-agent-tools/model-experience/tool-call-history-and-results:
87
87
  en: a8503137ad03720c
88
88
  zh: 611a2dadf7c0c706
89
- /qilin-tools/model-experience/tool-call-history-and-results/what-the-model-sees:
89
+ /qilin-agent-tools/model-experience/tool-call-history-and-results/what-the-model-sees:
90
90
  en: 7c568da5a45e99ab
91
91
  zh: 7e78f04448fc5450
92
- /qilin-tools/model-experience/tool-call-history-and-results/token-effect:
92
+ /qilin-agent-tools/model-experience/tool-call-history-and-results/token-effect:
93
93
  en: 8fe3f024f364ed9f
94
94
  zh: 89c1d5d24c5f950b
95
- /qilin-tools/model-experience/tool-call-history-and-results/kv-cache-effect:
95
+ /qilin-agent-tools/model-experience/tool-call-history-and-results/kv-cache-effect:
96
96
  en: 2fbf2175168e8244
97
97
  zh: ad59a120b54a0996
98
- /qilin-tools/known-limitations-and-deferred-work:
99
- en: 57ba640ee483c163
100
- zh: 551dab190d346131
101
- /qilin-tools/known-limitations-and-deferred-work/dev-note:
98
+ /qilin-agent-tools/known-limitations-and-deferred-work:
99
+ en: 4cd3c301d258a153
100
+ zh: f73ad30cd873cfee
101
+ /qilin-agent-tools/known-limitations-and-deferred-work/dev-note:
102
102
  en: e67f633dc6fe7773
103
103
  zh: 3bb0c20c93f16f98
package/README.md CHANGED
@@ -25,6 +25,8 @@ Use `qilin-tools` to expose typed capabilities to models, validate calls, enforc
25
25
  <a id="use-this-package"></a>
26
26
  ## Use this package
27
27
 
28
+ Each `run_code` program captures the Session's current working directory when it starts. A nested directory change affects subsequent tool calls, while the running program keeps its initial directory.
29
+
28
30
  Mount `qilin-tools` wherever agents call tools: it provides `ctx.tools`, the registry every tool plugin registers into and the loop dispatches through. Registering a tool is enough to make it visible — the registry feeds its schemas into the system-prompt assembly automatically.
29
31
 
30
32
  ### Register a tool
@@ -121,11 +123,11 @@ Each typed invocation materializes and freezes parsed arguments, assigns an opaq
121
123
 
122
124
  ### PTC mode
123
125
 
124
- Under `ptc` or `both`, the registry exposes the reserved `run_code` transport plus a deterministic SDK generated in the loaded runtime's language. Each SDK binding captures a frozen ToolSchema and passes it through the scheduler to its execution context. Before policy, a started call records only pairing ids, name, and normalized arguments; its settle event preserves the rendered result and optional structured error. Description and parameters remain transient and never enter Session events or SDK output. Calls are scheduled through a per-run pool that reuses the native concurrency contract. Under `ptc` alone, a model-direct call naming any other visible tool resolves to `UNKNOWN_TOOL` before policy — the announced surface and the callable surface stay the same. Intermediate binding values are execution-local; only the outer `run_code` result has a hard size cap. The [executor-collapse note](../../../.agents/notes/implemented/bug-fix/2026-08-07-ptc-executor-collapse.md) owns the collapse contract.
126
+ Under `ptc` or `both`, the registry exposes the reserved `run_code` transport plus a deterministic SDK generated in the loaded runtime's language. Each SDK binding captures a frozen ToolSchema and passes it through the scheduler to its execution context. Before policy, a started call records only pairing ids, name, and normalized arguments; its settle event preserves the rendered result, optional presentation metadata, and structured error. Metadata is projected from that call's canonical value and frozen; it changes neither the program value nor model content. Description and parameters remain transient and never enter Session events or SDK output. Calls are scheduled through a per-run pool that reuses the native concurrency contract. Under `ptc` alone, a model-direct call naming any other visible tool resolves to `UNKNOWN_TOOL` before policy — the announced surface and the callable surface stay the same. Intermediate binding values are execution-local; only the outer `run_code` result has a hard size cap. The [executor-collapse note](../../../.agents/notes/implemented/bug-fix/2026-08-07-ptc-executor-collapse.md) owns the collapse contract.
125
127
 
126
128
  New sub-calls use `<parent>:ptc:<n>` ids. Consumers treat these ids as opaque and correlate events by exact equality; restored historical ids retain their original bytes. The [PTC mode decision](../../../.agents/notes/implemented/feature/2026-06-15-ptc.md) owns durable naming and restoration rules.
127
129
 
128
- `run_code` accepts `timeoutMs` when the mounted runtime supports an override; its schema reports the configured default and maximum, the runtime's usage instructions and the Session working directory. The Node default is 120,000 ms with a 600,000 ms cap, including nested tool and approval waits. A wider `sandbox_permissions` mode requires a non-empty `justification` and approval before the program starts. The grant applies to that complete execution; standing Session policy and nested tools retain their own authority. Programs are never replayed automatically: inspect earlier effects before explicitly retrying a denied program.
130
+ `run_code` accepts `timeoutMs` when the mounted runtime supports an override; its schema reports the configured default and maximum, and the runtime's usage instructions. The Node default is 120,000 ms with a 600,000 ms cap, including nested tool and approval waits. A wider `sandbox_permissions` mode requires a non-empty `justification` and approval before the program starts. The grant applies to that complete execution; standing Session policy and nested tools retain their own authority. Programs are never replayed automatically: inspect earlier effects before explicitly retrying a denied program.
129
131
 
130
132
  <a id="extension-points"></a>
131
133
  ### Extension points
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
+ 每个 `run_code` 程序在启动时捕获 Session 的当前工作目录。嵌套调用改变目录只影响后续工具调用,运行中的程序保留其初始目录。
29
+
28
30
  在任何 agent 调用工具的地方挂载 `qilin-tools`:它提供 `ctx.tools`,即每个工具插件注册进去、循环分发所经过的注册表。注册一个工具就足以让它可见——注册表会自动把其 schema 送入系统提示词组装。
29
31
 
30
32
  ### 注册工具
@@ -121,11 +123,11 @@ ctx.tools.register(defineTool({
121
123
 
122
124
  ### PTC mode
123
125
 
124
- 在 `ptc` 或 `both` 下,注册表公开保留的 `run_code` 传输以及按所加载运行时语言生成的确定性 SDK。每个 SDK 绑定捕获冻结的 ToolSchema,经由调度器传入该次执行上下文。已开始的调用在策略之前只记录配对 id、名称和规范化参数;其结算事件保留渲染结果与可选结构化错误。描述与参数 schema 仅临时存活,不进入 Session 事件或 SDK 输出。调用通过复用原生并发约定的每次运行独有池调度。在纯 `ptc` 下,模型直呼其他任何可见工具都会在策略之前解析为 `UNKNOWN_TOOL`——通告面与可调用面保持一致。中间绑定值只存在于执行局部;只有外层 `run_code` 结果有硬大小上限。[执行器塌缩 note](../../../.agents/notes/implemented/bug-fix/2026-08-07-ptc-executor-collapse.zh.md) 拥有该收束约定。
126
+ 在 `ptc` 或 `both` 下,注册表公开保留的 `run_code` 传输以及按所加载运行时语言生成的确定性 SDK。每个 SDK 绑定捕获冻结的 ToolSchema,经由调度器传入该次执行上下文。已开始的调用在策略之前只记录配对 id、名称和规范化参数;其结算事件保留渲染结果、可选展示元数据与结构化错误。元数据由该调用的规范值投影并冻结,既不改变程序值,也不改变模型内容。描述与参数 schema 仅临时存活,不进入 Session 事件或 SDK 输出。调用通过复用原生并发约定的每次运行独有池调度。在纯 `ptc` 下,模型直呼其他任何可见工具都会在策略之前解析为 `UNKNOWN_TOOL`——通告面与可调用面保持一致。中间绑定值只存在于执行局部;只有外层 `run_code` 结果有硬大小上限。[执行器塌缩 note](../../../.agents/notes/implemented/bug-fix/2026-08-07-ptc-executor-collapse.zh.md) 拥有该收束约定。
125
127
 
126
128
  新子调用使用 `<parent>:ptc:<n>` 标识。消费方将这些标识视为不透明值,并通过精确相等关联事件;恢复的历史标识保留原始字节。[PTC mode 决策](../../../.agents/notes/implemented/feature/2026-06-15-ptc.zh.md) 负责持久化命名与恢复规则。
127
129
 
128
- 当已挂载运行时支持覆盖时,`run_code` 接受 `timeoutMs`;其 schema 报告配置的默认值和上限、运行时使用说明及 Session 工作目录。Node 默认值为 120,000 ms,上限为 600,000 ms,包含嵌套工具和审批等待。更宽的 `sandbox_permissions` 模式要求非空 `justification`,并在程序启动前获得审批。授权仅用于该次完整执行;常驻 Session 策略与嵌套工具保留各自权限。程序不会自动重放:显式重试被拒程序前,应检查先前已发生的效果。
130
+ 当已挂载运行时支持覆盖时,`run_code` 接受 `timeoutMs`;其 schema 报告配置的默认值和上限,以及运行时使用说明。Node 默认值为 120,000 ms,上限为 600,000 ms,包含嵌套工具和审批等待。更宽的 `sandbox_permissions` 模式要求非空 `justification`,并在程序启动前获得审批。授权仅用于该次完整执行;常驻 Session 策略与嵌套工具保留各自权限。程序不会自动重放:显式重试被拒程序前,应检查先前已发生的效果。
129
131
 
130
132
  <a id="extension-points"></a>
131
133
  ### 扩展点
package/lib/index.js CHANGED
@@ -1206,6 +1206,7 @@ function createRunCodeTool(registry, options) {
1206
1206
  mode: approvedMode
1207
1207
  };
1208
1208
  }
1209
+ const cwd = await options.resolveWorkingDirectory(exec);
1209
1210
  exec.signal.throwIfAborted();
1210
1211
  const runController = new AbortController();
1211
1212
  const onOuterAbort = () => {
@@ -1334,7 +1335,8 @@ function createRunCodeTool(registry, options) {
1334
1335
  arguments: normalized.logged,
1335
1336
  isError: result.isError,
1336
1337
  ...result.error?.info === void 0 ? {} : { error: result.error.info },
1337
- content: logged
1338
+ content: logged,
1339
+ ...result.meta === void 0 ? {} : { meta: result.meta }
1338
1340
  });
1339
1341
  })().finally(() => {
1340
1342
  logWork.delete(task);
@@ -1418,7 +1420,7 @@ function createRunCodeTool(registry, options) {
1418
1420
  }
1419
1421
  }],
1420
1422
  signal: runController.signal,
1421
- ...exec.agent?.session.header.cwd !== void 0 ? { cwd: exec.agent.session.header.cwd } : {},
1423
+ ...cwd !== void 0 ? { cwd } : {},
1422
1424
  ...policy !== void 0 ? { sandboxPolicy: policy } : {},
1423
1425
  ...args.timeoutMs !== void 0 ? { timeoutMs: args.timeoutMs } : {}
1424
1426
  }));
@@ -1452,7 +1454,7 @@ function createRunCodeTool(registry, options) {
1452
1454
  get: () => {
1453
1455
  const runtime = peekRuntime();
1454
1456
  const instructions = runtime?.executionInstructions;
1455
- return resolveFlavor(peekRuntime).description + (instructions ? ` ${instructions}` : "") + (runtime === void 0 ? "" : " The working directory is the Session's current directory.") + escalationGuidance(runtime);
1457
+ return resolveFlavor(peekRuntime).description + (instructions ? ` ${instructions}` : "") + (runtime === void 0 ? "" : " Each program starts in the Session's current directory. Running programs keep their initial directory.") + escalationGuidance(runtime);
1456
1458
  }
1457
1459
  });
1458
1460
  Object.defineProperty(definition, "parameters", {
@@ -1762,8 +1764,7 @@ function renderToolsSdk(schemas) {
1762
1764
  *
1763
1765
  * Under `mode: 'ptc'` the native tool schemas are omitted from the request, so this generated
1764
1766
  * SDK is the model's ONLY source for each tool's argument names, required fields, types,
1765
- * descriptions, and canonical output shapes; under `mode: 'both'` the native schemas ship
1766
- * alongside it and it is one of two. Object-shaped arguments and outputs therefore render as one
1767
+ * descriptions, and canonical output shapes. Object-shaped arguments and outputs therefore render as one
1767
1768
  * named `TypedDict` per tool (and per nested object), not an opaque `dict[str, Any]`, so the
1768
1769
  * shape survives into the program under the mode that has nothing else to carry it.
1769
1770
  * @module @qilin-agent/tools/src/py-types
@@ -2665,11 +2666,7 @@ function resolveMaxParallelSubCalls(value) {
2665
2666
  var ToolRuntime = class extends Service {
2666
2667
  static inject = ["systemPrompt"];
2667
2668
  static Config = z.object({
2668
- mode: z.union([
2669
- "native",
2670
- "ptc",
2671
- "both"
2672
- ]).default("native"),
2669
+ mode: z.union(["native", "ptc"]).default("native"),
2673
2670
  maxParallelSubCalls: z.natural().min(1).default(10)
2674
2671
  });
2675
2672
  /** Internal staged view consumed by `qilin-agent-loop`'s parallel scheduler. */
@@ -2722,7 +2719,7 @@ var ToolRuntime = class extends Service {
2722
2719
  * the deployment is inconsistent. Its order places the rule before that
2723
2720
  * guidance rather than after it.
2724
2721
  *
2725
- * `both` renders empty: native calls do execute there, so the rule is false.
2722
+ * Native scopes render no instruction.
2726
2723
  * @returns the section registration.
2727
2724
  */
2728
2725
  collapseSection() {
@@ -2783,6 +2780,12 @@ var ToolRuntime = class extends Service {
2783
2780
  */
2784
2781
  requirePtcTransport() {
2785
2782
  this.ptcTransport ??= createRunCodeTool(this, {
2783
+ resolveWorkingDirectory: async (exec) => {
2784
+ if (exec.agent === void 0) return void 0;
2785
+ const directories = this.ctx.get("workingDirectory");
2786
+ if (directories === void 0) throw new Error("qilin-tools: run_code with an Agent requires workingDirectory");
2787
+ return directories.ensure(exec.agent, exec.signal);
2788
+ },
2786
2789
  requireRuntime: () => this.requirePtcRuntime(this.defaultMode),
2787
2790
  peekApprover: () => this.ctx.get("approval"),
2788
2791
  resolveSandboxPolicy: (exec) => {
@@ -2836,14 +2839,9 @@ var ToolRuntime = class extends Service {
2836
2839
  knownNames: [...view.knownNames]
2837
2840
  };
2838
2841
  this.requirePtcRuntime(mode);
2839
- const schemas = [...view.visible.values()].map((definition) => this.schemaOf(definition, false));
2840
- if (mode === "ptc") return {
2841
- schemas: schemas.filter((schema) => schema.name === RUN_CODE_NAME),
2842
- knownNames: [RUN_CODE_NAME]
2843
- };
2844
2842
  return {
2845
- schemas,
2846
- knownNames: [...view.knownNames, RUN_CODE_NAME]
2843
+ schemas: [...view.visible.values()].map((definition) => this.schemaOf(definition, false)).filter((schema) => schema.name === RUN_CODE_NAME),
2844
+ knownNames: [RUN_CODE_NAME]
2847
2845
  };
2848
2846
  }
2849
2847
  /**
@@ -3542,7 +3540,7 @@ var ToolRuntime = class extends Service {
3542
3540
  }
3543
3541
  const content = snapshotProjection(tool.name, "render", rendered);
3544
3542
  let meta;
3545
- if (exec.parent === void 0 && tool.output.presentationMeta !== void 0) {
3543
+ if (tool.output.presentationMeta !== void 0) {
3546
3544
  let projected;
3547
3545
  try {
3548
3546
  projected = tool.output.presentationMeta(exec.arguments, value);
@@ -108,7 +108,7 @@ export interface ToolOutputDefinition {
108
108
  readonly schema: JsonSchemaNode;
109
109
  /** Pure projection from validated arguments and value to Native/model content. */
110
110
  render(args: unknown, value: JsonValue): ContentBlock[];
111
- /** Pure replayable presentation projection, computed only for top-level calls. */
111
+ /** Pure replayable presentation projection for native and nested calls. */
112
112
  presentationMeta?(args: unknown, value: JsonValue): JsonValue;
113
113
  }
114
114
  /** A registered tool: its schema plus the execution function. */
@@ -472,15 +472,15 @@ export type PostToolDecision = {
472
472
  additionalContexts?: UserMessage[];
473
473
  };
474
474
  /** How the registry presents its tools to the model (see {@link Config.mode}). */
475
- export type ToolPresentationMode = 'native' | 'ptc' | 'both';
475
+ export type ToolPresentationMode = 'native' | 'ptc';
476
476
  /** Plugin config: how the registered tools are presented to the model. */
477
477
  export interface Config {
478
478
  /**
479
479
  * Model presentation. `native` (default) sends every visible schema; `ptc`
480
480
  * sends only `run_code` plus a generated SDK prompt and collapses the
481
481
  * executor to the same surface (a model-direct call may only name
482
- * `run_code`; `run_code` SDK sub-dispatches keep every visible tool); `both`
483
- * sends both forms. PTC mode requires a `ctx.ptcRuntime` whose `language`
482
+ * `run_code`; `run_code` SDK sub-dispatches keep every visible tool).
483
+ * PTC mode requires a `ctx.ptcRuntime` whose `language`
484
484
  * has a registered SDK renderer (TypeScript or Python) and fail prompt
485
485
  * assembly when it is absent or has no renderer. Under `ptc`, native names
486
486
  * in `toolOrder` are invalid.
@@ -555,7 +555,7 @@ export declare class ToolRuntime extends Service {
555
555
  * the deployment is inconsistent. Its order places the rule before that
556
556
  * guidance rather than after it.
557
557
  *
558
- * `both` renders empty: native calls do execute there, so the rule is false.
558
+ * Native scopes render no instruction.
559
559
  * @returns the section registration.
560
560
  */
561
561
  private collapseSection;
@@ -222,7 +222,7 @@ function resolveMaxParallelSubCalls(value) {
222
222
  export class ToolRuntime extends Service {
223
223
  static inject = ['systemPrompt'];
224
224
  static Config = z.object({
225
- mode: z.union(['native', 'ptc', 'both']).default('native'),
225
+ mode: z.union(['native', 'ptc']).default('native'),
226
226
  maxParallelSubCalls: z.natural().min(1).default(10),
227
227
  });
228
228
  /** Internal staged view consumed by `qilin-agent-loop`'s parallel scheduler. */
@@ -275,7 +275,7 @@ export class ToolRuntime extends Service {
275
275
  * the deployment is inconsistent. Its order places the rule before that
276
276
  * guidance rather than after it.
277
277
  *
278
- * `both` renders empty: native calls do execute there, so the rule is false.
278
+ * Native scopes render no instruction.
279
279
  * @returns the section registration.
280
280
  */
281
281
  collapseSection() {
@@ -348,6 +348,16 @@ export class ToolRuntime extends Service {
348
348
  */
349
349
  requirePtcTransport() {
350
350
  this.ptcTransport ??= createRunCodeTool(this, {
351
+ resolveWorkingDirectory: async (exec) => {
352
+ // Only Agent-owned PTC requires directory state; native registries
353
+ // and unowned programs can run without this service.
354
+ if (exec.agent === undefined)
355
+ return undefined;
356
+ const directories = this.ctx.get('workingDirectory');
357
+ if (directories === undefined)
358
+ throw new Error('qilin-tools: run_code with an Agent requires workingDirectory');
359
+ return directories.ensure(exec.agent, exec.signal);
360
+ },
351
361
  requireRuntime: () => this.requirePtcRuntime(this.defaultMode),
352
362
  peekApprover: () => this.ctx.get('approval'),
353
363
  resolveSandboxPolicy: (exec) => {
@@ -419,13 +429,10 @@ export class ToolRuntime extends Service {
419
429
  // language with no SDK renderer.
420
430
  this.requirePtcRuntime(mode);
421
431
  const schemas = [...view.visible.values()].map(definition => this.schemaOf(definition, false));
422
- if (mode === 'ptc') {
423
- return {
424
- schemas: schemas.filter(schema => schema.name === RUN_CODE_NAME),
425
- knownNames: [RUN_CODE_NAME],
426
- };
427
- }
428
- return { schemas, knownNames: [...view.knownNames, RUN_CODE_NAME] };
432
+ return {
433
+ schemas: schemas.filter(schema => schema.name === RUN_CODE_NAME),
434
+ knownNames: [RUN_CODE_NAME],
435
+ };
429
436
  }
430
437
  /**
431
438
  * Resolve the PTC runtime or throw the actionable misconfiguration error.
@@ -1194,7 +1201,7 @@ export class ToolRuntime extends Service {
1194
1201
  }
1195
1202
  const content = snapshotProjection(tool.name, 'render', rendered);
1196
1203
  let meta;
1197
- if (exec.parent === undefined && tool.output.presentationMeta !== undefined) {
1204
+ if (tool.output.presentationMeta !== undefined) {
1198
1205
  let projected;
1199
1206
  try {
1200
1207
  projected = tool.output.presentationMeta(exec.arguments, value);
@@ -47,6 +47,8 @@ export declare class CodeRunFailedError extends HarnessError {
47
47
  * off its public service API and flow here as closures instead.
48
48
  */
49
49
  export interface RunCodeBridgeOptions {
50
+ /** Captures the calling Session current directory before program creation. */
51
+ resolveWorkingDirectory: (exec: ToolRunContext) => Promise<string | undefined>;
50
52
  /** Reads the approval channel when a program requests a wider sandbox mode. */
51
53
  peekApprover: () => ApprovalService | undefined;
52
54
  /** Resolves standing Session authority only for a runtime that enforces file policy. */
package/lib/types/ptc.js CHANGED
@@ -317,6 +317,7 @@ export function createRunCodeTool(registry, options) {
317
317
  });
318
318
  policy = { ...standingPolicy, mode: approvedMode };
319
319
  }
320
+ const cwd = await options.resolveWorkingDirectory(exec);
320
321
  exec.signal.throwIfAborted();
321
322
  // The run-scoped abort: follows the outer signal in, and fires when the
322
323
  // run settles for ANY reason, so an in-flight sub-dispatch is aborted
@@ -480,6 +481,7 @@ export function createRunCodeTool(registry, options) {
480
481
  isError: result.isError,
481
482
  ...result.error?.info === undefined ? {} : { error: result.error.info },
482
483
  content: logged,
484
+ ...result.meta === undefined ? {} : { meta: result.meta },
483
485
  });
484
486
  })().finally(() => { logWork.delete(task); });
485
487
  logWork.add(task);
@@ -590,7 +592,7 @@ export function createRunCodeTool(registry, options) {
590
592
  errorClass: { name: 'ToolCallError', memberNameProperty: 'toolName' },
591
593
  }],
592
594
  signal: runController.signal,
593
- ...exec.agent?.session.header.cwd !== undefined ? { cwd: exec.agent.session.header.cwd } : {},
595
+ ...cwd !== undefined ? { cwd } : {},
594
596
  ...policy !== undefined ? { sandboxPolicy: policy } : {},
595
597
  ...args.timeoutMs !== undefined ? { timeoutMs: args.timeoutMs } : {},
596
598
  }));
@@ -641,7 +643,7 @@ export function createRunCodeTool(registry, options) {
641
643
  const instructions = runtime?.executionInstructions;
642
644
  return resolveFlavor(peekRuntime).description
643
645
  + (instructions ? ` ${instructions}` : '')
644
- + (runtime === undefined ? '' : " The working directory is the Session's current directory.")
646
+ + (runtime === undefined ? '' : " Each program starts in the Session's current directory. Running programs keep their initial directory.")
645
647
  + escalationGuidance(runtime);
646
648
  },
647
649
  });
@@ -7,8 +7,7 @@
7
7
  *
8
8
  * Under `mode: 'ptc'` the native tool schemas are omitted from the request, so this generated
9
9
  * SDK is the model's ONLY source for each tool's argument names, required fields, types,
10
- * descriptions, and canonical output shapes; under `mode: 'both'` the native schemas ship
11
- * alongside it and it is one of two. Object-shaped arguments and outputs therefore render as one
10
+ * descriptions, and canonical output shapes. Object-shaped arguments and outputs therefore render as one
12
11
  * named `TypedDict` per tool (and per nested object), not an opaque `dict[str, Any]`, so the
13
12
  * shape survives into the program under the mode that has nothing else to carry it.
14
13
  * @module @qilin-agent/tools/src/py-types
@@ -7,8 +7,7 @@
7
7
  *
8
8
  * Under `mode: 'ptc'` the native tool schemas are omitted from the request, so this generated
9
9
  * SDK is the model's ONLY source for each tool's argument names, required fields, types,
10
- * descriptions, and canonical output shapes; under `mode: 'both'` the native schemas ship
11
- * alongside it and it is one of two. Object-shaped arguments and outputs therefore render as one
10
+ * descriptions, and canonical output shapes. Object-shaped arguments and outputs therefore render as one
12
11
  * named `TypedDict` per tool (and per nested object), not an opaque `dict[str, Any]`, so the
13
12
  * shape survives into the program under the mode that has nothing else to carry it.
14
13
  * @module @qilin-agent/tools/src/py-types
@@ -188,7 +188,7 @@ export interface DefineToolOptions<S extends ParameterSchemaSpec, O extends Valu
188
188
  readonly schema: O;
189
189
  /** Pure Native/model rendering of one validated canonical value. */
190
190
  render(args: InferArgs<S>, value: InferValue<NoInfer<O>>): ContentBlock[];
191
- /** Pure replayable presentation metadata for direct top-level calls. */
191
+ /** Pure replayable presentation metadata for native and nested calls. */
192
192
  presentationMeta?(args: InferArgs<S>, value: InferValue<NoInfer<O>>): JsonValue;
193
193
  };
194
194
  /** Requests deferred loading of the tool definition; see {@link @qilin-agent/llm#ToolSchema.deferLoading}. */
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import type { ToolCallId } from '@qilin-agent/llm/brand';
7
7
  import type { ContentBlock } from '@qilin-agent/llm/types';
8
+ import type { JsonValue } from '@qilin-agent/util-values';
8
9
  /** Payload recorded when one nested PTC mode Tool dispatch starts. */
9
10
  export interface PtcDispatchStartEventData {
10
11
  rootCallId: ToolCallId;
@@ -17,6 +18,8 @@ export interface PtcDispatchStartEventData {
17
18
  export interface PtcDispatchEventData extends PtcDispatchStartEventData {
18
19
  isError: boolean;
19
20
  content: ContentBlock[];
21
+ /** Replayable tool-owned presentation metadata, separate from model content. */
22
+ meta?: JsonValue;
20
23
  /** Optional failure identity and raw user-facing detail, outside model-facing content. */
21
24
  error?: {
22
25
  name: string;
@@ -45,10 +48,10 @@ declare module '@qilin-agent/session/types' {
45
48
  * `tool/ptc-dispatch-start` with the same `subCallId`), the tool `name`
46
49
  * with the same JSON-normalized `arguments`, and the sub-call's complete
47
50
  * durable outcome in `tool/result`'s own vocabulary (`content` + `isError`
48
- * + optional structured `error`), so UIs and SDKs render a sub-call through
49
- * the exact path used for a native call. Every started sub-call settles
50
- * with exactly one of these (abort included: the aborted pipeline result
51
- * is an `isError` outcome).
51
+ * + optional presentation `meta` and structured `error`), so UIs and SDKs
52
+ * render a sub-call through the exact path used for a native call. Every
53
+ * started sub-call settles with exactly one of these (abort included: the
54
+ * aborted pipeline result is an `isError` outcome).
52
55
  * Log-only: `deriveMessages()` ignores it, so sub-calls never re-enter
53
56
  * model context; persistence and UIs get every call. Appended inside the
54
57
  * parent `run_code`'s execution (the bridge drains in-flight dispatches
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qilin-agent/tools",
3
3
  "description": "Tool registry and execution pipeline for the QiLin",
4
- "version": "3.1.3",
4
+ "version": "3.1.5",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -39,33 +39,35 @@
39
39
  ],
40
40
  "license": "MIT",
41
41
  "peerDependencies": {
42
- "@qilin-agent/agent": "3.1.3",
43
- "@qilin-agent/scope": "3.1.3",
44
- "@qilin-agent/ptc-runtime": "3.1.3",
45
42
  "@qilin-agent/kylin": "~4.0.3",
46
- "@qilin-agent/session": "3.1.3",
47
- "@qilin-agent/system-prompt": "3.1.3",
48
- "@qilin-agent/user-approval": "3.1.3",
49
- "@qilin-agent/llm": "3.1.3",
50
- "@qilin-agent/sandbox": "3.1.3",
51
- "@qilin-agent/sandbox-policy": "3.1.3"
43
+ "@qilin-agent/ptc-runtime": "3.1.5",
44
+ "@qilin-agent/agent": "3.1.5",
45
+ "@qilin-agent/llm": "3.1.5",
46
+ "@qilin-agent/system-prompt": "3.1.5",
47
+ "@qilin-agent/session": "3.1.5",
48
+ "@qilin-agent/user-approval": "3.1.5",
49
+ "@qilin-agent/sandbox": "3.1.5",
50
+ "@qilin-agent/working-directory": "3.1.5",
51
+ "@qilin-agent/scope": "3.1.5",
52
+ "@qilin-agent/sandbox-policy": "3.1.5"
52
53
  },
53
54
  "dependencies": {
54
- "@qilin-agent/brand": "3.1.3",
55
- "@qilin-agent/util-values": "3.1.3",
55
+ "@qilin-agent/brand": "3.1.5",
56
+ "@qilin-agent/util-values": "3.1.5",
56
57
  "@qilin-agent/schemastery": "~3.18.3"
57
58
  },
58
59
  "devDependencies": {
59
- "@qilin-agent/agent": "3.1.3",
60
- "@qilin-agent/ptc-runtime": "3.1.3",
61
60
  "@qilin-agent/kylin": "~4.0.3",
62
- "@qilin-agent/llm": "3.1.3",
63
- "@qilin-agent/session": "3.1.3",
64
- "@qilin-agent/session-projection": "3.1.3",
65
- "@qilin-agent/scope": "3.1.3",
66
- "@qilin-agent/user-approval": "3.1.3",
67
- "@qilin-agent/system-prompt": "3.1.3",
68
- "@qilin-agent/sandbox": "3.1.3",
69
- "@qilin-agent/sandbox-policy": "3.1.3"
61
+ "@qilin-agent/agent": "3.1.5",
62
+ "@qilin-agent/ptc-runtime": "3.1.5",
63
+ "@qilin-agent/scope": "3.1.5",
64
+ "@qilin-agent/llm": "3.1.5",
65
+ "@qilin-agent/session-projection": "3.1.5",
66
+ "@qilin-agent/system-prompt": "3.1.5",
67
+ "@qilin-agent/sandbox": "3.1.5",
68
+ "@qilin-agent/user-approval": "3.1.5",
69
+ "@qilin-agent/working-directory": "3.1.5",
70
+ "@qilin-agent/sandbox-policy": "3.1.5",
71
+ "@qilin-agent/session": "3.1.5"
70
72
  }
71
73
  }