@deepseek-ai/dsh-ptc-runtime-node 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
@@ -9,23 +9,26 @@
9
9
  en: 7e1a8657a212c70b
10
10
  zh: afb7a8c6a3afd718
11
11
  /deepseek-ai-dsh-ptc-runtime-node/summary:
12
- en: 4d6be30d9289a58e
13
- zh: b1b2b4d773d32029
12
+ en: 91379c5dc7f04630
13
+ zh: 6ae48abc2097a7ef
14
14
  /deepseek-ai-dsh-ptc-runtime-node/table-of-contents:
15
15
  en: d152484eb41ac6b4
16
16
  zh: 725b47765ee8f30b
17
17
  /deepseek-ai-dsh-ptc-runtime-node/use-this-package:
18
18
  en: 246231cf2a529550
19
- zh: 2b4ed96194acc639
19
+ zh: 5d27b8e444ecd0f7
20
20
  /deepseek-ai-dsh-ptc-runtime-node/use-this-package/configuration:
21
- en: e5bca585d02f08ca
22
- zh: a2e9a32fe4052d90
21
+ en: 161f3b32c782bab4
22
+ zh: bd923e3d31261032
23
23
  /deepseek-ai-dsh-ptc-runtime-node/use-this-package/execution-and-results:
24
- en: 6d65b39223ca9f7a
25
- zh: 96f96341ecab1317
24
+ en: c79baab0c0a49ca7
25
+ zh: b90b78d0d75280fb
26
+ /deepseek-ai-dsh-ptc-runtime-node/use-this-package/in-memory-mode:
27
+ en: df9944346e78d7de
28
+ zh: e328efc31cbfb0bb
26
29
  /deepseek-ai-dsh-ptc-runtime-node/use-this-package/deadlines-and-cancellation:
27
- en: 803c1a6e876c68e6
28
- zh: 646232ebc4770680
30
+ en: ad72b8bdba6a3966
31
+ zh: 28a20fb5fb7c622d
29
32
  /deepseek-ai-dsh-ptc-runtime-node/use-this-package/failures:
30
33
  en: 7682e50f9dcfa25c
31
34
  zh: ddcb3502e12be06f
@@ -33,14 +36,14 @@
33
36
  en: 9020b491a39e4bf5
34
37
  zh: bcd1b2b1a3bde7f3
35
38
  /deepseek-ai-dsh-ptc-runtime-node/understand-the-implementation/launch-and-control:
36
- en: 45527dad94dd9362
39
+ en: 894cf1c1fdbe0092
37
40
  zh: c1e1179391e89a3f
38
41
  /deepseek-ai-dsh-ptc-runtime-node/understand-the-implementation/source-and-built-bootstraps:
39
- en: c01071304a9d563a
40
- zh: 2938a64b13a257d8
42
+ en: e7251a2f7cb8f134
43
+ zh: f68c08c507992969
41
44
  /deepseek-ai-dsh-ptc-runtime-node/understand-the-implementation/source-map:
42
- en: e4cab2eb3f09e74b
43
- zh: 5c10e8c4c0d9e56b
45
+ en: 2a702f70cac410d1
46
+ zh: f275136c6019b56d
44
47
  /deepseek-ai-dsh-ptc-runtime-node/further-exploration:
45
48
  en: ac2e2ae13d3f1394
46
49
  zh: 5d08b9c658fcf83a
@@ -51,8 +54,8 @@
51
54
  en: 40294c1c31b74824
52
55
  zh: d91e7b78c0619c7e
53
56
  /deepseek-ai-dsh-ptc-runtime-node/known-limitations-and-deferred-work:
54
- en: 88eac5d4119c11f6
55
- zh: ba0861bf07c5e9df
57
+ en: 7b8d67207e35bbb3
58
+ zh: 246cd770e79078ac
56
59
  /deepseek-ai-dsh-ptc-runtime-node/known-limitations-and-deferred-work/dev-note:
57
60
  en: 6373aba4e08f7205
58
61
  zh: 2a8c33d1f2839df4
