fix: self-contained built bundles + wire-size value cap (bot review)

Two findings from the GitHub review bot on the ready PR:

The tsdown two-entry build emitted the shared bootstrap module as a
lib/bootstrap-*.js chunk imported by both bundles, which the package.json
files whitelist (deliberately exact) omitted — a packed install had
dangling imports. The package now runs two single-entry builds, so each
bundle inlines its own bootstrap copy and every shipped file is
self-contained.

prepareValue admitted any cloneable value whose BOUNDED inspect rendering
fit maxValueBytes, so a huge container with a compact rendering (a
50k-element array renders as '... N more items') crossed the port raw,
bypassing the cap on both sides. The cap now measures the value's real
cross-boundary size — exact bytes for strings, the structured-clone wire
size (v8.serialize) for everything else — and oversized containers cross
as their bounded rendering instead.
This commit is contained in:
Tianyi Cui
2026-07-08 12:55:14 +08:00
parent aa2a7f9a8a
commit e20ce35ffb
6 changed files with 81 additions and 30 deletions
@@ -11,6 +11,7 @@
*/
import { inspect } from 'node:util'
import { serialize } from 'node:v8'
import type { CodeLogEntry } from '@deepseek-ai/dsh-code-runtime'
import { logTruncationMarker } from './protocol.ts'
import type { DoneMessage, ReplyMessage, WorkerBootData, WorkerToHost } from './protocol.ts'
@@ -119,29 +120,36 @@ export function captureStreamWrites(logs: LogBuffer, stream: PatchableStream, so
const INSPECT_OPTIONS = { depth: 4, maxArrayLength: 100, maxStringLength: 10_000 } as const
/**
* Prepare the program's completion value for the done message: a
* structured-clone-safe value whose rendering fits `maxValueBytes` crosses
* raw; anything else (non-cloneable, or oversized) is REPLACED by its
* bounded `util.inspect` rendering, truncated 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. Anything else
* (non-cloneable, or oversized) is REPLACED by its bounded `util.inspect`
* rendering, truncated 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.
* @param value - the program's completion value.
* @param maxValueBytes - the byte cap for the rendered value.
* @param maxValueBytes - the byte cap for the value.
* @returns the done-message fragment: `{}` for `undefined`, else `{ value }`.
*/
export function prepareValue(value: unknown, maxValueBytes: number): { value?: unknown } {
if (value === undefined) return {}
const rendered = typeof value === 'string' ? value : inspect(value, INSPECT_OPTIONS)
let cloneable = true
try {
structuredClone(value)
} catch {
// Only the verdict matters: the value has parts structured clone rejects
// (functions, classes, …) and must cross as its rendering instead.
cloneable = false
if (typeof value === 'string') {
if (Buffer.byteLength(value, 'utf8') <= maxValueBytes) return { value }
} else {
let size: number | undefined
try {
size = serialize(value).byteLength
} catch {
// Only the verdict matters: the value has parts the structured-clone
// algorithm rejects (functions, classes, …) and must cross as its
// rendering instead.
size = undefined
}
if (size !== undefined && size <= maxValueBytes) return { value }
}
if (cloneable && Buffer.byteLength(rendered, 'utf8') <= maxValueBytes) return { value }
const rendered = typeof value === 'string' ? value : inspect(value, INSPECT_OPTIONS)
const capped = rendered.length > maxValueBytes ? `${rendered.slice(0, maxValueBytes)}… [truncated]` : rendered
return { value: capped }
}
@@ -45,7 +45,11 @@ export interface Config {
maxWallMs?: number
/** Shared byte budget for captured log text (console + raw stream writes), truncation marked in-band. */
maxLogBytes?: number
/** Byte cap for the rendered completion value; an oversized or non-cloneable value crosses as a capped string rendering. */
/**
* Byte cap for the completion value, measured by its real cross-boundary
* size (string bytes, or structured-clone wire size); an oversized or
* non-cloneable value crosses as a capped string rendering.
*/
maxValueBytes?: number
/** The worker's max old-generation heap in MiB (`resourceLimits`); overflow kills the worker, surfacing as kind `'worker-exit'`. */
maxOldGenerationSizeMb?: number