The dsh-tools half of the Code Mode RFC (its fourth, final change): the registry gains its first config — mode: native | code | both — and OWNS how its tools reach the model. 'code' contributes exactly one wire tool, run_code, plus a lazy tools:sdk prompt section declaring every other tool as a generated TypeScript API (jsonSchemaToTs: total over the defineTool subset, unknown degradation, lexicographic byte-identical rendering); 'both' ships both representations; 'native' is byte-for-byte the old behavior. Non-native modes fail every assembly loudly without a typescript-language ctx.codeRuntime. run_code's dispatch bridge: JSON-normalizes each binding argument before dispatch (what dispatches is what the tool/code-dispatch event logs — the append can never fail on payload shape; BigInt/circulars reject that one call), serializes all program tool calls through a per-run queue (even Promise.all — no concurrency-safety metadata yet), routes every sub-call through tools/pre-execute → tools/post-execute (a deny rejects the program-side promise), drops sub-call additionalContext (no safe outlet mid-run; pinned), owns a run-scoped abort that follows the outer signal in and fires on settlement (in-flight sub-dispatch aborted, queued abandoned, queue drained before returning), and converts a failed run into CodeRunFailedError → a structured isError carrying kind + captured logs. tool/code-dispatch joins SessionEventMap by declaration merging (log-only; deriveMessages ignores it). The composed surface: the tools config forwards through agent-core and both app packages; examples/code-agent + demo:code run the worker runtime under mode code (keyless boot smoke + a with-key e2e proving the collapsed [run_code] header, the dispatch events, and the file the program wrote); two new snapshot scenarios (code-mode-turn, both-mode-turn) record the SDK section, collapsed header, dispatch events, and result card — each its own header-pinning class (the harness gains per-scenario config overlays and per-class pins). Catalogs, graphs, cookbook, hooks-bridge notes, and the RFC (moved to implemented/, restructured to decision-era headings) updated in the same change.
code-agent — the Code Mode demo
The Code Mode form of the coding agent: instead of one native tool call per step, the model is offered exactly ONE wire tool — run_code — plus a generated TypeScript SDK section declaring every other registered tool (bash, read, write, edit, todo_write). The model composes tools by writing a program; the program runs in a fresh worker thread (@deepseek-ai/dsh-code-runtime-worker), its tool calls bridge back through the ordinary tools/pre-execute/post-execute pipeline one at a time, each is logged as a tool/code-dispatch session event, and ONLY what the program prints or returns re-enters the model's context.
pnpm run demo:code # needs DEEPSEEK_API_KEY (repo-root .env works)
Try a task that spans several tool calls, e.g.:
Count the lines of every
*.mdfile under docs/ and write the three largest to summary.txt.
and watch the transcript: one run_code call, a program looping over tools, and a result the model curated instead of five round-trips of raw tool output.
Two lines of cordis.yml make the difference from examples/coding-agent: the code-runtime entry (the worker-thread backend registering ctx.codeRuntime) and tools: { mode: code } on the app (flip it to both to offer native calls AND run_code side by side; remove both lines and it IS the coding agent).
Tests: tests/keyless-smoke.e2e.ts boots the real cordis.yml through the Loader with no prompt (the export-shape guard); tests/code-mode.e2e.ts is the with-key proof — a real model, a two-tool task, asserting the wire tool list was exactly [run_code], the tool/code-dispatch events landed, and the curated answer came back.