package/README.md CHANGED
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- Execute model-written TypeScript under the same platform sandbox policy as Bash, with host-provided functions available as async bindings. Each call starts a fresh Node process and returns captured logs, an exact JSON value, or a structured failure. Direct Node APIs remain available within the selected restrictions. Elapsed deadlines, output bounds and a V8 heap limit constrain execution; cancellation and completion terminate the managed process range. A requested restricted mode fails when its sandbox backend is unavailable.
12
+ Execute model-written TypeScript with host-provided async functions. The default `per-call` mode starts a fresh Node process under the same platform sandbox policy as Bash. Opt-in `persistent-in-memory` mode retains a confined REPL across calls for each Agent. Both return captured logs, an exact JSON value, or a structured failure. Direct Node APIs remain available within the selected restrictions. Elapsed deadlines, output bounds and a V8 heap limit constrain execution; cancellation and per-call completion terminate the managed process range. A requested restricted mode fails when its sandbox backend is unavailable.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -34,6 +34,7 @@ Configure the provider row after its required services are available:
34
34
  ```yaml
35
35
  - name: '@deepseek-ai/dsh-ptc-runtime-node'
36
36
  config:
37
+ executionMode: per-call
37
38
  timeoutMs: 120000
38
39
  maxTimeoutMs: 600000
39
40
  maxOutputBytes: 67108864
@@ -45,6 +46,7 @@ Configure the provider row after its required services are available:
45
46
 
46
47
  | Field | Default | Meaning |
47
48
  |---|---|---|
49
+ | `executionMode` | `per-call` | `per-call` starts fresh processes under file policy; `persistent-in-memory` retains a confined REPL per owner |
48
50
  | `timeoutMs` | `120,000` | Default elapsed execution deadline, including nested tool and approval waits |
49
51
  | `maxTimeoutMs` | `600,000` | Elapsed deadline ceiling applied by the resolver |
50
52
  | `maxOutputBytes` | `67,108,864` | Combined serialized logs and completion or diagnostic budget |
@@ -52,22 +54,42 @@ Configure the provider row after its required services are available:
52
54
  | `maxMessageBytes` | `134,217,728` | Limit for a control frame, outstanding argument bytes and queued control writes |
53
55
  | `maxPendingCalls` | `128` | Maximum simultaneous host binding calls |
54
56
  | `graceMs` | `3,000` | Managed termination and output-drain grace |
55
- | `nodeExecutable` | Current Node executable | Executable resolved in the subprocess execution world |
56
- | `bootstrapPath` | Package bootstrap | Optional absolute path to a preinstalled built bootstrap in that world |
57
+ | `launch` | Local carrier | Explicit `{ kind: "node-script", executable, bootstrapPath? }` or `{ kind: "embedded", executable }` in the subprocess world |
57
58
 
58
- The [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-ptc-runtime-node) defines accepted config fields. `resolve(request)` supplies cwd, the numeric or null deadline choice and the execution policy; `run(spec)` accepts those resolved inputs and does not fill missing values.
59
+ The [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-ptc-runtime-node) defines accepted config fields. `resolve(request)` defaults cwd to the sandbox policy workspace root and supplies the numeric or null deadline choice and execution policy; `run(spec)` accepts those resolved inputs and does not fill missing values.
59
60
 
60
61
  ### Execution and results
61
62
 
62
- Programs are async function bodies: top-level `await` and `return` work, and only erasable TypeScript is accepted. A successful call returns its lossless-JSON value as `result.value` and captured text as `result.logs`. `result.sandbox` reports the selected mode, observed denial and the backend's full or partial enforcement independently of the program outcome.
63
+ In `per-call` mode, programs are async function bodies: top-level `await` and `return` work, and only erasable TypeScript is accepted. A successful call returns its lossless-JSON value as `result.value` and captured text as `result.logs`. `result.sandbox` reports the selected mode, observed denial and the backend's full or partial enforcement independently of the program outcome.
63
64
 
64
65
  Direct filesystem, network and subprocess operations remain Node operations, subject to the selected OS sandbox. Nested host bindings cross the control channel; PTC tool calls retain the registry's visibility, ordering, logging and approval rules. Running a program does not change the Session's standing policy or automatically replay it after a denial.
65
66
 
67
+ <a id="persistent-repl"></a>
68
+ ### In-memory mode
69
+
70
+ Set `executionMode: persistent-in-memory` on the existing `@deepseek-ai/dsh-ptc-runtime-node` plugin to retain state. Both modes require `fs`, `subprocess`, `sandbox` and `sandboxPolicy`; both apply the selected file sandbox policy. Enable it deliberately with a profile patch:
71
+
72
+ ```yaml
73
+ - id: ptc-runtime
74
+ config:
75
+ executionMode: persistent-in-memory
76
+ ```
77
+
78
+ Save the patch and pass its path to `dsh headless --patch <path>` in a composition with PTC tool presentation. The default `per-call` mode retains no program memory between calls. Changing the configuration reloads the provider and releases its execution resources. Packaged single-executable hosts require a `node-script` launch with `launch.executable` pointing to Node and `launch.bootstrapPath` pointing to this package's built `persistent-process.js` for in-memory execution.
79
+
80
+ Each live Agent keeps its own process and top-level variables, functions, and imported modules across `run_code` calls and turns. Use `await import(...)`, `console.log(...)`, and a final JSON expression; top-level `return` is not supported. Assignments to undeclared names create retained globals under Node REPL’s non-strict evaluation. `_` and `_error` are ordinary retained globals, without interactive REPL result setters. Node REPL declaration rules apply, including errors on redeclaring existing `let`, `const`, or `class` names; assign to a mutable binding or choose a new name. A leading `{ ... }` is a statement block and can contain top-level await and temporary declarations; parenthesize an object expression to return it. Retained functions and saved tool methods call the current evaluation's bindings. All tool calls must be awaited; callbacks from a completed evaluation cannot invoke tools in a later evaluation.
81
+
82
+ Memory is best-effort and never saved to disk. Restart, Agent disposal, provider unload, cancellation, timeout, protocol failure, output overflow, or process exit clears it. Missing variables raise normal reference errors; reacquire handles and recreate declarations. Exceptions in the active evaluation settle once and preserve earlier mutations. Exceptions thrown by callbacks from a completed evaluation are not reported in a later result; await asynchronous work before completing an evaluation. The Session still records programs, tool dispatches and visible results; restoring a Session or forking an Agent starts with empty memory. Each evaluation resets the process working directory to its resolved cwd; program calls to `process.chdir()` do not persist across evaluations. Direct Node access follows the resolved file policy. A retained owner cannot change mode, workspace root or Session identity until its environment is released.
83
+
84
+ Service consumers pass an object as `stateOwner` to reuse its environment and await `release(owner)` when finished. Requests without an owner run in temporary processes. Permission setters record the new mode synchronously. The runtime immediately invalidates affected processes and begins cancellation when the Session mode changes, including idle environments. The next program waits for their cleanup before starting; cleanup failure blocks that program and remains retryable. Permission-setting success does not mean old processes have finished stopping. A one-time approved escalation uses a separate environment and awaits its cleanup before returning; it cannot read the standing environment's variables or retain new declarations. Concurrent runs for one owner reject until execution and required cleanup complete; distinct owners may run concurrently. An idle environment has no expiration timer and keeps its process until release or failure. Raw stdout/stderr have no evaluation identity: bytes received during an evaluation share its output budget, even when written by an earlier child process; idle stdout is discarded and idle stderr retains only the bounded diagnostic tail. Await child-process completion before ending an evaluation. Process-exit diagnostics include the exit code and retained stderr tail; idle failures are written to the host logger. If process observation fails during cleanup, releasing the owner retries termination; new runs remain blocked until cleanup succeeds. Pipes that fail to drain after confirmed process exit produce a diagnostic but do not prevent releasing the environment.
85
+
66
86
  ### Deadlines and cancellation
67
87
 
68
- The PTC consumer exposes per-call timeout and approved sandbox choices as described in [dsh-tools](../../core/tools/README.md#ptc-mode). The runtime's readonly `timeout` descriptor reports its effective default and maximum to that consumer. Its `executionInstructions` describes fresh Node state, direct Node APIs, the empty program environment and file policy in the model-visible schema.
88
+ For calls carrying a Session policy, a mode change cancels admission even while waiting for cleanup or process startup. Restoring the previous mode does not revive a canceled call.
89
+
90
+ The PTC consumer exposes per-call timeout and approved sandbox choices as described in [dsh-tools](../../core/tools/README.md#ptc-mode). The runtime's readonly `timeout` descriptor reports its effective default and maximum to that consumer. The provider owns execution syntax, output syntax and state-retention guidance in `executionInstructions`. The tool consumer appends those mode-specific rules to its model-visible schema without inferring persistence from `programFormat`.
69
91
 
70
- Omitting `timeoutMs` uses the configured elapsed default; numeric requests are validated and capped. Service callers can explicitly pass `timeoutMs: null` to omit the elapsed timer, as the workflow adapter does; `run_code` continues to accept only positive numeric overrides. An enabled deadline covers runtime setup and execution, including time awaiting nested tools or approval. It is not a CPU meter. Timeout or cancellation stops a synchronous loop through the host's managed process owner; successful completion also cleans that managed range. The timer stops when an outcome is selected, before cleanup, so the returned call can take longer than its execution deadline while cleanup settles.
92
+ Omitting `timeoutMs` uses the configured elapsed default; numeric requests are validated and capped. Service callers can explicitly pass `timeoutMs: null` to omit the elapsed timer, as the workflow adapter does; `run_code` continues to accept only positive numeric overrides. An enabled deadline covers runtime setup and execution, including time awaiting nested tools or approval. It is not a CPU meter. Timeout or cancellation stops a synchronous loop through the host's managed process owner; successful per-call completion also cleans that managed range. The timer stops when an outcome is selected, before cleanup, so the returned call can take longer than its execution deadline while cleanup settles.
71
93
 
72
94
  ### Failures
73
95
 
@@ -85,19 +107,23 @@ The host owns policy, deadlines, binding lookup and process cleanup. The child o
85
107
 
86
108
  ### Launch and control
87
109
 
88
- The host strips erasable types, resolves the executable and bootstrap in the configured execution world, awaits argv confinement through `ctx.sandbox`, then spawns through `ctx.subprocess`. Cancellation is checked again after confinement, so a provider returning after cancellation cannot start the program. After adopting the inherited control channel, the child retains only executable-search, Windows system, and temporary paths in its OS environment and replaces the program-visible `process.env` with an empty dictionary. Windows ACL setup receives the parent's distinct `TEMP` and `TMP` values for shared grant locks, then replaces both with its private directory before starting the program. These native paths keep nested process creation and native temporary-file APIs functional. The host preserves `ELECTRON_RUN_AS_NODE` only for child startup so the Desktop executable runs the Node bootstrap; the bootstrap removes the selector before evaluating model code. The heap limit uses Node argv or a provider-created `NODE_OPTIONS` value for packaged executables; ambient loader and inspector flags are discarded.
110
+ For per-call execution, the host strips erasable types, resolves the executable and bootstrap in the configured execution world, awaits argv confinement through `ctx.sandbox`, then spawns through `ctx.subprocess`. Cancellation is checked again after confinement, so a provider returning after cancellation cannot start the program. After adopting the inherited control channel, the child retains only executable-search, Windows system, and temporary paths in its OS environment and replaces the program-visible `process.env` with an empty dictionary. Windows ACL setup receives the parent's distinct `TEMP` and `TMP` values for shared grant locks, then replaces both with its private directory before starting the program. These native paths keep nested process creation and native temporary-file APIs functional. The host preserves `ELECTRON_RUN_AS_NODE` only for child startup so the Desktop executable runs the Node bootstrap; the bootstrap removes the selector before evaluating model code. The heap limit uses Node argv or a provider-created `NODE_OPTIONS` value for packaged executables; ambient loader and inspector flags are discarded.
89
111
 
90
112
  Length-framed JSON travels separately from stdout/stderr. The host bounds frames and queued writes, validates call identity and declared binding names before dispatch, and refuses invalid traffic. The child flushes its terminal frame and keeps the control channel open until the host closes it. After submitting that frame, it ignores later binding replies and sends no further program control messages. Output capture meters serialized logs plus the completion or diagnostic; fixed result-envelope fields and sandbox metadata are outside that ledger.
91
113
 
92
114
  ### Source and built bootstraps
93
115
 
94
- Source execution loads an erasable-only bootstrap closure without relying on sibling built exports. Built execution uses the packaged `process.js` entry. An execution world that cannot map the host bootstrap requires a preinstalled compatible `bootstrapPath`; a host path is never assumed to name the same remote file.
116
+ Source execution loads an erasable-only bootstrap closure without relying on sibling built exports. Built script execution uses `process.js` for per-call programs or `persistent-process.js` for retained REPL environments. Persistent mode requires a `node-script` launch. A remote script deployment supplies the matching `launch.bootstrapPath`. Embedded carriers launch their private worker through `launch.executable`. `resolveLaunch()` selects the local default during construction; an explicit remote invocation never depends on whether the client itself is packaged. A host path is never assumed to name the same remote file.
95
117
 
96
118
  ### Source map
97
119
 
98
120
  | File | Role |
99
121
  |---|---|
100
- | [`src/index.ts`](src/index.ts) | Configuration, resolution, policy, bindings and managed execution |
122
+ | [`src/index.ts`](src/index.ts) | Node provider: mode selection, per-call resolution, policy and managed execution |
123
+ | [`src/config.ts`](src/config.ts) | Execution mode, validated limits and defaults |
124
+ | [`src/persistent.ts`](src/persistent.ts) | In-memory process ownership, evaluation deadlines and cleanup |
125
+ | [`src/persistent-process.ts`](src/persistent-process.ts) | Child REPL, retained declarations and current binding dispatch |
126
+ | [`src/output-stream.ts`](src/output-stream.ts) | Bounded stream capture and process-output draining |
101
127
  | [`src/launch.ts`](src/launch.ts) | Executable/bootstrap arguments and execution-world asset mapping |
102
128
  | [`src/process.ts`](src/process.ts) | Child handshake, environment clearing and program lifecycle |
103
129
  | [`src/bootstrap.ts`](src/bootstrap.ts) | Program evaluation, binding proxies and output capture |
@@ -138,7 +164,8 @@ These limits qualify the execution guarantees and retained output.
138
164
  - **Confinement inherits the selected backend's limits** — full and partial enforcement are reported separately; sandbox policy and managed-process containment are distinct guarantees.
139
165
  - **The heap cap is not a process-tree memory limit** — native allocations and descendant memory are outside the V8 old-generation bound. No process-tree CPU meter is supplied.
140
166
  - **Cleanup inherits subprocess observability** — escaped descendants on a fallback platform may remain outside the managed range; see the subprocess provider's stated limits.
141
- - **Execution is one-shot** — no yield/wait API, live result stream or retained program state exists between calls.
167
+ - **Default execution is one-shot** — retained state requires `executionMode: persistent-in-memory`; neither mode offers a yield/wait API.
168
+ - **In-memory environments retain one process per live owner** — idle owners keep their process and heap until explicit release, owner disposal or failure. Fan-out can retain many processes; idle expiration remains deferred.
142
169
  - **Output caps reject rather than retain every byte** — spill can preserve only the bounded result delivered by this provider.
143
170
  - **Bindings are bounded at transport admission** — control limits do not bound the memory a host binding allocates while producing its result.
144
171
  - **The console shim has five methods** — `log`, `info`, `warn`, `error` and `debug`.
package/README.zh.md CHANGED
@@ -9,7 +9,7 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- 在与 Bash 相同的平台沙箱策略下执行模型编写的 TypeScript,并通过异步绑定调用 Host 提供的函数。每次调用启动一个全新的 Node 进程,返回捕获日志、精确 JSON 值或结构化失败。直接 Node API 在所选限制内仍可使用。经过时间截止、输出上限和 V8 堆限制约束执行;取消和完成都会终止受管进程范围。请求受限模式但沙箱后端不可用时,执行失败。
12
+ 执行模型编写的 TypeScript,并提供宿主异步函数。默认的 `per-call` 模式每次启动新 Node 进程,使用与 Bash 相同的平台沙箱策略。显式启用的 `persistent-in-memory` 模式为每个 Agent 跨调用保留受限 REPL。两种模式都返回捕获的日志、精确 JSON 值或结构化失败。直接 Node API 受所选模式的限制。执行时限、输出上限和 V8 堆上限约束运行;取消与逐次执行完成后清理托管进程范围。请求受限模式而沙箱后端不可用时,执行失败。
13
13
 
14
14
  ## 目录
15
15
 
@@ -25,7 +25,7 @@ kind: "package-reference"
25
25
  <a id="use-this-package"></a>
26
26
  ## 使用本包
27
27
 
28
- 在提供 `fs`、`subprocess`、`sandbox` 与 `sandboxPolicy` 的组合中挂载本提供方。`dsh-tools` 的 PTC 模式传入调用 Session 的目录和常设策略;直接运行时消费方在执行前解析这些选项。
28
+ 在提供 `fs`、`subprocess`、`sandbox` 和 `sandboxPolicy` 的组合中挂载本提供方。`dsh-tools` 的 PTC 模式传入调用 Session 的目录和常设策略;直接运行时消费方在执行前解析这些选项。
29
29
 
30
30
  ### 配置
31
31
 
@@ -34,6 +34,7 @@ kind: "package-reference"
34
34
  ```yaml
