diff --git a/packages/core/tools/README.i18n.yaml b/packages/core/tools/README.i18n.yaml index c3e4554f70..9ff6974195 100644 --- a/packages/core/tools/README.i18n.yaml +++ b/packages/core/tools/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/core/tools/README.md -README.md: ac08bc72c6f9c6de6a0aef5cb866cd0488b1dd5c -README.zh.md: e040d85b3eb75cf23f7fb2fa8d16d0685ff2f4ac +README.md: 1b19a080759fa8b21f0c1058d049b2c3f6cf64fe +README.zh.md: 07fc85e2fc51c0b528eb37f6e7599d72144db8fb diff --git a/packages/core/tools/README.md b/packages/core/tools/README.md index ac08bc72c6..1b19a08075 100644 --- a/packages/core/tools/README.md +++ b/packages/core/tools/README.md @@ -190,6 +190,6 @@ Append-only; newly visible content follows the reusable request prefix and does - **`tools/pre-execute` deliberately cannot rewrite `exec.arguments`** — logged and rendered args would desync from what ran; the rewrite design is [a proposed Agent Note](../../../.agents/notes/proposed/feature/2026-06-30-pre-tool-input-rewrite.md). - **Caller-defined subagent and workflow structured outputs remain object-rooted** — this is a consumer-level guard; the shared schema vocabulary and tool outputs support every JSON root. - **`timeoutMs` on a definition is declarative only** — the registry never enforces deadlines; enforcement requires the `@deepseek-ai/dsh-timeout-policy` wrapper. -- **Code Mode's SDK language follows the one loaded runtime and the presentation mode is service-wide** — `mode: code`/`both` rejects prompt assembly unless `ctx.codeRuntime.language` has a registered SDK renderer (`typescript` via the worker backend, `python` via the python backend); scoped restrictions/shadows still choose each agent's visible bindings, but one tool cannot be native-only while another is code-only, and a single runtime fixes the language service-wide. +- **Code Mode's SDK language follows the one loaded runtime and the presentation mode is service-wide** — `mode: code`/`both` rejects prompt assembly unless `ctx.codeRuntime.language` has a registered SDK renderer (`typescript` via the worker backend, `python` via the python backend); scoped restrictions/shadows still choose each agent's visible bindings, but one tool cannot be native-only while another is code-only, and a single runtime fixes the language service-wide (the [language-dispatch Agent Note](../../../.agents/notes/implemented/feature/2026-07-31-code-mode-language-dispatch.md) owns why per-agent language switching is deferred). - **Code Mode intermediate values are execution-local and unbounded by bytes** — the canonical typed values 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. The durable log copy of each sub-call IS bounded: the `tools/code-dispatch-log` waterfall lets the spill policy replace an oversized `tool/code-dispatch` content with a preview + locator ([rationale](../../../.agents/notes/implemented/feature/2026-07-26-code-dispatch-log-spill.md)). - **`run_code` state is fresh per run** — a persistent REPL-style kernel is rejected for the MVP (cross-call state would be invisible to the log); see [the Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md). diff --git a/packages/core/tools/README.zh.md b/packages/core/tools/README.zh.md index e040d85b3e..07fc85e2fc 100644 --- a/packages/core/tools/README.zh.md +++ b/packages/core/tools/README.zh.md @@ -190,6 +190,6 @@ The available tools: - **`tools/pre-execute` 有意不允许改写 `exec.arguments`**:否则日志记录和呈现的参数会与实际运行内容失去同步;改写设计记录在[拟议的 Agent Note](../../../.agents/notes/proposed/feature/2026-06-30-pre-tool-input-rewrite.md)中。 - **调用方定义的 subagent 与工作流结构化输出仍要求对象根**:这是消费方层面的守卫;共享 schema 词汇和工具输出支持任意 JSON 根。 - **定义上的 `timeoutMs` 仅为声明**:注册表绝不会强制执行截止时间;要强制执行,必须使用 `@deepseek-ai/dsh-timeout-policy` 包装层。 -- **Code Mode 只支持 TypeScript,且呈现模式在服务内统一**:`mode: code`/`both` 会拒绝组装提示词,除非 `ctx.codeRuntime.language === 'typescript'`;作用域限制/遮蔽仍会选择每个 agent 的可见绑定,但不能让一个工具仅使用 Native,而另一个仅使用 Code。 +- **Code Mode 的 SDK 语言跟随唯一加载的运行时,且呈现模式在服务内统一**:`mode: code`/`both` 会拒绝组装提示词,除非 `ctx.codeRuntime.language` 有已注册的 SDK 渲染器(`typescript` 经 worker 后端,`python` 经 python 后端);作用域限制/遮蔽仍会选择每个 agent 的可见绑定,但不能让一个工具仅使用 Native、另一个仅使用 Code,且单个运行时把语言固定为服务级([语言分发 Agent Note](../../../.agents/notes/implemented/feature/2026-07-31-code-mode-language-dispatch.md) 负责说明为何暂缓逐 agent 切换语言)。 - **Code Mode 中间值只存在于执行局部,且没有字节上限**:这些规范的类型化值无法从会话回放重建,并可能耗尽进程或 worker 内存;只有外层 `run_code` 输出受 worker 可配置的硬上限约束。每个子调用的持久日志副本则确实有上限:`tools/code-dispatch-log` waterfall 允许 spill 策略把过大的 `tool/code-dispatch` 内容替换为预览加定位符([原理](../../../.agents/notes/implemented/feature/2026-07-26-code-dispatch-log-spill.md))。 - **每次运行都会获得全新的 `run_code` 状态**:MVP 不采用持久 REPL 风格内核(跨调用状态不会出现在日志中);参见 [Code Mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-code-mode.md)。 diff --git a/packages/core/tools/src/code-mode.ts b/packages/core/tools/src/code-mode.ts index 38a0654ced..22a660a8ef 100644 --- a/packages/core/tools/src/code-mode.ts +++ b/packages/core/tools/src/code-mode.ts @@ -120,18 +120,22 @@ const RUN_CODE_DESCRIPTION_PARAM_DESCRIPTION /** * Resolve the {@link RunCodeFlavor} for the loaded runtime's language, read at * schema-emission time so the model-visible `run_code` schema always matches - * the SDK section's language. When no runtime is mounted the schema harvest - * degrades to {@link TYPESCRIPT_FLAVOR} (a doc-only path — an assembly always - * has one). A mounted runtime whose language has no flavor entry fails loud, - * keeping this table coupled to `SDK_RENDERERS`. + * the SDK section's language. When no runtime is mounted, or one whose language + * has no renderer is, the schema harvest degrades to {@link TYPESCRIPT_FLAVOR} + * (a doc-only path — a real assembly always mounts a valid runtime, and + * `requireCodeRuntime` rejects an invalid language there first). A mounted + * runtime whose language passes that guard but is absent from this table fails + * loud, keeping this table coupled to `SDK_RENDERERS`. */ function resolveFlavor(requireRuntime: () => CodeRuntime): RunCodeFlavor { let runtime: CodeRuntime try { runtime = requireRuntime() } catch { - // No runtime mounted: the only reader here is the static schema harvest - // (doc catalog), which never reaches a model — degrade to the TS default. + // Reached only by the static schema harvest (doc catalog), which never + // feeds a model: either no runtime is mounted, or requireRuntime rejected + // a language with no renderer. Both degrade to the TS default here; a real + // assembly hits requireCodeRuntime's loud rejection before this runs. return TYPESCRIPT_FLAVOR } // Own-property read: a language like `toString`/`constructor` would otherwise diff --git a/packages/core/tools/src/index.ts b/packages/core/tools/src/index.ts index 17d1935cf1..5f89fa23c6 100644 --- a/packages/core/tools/src/index.ts +++ b/packages/core/tools/src/index.ts @@ -806,6 +806,10 @@ export class ToolRegistry extends Service { if (this.mode === 'native') { return { schemas, knownNames: [...view.knownNames] } } + // Redundant with the per-getter resolveFlavor path (schemaOf's run_code + // description/parameters getters call requireCodeRuntime again): kept as a + // single explicit gate so a mode collapse rejects here regardless of + // whether any getter runs. The call is idempotent (ctx.get + Object.hasOwn). this.requireCodeRuntime() if (this.mode === 'code') { return {