Merge branch 'codex/simp-prune-tools-prompt-surface' into codex/simp-prune-code-runtime-surface

# Conflicts:
#	docs/config-catalog.md
#	docs/cordis-catalog/services.md
#	docs/rfc/implemented/feature/2026-06-15-code-mode.md
This commit is contained in:
Tianyi Cui
2026-07-14 19:05:23 +08:00
562 changed files with 4440 additions and 12566 deletions
@@ -29,13 +29,13 @@ Every field is validated (positive numbers) and defaulted; there are no other tu
## The worker entry, unbuilt and built
`worker.ts` is deliberately erasable-only TypeScript with type-only cross-package imports: unbuilt (vitest/tsx), the host spawns `src/worker.ts` directly and Node's native type stripping loads it; built, the entry ships as the sibling CommonJS bundle `lib/worker.cjs` (its own tsdown entry). The CommonJS format is required because pkg's VFS Worker hook compiles filesystem-string entries as CommonJS. The host converts either entry URL to a filesystem string before constructing `Worker`, which works through both ordinary Node resolution and that pkg hook. The built path is pinned by `tests/built-lib.e2e.ts`, the real-load-path guard from [docs/testing.md](../../../docs/testing.md).
Source mode loads erasable-only `src/worker.ts` through Node's native type stripping. Built mode passes the sibling `lib/worker.cjs` as a filesystem path because pkg's VFS Worker hook expects CommonJS; the same path works under ordinary Node. `tests/built-lib.e2e.ts` pins the real load path required by [docs/testing.md](../../../docs/testing.md).
The SDK surface is the default/named `WorkerCodeRuntime` class plus `Config`. The operational `./worker` subpath exists only as the packaged spawn entry; the wire protocol and bootstrap helpers are source-private implementation details.
## Model Experience
Indirectly, through Code Mode in `dsh-tools`, which renders this worker's capped printed or returned data, exact `[dsh-code-runtime-worker] log capture truncated at <maxLogBytes> bytes` and `… [truncated]` markers, and `Error: code run failed (<kind>): <message>` failures into a retained `run_code` result while keeping binding traffic and worker internals outside context.
Indirectly, through Code Mode in [`dsh-tools`](../../core/tools/README.md), which renders this worker's capped printed or returned data and exact `[dsh-code-runtime-worker] log capture truncated at <maxLogBytes> bytes` and `… [truncated]` markers into a retained `run_code` result. Binding traffic and worker internals stay outside context.
## Known Limitations and Deferred Work
@@ -1,12 +1,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). The real worker entry (`worker.ts`) is a thin
* self-executing glue file over {@link runWorkerMain}, excluded from
* coverage the same way `bin.ts` entrypoints are, and exercised end-to-end
* by the integration tests that spawn real workers.
*
* 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/src/bootstrap
*/
@@ -95,12 +90,11 @@ export function makeConsoleShim(logs: LogBuffer): Record<(typeof CONSOLE_LEVELS)
/**
* Redirect a stream's `write` into the log buffer (the program-visible
* `process.stdout`/`process.stderr` in the real worker), so raw writes land
* in emission order alongside console output instead of racing down a pipe.
* The shim keeps Node's `write(chunk[, encoding][, callback])` contract: the
* callback fires asynchronously once the chunk is admitted (a program
* awaiting flush completion must complete, not sit until the wall timeout),
* even for writes the exhausted budget drops.
* `process.stdout`/`process.stderr` in the real worker), so raw writes land in emission order
* alongside console output instead of racing down a pipe. It preserves Node's optional callback
* contract: the callback runs asynchronously after admission, even when the log budget drops
* the write.
*
* @param logs - the buffer captured writes are pushed into.
* @param stream - the stream whose `write` slot is patched.
* @returns the restore function (the in-process tests un-patch; the real
@@ -150,16 +144,12 @@ export function truncateUtf8Bytes(text: string, maxBytes: number): string {
}
/**
* Prepare the program's completion value for the done message: a value whose
* MEASURED cross-boundary size fits `maxValueBytes` crosses raw — exact
* bytes for a string, the structured-clone wire size (`v8.serialize`) for
* everything else, so a huge container whose BOUNDED inspect rendering
* happens to be small cannot smuggle itself past the cap. Anything else
* (non-cloneable, or oversized) is REPLACED by its bounded `util.inspect`
* rendering, byte-truncated ({@link truncateUtf8Bytes}) with an in-band
* marker — the seam contract's "a non-transferable value is replaced by a
* string rendering", extended to oversized ones so a huge return cannot
* flood the host.
* Prepare the program's completion value for the done message: a value whose MEASURED
* cross-boundary size fits `maxValueBytes` crosses raw — exact bytes for a string, the
* structured-clone wire size (`v8.serialize`) for everything else, so a huge container whose
* bounded inspect rendering happens to be small cannot smuggle itself past the cap. Oversized
* or non-cloneable values are replaced by a bounded string rendering with an in-band marker.
*
* @param value - the program's completion value.
* @param maxValueBytes - the byte cap for the value.
* @returns the done-message fragment: `{}` for `undefined`, else `{ value }`.
@@ -213,13 +203,11 @@ export function wireReplies(port: BootstrapPort, pending: Map<number, PendingCal
}
/**
* Build the binding namespace objects the program sees: one null-prototype
* global per namespace, each declared name an own enumerable async function
* that bridges over the port (`__proto__`/`constructor`/`toString` are
* ordinary keys, never prototype collisions). A non-cloneable argument
* rejects that one call with a descriptive error; the host's reply (`ok`
* false) rejects it likewise, so a failed tool call surfaces in the program
* as an ordinary promise rejection.
* Build the binding namespace objects the program sees: one null-prototype global per
* namespace, each declared name an own enumerable async function that bridges over the port
* (`__proto__`/`constructor`/`toString` are ordinary keys, never prototype collisions).
* Non-cloneable arguments and host failure replies reject only the corresponding call.
*
* @param data - the boot payload's namespace declarations (globals + names).
* @param port - the port binding calls are posted to.
* @param pending - the id-keyed map each posted call parks its handles in.
@@ -254,17 +242,12 @@ export function makeNamespaces(
}
/**
* Run one program to settlement and post the {@link DoneMessage}: wires the
* reply handler, materializes the namespaces and console shim, compiles the
* type-stripped body as an async function (top-level `await`/`return`
* work), and reports a thrown program error as the done message's `error`
* field. Exactly one done message is ever posted.
* @param port - the message port to the host (the real `parentPort`, or the tests' fake).
* Run one strict async-function body, allowing top-level `await` and `return`, and post exactly
* one terminal {@link DoneMessage}; a thrown program error becomes its `error` field.
* @param port - host message port or test double.
* @param data - the boot payload the host sent.
* @param streams - the stream objects whose `write` is captured (the real
* `process.stdout`/`process.stderr` in the worker; fakes in tests).
* @returns resolves after the done message is posted (the tests await it;
* the real entry lets the worker exit naturally).
* @param streams - stdout/stderr objects captured as program logs.
* @returns after posting the done message.
*/
export async function runWorkerMain(
port: BootstrapPort,
@@ -1,14 +1,8 @@
/**
* Worker-thread implementation of the code-execution seam: one fresh Node
* worker per run, executing the model's TypeScript after a host-side
* type-strip, with bindings bridged over the message port. Containment, not
* a security boundary (bash-equivalent trust — see the Code Mode RFC's
* trust-posture section): the worker gets an EMPTY environment, a heap cap,
* and two independent budgets — `computeMs` metered on the worker's
* measured event-loop busy time (a hot loop cannot hide behind a pending
* binding call) and a never-pausing `maxWallMs` ceiling — all funneling
* into `worker.terminate()`, which ends hot synchronous loops too.
*
* Worker-thread code runtime: a fresh worker runs each host-type-stripped TypeScript program
* 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
*/
@@ -263,11 +257,9 @@ export class WorkerCodeRuntime extends CodeRuntime {
// Model code gets NO ambient environment — stronger than the scrubbed
// env the defensive-patterns rule requires for spawned commands.
env: {},
// Hermetic flags too: without this the worker inherits the host
// process's execArgv (a test runner's or tsx's loader hooks), which a
// bare isolate with an empty environment cannot satisfy. The entry
// needs nothing beyond native type stripping, on this repo's whole
// Node range.
// Hermetic flags too: without this the worker inherits the host process's execArgv (a
// test runner's or tsx's loader hooks), which a bare isolate with an empty environment
// cannot satisfy.
execArgv: [],
resourceLimits: { maxOldGenerationSizeMb: this.config.maxOldGenerationSizeMb },
// Backstop capture: the bootstrap patches JS-level writes into its own
@@ -283,12 +275,8 @@ export class WorkerCodeRuntime extends CodeRuntime {
const logs: string[] = []
const strayLogs: string[] = []
// ONE host-side ledger for everything that lands in `logs`/`strayLogs`,
// whatever the path: honest port entries, FORGED port entries (model
// code posting `log` messages directly, bypassing the worker-side
// LogBuffer), and stray pipe bytes. On the first overflow it emits the
// same in-band marker the worker's LogBuffer would and drops the rest,
// so the documented cap is one shared `maxLogBytes` however it is hit.
// One host-side budget covers normal, forged, and stray-pipe log entries. The first
// overflow emits the shared in-band marker and drops everything after it.
let logBudget = this.config.maxLogBytes
let logsTruncated = false
const admit = (text: string, sink: string[]): void => {
@@ -312,11 +300,8 @@ export class WorkerCodeRuntime extends CodeRuntime {
worker.stdout.on('data', captureStray)
worker.stderr.on('data', captureStray)
// Settlement: exactly one outcome wins; every path funnels through
// here, cleans up the timers/listeners, terminates the worker, and
// resolves only after the worker actually exited (quiescence). Logs
// streamed eagerly before the settlement are kept — a timed-out or
// killed program still shows the model what it printed.
// Exactly one outcome wins. Every path cleans up, terminates, and awaits the worker;
// logs captured before timeout, abort, or failure remain in the result.
let finishResolve!: () => void
const finished = new Promise<void>((done) => { finishResolve = done })
const finish = (result: Omit<CodeRunResult, 'logs'>): void => {
@@ -334,11 +319,8 @@ export class WorkerCodeRuntime extends CodeRuntime {
const onDone = (message: WorkerToHost): void => {
if (message.type !== 'done') return
// Re-cap the completion value HOST-side: the honest path already
// capped it in the worker (prepareValue there), but a forged done
// message bypasses the bootstrap entirely — without this, model code
// could flood the host past maxValueBytes. Honest values pass
// unchanged (see VALUE_RENDER_SLACK); the error text is bounded too.
// Re-cap forged completion traffic at the hostile boundary. Honest worker-capped values
// pass unchanged via VALUE_RENDER_SLACK; error text is bounded too.
finish({
...prepareValue(message.value, this.config.maxValueBytes + VALUE_RENDER_SLACK),
...message.error ? { error: { kind: 'exception' as const, message: truncateUtf8Bytes(message.error.message, this.config.maxValueBytes) } } : {},
@@ -1,11 +1,7 @@
/**
* Wire protocol between the host runtime and the worker bootstrap. Everything
* crossing the message port is structured-clone-plain and versionless — both
* ends ship in this package, always at the same version. The host treats
* inbound traffic as HOSTILE (the worker runs model code, which can reach
* `parentPort` via `import('node:worker_threads')` and forge any of these
* shapes); the worker treats inbound traffic as trusted.
*
* 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/src/protocol
*/
@@ -1,12 +1,6 @@
/**
* The worker-thread entrypoint: self-executing glue over
* `bootstrap.ts`'s {@link runWorkerMain}, kept to the spawn wiring alone.
* Like `bin.ts` CLI entrypoints, this file executes only inside a spawned
* worker isolate — a place the coverage provider cannot observe — so it is
* excluded from the coverage gate while every line of actual logic lives in
* `bootstrap.ts`, unit-tested in-process; the real spawn path is pinned by
* the integration tests that run genuine workers.
*
* 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/src/worker
*/
@@ -5,19 +5,10 @@ import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
/**
* BUILT-ARTIFACT smoke for the published package (the real-load-path guard
* from docs/testing.md): the unit suite runs `src/` under vitest, where the
* worker entry resolves to `src/worker.ts` — a consumer runs `lib/index.js`
* under plain `node`, where it must resolve the sibling `lib/worker.cjs`
* bundle instead. This spawns plain `node` (NOT tsx) from inside the package
* directory and imports the package BY NAME, so resolution flows through the
* real `exports` map exactly as it would from a downstream install; the
* program exercises the type-strip, the worker spawn, the binding bridge,
* and log capture end-to-end through the built bundles.
*
* It build-gates: SKIPS when the built artifacts are absent (suite run
* without `pnpm run build`); CI runs it after the build step. KEYLESS — no
* model is involved.
* Keyless built-artifact smoke: plain Node imports the package by name through its exports map,
* then exercises type stripping, sibling `worker.cjs` loading, bindings, and logs. Unit tests use
* `src/worker.ts`; this pins the downstream `lib/index.js` path. It skips when `lib/` is absent,
* and CI runs it after the build.
*/
const pkgDir = fileURLToPath(new URL('..', import.meta.url))
@@ -250,10 +250,8 @@ describe('WorkerCodeRuntime — budgets and containment (real workers)', () => {
it('captures pipe writes that bypass the patched write slot as stray logs, capped by the same budget', async () => {
const { runtime } = await setup({ maxLogBytes: 4 })
const result = await runtime.run({
// The bootstrap patches the stream instance's own `write`; going
// through the prototype's slot reaches the real pipe underneath, so
// the bytes arrive host-side as stray data. The pauses keep the two
// writes in separate pipe chunks and let them land before settlement.
// The prototype write bypasses the patched instance and reaches the real pipe. Pauses keep
// writes in separate chunks and let both reach the host before settlement.
program: `
const write = (text) => Object.getPrototypeOf(process.stdout).write.call(process.stdout, text);
write('abcd');
@@ -1,17 +1,9 @@
import { defineConfig } from 'tsdown'
/**
* Package-shape override (see the root tsdown.config.ts): besides the
* default lib/index.js bundle, the worker BOOTSTRAP ships as its own
* sibling CommonJS entry — `new Worker(fileURLToPath(new URL('./worker.cjs', import.meta.url)))`
* loads it as a file, so it cannot be part of the index bundle. pkg's VFS
* Worker hook compiles string-path entries as CommonJS, so an ESM worker is
* not viable inside the executable. TWO
* single-entry builds, not one two-entry build: a multi-entry build emits
* the shared bootstrap module as a `lib/bootstrap-*.js` chunk both bundles
* import, which the package.json `files` whitelist (deliberately exact)
* would omit from the packed artifact — each single-entry build inlines its
* own bootstrap copy instead, keeping every shipped file self-contained.
* Build the index and worker as separate single-entry bundles. The sibling `worker.cjs` is loaded
* by file and must be CommonJS for pkg's VFS Worker hook. A multi-entry build emits an unlisted
* shared chunk omitted by the package's exact `files` whitelist; separate builds inline it.
*/
export default defineConfig([
{