35
35
  - name: '@deepseek-ai/dsh-ptc-runtime-node'
36
36
  config:
37
+ executionMode: per-call
37
38
  timeoutMs: 120000
38
39
  maxTimeoutMs: 600000
39
40
  maxOutputBytes: 67108864
@@ -45,6 +46,7 @@ kind: "package-reference"
45
46
 
46
47
  | 字段 | 默认值 | 含义 |
47
48
  |---|---|---|
49
+ | `executionMode` | `per-call` | `per-call` 每次按文件策略启动新进程;`persistent-in-memory` 为每个所有者保留受限 REPL |
48
50
  | `timeoutMs` | `120,000` | 默认经过时间截止,包括嵌套工具与审批等待 |
49
51
  | `maxTimeoutMs` | `600,000` | 解析器应用的经过时间截止上限 |
50
52
  | `maxOutputBytes` | `67,108,864` | 序列化日志与完成值或诊断的合计预算 |
@@ -52,22 +54,42 @@ kind: "package-reference"
52
54
  | `maxMessageBytes` | `134,217,728` | 控制帧、未完成参数字节和排队控制写入的上限 |
53
55
  | `maxPendingCalls` | `128` | 同时进行的 Host 绑定调用数量上限 |
54
56
  | `graceMs` | `3,000` | 受管终止与输出排空宽限时间 |
