refactor(code-runtime): name the Node runtime provider
This commit is contained in:
1 parent
b35a3b29eb
commit
f95f7ec8dc
68 files changed
+138
-138
No files matched your search
@@ -27,7 +27,7 @@ These three packages together provide program execution; each README describes w
|
||||
| Package | Role | ctx key |
|
||||
|---|---|---|
|
||||
| [`code-runtime/`](code-runtime/README.md) | Defines what a code runtime does: run one program against host-provided bindings and report what it printed and returned | `ctx.codeRuntime` |
|
||||
| [`code-runtime-worker-thread/`](code-runtime-worker-thread/README.md) | Executes TypeScript programs, each in a fresh Node worker thread | registers `ctx.codeRuntime` |
|
||||
| [`code-runtime-node/`](code-runtime-node/README.md) | Executes TypeScript programs, each in a fresh Node worker thread | registers `ctx.codeRuntime` |
|
||||
| [`experimental/code-runtime-python/`](../experimental/code-runtime-python/README.md) | The experimental Python backend: owns the fd-3 wire protocol between a Node host and a CPython subprocess and the CPython runtime implementation | — |
|
||||
|
||||
-----
|
||||
|
||||
@@ -27,7 +27,7 @@ kind: "package-group"
|
||||
| 包 | 角色 | ctx 键 |
|
||||
|---|---|---|
|
||||
| [`code-runtime/`](code-runtime/README.zh.md) | 定义代码运行时做什么:针对宿主提供的绑定运行一个程序,并报告其打印和返回的内容 | `ctx.codeRuntime` |
|
||||
| [`code-runtime-worker-thread/`](code-runtime-worker-thread/README.zh.md) | 在全新的 Node Worker 线程中执行 TypeScript 程序 | 注册 `ctx.codeRuntime` |
|
||||
| [`code-runtime-node/`](code-runtime-node/README.zh.md) | 在全新的 Node Worker 线程中执行 TypeScript 程序 | 注册 `ctx.codeRuntime` |
|
||||
| [`experimental/code-runtime-python/`](../experimental/code-runtime-python/README.zh.md) | 实验性 Python 后端:负责 Node 宿主与 CPython 子进程之间的 fd-3 协议,以及 CPython 运行时实现 | — |
|
||||
|
||||
-----
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# 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/code-runtime/code-runtime-worker-thread/README.md
|
||||
README.md: c26f349762ab2dac9956099ab637cde9d6d93771
|
||||
README.zh.md: b5ffeac9c06733099001189fb8cc5fa1b60e662b
|
||||
# pnpm run verify-translation-pairing --write packages/code-runtime/code-runtime-node/README.md
|
||||
README.md: d03fd010db7d1475cc153632ca28fc83f782704b
|
||||
README.zh.md: bfc58f8ba0a9adff4a687cc233cc7da56224564a
|
||||
+5
-5
@@ -3,7 +3,7 @@ description: "Worker-thread code execution for users and maintainers composing,
|
||||
kind: "package-reference"
|
||||
---
|
||||
|
||||
# @deepseek-ai/dsh-code-runtime-worker-thread
|
||||
# @deepseek-ai/dsh-code-runtime-node
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
@@ -31,7 +31,7 @@ Mount this backend with the code-runtime seam when a composition should execute
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-code-runtime'
|
||||
- name: '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
- name: '@deepseek-ai/dsh-code-runtime-node'
|
||||
config:
|
||||
computeMs: 60000 # busy-time budget (measured event-loop active time)
|
||||
maxWallMs: 600000 # wall-clock ceiling; never pauses for anything
|
||||
@@ -46,7 +46,7 @@ Mount this backend with the code-runtime seam when a composition should execute
|
||||
| `maxOutputBytes` | `67,108,864` | Hard cap for serialized logs plus the completion value or failure message; at least `4` |
|
||||
| `maxOldGenerationSizeMb` | `512` | Worker heap cap; overflow kills the worker and surfaces as `worker-exit` |
|
||||
|
||||
Every field is validated and defaulted at load; there are no other tunables. The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-code-runtime-worker-thread) is the exhaustive source for every accepted field.
|
||||
Every field is validated and defaulted at load; there are no other tunables. The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-code-runtime-node) is the exhaustive source for every accepted field.
|
||||
|
||||
### What a run returns
|
||||
|
||||
@@ -94,7 +94,7 @@ Two independent budgets exist because the peer is hostile: `computeMs` meters th
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | Plugin entry: `Config` schema, `WorkerThreadCodeRuntime`, run orchestration, output ledger |
|
||||
| [`src/index.ts`](src/index.ts) | Plugin entry: `Config` schema, `NodeCodeRuntime`, run orchestration, output ledger |
|
||||
| [`src/worker.ts`](src/worker.ts) | Source-mode worker entry (erasable TypeScript, no `lib/` dependency) |
|
||||
| [`src/bootstrap.ts`](src/bootstrap.ts) | Worker-side bootstrap: namespace materialization, console shim, log capture |
|
||||
| [`src/protocol.ts`](src/protocol.ts) | Port message vocabulary between host and worker |
|
||||
@@ -118,7 +118,7 @@ Read these when the backend contract is not enough. They move from the seam defi
|
||||
- [Code runtime seam](../code-runtime/README.md) — the abstract contract this backend implements.
|
||||
- [PTC mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-ptc.md) — how `dsh-tools` consumes `ctx.codeRuntime` and presents `run_code`.
|
||||
- [Code runtime subsystem reference](../../../docs/subsystems/code-runtime.md) — request/result vocabulary, bindings, and failure taxonomy.
|
||||
- [Generated configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-code-runtime-worker-thread) — every accepted config field and its source declaration.
|
||||
- [Generated configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-code-runtime-node) — every accepted config field and its source declaration.
|
||||
|
||||
-----
|
||||
|
||||
+5
-5
@@ -3,7 +3,7 @@ description: "Worker 线程代码执行,面向组装、容量规划或调试
|
||||
kind: "package-reference"
|
||||
---
|
||||
|
||||
# @deepseek-ai/dsh-code-runtime-worker-thread
|
||||
# @deepseek-ai/dsh-code-runtime-node
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
@@ -31,7 +31,7 @@ kind: "package-reference"
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-code-runtime'
|
||||
- name: '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
- name: '@deepseek-ai/dsh-code-runtime-node'
|
||||
config:
|
||||
computeMs: 60000 # busy-time budget (measured event-loop active time)
|
||||
maxWallMs: 600000 # wall-clock ceiling; never pauses for anything
|
||||
@@ -46,7 +46,7 @@ kind: "package-reference"
|
||||
| `maxOutputBytes` | `67,108,864` | 序列化日志加完成值或失败消息的硬上限;至少 `4` |
|
||||
| `maxOldGenerationSizeMb` | `512` | worker 堆上限;溢出会杀死 worker,并以 `worker-exit` 呈现 |
|
||||
|
||||
每个字段在加载时都会验证并提供默认值;没有其他可调项。生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-code-runtime-worker-thread)是所有受支持字段的完整参考。
|
||||
每个字段在加载时都会验证并提供默认值;没有其他可调项。生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-code-runtime-node)是所有受支持字段的完整参考。
|
||||
|
||||
### 运行返回什么
|
||||
|
||||
@@ -94,7 +94,7 @@ kind: "package-reference"
|
||||
|
||||
| 文件 | 职责 |
|
||||
|---|---|
|
||||
| [`src/index.ts`](src/index.ts) | 插件入口:`Config` schema、`WorkerThreadCodeRuntime`、运行编排、输出账本 |
|
||||
| [`src/index.ts`](src/index.ts) | 插件入口:`Config` schema、`NodeCodeRuntime`、运行编排、输出账本 |
|
||||
| [`src/worker.ts`](src/worker.ts) | 源码模式 worker 入口(可擦除 TypeScript,不依赖 `lib/`) |
|
||||
| [`src/bootstrap.ts`](src/bootstrap.ts) | worker 侧 bootstrap:命名空间物化、console shim、日志捕获 |
|
||||
| [`src/protocol.ts`](src/protocol.ts) | host 与 worker 之间的端口消息词汇 |
|
||||
@@ -118,7 +118,7 @@ kind: "package-reference"
|
||||
- [代码运行时 seam](../code-runtime/README.zh.md)——此后端实现的抽象约定。
|
||||
- [PTC mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-ptc.zh.md)——`dsh-tools` 如何消费 `ctx.codeRuntime` 并呈现 `run_code`。
|
||||
- [代码运行时子系统参考](../../../docs/subsystems/code-runtime.zh.md)——请求/结果词汇、绑定与失败分类体系。
|
||||
- [生成配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-code-runtime-worker-thread)——每个受支持配置字段及其源声明。
|
||||
- [生成配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-code-runtime-node)——每个受支持配置字段及其源声明。
|
||||
|
||||
-----
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-code-runtime-worker-thread",
|
||||
"name": "@deepseek-ai/dsh-code-runtime-node",
|
||||
"description": "Worker-thread implementation of the DeepSeek Harness code-execution seam",
|
||||
"version": "0.1.5-rc.2",
|
||||
"publishConfig": {
|
||||
@@ -8,7 +8,7 @@
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
||||
"directory": "packages/code-runtime/code-runtime-worker-thread"
|
||||
"directory": "packages/code-runtime/code-runtime-node"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
* Worker-side execution logic, written as plain functions over an injected port so the unit
|
||||
* suite can run every line IN-PROCESS against a fake port (a real worker thread is a separate
|
||||
* V8 isolate the coverage provider cannot observe).
|
||||
* @module @deepseek-ai/dsh-code-runtime-worker-thread/src/bootstrap
|
||||
* @module @deepseek-ai/dsh-code-runtime-node/src/bootstrap
|
||||
*/
|
||||
|
||||
import { inspect } from 'node:util'
|
||||
+14
-14
@@ -3,7 +3,7 @@
|
||||
* and bridges bindings over its message port. This is containment, not a security boundary:
|
||||
* model code has bash-equivalent trust despite an empty environment, a heap cap, measured
|
||||
* event-loop busy-time and wall-time budgets, and termination that also stops synchronous loops.
|
||||
* @module @deepseek-ai/dsh-code-runtime-worker-thread
|
||||
* @module @deepseek-ai/dsh-code-runtime-node
|
||||
*/
|
||||
|
||||
import { Worker } from 'node:worker_threads'
|
||||
@@ -235,7 +235,7 @@ class OutputLedger {
|
||||
* the contract this implements (error-as-field, hostile-peer port,
|
||||
* no cross-run state, dispose to quiescence).
|
||||
*/
|
||||
export class WorkerThreadCodeRuntime extends CodeRuntime {
|
||||
export class NodeCodeRuntime extends CodeRuntime {
|
||||
static Config: z<Config> = z.object({
|
||||
computeMs: z.number().default(60_000),
|
||||
maxWallMs: z.number().default(600_000),
|
||||
@@ -256,16 +256,16 @@ export class WorkerThreadCodeRuntime extends CodeRuntime {
|
||||
// semantic check the schema's plain number type does not carry.
|
||||
this.config = config as ResolvedConfig
|
||||
for (const [key, value] of Object.entries(this.config)) {
|
||||
if (!(Number.isFinite(value) && value > 0)) throw new Error(`dsh-code-runtime-worker-thread: config.${key} must be a positive number, got ${String(value)}`)
|
||||
if (!(Number.isFinite(value) && value > 0)) throw new Error(`dsh-code-runtime-node: config.${key} must be a positive number, got ${String(value)}`)
|
||||
}
|
||||
if (!Number.isSafeInteger(this.config.maxOutputBytes) || this.config.maxOutputBytes < MIN_OUTPUT_BYTES) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: config.maxOutputBytes must be a safe integer of at least ${MIN_OUTPUT_BYTES}, got ${String(this.config.maxOutputBytes)}`)
|
||||
throw new Error(`dsh-code-runtime-node: config.maxOutputBytes must be a safe integer of at least ${MIN_OUTPUT_BYTES}, got ${String(this.config.maxOutputBytes)}`)
|
||||
}
|
||||
// maxWallMs reaches setTimeout, which clamps any delay above
|
||||
// MAX_TIMER_DELAY_MS to 1 ms; the positivity check above accepts such a
|
||||
// value, so a 25-day ceiling would time the run out immediately.
|
||||
if (this.config.maxWallMs > MAX_TIMER_DELAY_MS) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: config.maxWallMs must be at most ${MAX_TIMER_DELAY_MS} (Node clamps a longer setTimeout delay to 1ms), got ${String(this.config.maxWallMs)}`)
|
||||
throw new Error(`dsh-code-runtime-node: config.maxWallMs must be at most ${MAX_TIMER_DELAY_MS} (Node clamps a longer setTimeout delay to 1ms), got ${String(this.config.maxWallMs)}`)
|
||||
}
|
||||
ctx.effect(() => () => this.teardown(), 'worker code-runtime teardown')
|
||||
}
|
||||
@@ -291,7 +291,7 @@ export class WorkerThreadCodeRuntime extends CodeRuntime {
|
||||
* @returns the run's outcome per the seam contract.
|
||||
*/
|
||||
async run(request: CodeRunRequest): Promise<CodeRunResult> {
|
||||
if (this.disposed) throw new Error('dsh-code-runtime-worker-thread: run() after disposal')
|
||||
if (this.disposed) throw new Error('dsh-code-runtime-node: run() after disposal')
|
||||
const bindings = this.validateBindings(request)
|
||||
if (request.signal?.aborted) {
|
||||
return this.failureBeforeWorker({ kind: 'abort', message: String(request.signal.reason) })
|
||||
@@ -321,7 +321,7 @@ export class WorkerThreadCodeRuntime extends CodeRuntime {
|
||||
const bindings = new Map<string, CodeBindingNamespace>()
|
||||
for (const namespace of request.bindings) {
|
||||
if (!IDENTIFIER.test(namespace.global) || PORTABLE_RESERVED_WORDS.has(namespace.global)) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: binding global ${JSON.stringify(namespace.global)} is not a usable identifier`)
|
||||
throw new Error(`dsh-code-runtime-node: binding global ${JSON.stringify(namespace.global)} is not a usable identifier`)
|
||||
}
|
||||
// RESERVED_BINDING_GLOBALS is the seam's shared backend-owned set:
|
||||
// `console` is THIS backend's log-capture slot; the dunder entries exist
|
||||
@@ -330,10 +330,10 @@ export class WorkerThreadCodeRuntime extends CodeRuntime {
|
||||
// portable across backends. The seam declaration is the single home for
|
||||
// why each entry is reserved.
|
||||
if (RESERVED_BINDING_GLOBALS.has(namespace.global)) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: reserved binding global ${JSON.stringify(namespace.global)}`)
|
||||
throw new Error(`dsh-code-runtime-node: reserved binding global ${JSON.stringify(namespace.global)}`)
|
||||
}
|
||||
if (bindings.has(namespace.global)) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: duplicate binding global ${JSON.stringify(namespace.global)}`)
|
||||
throw new Error(`dsh-code-runtime-node: duplicate binding global ${JSON.stringify(namespace.global)}`)
|
||||
}
|
||||
bindings.set(namespace.global, namespace)
|
||||
}
|
||||
@@ -343,17 +343,17 @@ export class WorkerThreadCodeRuntime extends CodeRuntime {
|
||||
const descriptor = namespace.errorClass
|
||||
if (!descriptor) continue
|
||||
if (!IDENTIFIER.test(descriptor.name) || PORTABLE_RESERVED_WORDS.has(descriptor.name)) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: binding error class ${JSON.stringify(descriptor.name)} is not a usable identifier`)
|
||||
throw new Error(`dsh-code-runtime-node: binding error class ${JSON.stringify(descriptor.name)} is not a usable identifier`)
|
||||
}
|
||||
if (RESERVED_BINDING_GLOBALS.has(descriptor.name)) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: reserved binding global ${JSON.stringify(descriptor.name)}`)
|
||||
throw new Error(`dsh-code-runtime-node: reserved binding global ${JSON.stringify(descriptor.name)}`)
|
||||
}
|
||||
if (bindings.has(descriptor.name) || errorClassNames.has(descriptor.name)) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: duplicate injected global ${JSON.stringify(descriptor.name)}`)
|
||||
throw new Error(`dsh-code-runtime-node: duplicate injected global ${JSON.stringify(descriptor.name)}`)
|
||||
}
|
||||
const member = descriptor.memberNameProperty
|
||||
if (member.length === 0 || RESERVED_ERROR_MEMBERS.has(member) || DUNDER_MEMBER.test(member)) {
|
||||
throw new Error(`dsh-code-runtime-worker-thread: binding error member property ${JSON.stringify(descriptor.memberNameProperty)} is not usable`)
|
||||
throw new Error(`dsh-code-runtime-node: binding error member property ${JSON.stringify(descriptor.memberNameProperty)} is not usable`)
|
||||
}
|
||||
errorClassNames.add(descriptor.name)
|
||||
}
|
||||
@@ -558,4 +558,4 @@ export class WorkerThreadCodeRuntime extends CodeRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
export default WorkerThreadCodeRuntime
|
||||
export default NodeCodeRuntime
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/** JSON string-prefix accounting for the outer-output ledger. @module @deepseek-ai/dsh-code-runtime-worker-thread/output-json */
|
||||
/** JSON string-prefix accounting for the outer-output ledger. @module @deepseek-ai/dsh-code-runtime-node/output-json */
|
||||
|
||||
import type { CodeJsonValue } from '@deepseek-ai/dsh-code-runtime'
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
* Versionless, structured-clone wire protocol between co-shipped host and worker code. The host
|
||||
* treats inbound traffic as hostile because model code can forge `parentPort` messages; the
|
||||
* worker trusts host replies.
|
||||
* @module @deepseek-ai/dsh-code-runtime-worker-thread/src/protocol
|
||||
* @module @deepseek-ai/dsh-code-runtime-node/src/protocol
|
||||
*/
|
||||
|
||||
import type { WorkerJsonWire } from './worker-json.ts'
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Lossless-JSON snapshots for the dependency-free source worker closure.
|
||||
* @module @deepseek-ai/dsh-code-runtime-worker-thread/worker-json
|
||||
* @module @deepseek-ai/dsh-code-runtime-node/worker-json
|
||||
*/
|
||||
|
||||
import type { CodeJsonValue } from '@deepseek-ai/dsh-code-runtime'
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Spawn-only worker entrypoint over {@link runWorkerMain}. Executable logic stays in
|
||||
* `bootstrap.ts` for in-process coverage; real-worker tests cover this glue.
|
||||
* @module @deepseek-ai/dsh-code-runtime-worker-thread/src/worker
|
||||
* @module @deepseek-ai/dsh-code-runtime-node/src/worker
|
||||
*/
|
||||
|
||||
import { parentPort, workerData } from 'node:worker_threads'
|
||||
@@ -9,6 +9,6 @@ import { runWorkerMain } from './bootstrap.ts'
|
||||
import type { WorkerBootData } from './protocol.ts'
|
||||
|
||||
// A worker always has a parent port; guard loudly rather than run detached.
|
||||
if (!parentPort) throw new Error('dsh-code-runtime-worker-thread: worker entry loaded outside a worker thread')
|
||||
if (!parentPort) throw new Error('dsh-code-runtime-node: worker entry loaded outside a worker thread')
|
||||
|
||||
void runWorkerMain(parentPort, workerData as WorkerBootData, { stdout: process.stdout, stderr: process.stderr })
|
||||
File renamed without changes.
+2
-2
@@ -1,7 +1,7 @@
|
||||
/** Host budget decisions use controlled clocks and ELU samples; worker execution and binding transport stay real. */
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { WorkerThreadCodeRuntime } from '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
import { NodeCodeRuntime } from '@deepseek-ai/dsh-code-runtime-node'
|
||||
import type { CodeRunResult } from '@deepseek-ai/dsh-code-runtime'
|
||||
|
||||
const meter = vi.hoisted(() => ({ sample: vi.fn() }))
|
||||
@@ -52,7 +52,7 @@ describe('worker budgets with controlled ELU samples and real binding transport'
|
||||
})
|
||||
|
||||
async function pendingBinding(): Promise<void> {
|
||||
await ctx.plugin(WorkerThreadCodeRuntime, { computeMs: 1_000, maxWallMs: 30_000 })
|
||||
await ctx.plugin(NodeCodeRuntime, { computeMs: 1_000, maxWallMs: 30_000 })
|
||||
let entered!: () => void
|
||||
const ready = new Promise<void>((resolve) => { entered = resolve })
|
||||
const binding = new Promise<string>((resolve) => { release = () => { resolve('slow-done') } })
|
||||
+2
-2
@@ -19,9 +19,9 @@ describe.skipIf(!built)('built lib real load path (plain node)', () => {
|
||||
it('runs a TypeScript program with a binding through lib/index.js and its lib/worker.cjs entry', async () => {
|
||||
const script = `
|
||||
const { Context } = await import('@deepseek-ai/cordis')
|
||||
const { WorkerThreadCodeRuntime } = await import('@deepseek-ai/dsh-code-runtime-worker-thread')
|
||||
const { NodeCodeRuntime } = await import('@deepseek-ai/dsh-code-runtime-node')
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(WorkerThreadCodeRuntime, {})
|
||||
await ctx.plugin(NodeCodeRuntime, {})
|
||||
const result = await ctx.codeRuntime.run({
|
||||
program: 'const doubled: number = await tools.double({ n: 21 }); console.log("halfway", doubled); let failure; try { await tools.fail({}) } catch (error) { failure = { typed: error instanceof ToolCallError, name: error.name, toolName: error.toolName, message: error.message } } return { doubled, failure };',
|
||||
bindings: [{
|
||||
File renamed without changes.
+17
-17
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it, onTestFinished } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { WorkerThreadCodeRuntime } from '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
import type { Config } from '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
import { NodeCodeRuntime } from '@deepseek-ai/dsh-code-runtime-node'
|
||||
import type { Config } from '@deepseek-ai/dsh-code-runtime-node'
|
||||
import type { CodeBindingFunction, CodeBindingNamespace, CodeRunResult } from '@deepseek-ai/dsh-code-runtime'
|
||||
|
||||
/**
|
||||
@@ -11,8 +11,8 @@ import type { CodeBindingFunction, CodeBindingNamespace, CodeRunResult } from '@
|
||||
*/
|
||||
async function setup(config: Config = {}) {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(WorkerThreadCodeRuntime, config)
|
||||
const runtime = ctx.codeRuntime as WorkerThreadCodeRuntime
|
||||
await ctx.plugin(NodeCodeRuntime, config)
|
||||
const runtime = ctx.codeRuntime as NodeCodeRuntime
|
||||
return { ctx, runtime }
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ function tools(functions: Record<string, (args: unknown) => Promise<unknown>>):
|
||||
}]
|
||||
}
|
||||
|
||||
describe('WorkerThreadCodeRuntime — programs and bindings (real workers)', () => {
|
||||
describe('NodeCodeRuntime — programs and bindings (real workers)', () => {
|
||||
it('registers with the seam descriptors', async () => {
|
||||
const { runtime } = await setup()
|
||||
expect(runtime.language).toBe('typescript')
|
||||
@@ -170,7 +170,7 @@ describe('WorkerThreadCodeRuntime — programs and bindings (real workers)', ()
|
||||
})
|
||||
})
|
||||
|
||||
describe('WorkerThreadCodeRuntime — budgets and containment (real workers)', () => {
|
||||
describe('NodeCodeRuntime — budgets and containment (real workers)', () => {
|
||||
it('ends a hot loop at the compute budget — including behind a pending decoy dispatch', async () => {
|
||||
const { runtime } = await setup({ computeMs: 300, maxWallMs: 30_000 })
|
||||
const result = await runtime.run({
|
||||
@@ -447,7 +447,7 @@ describe('WorkerThreadCodeRuntime — budgets and containment (real workers)', (
|
||||
}, 15_000)
|
||||
})
|
||||
|
||||
describe('WorkerThreadCodeRuntime — hostile programs (real workers)', () => {
|
||||
describe('NodeCodeRuntime — hostile programs (real workers)', () => {
|
||||
it('survives forged port traffic: unknown binding names, duplicate ids, junk shapes', async () => {
|
||||
const { runtime } = await setup()
|
||||
const result = await runtime.run({
|
||||
@@ -790,7 +790,7 @@ describe('WorkerThreadCodeRuntime — hostile programs (real workers)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('WorkerThreadCodeRuntime — seam misuse and lifecycle', () => {
|
||||
describe('NodeCodeRuntime — seam misuse and lifecycle', () => {
|
||||
it('rejects invalid and duplicate binding globals loudly', async () => {
|
||||
const { runtime } = await setup()
|
||||
const cases: [string, RegExp][] = [
|
||||
@@ -853,23 +853,23 @@ describe('WorkerThreadCodeRuntime — seam misuse and lifecycle', () => {
|
||||
|
||||
it('rejects config values that are not positive numbers', async () => {
|
||||
const ctx = new Context()
|
||||
await expect(ctx.plugin(WorkerThreadCodeRuntime, { computeMs: -1 })).rejects.toThrow(/positive number/)
|
||||
await expect(ctx.plugin(NodeCodeRuntime, { computeMs: -1 })).rejects.toThrow(/positive number/)
|
||||
})
|
||||
|
||||
it('rejects a maxWallMs above Node\'s maximum timer delay', async () => {
|
||||
// setTimeout clamps a delay past 2^31-1 ms to 1 ms, so the positivity check
|
||||
// alone would accept a 25-day ceiling that expires on the first tick.
|
||||
const ctx = new Context()
|
||||
await expect(ctx.plugin(WorkerThreadCodeRuntime, { maxWallMs: 2_147_483_648 }))
|
||||
await expect(ctx.plugin(NodeCodeRuntime, { maxWallMs: 2_147_483_648 }))
|
||||
.rejects.toThrow(/maxWallMs must be at most 2147483647/)
|
||||
// The boundary itself is usable.
|
||||
await expect(ctx.plugin(WorkerThreadCodeRuntime, { maxWallMs: 2_147_483_647 })).resolves.toBeTruthy()
|
||||
await expect(ctx.plugin(NodeCodeRuntime, { maxWallMs: 2_147_483_647 })).resolves.toBeTruthy()
|
||||
})
|
||||
|
||||
it('requires maxOutputBytes to fit the smallest counted outer payloads', async () => {
|
||||
const ctx = new Context()
|
||||
await expect(ctx.plugin(WorkerThreadCodeRuntime, { maxOutputBytes: 3 })).rejects.toThrow(/safe integer of at least 4/)
|
||||
await expect(ctx.plugin(WorkerThreadCodeRuntime, { maxOutputBytes: 4.5 })).rejects.toThrow(/safe integer of at least 4/)
|
||||
await expect(ctx.plugin(NodeCodeRuntime, { maxOutputBytes: 3 })).rejects.toThrow(/safe integer of at least 4/)
|
||||
await expect(ctx.plugin(NodeCodeRuntime, { maxOutputBytes: 4.5 })).rejects.toThrow(/safe integer of at least 4/)
|
||||
})
|
||||
|
||||
it('keeps runs isolated: no state survives from one run to the next', async () => {
|
||||
@@ -881,8 +881,8 @@ describe('WorkerThreadCodeRuntime — seam misuse and lifecycle', () => {
|
||||
|
||||
it('disposal aborts in-flight runs, awaits worker exit, and rejects later runs', async () => {
|
||||
const ctx = new Context()
|
||||
const fiber = await ctx.plugin(WorkerThreadCodeRuntime)
|
||||
const runtime = ctx.codeRuntime as WorkerThreadCodeRuntime
|
||||
const fiber = await ctx.plugin(NodeCodeRuntime)
|
||||
const runtime = ctx.codeRuntime as NodeCodeRuntime
|
||||
const inflight: Promise<CodeRunResult> = runtime.run({ program: 'for (;;) {}', bindings: [] })
|
||||
// Give the worker a moment to actually start spinning.
|
||||
await new Promise(resolve => setTimeout(resolve, 200))
|
||||
@@ -894,8 +894,8 @@ describe('WorkerThreadCodeRuntime — seam misuse and lifecycle', () => {
|
||||
|
||||
it('removes ctx.codeRuntime when the providing fiber disposes (HMR safety)', async () => {
|
||||
const ctx = new Context()
|
||||
const fiber = await ctx.plugin(WorkerThreadCodeRuntime)
|
||||
expect(ctx.get('codeRuntime')).toBeInstanceOf(WorkerThreadCodeRuntime)
|
||||
const fiber = await ctx.plugin(NodeCodeRuntime)
|
||||
expect(ctx.get('codeRuntime')).toBeInstanceOf(NodeCodeRuntime)
|
||||
await fiber.dispose()
|
||||
expect(ctx.get('codeRuntime')).toBeUndefined()
|
||||
})
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -41,7 +41,7 @@ const result = await ctx.codeRuntime.run({
|
||||
|
||||
### Choose a backend
|
||||
|
||||
Backends declare two descriptors you can rely on: `language` — what the program must be written in, with `'typescript'` and `'python'` as the well-known values — and `isolation` — the execution substrate (`'worker-thread'`, `'process'`, `'container'`), a label for deployments and diagnostics, not a security claim. [`dsh-code-runtime-worker-thread`](../code-runtime-worker-thread/README.md) executes TypeScript in a fresh Node worker thread; the private [`dsh-experimental-code-runtime-python`](../../experimental/code-runtime-python/README.md) package executes Python in a fresh CPython subprocess for opt-in compositions.
|
||||
Backends declare two descriptors you can rely on: `language` — what the program must be written in, with `'typescript'` and `'python'` as the well-known values — and `isolation` — the execution substrate (`'worker-thread'`, `'process'`, `'container'`), a label for deployments and diagnostics, not a security claim. [`dsh-code-runtime-node`](../code-runtime-node/README.md) executes TypeScript in a fresh Node worker thread; the private [`dsh-experimental-code-runtime-python`](../../experimental/code-runtime-python/README.md) package executes Python in a fresh CPython subprocess for opt-in compositions.
|
||||
|
||||
### Name your bindings portably
|
||||
|
||||
@@ -97,7 +97,7 @@ Binding-global and error-class names are language-portable: they must match the
|
||||
Read these when the package-level contract is not enough. They move from the PTC mode consumer to the backends and the capability-seam model.
|
||||
|
||||
- [PTC mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-ptc.md) — how the tool registry consumes `ctx.codeRuntime` and presents `run_code` to the model.
|
||||
- [Worker-thread backend](../code-runtime-worker-thread/README.md) — the shipped TypeScript execution backend.
|
||||
- [Worker-thread backend](../code-runtime-node/README.md) — the shipped TypeScript execution backend.
|
||||
- [Experimental Python backend](../../experimental/code-runtime-python/README.md) — the private CPython subprocess provider and its fd-3 protocol.
|
||||
- [Code runtime subsystem reference](../../../docs/subsystems/code-runtime.md) — request/result vocabulary, bindings, and the `ctx.codeRuntime` cordis surface.
|
||||
- [Capability seams](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) — the Service Definition / Service Provider / Consumer split.
|
||||
|
||||
@@ -41,7 +41,7 @@ const result = await ctx.codeRuntime.run({
|
||||
|
||||
### 选择后端
|
||||
|
||||
后端声明两个你可以依赖的描述符:`language`——程序必须使用的源语言,已知值为 `'typescript'` 与 `'python'`——以及 `isolation`——执行基底(`'worker-thread'`、`'process'`、`'container'`),仅供部署与诊断使用,不构成安全声明。[`dsh-code-runtime-worker-thread`](../code-runtime-worker-thread/README.zh.md) 在全新的 Node Worker 线程中执行 TypeScript;私有的 [`dsh-experimental-code-runtime-python`](../../experimental/code-runtime-python/README.zh.md) 包在全新的 CPython 子进程中执行 Python,供选择性组合使用。
|
||||
后端声明两个你可以依赖的描述符:`language`——程序必须使用的源语言,已知值为 `'typescript'` 与 `'python'`——以及 `isolation`——执行基底(`'worker-thread'`、`'process'`、`'container'`),仅供部署与诊断使用,不构成安全声明。[`dsh-code-runtime-node`](../code-runtime-node/README.zh.md) 在全新的 Node Worker 线程中执行 TypeScript;私有的 [`dsh-experimental-code-runtime-python`](../../experimental/code-runtime-python/README.zh.md) 包在全新的 CPython 子进程中执行 Python,供选择性组合使用。
|
||||
|
||||
### 可移植地命名绑定
|
||||
|
||||
@@ -97,7 +97,7 @@ binding-global 与 error-class 名称是语言可移植的:必须匹配标识
|
||||
当包级约定不够用时阅读以下内容。它们从 PTC mode 消费方进入后端与能力 seam 模型。
|
||||
|
||||
- [PTC mode Agent Note](../../../.agents/notes/implemented/feature/2026-06-15-ptc.zh.md)——工具注册表如何消费 `ctx.codeRuntime` 并把 `run_code` 呈现给模型。
|
||||
- [Worker 线程后端](../code-runtime-worker-thread/README.zh.md)——已发布的 TypeScript 执行后端。
|
||||
- [Worker 线程后端](../code-runtime-node/README.zh.md)——已发布的 TypeScript 执行后端。
|
||||
- [实验性 Python 后端](../../experimental/code-runtime-python/README.zh.md)——私有的 CPython 子进程提供方及其 fd-3 协议。
|
||||
- [代码运行时子系统参考](../../../docs/subsystems/code-runtime.zh.md)——请求/结果词汇、绑定与 `ctx.codeRuntime` 的 cordis 接口面。
|
||||
- [能力 seam](../../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.zh.md)——Service Definition / Service Provider / Consumer 拆分。
|
||||
|
||||
Reference in new issue
Block a user