From 1f45e38279ccd0474d09cbbd7d6d6a8eacef7e9b Mon Sep 17 00:00:00 2001 From: _Kerman Date: Tue, 20 Oct 2026 23:16:24 +0800 Subject: [PATCH] feat(ptc-runtime): expose Script syntax and state retention --- docs/subsystems/ptc-runtime.i18n.yaml | 4 ++-- docs/subsystems/ptc-runtime.md | 12 +++++++----- docs/subsystems/ptc-runtime.zh.md | 12 +++++++----- packages/core/tools/README.i18n.yaml | 12 ++++++------ packages/core/tools/README.md | 6 +++--- packages/core/tools/README.zh.md | 6 +++--- packages/core/tools/src/index.ts | 4 ++-- packages/core/tools/src/ts-types.ts | 11 ++++++----- packages/ptc-runtime/ptc-runtime/README.i18n.yaml | 8 ++++---- packages/ptc-runtime/ptc-runtime/README.md | 4 ++-- packages/ptc-runtime/ptc-runtime/README.zh.md | 4 ++-- packages/ptc-runtime/ptc-runtime/src/index.ts | 5 ++++- packages/ptc-runtime/ptc-runtime/src/types.ts | 10 ++++++---- packages/workflow/workflow-ptc/README.i18n.yaml | 4 ++-- packages/workflow/workflow-ptc/README.md | 2 +- packages/workflow/workflow-ptc/README.zh.md | 2 +- packages/workflow/workflow-ptc/src/host.ts | 6 +++++- 17 files changed, 63 insertions(+), 49 deletions(-) diff --git a/docs/subsystems/ptc-runtime.i18n.yaml b/docs/subsystems/ptc-runtime.i18n.yaml index 7c6f634157..b9a617739e 100644 --- a/docs/subsystems/ptc-runtime.i18n.yaml +++ b/docs/subsystems/ptc-runtime.i18n.yaml @@ -6,8 +6,8 @@ en: 337a6580d7571274 zh: f4ae98899120d122 /ptc-runtime/the-run-request-in-result-out: - en: 0305ed1d4f8bc618 - zh: fcfeb156574b5779 + en: 6dfa7da8b13a4f17 + zh: 09a3c8c4922239ef /ptc-runtime/bindings-host-functions-as-program-globals: en: 182147ddf388c600 zh: c0a7d77602c78bcd diff --git a/docs/subsystems/ptc-runtime.md b/docs/subsystems/ptc-runtime.md index d9ad8138a0..3f01cbf4ac 100644 --- a/docs/subsystems/ptc-runtime.md +++ b/docs/subsystems/ptc-runtime.md @@ -19,9 +19,11 @@ interface PtcRunRequest { /** * The program source, in the runtime's {@link ../index.ts | language}. It * follows the provider's programFormat: an async function body supports - * top-level `await` and `return`; a REPL supports top-level declarations, - * `await`, and a final expression. The completion value becomes - * {@link PtcRunResult.value}. + * top-level `await` and `return`; REPL and Script programs support top-level + * declarations, `await`, and a final expression, but not top-level `return`. + * The Script provider lowers top-level await; its executionInstructions and + * documentation define retained-binding semantics. The completion value + * becomes {@link PtcRunResult.value}. */ program: string /** @@ -84,7 +86,7 @@ interface PtcRunResult { /** Applied file policy and observed denial, when the provider enforces file policy. */ sandbox?: PtcRunSandbox /** - * The program's completion value (a return or final REPL expression), when it ran to + * The program's completion value (a return or final REPL/Script expression), when it ran to * completion and the value crossed the runtime's lossless-JSON boundary. * Invalid or over-limit completions fail the run instead of substituting a * rendered string; a failed or value-less run leaves this absent. @@ -101,7 +103,7 @@ interface PtcRunResult { } ``` -`programFormat` distinguishes async function bodies from REPL statements. `stateOwner` is an in-process object identity for optional retained memory; distinct objects remain isolated. Consumers await `release(owner)` when that owner ends; cleanup failures reject that call. Omitted owners are one-shot, and stateless providers ignore ownership. The [persistent Node provider](../../packages/ptc-runtime/ptc-runtime-node/README.md#persistent-repl) defines reset and recovery behavior; no retained object enters the durable Session format. +`programFormat` distinguishes async function bodies, REPL statements, and scripts. REPL and Script programs accept top-level `await`, declarations, and a final expression; top-level `return` is not supported. The Node Script provider lowers top-level await and awaits the completion value; its [declaration limitations](../../packages/ptc-runtime/ptc-runtime-node/README.md#known-limitations-and-deferred-work) apply to transformed programs. `retainsState` reports memory retention independently of source syntax. `stateOwner` is an in-process object identity for optional retained memory; distinct objects remain isolated. Consumers await `release(owner)` when that owner ends; cleanup failures reject that call. Omitted owners are one-shot, and stateless providers ignore ownership. The [persistent Node provider](../../packages/ptc-runtime/ptc-runtime-node/README.md#persistent-repl) defines reset and recovery behavior; no retained object enters the durable Session format. ## Bindings: host functions as program globals diff --git a/docs/subsystems/ptc-runtime.zh.md b/docs/subsystems/ptc-runtime.zh.md index ba747b5369..cbb69aad8d 100644 --- a/docs/subsystems/ptc-runtime.zh.md +++ b/docs/subsystems/ptc-runtime.zh.md @@ -19,9 +19,11 @@ interface PtcRunRequest { /** * The program source, in the runtime's {@link ../index.ts | language}. It * follows the provider's programFormat: an async function body supports - * top-level `await` and `return`; a REPL supports top-level declarations, - * `await`, and a final expression. The completion value becomes - * {@link PtcRunResult.value}. + * top-level `await` and `return`; REPL and Script programs support top-level + * declarations, `await`, and a final expression, but not top-level `return`. + * The Script provider lowers top-level await; its executionInstructions and + * documentation define retained-binding semantics. The completion value + * becomes {@link PtcRunResult.value}. */ program: string /** @@ -84,7 +86,7 @@ interface PtcRunResult { /** Applied file policy and observed denial, when the provider enforces file policy. */ sandbox?: PtcRunSandbox /** - * The program's completion value (a return or final REPL expression), when it ran to + * The program's completion value (a return or final REPL/Script expression), when it ran to * completion and the value crossed the runtime's lossless-JSON boundary. * Invalid or over-limit completions fail the run instead of substituting a * rendered string; a failed or value-less run leaves this absent. @@ -101,7 +103,7 @@ interface PtcRunResult { } ``` -`programFormat` 区分异步函数体与 REPL 语句。`stateOwner` 是标识可选保留内存的进程内对象身份;不同对象相互隔离。消费者在所有者结束时等待 `release(owner)`;清理失败时该调用拒绝。省略所有者时仅执行一次,无状态提供方忽略所有权。[持久 Node 提供方](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#persistent-repl)定义重置和恢复行为;保留对象不会进入持久 Session 格式。 +`programFormat` 区分异步函数体、REPL 语句与脚本。REPL 与 Script 程序接受顶层 `await`、声明和末尾表达式,不支持顶层 `return`。Node Script 提供方转换顶层 await 并等待完成值;其[声明限制](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#known-limitations-and-deferred-work)适用于转换后的程序。`retainsState` 独立于源码语法报告是否保留内存。`stateOwner` 是标识可选保留内存的进程内对象身份;不同对象相互隔离。消费者在所有者结束时等待 `release(owner)`;清理失败时该调用拒绝。省略所有者时仅执行一次,无状态提供方忽略所有权。[持久 Node 提供方](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#persistent-repl)定义重置和恢复行为;保留对象不会进入持久 Session 格式。 ## 绑定:宿主函数作为程序全局变量 diff --git a/packages/core/tools/README.i18n.yaml b/packages/core/tools/README.i18n.yaml index f90a284f26..e94e8d7713 100644 --- a/packages/core/tools/README.i18n.yaml +++ b/packages/core/tools/README.i18n.yaml @@ -45,8 +45,8 @@ en: dc44a88997777988 zh: 56454aeace1c8b77 /deepseek-ai-dsh-tools/understand-the-implementation/ptc-mode: - en: 387700aa396f7ca2 - zh: d440b283027e4fbd + en: 1bac667d5e2dba60 + zh: 766b31cd4e356e04 /deepseek-ai-dsh-tools/understand-the-implementation/extension-points: en: c2a14d6f22bc9428 zh: 89c1414fca465931 @@ -72,8 +72,8 @@ en: eaefd7303f22977d zh: 9c425f9501128224 /deepseek-ai-dsh-tools/model-experience/ptc-mode-schema-and-system-prompt/what-the-model-sees: - en: 3e170a222d746e98 - zh: 1ea442fc59874cc5 + en: 0c6441978f5d9bfc + zh: 87553f9bb87ce9b6 /deepseek-ai-dsh-tools/model-experience/ptc-mode-schema-and-system-prompt/what-the-model-sees/typescript-ptc-mode-sdk-instructions-with-bash: en: 3a8df15e4ae32f9e zh: fc4a800ba363e835 @@ -96,8 +96,8 @@ en: 2fbf2175168e8244 zh: ad59a120b54a0996 /deepseek-ai-dsh-tools/known-limitations-and-deferred-work: - en: 4a412f89b8a71b5a - zh: 803d995b036d5dbf + en: c42ac2124a619bdc + zh: ec142b05a3912a49 /deepseek-ai-dsh-tools/known-limitations-and-deferred-work/dev-note: en: e67f633dc6fe7773 zh: 3bb0c20c93f16f98 diff --git a/packages/core/tools/README.md b/packages/core/tools/README.md index a5a7044916..77f3a899e4 100644 --- a/packages/core/tools/README.md +++ b/packages/core/tools/README.md @@ -133,7 +133,7 @@ New sub-calls use `:ptc:` ids. Consumers treat these ids as opaque an Successful image-bearing subcall results become deferred user-message context with `source.kind` set to `ptc-mode`. Other additional contexts retain their producing tool's attribution. -`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 schema asks the model to write that reason in the current user's language. 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. Retained PTC environments follow the standing file policy. PTC observes committed Session mode changes and immediately cancels affected calls in both Node modes. Later PTC calls wait for their nested-tool cleanup before resolving the latest policy. The runtime owns process invalidation and cleanup; permission setters remain synchronous. One-time escalations omit the state owner and complete in a temporary environment; standing variables remain available to ordinary calls. +`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 schema asks the model to write that reason in the current user's language. 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. Retained PTC environments follow the standing file policy. PTC observes committed Session mode changes and immediately cancels affected calls in all Node modes. Later PTC calls wait for their nested-tool cleanup before resolving the latest policy. The runtime owns process invalidation and cleanup; permission setters remain synchronous. One-time escalations omit the state owner and complete in a temporary environment; standing variables remain available to ordinary calls. ### Extension points @@ -179,7 +179,7 @@ Prefix-stable while visible definitions and their order are unchanged. Registrat #### What the model sees -PTC mode exposes the generated [`run_code` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tools), the SDK instructions below, and the generated exact SDK block for the loaded runtime's language. Both runtime languages list `code` before `description`; this is presentation order, not an enforced JSON member order. The TypeScript instructions use a return-value example for function-body runtimes and a printed-output example for REPL runtimes. They identify generated declarations as program-only bindings. When the current `bash` parameter schema accepts the example arguments, they also show a complete `run_code` call around `tools.bash(...)`. The `tools:sdk` section uses first-party order 5000 and disables prompt-variable interpolation, preserving literal `{{…}}` text in tool descriptions and schemas for both runtime languages. Under `ptc`, the prompt also carries the `tools:ptc-only` rule earlier in the first-party order, so the model reads which tools it may call before it reads what each one is for. +PTC mode exposes the generated [`run_code` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tools), the SDK instructions below, and the generated exact SDK block for the loaded runtime's language. Both runtime languages list `code` before `description`; this is presentation order, not an enforced JSON member order. REPL and Script runtimes share the generic tool description and SDK instructions; their `executionInstructions` supply syntax and state rules. The TypeScript bash example returns a value for function-body runtimes, and prints output for REPL and Script runtimes. The instructions identify generated declarations as program-only bindings. When the current `bash` parameter schema accepts the example arguments, they also show a complete `run_code` call around `tools.bash(...)`. The `tools:sdk` section uses first-party order 5000 and disables prompt-variable interpolation, preserving literal `{{…}}` text in tool descriptions and schemas for both runtime languages. Under `ptc`, the prompt also carries the `tools:ptc-only` rule earlier in the first-party order, so the model reads which tools it may call before it reads what each one is for. ##### TypeScript PTC mode SDK instructions with bash @@ -235,7 +235,7 @@ These limits define when the registry needs special care. They are current packa - **`timeoutMs` on a definition is declarative only** — the registry never enforces deadlines; enforcement requires the `@deepseek-ai/dsh-tool-call-timeout-policy` wrapper. - **PTC mode's SDK language follows the one loaded runtime, and a presentation is per agent rather than per tool** — `mode: ptc` rejects prompt assembly unless `ctx.ptcRuntime.language` has a registered SDK renderer; within one agent no tool can be native-only while another is ptc-only. - **PTC mode intermediate values are execution-local and unbounded by bytes** — they cannot be reconstructed from session replay and may exhaust process or worker memory; only the outer `run_code` output has the worker's configurable hard cap. -- **State depends on the runtime**: the default backend starts fresh; a REPL backend retains memory per live Agent. Agent disposal awaits release. Restart and execution failures can clear memory; model-visible guidance explains how to recreate missing variables. Programs and results remain in the Session log, without serializing live objects. +- **State depends on the runtime**: the default backend starts fresh; the Node REPL and Script mode with `scriptPersistence: true` retain memory per live Agent. Agent disposal awaits release. Restart and execution failures can clear memory; model-visible guidance explains how to recreate missing variables. Programs and results remain in the Session log, without serializing live objects. `defineTool()`, registry schema projection, and system-prompt assembly preserve `deferLoading: true`. The marker requests deferred definition loading and does not imply a `tool-addition` record; the [LLM package](../../../packages/llm/llm/README.md#known-limitations-and-deferred-work) documents provider enforcement limits. diff --git a/packages/core/tools/README.zh.md b/packages/core/tools/README.zh.md index 6316543088..9915060651 100644 --- a/packages/core/tools/README.zh.md +++ b/packages/core/tools/README.zh.md @@ -133,7 +133,7 @@ ctx.tools.register(defineTool({ 成功且包含图片的子调用结果会成为延后的 user-message 上下文,其 `source.kind` 为 `ptc-mode`。其他 additional context 保留其生产工具的归属。 -当已挂载运行时支持覆盖时,`run_code` 接受 `timeoutMs`;其 schema 报告配置的默认值和上限以及运行时使用说明。Node 默认值为 120,000 ms,上限为 600,000 ms,包含嵌套工具和审批等待。更宽的 `sandbox_permissions` 模式要求非空 `justification`,并在程序启动前获得审批。schema 提示模型使用当前用户的语言撰写理由。授权仅用于该次完整执行;常驻 Session 策略与嵌套工具保留各自权限。程序不会自动重放:显式重试被拒程序前,应检查先前已发生的效果。 保留状态的 PTC 环境遵循会话文件策略。PTC 观察已提交的 Session 模式变化,并立即取消两种 Node 模式下受影响的调用。后续 PTC 调用等待这些调用的嵌套工具清理后,再解析最新策略。运行时负责进程失效和清理,权限设置保持同步。单次提权省略状态所有者,在临时环境中执行;普通调用仍可访问原环境的变量。 +当已挂载运行时支持覆盖时,`run_code` 接受 `timeoutMs`;其 schema 报告配置的默认值和上限以及运行时使用说明。Node 默认值为 120,000 ms,上限为 600,000 ms,包含嵌套工具和审批等待。更宽的 `sandbox_permissions` 模式要求非空 `justification`,并在程序启动前获得审批。schema 提示模型使用当前用户的语言撰写理由。授权仅用于该次完整执行;常驻 Session 策略与嵌套工具保留各自权限。程序不会自动重放:显式重试被拒程序前,应检查先前已发生的效果。 保留状态的 PTC 环境遵循会话文件策略。PTC 观察已提交的 Session 模式变化,并立即取消所有 Node 模式下受影响的调用。后续 PTC 调用等待这些调用的嵌套工具清理后,再解析最新策略。运行时负责进程失效和清理,权限设置保持同步。单次提权省略状态所有者,在临时环境中执行;普通调用仍可访问原环境的变量。 ### 扩展点 @@ -179,7 +179,7 @@ ctx.tools.register(defineTool({ #### 模型看到什么 -PTC mode 会公开生成的 [`run_code` schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tools)、下方 SDK 说明,以及按所加载运行时语言生成的精确 SDK 块。两种运行时语言都将 `code` 列在 `description` 前;这是呈现顺序,不强制 JSON 成员顺序。TypeScript 说明对函数体运行时使用返回值示例,对 REPL 运行时使用打印输出示例,并把生成声明明确标为只能在程序内使用的绑定。当当前 `bash` 参数 schema 接受示例参数时,说明还会给出以 `run_code` 包住 `tools.bash(...)` 的完整调用。`tools:sdk` 段使用 first-party 顺序 5000,并关闭提示词变量插值,使两种运行时语言都原样保留工具描述和 schema 中的 `{{…}}` 文本。在 `ptc` 下,提示词还会带上处于更早 first-party 顺序的 `tools:ptc-only` 规则,让模型先读到「可以调用哪些工具」再读「每个工具做什么」。 +PTC mode 会公开生成的 [`run_code` schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tools)、下方 SDK 说明,以及按所加载运行时语言生成的精确 SDK 块。两种运行时语言都将 `code` 列在 `description` 前;这是呈现顺序,不强制 JSON 成员顺序。REPL 与 Script 运行时共用通用工具描述和 SDK 说明;语法与状态规则由各自的 `executionInstructions` 提供。TypeScript bash 示例对函数体运行时返回值,对 REPL 和 Script 运行时打印输出。说明将生成声明明确标为只能在程序内使用的绑定。当当前 `bash` 参数 schema 接受示例参数时,说明还会给出以 `run_code` 包住 `tools.bash(...)` 的完整调用。`tools:sdk` 段使用 first-party 顺序 5000,并关闭提示词变量插值,使两种运行时语言都原样保留工具描述和 schema 中的 `{{…}}` 文本。在 `ptc` 下,提示词还会带上处于更早 first-party 顺序的 `tools:ptc-only` 规则,让模型先读到「可以调用哪些工具」再读「每个工具做什么」。 ##### 带 bash 的 TypeScript PTC mode SDK 说明 @@ -235,7 +235,7 @@ Program-only SDK bindings: - **定义中的 `timeoutMs` 仅作声明之用**:注册表绝不会强制执行截止时间;要强制执行,必须使用 `@deepseek-ai/dsh-tool-call-timeout-policy` 包装层。 - **PTC mode 的 SDK 语言由当前加载的运行时决定,且呈现方式按 agent 而非按工具**:`mode: ptc` 会拒绝组装提示词,除非 `ctx.ptcRuntime.language` 有已注册的 SDK 渲染器;同一个 agent 内不能让一个工具仅使用 Native,而另一个仅使用 PTC。 - **PTC mode 中间值只存在于执行局部,且没有字节上限**:它们无法从会话回放重建,并可能耗尽进程或 worker 内存;只有外层 `run_code` 输出受 worker 可配置的硬上限约束。 -- **状态由运行时决定**:默认后端每次重新开始;REPL 后端按存活 Agent 保留内存。Agent 销毁时等待环境释放。重启与执行失败可能清除内存;模型说明会指导重新创建缺失变量。程序与结果仍写入 Session 日志,不序列化运行中的对象。 +- **状态由运行时决定**:默认后端每次重新开始;Node REPL 和启用 `scriptPersistence: true` 的 Script 模式按存活 Agent 保留内存。Agent 销毁时等待环境释放。重启与执行失败可能清除内存;模型说明会指导重新创建缺失变量。程序与结果仍写入 Session 日志,不序列化运行中的对象。 `defineTool()`、注册表模式投影和系统提示组装会保留 `deferLoading: true`。该标记请求延迟加载工具定义,并不意味着存在 `tool-addition` 记录;提供方执行语义的限制见 [LLM 包](../../../packages/llm/llm/README.zh.md#known-limitations-and-deferred-work)。 diff --git a/packages/core/tools/src/index.ts b/packages/core/tools/src/index.ts index ca939d4dfb..ba40e7053d 100644 --- a/packages/core/tools/src/index.ts +++ b/packages/core/tools/src/index.ts @@ -59,10 +59,10 @@ declare module '@deepseek-ai/dsh-llm' { */ const PTC_ONLY_INSTRUCTION = `\`${RUN_CODE_NAME}\` is the only tool you can call directly — a tool call naming any other tool fails. Reach every tool the SDK declares below from inside the program.` -const SDK_RENDERERS: Record string> = { +const SDK_RENDERERS: Record string> = { typescript: renderToolsSdk, python: renderToolsSdkPy, -} satisfies Record string> +} satisfies Record string> export { defineTool, diff --git a/packages/core/tools/src/ts-types.ts b/packages/core/tools/src/ts-types.ts index 1c1444e0b1..19829d7a64 100644 --- a/packages/core/tools/src/ts-types.ts +++ b/packages/core/tools/src/ts-types.ts @@ -7,6 +7,7 @@ */ import type { ToolSchema } from '@deepseek-ai/dsh-llm' +import type { PtcRuntime } from '@deepseek-ai/dsh-ptc-runtime' import { assertSupportedJsonSchema } from './json-schema.ts' import type { JsonSchemaNode, JsonSchemaScalar } from './json-schema.ts' /** Internal PTC mode projection: the model-facing schema plus the canonical output schema. */ @@ -247,7 +248,7 @@ export function jsonSchemaToTs(schema: unknown, indent = 0): string { } /** Render the argument and call instructions for the selected execution syntax. */ -function renderSdkInstructions(programFormat: 'function-body' | 'repl'): string { +function renderSdkInstructions(programFormat: PtcRuntime['programFormat']): string { const programDescription = programFormat === 'function-body' ? 'the body of an async TypeScript function (erasable syntax only — no `enum` or namespaces; type annotations are advisory, the code runs type-stripped)' : 'the program to execute' @@ -257,7 +258,7 @@ function renderSdkInstructions(programFormat: 'function-body' | 'repl'): string } /** Render tool execution and output instructions for the selected execution syntax. */ -function renderSdkProgramInstructions(programFormat: 'function-body' | 'repl'): string { +function renderSdkProgramInstructions(programFormat: PtcRuntime['programFormat']): string { const outputInstruction = programFormat === 'function-body' ? 'Emit results with `return` and/or `console.log(...)`. Only what you print or return is program output.' : 'Only values emitted as program output enter the conversation.' @@ -279,7 +280,7 @@ function acceptsExampleString(schema: JsonSchemaNode | undefined, value: string) } /** Render the bash example only when its literal arguments satisfy the current parameter schema. */ -function renderBashExample(schemas: ToolSdkSchema[], programFormat: 'function-body' | 'repl'): string { +function renderBashExample(schemas: ToolSdkSchema[], programFormat: PtcRuntime['programFormat']): string { const bash = schemas.find(schema => schema.name === 'bash') if (bash === undefined) return '' const parameters = bash.parameters as JsonSchemaNode @@ -306,10 +307,10 @@ function renderBashExample(schemas: ToolSdkSchema[], programFormat: 'function-bo * by name, so the input never carries a duplicate. * @param schemas - the tool schemas to declare (the caller excludes * `run_code` itself). - * @param programFormat - Runtime syntax; function bodies support returning a result, REPLs print it. + * @param programFormat - Runtime syntax selecting function-body, REPL, or Script instructions and examples. * @returns the complete section text. */ -export function renderToolsSdk(schemas: ToolSdkSchema[], programFormat: 'function-body' | 'repl' = 'function-body'): string { +export function renderToolsSdk(schemas: ToolSdkSchema[], programFormat: PtcRuntime['programFormat'] = 'function-body'): string { const sorted = [...schemas].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0) const argsMembers: string[] = [] const outputMembers: string[] = [] diff --git a/packages/ptc-runtime/ptc-runtime/README.i18n.yaml b/packages/ptc-runtime/ptc-runtime/README.i18n.yaml index 6062a8c287..9f56e65d05 100644 --- a/packages/ptc-runtime/ptc-runtime/README.i18n.yaml +++ b/packages/ptc-runtime/ptc-runtime/README.i18n.yaml @@ -9,8 +9,8 @@ en: cced8c691b58657a zh: 3da9cdf76a1a07ff /deepseek-ai-dsh-ptc-runtime/summary: - en: b04917e62d63c7ff - zh: 12cb9f38cbf8ee3f + en: 6bf8184a933be9fa + zh: 19fe0bb198744a77 /deepseek-ai-dsh-ptc-runtime/table-of-contents: en: d152484eb41ac6b4 zh: 09388d293f9be9cb @@ -18,8 +18,8 @@ en: 7e5ebf7420c13af4 zh: 9ad1e056e794ca4a /deepseek-ai-dsh-ptc-runtime/use-this-package/run-a-program: - en: c856760ebc15d59e - zh: dc093083b29794e0 + en: ef030201a816ac84 + zh: 2c3f6acfb57ad506 /deepseek-ai-dsh-ptc-runtime/use-this-package/choose-a-backend: en: fc0d515f0c3664f3 zh: 0a1b646b5cf92232 diff --git a/packages/ptc-runtime/ptc-runtime/README.md b/packages/ptc-runtime/ptc-runtime/README.md index 1c0c76327a..51e676695b 100644 --- a/packages/ptc-runtime/ptc-runtime/README.md +++ b/packages/ptc-runtime/ptc-runtime/README.md @@ -9,7 +9,7 @@ English | [中文](README.zh.md) ## Summary -Use `dsh-ptc-runtime` to execute model programs against host-provided asynchronous functions. Requests return lossless JSON, captured logs, or structured failures; rejected promises indicate caller misuse. Providers isolate distinct state owners and declare whether source is an async function body or REPL statements. A provider may retain memory for an explicit owner until release; it never restores that memory from a Session. Language and isolation descriptors identify syntax and execution substrate, not security guarantees. +Use `dsh-ptc-runtime` to execute model programs against host-provided asynchronous functions. Requests return lossless JSON, captured logs, or structured failures; rejected promises indicate caller misuse. Providers isolate distinct state owners and declare whether source is an async function body, REPL statements, or a script. `retainsState` reports whether a provider retains memory for an explicit owner until release; it never restores that memory from a Session. Language and isolation descriptors identify syntax and execution substrate, not security guarantees. ## Table of Contents @@ -29,7 +29,7 @@ Choose this package when you compose a deployment that executes model-written pr ### Run a program -Call `resolve(request)` followed by `run(spec)` with a program and binding namespaces. Resolution validates cwd, timeout and sandbox choices and applies provider defaults. `programFormat` selects an async function body with top-level `await` and `return`, or REPL statements with top-level declarations, `await`, and a final expression. Lossless-JSON completion becomes `result.value`, text becomes `result.logs`, and failures become `result.error`. +Call `resolve(request)` followed by `run(spec)` with a program and binding namespaces. Resolution validates cwd, timeout and sandbox choices and applies provider defaults. `programFormat` selects an async function body with top-level `await` and `return`, or REPL/Script statements with top-level declarations, `await`, and a final expression. The Node Script provider lowers top-level await and awaits the completion value; its [declaration limitations](../ptc-runtime-node/README.md#known-limitations-and-deferred-work) apply to transformed programs. Lossless-JSON completion becomes `result.value`, text becomes `result.logs`, and failures become `result.error`. ```text const spec = ctx.ptcRuntime.resolve({ diff --git a/packages/ptc-runtime/ptc-runtime/README.zh.md b/packages/ptc-runtime/ptc-runtime/README.zh.md index 902bb9b559..823a2de968 100644 --- a/packages/ptc-runtime/ptc-runtime/README.zh.md +++ b/packages/ptc-runtime/ptc-runtime/README.zh.md @@ -9,7 +9,7 @@ kind: "package-reference" ## 概述 -使用 `dsh-ptc-runtime` 执行调用宿主异步函数的模型程序。请求返回无损 JSON、捕获日志或结构化失败;Promise 拒绝表示调用方误用。提供方隔离不同状态所有者,并声明源码是异步函数体还是 REPL 语句。提供方可以为显式所有者保留内存,直到释放,但不会从 Session 恢复这些内存。语言与隔离描述符标识语法和执行基底,不提供安全保证。 +使用 `dsh-ptc-runtime` 执行调用宿主异步函数的模型程序。请求返回无损 JSON、捕获日志或结构化失败;Promise 拒绝表示调用方误用。提供方隔离不同状态所有者,并声明源码是异步函数体、REPL 语句还是脚本。`retainsState` 报告提供方是否为显式所有者保留内存,直到释放,但不会从 Session 恢复这些内存。语言与隔离描述符标识语法和执行基底,不提供安全保证。 ## 目录 @@ -29,7 +29,7 @@ kind: "package-reference" ### 运行一个程序 -传入程序和绑定命名空间,依次调用 `resolve(request)` 和 `run(spec)`。解析阶段验证 cwd、超时与沙盒选项,并应用提供方默认值。`programFormat` 选择支持顶层 `await`、`return` 的异步函数体,或支持顶层声明、`await` 和末尾表达式的 REPL 语句。无损 JSON 完成值进入 `result.value`,文本进入 `result.logs`,失败进入 `result.error`。 +传入程序和绑定命名空间,依次调用 `resolve(request)` 和 `run(spec)`。解析阶段验证 cwd、超时与沙盒选项,并应用提供方默认值。`programFormat` 选择支持顶层 `await`、`return` 的异步函数体,或支持顶层声明、`await` 和末尾表达式的 REPL/Script 语句。Node Script 提供方转换顶层 await 并等待完成值;其[声明限制](../ptc-runtime-node/README.zh.md#known-limitations-and-deferred-work)适用于转换后的程序。无损 JSON 完成值进入 `result.value`,文本进入 `result.logs`,失败进入 `result.error`。 ```text const spec = ctx.ptcRuntime.resolve({ diff --git a/packages/ptc-runtime/ptc-runtime/src/index.ts b/packages/ptc-runtime/ptc-runtime/src/index.ts index be6b8b2eb2..14455e309a 100644 --- a/packages/ptc-runtime/ptc-runtime/src/index.ts +++ b/packages/ptc-runtime/ptc-runtime/src/index.ts @@ -122,7 +122,10 @@ export abstract class PtcRuntime extends Service { abstract readonly isolation: string /** Source evaluation form, independent of whether the provider retains state for an owner. */ - get programFormat(): 'function-body' | 'repl' { return 'function-body' } + get programFormat(): 'function-body' | 'repl' | 'script' { return 'function-body' } + + /** Whether this provider retains program memory across runs for the same stateOwner. */ + get retainsState(): boolean { return false } /** * Release an owner's retained environment and await its execution resources. diff --git a/packages/ptc-runtime/ptc-runtime/src/types.ts b/packages/ptc-runtime/ptc-runtime/src/types.ts index a894a83355..022a40f8b3 100644 --- a/packages/ptc-runtime/ptc-runtime/src/types.ts +++ b/packages/ptc-runtime/ptc-runtime/src/types.ts @@ -74,9 +74,11 @@ export interface PtcRunRequest { /** * The program source, in the runtime's {@link ../index.ts | language}. It * follows the provider's programFormat: an async function body supports - * top-level `await` and `return`; a REPL supports top-level declarations, - * `await`, and a final expression. The completion value becomes - * {@link PtcRunResult.value}. + * top-level `await` and `return`; REPL and Script programs support top-level + * declarations, `await`, and a final expression, but not top-level `return`. + * The Script provider lowers top-level await; its executionInstructions and + * documentation define retained-binding semantics. The completion value + * becomes {@link PtcRunResult.value}. */ program: string /** @@ -152,7 +154,7 @@ export interface PtcRunResult { /** Applied file policy and observed denial, when the provider enforces file policy. */ sandbox?: PtcRunSandbox /** - * The program's completion value (a return or final REPL expression), when it ran to + * The program's completion value (a return or final REPL/Script expression), when it ran to * completion and the value crossed the runtime's lossless-JSON boundary. * Invalid or over-limit completions fail the run instead of substituting a * rendered string; a failed or value-less run leaves this absent. diff --git a/packages/workflow/workflow-ptc/README.i18n.yaml b/packages/workflow/workflow-ptc/README.i18n.yaml index 6582426091..5678e3ac80 100644 --- a/packages/workflow/workflow-ptc/README.i18n.yaml +++ b/packages/workflow/workflow-ptc/README.i18n.yaml @@ -24,8 +24,8 @@ en: 0626f232df315a7d zh: 573e9a12bc69ac6d /deepseek-ai-dsh-workflow-ptc/use-this-package/file-policy-and-cancellation: - en: 5a13be99e2c2ca39 - zh: ff16dbe6bc83a75d + en: 7c0287dbaef61267 + zh: 874c6efa4b39ed60 /deepseek-ai-dsh-workflow-ptc/understand-the-implementation: en: ff9de0f5f3423c12 zh: 4c5ae9845d452cc1 diff --git a/packages/workflow/workflow-ptc/README.md b/packages/workflow/workflow-ptc/README.md index 46503f6d35..62f347031e 100644 --- a/packages/workflow/workflow-ptc/README.md +++ b/packages/workflow/workflow-ptc/README.md @@ -56,7 +56,7 @@ Invalid metadata, an unparseable body, an unavailable provider route or a per-ru ### File policy and cancellation -The engine captures the calling Session's effective working directory and standing file policy separately. The PTC process and every child started by that workflow retain the captured directory when the parent later moves. A runtime without confinement is accepted only for `danger-full-access`; `read-only` and `workspace-write` fail before execution. Node in-memory mode executes an async wrapper in a temporary environment, so workflow-local variables never join the Agent's retained REPL. The VM retains the documented helper API, but it is not a security boundary: code that reaches Node follows the selected runtime's file policy. The program-visible environment is empty. Network access is not restricted by the file policy. +The engine captures the calling Session's effective working directory and standing file policy separately. The PTC process and every child started by that workflow retain the captured directory when the parent later moves. A runtime without confinement is accepted only for `danger-full-access`; `read-only` and `workspace-write` fail before execution. Node in-memory mode executes an async wrapper in a temporary environment, so workflow-local variables never join the Agent's retained REPL. Script mode uses an async function expression whose Promise completion carries the workflow result. The VM retains the documented helper API, but it is not a security boundary: code that reaches Node follows the selected runtime's file policy. The program-visible environment is empty. Network access is not restricted by the file policy. The workflow requests `timeoutMs: null` from PTC. Its initial VM slice still has `syncTimeoutMs`, and a caller's abort signal still applies, including an enclosing tool deadline. Cancellation immediately aborts the PTC process and pending or active subagents. The caller must dispose every run and await child cleanup; there is no separate workflow cleanup timer. diff --git a/packages/workflow/workflow-ptc/README.zh.md b/packages/workflow/workflow-ptc/README.zh.md index 81f19ea8d5..97db20b6d0 100644 --- a/packages/workflow/workflow-ptc/README.zh.md +++ b/packages/workflow/workflow-ptc/README.zh.md @@ -56,7 +56,7 @@ Node PTC 提供方的 `maxPendingCalls` 也限制工作流并发:子 agent 启 ### 文件策略与取消 -引擎分别捕获调用 Session 的有效工作目录与常设文件策略。父级之后切换目录时,PTC 进程及该工作流随后启动的每个子级都保留捕获的目录。不支持文件约束的运行时只允许用于 `danger-full-access`;`read-only` 和 `workspace-write` 在执行前失败。Node 内存保留模式在临时环境中执行异步包装函数,因此工作流局部变量不会进入 Agent 保留的 REPL。VM 保留文档说明的辅助 API,但它不是安全边界:触达 Node 的代码遵循所选运行时的文件策略。程序可见的环境为空。文件策略不限制网络访问。 +引擎分别捕获调用 Session 的有效工作目录与常设文件策略。父级之后切换目录时,PTC 进程及该工作流随后启动的每个子级都保留捕获的目录。不支持文件约束的运行时只允许用于 `danger-full-access`;`read-only` 和 `workspace-write` 在执行前失败。Node 内存保留模式在临时环境中执行异步包装函数,因此工作流局部变量不会进入 Agent 保留的 REPL。Script 模式使用 async 函数表达式,通过其 Promise 完成值返回工作流结果。VM 保留文档说明的辅助 API,但它不是安全边界:触达 Node 的代码遵循所选运行时的文件策略。程序可见的环境为空。文件策略不限制网络访问。 工作流向 PTC 请求 `timeoutMs: null`。最初的 VM 片段仍受 `syncTimeoutMs` 限制,调用方的中止信号仍然生效,包括外层工具的截止。取消立即中止 PTC 进程及待启动或活跃的 subagent。调用方必须释放每次运行并等待子 agent 清理;不另设工作流清理定时器。 diff --git a/packages/workflow/workflow-ptc/src/host.ts b/packages/workflow/workflow-ptc/src/host.ts index 7a2266e778..71b5a442b6 100644 --- a/packages/workflow/workflow-ptc/src/host.ts +++ b/packages/workflow/workflow-ptc/src/host.ts @@ -288,7 +288,11 @@ export class PtcWorkflowRun implements WorkflowRun { throw new Error(`workflow runtime cannot enforce the ${this.policy.mode} file policy`) } const outcome = await this.runtime.run(this.runtime.resolve({ - program: this.runtime.programFormat === 'repl' ? `await (async () => {\n${PROGRAM}\n})()` : PROGRAM, + program: { + 'function-body': PROGRAM, + repl: `await (async () => {\n${PROGRAM}\n})()`, + script: `(async () => {\n${PROGRAM}\n})()`, + }[this.runtime.programFormat], bindings: [{ global: 'workflowHost', functions: this.bindings() }], cwd, ...this.runtime.sandboxMode === undefined ? {} : { sandboxPolicy: this.policy },