55
- | `nodeExecutable` | 当前 Node 可执行文件 | 在子进程执行世界中解析的可执行文件 |
56
- | `bootstrapPath` | 包内 bootstrap | 该执行世界中预先安装的构建后 bootstrap 的可选绝对路径 |
57
+ | `launch` | 本地载体 | 子进程环境中显式的 `{ kind: "node-script", executable, bootstrapPath? }` 或 `{ kind: "embedded", executable }` |
57
58
 
58
- [配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-ptc-runtime-node)定义可接受的配置字段。`resolve(request)` 补全 cwd、数值或 null 截止选择与执行策略;`run(spec)` 接受这些已解析输入,不补缺省值。
59
+ [配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-ptc-runtime-node)定义可接受的配置字段。`resolve(request)` 将 cwd 默认设为沙箱策略的工作区根目录,并补全数值或 null 截止选择与执行策略;`run(spec)` 接受这些已解析输入,不补缺省值。
59
60
 
60
61
  ### 执行与结果
61
62
 
62
- 程序是异步函数体:支持顶层 `await` 与 `return`,且只接受可擦除 TypeScript。成功调用以 `result.value` 返回无损 JSON 值,以 `result.logs` 返回捕获文本。`result.sandbox` 独立于程序结果报告所选模式、观察到的拒绝,以及后端完整或部分的强制能力。
63
+ `per-call` 模式中的程序是异步函数体:支持顶层 `await` 与 `return`,且只接受可擦除 TypeScript。成功调用以 `result.value` 返回无损 JSON 值,以 `result.logs` 返回捕获文本。`result.sandbox` 独立于程序结果报告所选模式、观察到的拒绝,以及后端完整或部分的强制能力。
63
64
 
64
65
  直接文件系统、网络与子进程操作仍是 Node 操作,受所选 OS 沙箱约束。嵌套 Host 绑定通过控制通道调用;PTC 工具调用保留注册表的可见性、排序、日志和审批规则。运行程序不会改变 Session 的常设策略,也不会在拒绝后自动重放程序。
65
66
 
67
+ <a id="persistent-repl"></a>
68
+ ### 内存保留模式
69
+
70
+ 在现有 `@deepseek-ai/dsh-ptc-runtime-node` 插件上设置 `executionMode: persistent-in-memory` 即可保留状态。两种模式都需要 `fs`、`subprocess`、`sandbox` 和 `sandboxPolicy`;两种模式都应用所选文件沙箱策略。通过配置档补丁显式启用:
71
+
72
+ ```yaml
73
+ - id: ptc-runtime
74
+ config:
75
+ executionMode: persistent-in-memory
76
+ ```
77
+
78
+ 保存补丁,在使用 PTC 工具展示的配置中通过 `dsh headless --patch <path>` 加载。默认的 `per-call` 模式不跨调用保留程序内存。修改配置会重载提供方并释放其执行资源。单文件打包宿主使用内存保留模式时,需要使用 `node-script` 启动方式,将 `launch.executable` 指向 Node,并将 `launch.bootstrapPath` 指向本包构建出的 `persistent-process.js`。
79
+
80
+ 每个存活 Agent 保留独立进程,跨 `run_code` 调用和轮次保留顶层变量、函数及导入模块。使用 `await import(...)`、`console.log(...)` 和末尾 JSON 表达式;不支持顶层 `return`。Node REPL 使用非严格模式,给未声明的名称赋值会创建保留的全局变量。`_` 和 `_error` 是普通的保留全局变量,不使用交互式 REPL 的结果设置器。声明遵循 Node REPL 规则,包括重复声明已有 `let`、`const` 或 `class` 名称时报错;应给可变绑定赋值或选择新名称。开头的 `{ ... }` 按语句块执行,可以包含顶层 await 和临时声明;需要返回对象表达式时,用圆括号包裹。保留的函数和工具方法引用调用当前执行的绑定。必须等待所有工具调用;已完成执行的回调不能在后续执行中调用工具。
81
+
82
+ 内存按尽力保留处理,不保存到磁盘。重启、Agent 销毁、提供方卸载、取消、超时、协议失败、输出超限或进程退出都会清除内存。缺失变量产生普通引用错误,模型需要重新获取句柄和创建声明。当前执行中的异常只结算一次,并保留此前发生的修改。已完成执行的回调抛出的异常不会在后续结果中报告;结束执行前应等待异步工作完成。Session 仍记录程序、工具分派和可见结果;恢复 Session 或派生 Agent 时从空内存开始。每次执行都会将进程工作目录重置为本次解析的 cwd;程序中的 `process.chdir()` 不跨执行保留。直接 Node 访问遵循已解析的文件策略。保留状态的所有者必须先释放环境,才能更改权限模式、工作区根目录或 Session 身份。
83
+
84
+ 服务消费者通过 `stateOwner` 对象复用环境,并在结束时等待 `release(owner)`。没有所有者的请求在临时进程中执行。权限设置同步记录新模式。Session 模式变化时,运行时立即禁止复用受影响的进程并开始取消,包括空闲环境。下一次程序执行前等待这些进程清理;清理失败会阻止本次程序启动,并允许重试。权限设置成功时,旧进程可能仍在停止过程中。单次获准的提权使用独立环境,返回前等待清理;该次执行无法访问原环境的变量,也不会保留新声明。执行及必要清理完成之前,同一所有者的并发调用会被拒绝;不同所有者可以并发。空闲环境没有过期计时器,进程保留到释放或失败为止。原始 stdout/stderr 不携带执行标识:执行期间收到的字节计入本次输出预算,包括较早启动的子进程此时写出的内容;空闲期间丢弃 stdout,只保留限额内的 stderr 诊断尾部。结束本次执行前,应等待子进程完成。进程退出诊断包含退出码和保留的 stderr 尾部;空闲期间的失败写入宿主日志。清理期间无法观测进程范围时,释放所有者会重试终止;清理成功前拒绝新执行。确认进程退出后仍未排空的管道会产生诊断,但不阻止释放环境。
85
+
66
86
  ### 截止时间与取消
67
87
 
68
- PTC 消费方按 [dsh-tools](../../core/tools/README.zh.md#ptc-mode) 的说明公开逐次超时与经审批的沙箱选择。运行时只读 `timeout` 描述符向该消费方报告有效默认值与上限。 其 `executionInstructions` 在面向模型的 schema 中说明全新 Node 状态、直接 Node API、空程序环境和文件策略。
88
+ 对于携带 Session 策略的调用,模式变化会取消其准入,即使调用仍在等待清理或进程启动。恢复先前的模式不会重新启用已取消的调用。
89
+
90
+ PTC 消费方按 [dsh-tools](../../core/tools/README.zh.md#ptc-mode) 的说明公开逐次超时与经审批的沙箱选择。运行时只读 `timeout` 描述符向该消费方报告有效默认值与上限。提供方通过 `executionInstructions` 负责求值语法、输出方式和状态保留指引。工具消费者将对应模式的规则附加到面向模型的 schema,不根据 `programFormat` 推断是否保留状态。
69
91
 
70
- 省略 `timeoutMs` 使用配置的经过时间默认值;数值请求经过验证并封顶。服务调用方可以显式传入 `timeoutMs: null` 来省略经过时间定时器,工作流适配器即如此;`run_code` 仍只接受正数覆盖值。启用的截止覆盖运行时准备和执行,包括等待嵌套工具或审批的时间。它不是 CPU 计量器。超时或取消通过 Host 的受管进程所有者停止同步循环;成功完成也会清理该受管范围。选择结果后、清理前停止计时器,因此调用可能要在执行截止之后等待清理结算才返回。
92
+ 省略 `timeoutMs` 使用配置的经过时间默认值;数值请求经过验证并封顶。服务调用方可以显式传入 `timeoutMs: null` 来省略经过时间定时器,工作流适配器即如此;`run_code` 仍只接受正数覆盖值。启用的截止覆盖运行时准备和执行,包括等待嵌套工具或审批的时间。它不是 CPU 计量器。超时或取消通过 Host 的受管进程所有者停止同步循环;逐次执行成功完成也会清理该受管范围。选择结果后、清理前停止计时器,因此调用可能要在执行截止之后等待清理结算才返回。
71
93
 
72
94
  ### 失败
73
95
 
@@ -91,13 +113,17 @@ Host 擦除可擦除类型,在配置的执行世界中解析可执行文件与
91
113
 
92
114
  ### 源代码与构建后 bootstrap
93
115
 
94
- 源代码执行加载仅含可擦除语法的 bootstrap 依赖,不依赖同级包的构建后导出。构建后执行使用包内 `process.js` 入口。无法映射 Host bootstrap 的执行世界需要预先安装兼容的 `bootstrapPath`;不会假设 Host 路径对应同一个远程文件。
116
+ 源代码执行加载仅含可擦除语法的 bootstrap 依赖,不依赖同级包的构建后导出。构建后脚本通过 `process.js` 运行逐次程序,通过 `persistent-process.js` 运行保留状态的 REPL。保留模式要求 `node-script` 启动方式。远端脚本部署提供对应的 `launch.bootstrapPath`。内嵌载体通过 `launch.executable` 启动私有 worker。`resolveLaunch()` 在构造时选择本地默认值;显式的远端调用不依赖客户端自身是否打包。不会假设 Host 路径对应同一个远程文件。
95
117
 
96
118
  ### 源码索引
97
119
 
98
120
  | 文件 | 职责 |
99
121
  |---|---|
100
- | [`src/index.ts`](src/index.ts) | 配置、解析、策略、绑定与受管执行 |
122
+ | [`src/index.ts`](src/index.ts) | 默认提供方的解析、策略、绑定与受管执行 |
123
+ | [`src/config.ts`](src/config.ts) | 执行模式、限制校验与默认值 |
124
+ | [`src/persistent.ts`](src/persistent.ts) | 内存保留模式的进程所有权、执行截止与清理 |
125
+ | [`src/persistent-process.ts`](src/persistent-process.ts) | 子进程 REPL、保留声明与当前绑定分派 |
126
+ | [`src/output-stream.ts`](src/output-stream.ts) | 有界流捕获与进程输出排空 |
101
127
  | [`src/launch.ts`](src/launch.ts) | 可执行文件/bootstrap 参数与执行世界资源映射 |
102
128
  | [`src/process.ts`](src/process.ts) | 子进程握手、环境清空与程序生命周期 |
103
129
  | [`src/bootstrap.ts`](src/bootstrap.ts) | 程序求值、绑定代理与输出捕获 |
@@ -138,7 +164,8 @@ Host 擦除可擦除类型,在配置的执行世界中解析可执行文件与
138
164
  - **约束继承所选后端的限制**——完整与部分强制能力分开报告;沙箱策略与受管进程约束是不同保证。
139
165
  - **堆上限不是进程树内存限制**——原生分配与后代进程内存不属于 V8 老生代上限。不提供进程树 CPU 计量器。
140
166
  - **清理继承子进程的可观测范围**——使用 fallback 的平台上,逃逸的后代可能仍在受管范围之外;参见子进程提供方声明的限制。
141
- - **执行是一次性的**——没有 yield/wait API、实时结果流或跨调用保留的程序状态。
167
+ - **默认执行是一次性的**:保留状态需要设置 `executionMode: persistent-in-memory`;两种模式都不提供 yield/wait API。
168
+ - **内存保留环境为每个存活所有者保留一个进程**——空闲所有者保留进程及堆内存,直到显式释放、所有者销毁或执行失败。并行创建多个所有者会保留多个进程;空闲过期机制留待后续处理。
142
169
  - **输出上限拒绝超量内容,而不保留每个字节**——溢出只能保存本提供方交付的有界结果。
143
170
  - **绑定在传输接纳时受限**——控制限制不约束 Host 绑定生成结果期间分配的内存。
144
171
  - **console shim 有五个方法**——`log`、`info`、`warn`、`error` 与 `debug`。