@deepseek-ai/dsh-workflow-ptc 0.1.7-rc.2 → 0.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +1 -1
- package/lib/types/guest-source.d.ts +1 -1
- package/package.json +35 -35
package/lib/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { assertNever, snapshotJsonValue } from "@deepseek-ai/dsh-util-values";
|
|
|
9
9
|
//#region lib/types/guest-source.js
|
|
10
10
|
/** Generated by scripts/gen-workflow-guest.ts. Do not edit directly. */
|
|
11
11
|
/** Self-contained ESM guest transported into the mounted PTC runtime. */
|
|
12
|
-
const WORKFLOW_GUEST_SOURCE = "import * as vm from \"node:vm\";\n//#region packages/workflow/workflow-ptc/src/realm.ts\n/**\n* Materializes script VM values as plain JSON and renders thrown values.\n* Getters and proxy traps may execute inside the confined Node process;\n* process isolation and cancellation belong to PTC, not the VM.\n* @module @deepseek-ai/dsh-workflow-ptc/realm\n*/\n/** Thrown by {@link materializeFromRealm}; the caller wraps it into the right `WorkflowError` code. */\nvar MaterializeError = class extends Error {\n path;\n reason;\n constructor(path, reason) {\n super(`${path}: ${reason}`);\n this.path = path;\n this.reason = reason;\n this.name = \"MaterializeError\";\n }\n};\n/**\n* Render a thrown value to failure text without ever throwing: prefer the\n* `stack` (host or realm — a realm error's `stack` is a plain string read),\n* fall back to `message`, then `String()`. Reading those properties MAY run\n* script code; if that code itself throws, a fixed label is returned instead.\n* @param error - any value thrown in the host or guest realm.\n* @returns human-readable text for the failure report; prefers the stack.\n*/\nfunction renderThrown(error) {\n try {\n const stack = error?.stack;\n if (typeof stack === \"string\" && stack.length > 0) return stack;\n const message = error?.message;\n if (typeof message === \"string\" && message.length > 0) return message;\n return String(error);\n } catch {\n return \"[unrenderable thrown value]\";\n }\n}\n/**\n* Whether an object's prototype chain represents a plain data object: `null`, or a prototype\n* whose own prototype is `null` (the realm's `Object.prototype` — which we\n* cannot compare by identity across realms). A `Date`/`Map`/class instance\n* has a longer chain and is rejected.\n*/\nfunction hasPlainPrototype(value) {\n const proto = Object.getPrototypeOf(value);\n if (proto === null) return true;\n return Object.getPrototypeOf(proto) === null;\n}\n/**\n* Copy `value` (typically from the vm realm) into plain host JSON data. Root `undefined` is\n* returned unchanged; nested `undefined` and values JSON cannot represent losslessly fail\n* with the offending path. Property accessors run normally, and a throwing read is wrapped\n* with its rendered failure.\n*\n* @param value - the realm value to materialize.\n* @param root - the path label for the root value (error messages).\n* @returns the host-realm copy (plain objects/arrays/scalars only).\n* @throws {@link MaterializeError} for unsupported values, cycles, sparse arrays, exotic\n* prototypes, or property reads that throw.\n*/\nfunction materializeFromRealm(value, root = \"value\") {\n if (value === void 0) return void 0;\n try {\n return materialize(value, root, /* @__PURE__ */ new Set());\n } catch (error) {\n if (error instanceof MaterializeError) throw error;\n throw new MaterializeError(root, `reading the value threw: ${renderThrown(error)}`);\n }\n}\nfunction materialize(value, path, seen) {\n switch (typeof value) {\n case \"boolean\":\n case \"string\": return value;\n case \"number\":\n if (!Number.isFinite(value)) throw new MaterializeError(path, \"non-finite numbers are not JSON data\");\n return value;\n case \"bigint\": throw new MaterializeError(path, \"bigints are not JSON data\");\n case \"function\": throw new MaterializeError(path, \"functions are not plain JSON data\");\n case \"symbol\": throw new MaterializeError(path, \"symbols are not plain JSON data\");\n case \"undefined\": throw new MaterializeError(path, \"undefined is not JSON data\");\n case \"object\": break;\n }\n if (value === null) return null;\n const objectValue = value;\n if (seen.has(objectValue)) throw new MaterializeError(path, \"circular references are not JSON data\");\n seen.add(objectValue);\n try {\n if (Array.isArray(objectValue)) return materializeArray(objectValue, path, seen);\n return materializeObject(objectValue, path, seen);\n } finally {\n seen.delete(objectValue);\n }\n}\nfunction materializeArray(value, path, seen) {\n const out = [];\n for (let index = 0; index < value.length; index++) {\n if (!(index in value)) throw new MaterializeError(`${path}[${index}]`, \"sparse arrays are not JSON data\");\n out.push(materialize(value[index], `${path}[${index}]`, seen));\n }\n for (const key of Object.keys(value)) {\n const index = Number(key);\n if (!Number.isInteger(index) || index < 0 || index >= value.length) throw new MaterializeError(`${path}.${key}`, \"arrays with non-index properties are not JSON data\");\n }\n if (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n return out;\n}\nfunction materializeObject(value, path, seen) {\n if (!hasPlainPrototype(value)) throw new MaterializeError(path, \"only plain objects and arrays are JSON data (exotic prototype)\");\n if (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n const out = {};\n for (const key of Object.keys(value)) Object.defineProperty(out, key, {\n value: materialize(value[key], `${path}.${key}`, seen),\n enumerable: true,\n writable: true,\n configurable: true\n });\n return out;\n}\n//#endregion\n//#region packages/util/brand/src/index.ts\n/**\n* Apply a compile-time string brand without changing the value.\n* @param value - string admitted by the domain that owns the target brand.\n* @returns the same string with the requested compile-time brand.\n*/\nfunction brandString(value) {\n return value;\n}\n//#endregion\n//#region packages/llm/llm/src/error.ts\n/**\n* Harness error base with a stable machine-routable code and chained cause.\n* Package errors extend it so tool results and replay can retain failure class.\n* @module @deepseek-ai/dsh-llm/error\n*/\n/**\n* Base class for all harness errors. Carries a `code` (stable, programmatic —\n* e.g. `NO_ADAPTER`, `INVALID_ARGS`, `INVARIANT`) distinct from the\n* human-readable `message`, and supports `cause` chaining via the standard\n* `ErrorOptions`. `name` defaults to the subclass constructor name.\n*/\nvar HarnessError = class extends Error {\n /** Stable machine-routable failure class (e.g. `RATE_LIMIT`); route on this, never by parsing `message`. */\n code;\n constructor(message, code, options) {\n super(message, options);\n this.code = code;\n this.name = new.target.name;\n }\n};\nnew RegExp(String.raw`(?:^|[^a-z0-9])context[\\s_-](?:length|window)[\\s_-]` + String.raw`(?:exceed(?:ed|s)?|overflow(?:ed)?|limit[\\s_-]exceeded)(?:$|[^a-z0-9])`, \"i\");\nnew RegExp(String.raw`\\b(?:request|prompt|input|messages?)\\s+(?:is\\s+|are\\s+)?` + String.raw`too\\s+(?:large|long)\\s+for\\s+(?:(?:this|the)\\s+)?` + String.raw`(?:model(?:'s)?\\s+)?context(?:\\s+window)?\\b`, \"i\");\nnew RegExp(String.raw`\\b(?:input|prompt|request|messages?)\\b.{0,40}` + String.raw`\\b(?:exceed(?:s|ed)?|overflows?|is\\s+larger\\s+than)\\b.{0,40}` + String.raw`\\b(?:the\\s+)?(?:model(?:'s)?\\s+)?context(?:\\s+(?:length|window))?\\b`, \"i\");\n//#endregion\n//#region packages/util/values/src/index.ts\n/**\n* Mark an unreachable closed-union branch.\n* @param value - impossible value; an unhandled typed variant fails at the call site.\n* @param context - optional switch-site label included in the failure message.\n* @returns never; a runtime value that escaped its type always throws.\n*/\nfunction assertNever(value, context) {\n const rendered = JSON.stringify(value) ?? String(value);\n throw new Error(`unreachable variant${context ? ` in ${context}` : \"\"}: ${rendered}`);\n}\n/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */\nfunction hasIntrinsicConstructor$1(prototype, name) {\n const constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n if (typeof constructor !== \"function\") return false;\n try {\n return constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === `function ${name}() { [native code] }`;\n } catch {\n return false;\n }\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype$1(value) {\n return Object.getPrototypeOf(value) === null && hasIntrinsicConstructor$1(value, \"Object\");\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */\nfunction hasPlainArrayPrototype$1(value) {\n const prototype = Object.getPrototypeOf(value);\n if (!Array.isArray(prototype) || !hasIntrinsicConstructor$1(prototype, \"Array\")) return false;\n const objectPrototype = Object.getPrototypeOf(prototype);\n return typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype$1(objectPrototype);\n}\n/** Whether an object is a plain or null-prototype record from any JavaScript realm. */\nfunction hasPlainObjectPrototype(value) {\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype$1(prototype);\n}\n/** Return every JSON-visible object key, or reject own data JSON would discard. */\nfunction enumerableStringKeys(value) {\n const keys = Reflect.ownKeys(value);\n if (keys.some((key) => typeof key !== \"string\" || !Object.prototype.propertyIsEnumerable.call(value, key))) return void 0;\n return keys;\n}\n/** Validate lossless JSON iteratively, optionally materializing a detached snapshot. */\nfunction walkJsonValue(value, detach) {\n const ancestors = /* @__PURE__ */ new Set();\n let root;\n const assign = (destination, item) => {\n if (destination === void 0) return;\n if (destination.kind === \"root\") root = item;\n else if (destination.kind === \"array\") destination.target[destination.index] = item;\n else Object.defineProperty(destination.target, destination.key, {\n value: item,\n enumerable: true,\n configurable: true,\n writable: true\n });\n };\n const tasks = [{\n kind: \"visit\",\n value,\n ...detach ? { destination: { kind: \"root\" } } : {}\n }];\n for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n if (task.kind === \"leave\") {\n ancestors.delete(task.source);\n continue;\n }\n if (task.kind === \"array-item\") {\n if (!Object.prototype.hasOwnProperty.call(task.source, task.index)) return void 0;\n tasks.push({\n kind: \"visit\",\n value: task.source[task.index],\n ...task.target === void 0 ? {} : { destination: {\n kind: \"array\",\n target: task.target,\n index: task.index\n } }\n });\n continue;\n }\n if (task.kind === \"object-property\") {\n tasks.push({\n kind: \"visit\",\n value: task.source[task.key],\n ...task.target === void 0 ? {} : { destination: {\n kind: \"object\",\n target: task.target,\n key: task.key\n } }\n });\n continue;\n }\n const current = task.value;\n if (current === null) {\n assign(task.destination, null);\n continue;\n }\n if (typeof current === \"boolean\" || typeof current === \"string\") {\n assign(task.destination, current);\n continue;\n }\n if (typeof current === \"number\") {\n if (!Number.isFinite(current) || Object.is(current, -0)) return void 0;\n assign(task.destination, current);\n continue;\n }\n if (typeof current !== \"object\") return void 0;\n if (ancestors.has(current)) return void 0;\n if (Array.isArray(current)) {\n if (!hasPlainArrayPrototype$1(current)) return void 0;\n const length = current.length;\n if (Reflect.ownKeys(current).length !== length + 1) return void 0;\n const target = detach ? [] : void 0;\n if (target !== void 0) assign(task.destination, target);\n ancestors.add(current);\n tasks.push({\n kind: \"leave\",\n source: current\n });\n for (let index = length - 1; index >= 0; index--) tasks.push({\n kind: \"array-item\",\n source: current,\n index,\n ...target === void 0 ? {} : { target }\n });\n continue;\n }\n if (!hasPlainObjectPrototype(current)) return void 0;\n const keys = enumerableStringKeys(current);\n if (keys === void 0) return void 0;\n const target = detach ? {} : void 0;\n if (target !== void 0) assign(task.destination, target);\n ancestors.add(current);\n tasks.push({\n kind: \"leave\",\n source: current\n });\n for (let index = keys.length - 1; index >= 0; index--) {\n const key = keys[index];\n /* v8 ignore next -- the loop is bounded by the captured key count. */\n if (key === void 0) return void 0;\n tasks.push({\n kind: \"object-property\",\n source: current,\n key,\n ...target === void 0 ? {} : { target }\n });\n }\n }\n return detach ? root : true;\n}\n/**\n* Test the same lossless JSON rules as {@link snapshotJsonValue} without detaching the value.\n* @param value - candidate value to test.\n* @returns whether the value survives a JSON round trip without loss.\n*/\nfunction isJsonValue(value) {\n return walkJsonValue(value, false) === true;\n}\n//#endregion\n//#region packages/core/tools/src/json-schema.ts\n/**\n* Enforced JSON Schema subset shared by tool outputs, generated PTC mode\n* types, subagents, and workflows. The subset accepts any JSON root, an\n* annotation-only schema for unconstrained JSON, one scalar `type`, object\n* `properties`/`required`/boolean `additionalProperties`, array `items`,\n* type-correct scalar `enum`/`const`, and exact-one `oneOf`.\n*\n* Unsupported or misplaced keywords reject rather than being accepted without\n* enforcement. Consumers that require an object root apply\n* {@link assertObjectJsonSchema} before accepting input.\n* @module dsh-tools/json-schema\n*/\n/**\n* Thrown when a raw schema falls outside the enforced subset. `violations`\n* lists every offending path instead of stopping at the first author error.\n*/\nvar JsonSchemaError = class extends HarnessError {\n /** Individual schema violations in walk order. */\n violations;\n constructor(violations) {\n super(`unsupported JSON schema: ${violations.join(\"; \")}`, \"UNSUPPORTED_SCHEMA\");\n this.name = \"JsonSchemaError\";\n this.violations = violations;\n }\n};\nconst CONSTRAINT_KEYWORDS = new Set([\n \"type\",\n \"oneOf\",\n \"properties\",\n \"required\",\n \"additionalProperties\",\n \"items\",\n \"enum\",\n \"const\"\n]);\nconst ANNOTATION_KEYWORDS = new Set([\n \"description\",\n \"title\",\n \"default\",\n \"examples\"\n]);\nconst SCHEMA_TYPES = [\n \"object\",\n \"array\",\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"null\"\n];\n/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */\nfunction hasIntrinsicConstructor(prototype, name) {\n const constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n if (typeof constructor !== \"function\") return false;\n try {\n return constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === `function ${name}() { [native code] }`;\n } catch {\n return false;\n }\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype(value) {\n return Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, \"Object\");\n}\n/**\n* Test for a realm-agnostic plain JSON record without accepting arrays or\n* exotic objects.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the value has a plain-object prototype chain.\n*/\nfunction isPlainJsonRecord(value) {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n try {\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype(prototype);\n } catch {\n return false;\n }\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`. */\nfunction hasPlainArrayPrototype(value) {\n const prototype = Object.getPrototypeOf(value);\n if (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, \"Array\")) return false;\n const objectPrototype = Object.getPrototypeOf(prototype);\n return typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype(objectPrototype);\n}\n/** Return whether a record contains only own enumerable string keys. */\nfunction hasOnlyEnumerableStringKeys(value) {\n try {\n return Reflect.ownKeys(value).every((key) => typeof key === \"string\" && Object.prototype.propertyIsEnumerable.call(value, key));\n } catch {\n return false;\n }\n}\n/**\n* Test for an ordinary schema record whose keys survive JSON projection.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the record has an intrinsic prototype and only own enumerable string keys.\n*/\nfunction isJsonSchemaRecord(value) {\n return isPlainJsonRecord(value) && hasOnlyEnumerableStringKeys(value);\n}\n/**\n* Test for a dense ordinary array with no JSON-invisible decorations.\n* @param value - candidate array from any JavaScript realm.\n* @returns Whether the array is intrinsic, dense, and undecorated.\n*/\nfunction isPlainJsonArray(value) {\n if (!Array.isArray(value)) return false;\n try {\n if (!hasPlainArrayPrototype(value) || Reflect.ownKeys(value).length !== value.length + 1) return false;\n for (let index = 0; index < value.length; index++) if (!Object.hasOwn(value, index)) return false;\n return true;\n } catch {\n return false;\n }\n}\n/** Lossless finite JSON number, excluding negative zero. */\nfunction isJsonNumber(value) {\n return typeof value === \"number\" && Number.isFinite(value) && !Object.is(value, -0);\n}\n/** Whether a scalar is valid for one declared schema type. */\nfunction scalarMatches(type, value) {\n switch (type) {\n case \"string\": return typeof value === \"string\";\n case \"number\": return isJsonNumber(value);\n case \"integer\": return isJsonNumber(value) && Number.isInteger(value);\n case \"boolean\": return typeof value === \"boolean\";\n case \"null\": return value === null;\n /* v8 ignore next -- JsonSchemaScalarType is closed; this retains compile-time exhaustiveness. */\n default: return assertNever(type, \"JsonSchemaType\");\n }\n}\n/** Keywords that are invalid beside `oneOf`. */\nconst ONE_OF_SIBLING_KEYWORDS = [\n \"properties\",\n \"required\",\n \"additionalProperties\",\n \"items\",\n \"enum\",\n \"const\"\n];\n/** Validate object-only fields after its property schemas have been visited. */\nfunction checkObjectSchemaTail(node, path, properties, violations) {\n const hasRequired = Object.hasOwn(node, \"required\");\n const required = hasRequired ? node.required : void 0;\n if (hasRequired) if (!isPlainJsonArray(required) || required.some((entry) => typeof entry !== \"string\")) violations.push(`${path}.required must be an array of strings`);\n else {\n const declared = isJsonSchemaRecord(properties) ? properties : {};\n for (const key of required) if (!Object.hasOwn(declared, key)) violations.push(`${path}.required names \"${key}\" which is not in properties`);\n }\n if (Object.hasOwn(node, \"additionalProperties\") && typeof node.additionalProperties !== \"boolean\") violations.push(`${path}.additionalProperties must be a boolean`);\n}\n/** Collect every violation for one raw schema tree without using the JavaScript call stack. */\nfunction checkSchemaNode(root, rootPath, violations, seen) {\n const tasks = [{\n kind: \"enter\",\n node: root,\n path: rootPath\n }];\n for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n if (task.kind === \"leave\") {\n seen.delete(task.node);\n continue;\n }\n if (task.kind === \"one-of-tail\") {\n for (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(task.node, key)) violations.push(`${task.path}.${key} is not supported beside oneOf`);\n continue;\n }\n if (task.kind === \"object-tail\") {\n checkObjectSchemaTail(task.node, task.path, task.properties, violations);\n continue;\n }\n const { node, path } = task;\n if (!isJsonSchemaRecord(node)) {\n violations.push(`${path} must be a schema object`);\n continue;\n }\n if (seen.has(node)) {\n violations.push(`${path} is circular`);\n continue;\n }\n seen.add(node);\n tasks.push({\n kind: \"leave\",\n node\n });\n for (const key of Object.keys(node)) {\n if (CONSTRAINT_KEYWORDS.has(key)) continue;\n if (ANNOTATION_KEYWORDS.has(key)) {\n try {\n if (!isJsonValue(node[key])) violations.push(`${path}.${key} annotation must be lossless JSON data`);\n } catch {\n violations.push(`${path}.${key} annotation must be lossless JSON data`);\n }\n continue;\n }\n violations.push(`${path}.${key} is not a supported keyword (subset: type/oneOf/properties/required/additionalProperties/items/enum/const + annotations)`);\n }\n if (Object.hasOwn(node, \"description\") && typeof node.description !== \"string\") violations.push(`${path}.description must be a string`);\n if (Object.hasOwn(node, \"title\") && typeof node.title !== \"string\") violations.push(`${path}.title must be a string`);\n const hasType = Object.hasOwn(node, \"type\");\n const hasOneOf = Object.hasOwn(node, \"oneOf\");\n if (hasType && hasOneOf) {\n violations.push(`${path} cannot declare both type and oneOf`);\n continue;\n }\n if (!hasType && !hasOneOf) {\n for (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(node, key)) violations.push(`${path}.${key} requires type or oneOf`);\n continue;\n }\n if (hasOneOf) {\n const oneOf = node.oneOf;\n tasks.push({\n kind: \"one-of-tail\",\n node,\n path\n });\n if (!isPlainJsonArray(oneOf) || oneOf.length < 2) violations.push(`${path}.oneOf must be an array of at least two schemas`);\n else for (let index = oneOf.length - 1; index >= 0; index--) tasks.push({\n kind: \"enter\",\n node: oneOf[index],\n path: `${path}.oneOf[${index}]`\n });\n continue;\n }\n const type = node.type;\n if (typeof type !== \"string\" || !SCHEMA_TYPES.includes(type)) {\n violations.push(Array.isArray(type) ? `${path}.type must be a single type string (type arrays are not supported)` : `${path}.type must be one of ${SCHEMA_TYPES.join(\"/\")}`);\n continue;\n }\n const schemaType = type;\n for (const [key, types] of Object.entries({\n properties: [\"object\"],\n required: [\"object\"],\n additionalProperties: [\"object\"],\n items: [\"array\"],\n enum: [\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"null\"\n ],\n const: [\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"null\"\n ]\n })) if (Object.hasOwn(node, key) && !types.includes(schemaType)) violations.push(`${path}.${key} is not supported on type \"${schemaType}\"`);\n switch (schemaType) {\n case \"object\": {\n const properties = Object.hasOwn(node, \"properties\") ? node.properties : void 0;\n tasks.push({\n kind: \"object-tail\",\n node,\n path,\n properties\n });\n if (Object.hasOwn(node, \"properties\")) if (!isJsonSchemaRecord(properties)) violations.push(`${path}.properties must be an object of schemas`);\n else {\n const entries = Object.entries(properties);\n for (let index = entries.length - 1; index >= 0; index--) {\n const entry = entries[index];\n /* v8 ignore next -- the loop is bounded by the captured entry count. */\n if (entry === void 0) continue;\n tasks.push({\n kind: \"enter\",\n node: entry[1],\n path: `${path}.properties.${entry[0]}`\n });\n }\n }\n break;\n }\n case \"array\":\n if (Object.hasOwn(node, \"items\")) tasks.push({\n kind: \"enter\",\n node: node.items,\n path: `${path}.items`\n });\n break;\n case \"string\":\n case \"number\":\n case \"integer\":\n case \"boolean\":\n case \"null\": {\n const hasEnum = Object.hasOwn(node, \"enum\");\n const allowed = hasEnum ? node.enum : void 0;\n const enumValid = isPlainJsonArray(allowed) && allowed.length > 0 && allowed.every((entry) => scalarMatches(schemaType, entry));\n if (hasEnum && !enumValid) violations.push(`${path}.enum must be a non-empty array of ${schemaType} values`);\n const hasConst = Object.hasOwn(node, \"const\");\n const declaredConst = hasConst ? node.const : void 0;\n const constValid = scalarMatches(schemaType, declaredConst);\n if (hasConst) {\n if (!constValid) violations.push(`${path}.const must be a ${schemaType} value`);\n else if (enumValid && !allowed.includes(declaredConst)) violations.push(`${path}.const must be one of ${path}.enum when both are declared`);\n }\n break;\n }\n /* v8 ignore next -- schemaType was narrowed from the closed SCHEMA_TYPES table above. */\n default: assertNever(schemaType, \"JsonSchemaType\");\n }\n }\n}\n/**\n* Assert the enforced subset plus the object-root constraint retained by\n* subagent and workflow structured outputs.\n* @param schema - untrusted caller-supplied schema.\n* @returns Assertion that the schema belongs to the supported subset and has an object root.\n*/\nfunction assertObjectJsonSchema(schema) {\n const violations = [];\n checkSchemaNode(schema, \"schema\", violations, /* @__PURE__ */ new Set());\n if (violations.length === 0 && (!isJsonSchemaRecord(schema) || !Object.hasOwn(schema, \"type\") || schema.type !== \"object\")) violations.push(\"schema.type must be \\\"object\\\" (structured output is object-rooted)\");\n if (violations.length > 0) throw new JsonSchemaError(violations);\n}\n//#endregion\n//#region packages/workflow/workflow/src/index.ts\n/**\n* Typed error for workflow-seam failures. Extends {@link HarnessError}, so the\n* `code` is machine-routable taxonomy. `fatal` drives the combinator\n* discipline: `parallel()`/`pipeline()` re-throw a fatal error (a typo'd\n* option or a tripped cap must kill the script loudly), and reserve the\n* per-item `null` for child-run failures and ordinary in-stage script errors.\n* Every {@link WorkflowErrorCode} is fatal; the flag exists so the\n* distinction is explicit at every catch site rather than implied.\n*/\nvar WorkflowError = class extends HarnessError {\n /** Whether combinators must propagate this error instead of nulling the item. */\n fatal;\n constructor(message, code, options) {\n super(message, code, options);\n this.name = \"WorkflowError\";\n this.fatal = options?.fatal ?? true;\n }\n};\n/**\n* Whether combinators must re-throw `error` instead of mapping the item to `null`.\n* @param error - any thrown value; fatality is host `instanceof` (unforgeable from a script realm).\n* @returns true iff `error` is a {@link WorkflowError} whose `fatal` flag is set.\n*/\nfunction isFatalWorkflowError(error) {\n return error instanceof WorkflowError && error.fatal;\n}\n//#endregion\n//#region packages/workflow/workflow-ptc/src/runtime.ts\n/**\n* Workflow VM hooks, child callbacks, ordinary concurrency limits and result serialization.\n* PTC owns process confinement and cancellation. Fatal hook and provider failures propagate\n* through combinators; ordinary child failures and stage errors become per-item nulls.\n* @module @deepseek-ai/dsh-workflow-ptc/runtime\n*/\n/** The `agent()` options the script may pass; everything else rejects loud. */\nconst SUPPORTED_AGENT_OPTIONS = new Set([\n \"label\",\n \"phase\",\n \"schema\",\n \"provider\",\n \"model\"\n]);\n/** Deferred Claude Code options we name explicitly in the rejection message. */\nconst DEFERRED_AGENT_OPTIONS = new Set([\n \"effort\",\n \"isolation\",\n \"agentType\"\n]);\n/** Flatten a child's final output blocks to text (the non-schema `agent()` result). */\nfunction outputText(blocks) {\n return blocks.filter((block) => block.type === \"text\").map((block) => block.text).join(\"\");\n}\n/** A short display label derived from the prompt when the script passes none. */\nfunction defaultLabel(prompt) {\n const newline = prompt.indexOf(\"\\n\");\n const line = newline === -1 ? prompt : prompt.slice(0, newline);\n return line.length <= 48 ? line : `${line.slice(0, 47)}…`;\n}\n/**\n* One script execution inside the confined Node process. The host owns\n* cancellation and cleanup of any dropped child work.\n*/\nvar WorkflowExecution = class {\n limits;\n observer;\n children;\n /** 1-based count of `agent()` calls started (the `agentsStarted` result field). */\n started = 0;\n activeSlots = 0;\n slotWaiters = [];\n currentPhase;\n context;\n compiled;\n constructor(meta, body, args, limits, observer, children) {\n this.limits = limits;\n this.observer = observer;\n this.children = children;\n try {\n this.compiled = new vm.Script(`(async () => {\\n${body}\\n})()`, {\n filename: `workflow:${meta.name}`,\n lineOffset: -1\n });\n } catch (error) {\n throw new WorkflowError(`workflow script does not parse: ${String(error)}`, \"SCRIPT_PARSE\", { cause: error });\n }\n this.context = vm.createContext({}, { name: `workflow:${meta.name}` });\n const globals = {\n agent: (prompt, opts) => this.contain(this.agent(prompt, opts)),\n parallel: (thunks) => this.contain(this.parallel(thunks)),\n pipeline: (items, ...stages) => this.contain(this.pipeline(items, stages)),\n phase: (title) => {\n this.phase(title);\n },\n log: (message) => {\n this.log(message);\n },\n args\n };\n for (const [key, value] of Object.entries(globals)) this.context[key] = typeof value === \"function\" ? Object.freeze(value) : value;\n }\n /**\n * Run the script and materialize its JSON return value.\n * @returns A completed or error result; script failures never reject.\n */\n async drive() {\n try {\n const scriptPromise = this.compiled.runInContext(this.context, { timeout: this.limits.syncTimeoutMs });\n const raw = await this.contain(Promise.resolve(scriptPromise));\n return {\n value: raw === void 0 ? null : this.materializeResult(raw),\n stopReason: \"completed\",\n agentsStarted: this.started\n };\n } catch (error) {\n return {\n value: null,\n stopReason: \"error\",\n error: renderThrown(error),\n agentsStarted: this.started\n };\n }\n }\n /**\n * Attach a no-op rejection consumer WITHOUT changing what the caller\n * receives: if the script drops the promise, a host rejection cannot become\n * an unhandled rejection that kills the process; if\n * the script does await it, it still observes the rejection.\n */\n contain(promise) {\n promise.catch(() => {});\n return promise;\n }\n /** Materialize the script's return value; violations become RESULT_UNSERIALIZABLE. */\n materializeResult(raw) {\n try {\n return materializeFromRealm(raw, \"workflow result\");\n } catch (error) {\n /* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n if (!(error instanceof MaterializeError)) throw error;\n throw new WorkflowError(`the workflow's return value is not plain JSON data — ${error.message}. Return only JSON-serializable objects/arrays/scalars.`, \"RESULT_UNSERIALIZABLE\", { cause: error });\n }\n }\n /** Acquire one concurrency slot in FIFO order. */\n acquireSlot() {\n if (this.activeSlots < this.limits.maxConcurrentAgents) {\n this.activeSlots += 1;\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n this.slotWaiters.push(() => {\n this.activeSlots += 1;\n resolve();\n });\n });\n }\n releaseSlot() {\n this.activeSlots -= 1;\n const next = this.slotWaiters.shift();\n if (next) next();\n }\n /** The `agent(prompt, opts)` hook. */\n async agent(rawPrompt, rawOpts) {\n if (typeof rawPrompt !== \"string\" || rawPrompt.length === 0) throw new WorkflowError(\"agent() requires a non-empty prompt string\", \"INVALID_ARGUMENT\");\n const opts = this.readAgentOptions(rawOpts);\n if (this.started >= this.limits.maxTotalAgents) throw new WorkflowError(`this run reached its total agent cap (${this.limits.maxTotalAgents}) — a runaway-loop backstop; raise the applicable maxTotalAgents limit if the scale is intentional`, \"AGENT_CAP\");\n this.started += 1;\n const seq = this.started;\n const label = opts.label ?? defaultLabel(rawPrompt);\n const phase = opts.phase ?? this.currentPhase;\n await this.acquireSlot();\n try {\n let run;\n try {\n run = await this.children.startAgent({\n prompt: rawPrompt,\n ...opts.schema !== void 0 ? { schema: opts.schema } : {},\n ...opts.provider !== void 0 ? { provider: opts.provider } : {},\n ...opts.model !== void 0 ? { model: opts.model } : {}\n });\n } catch (error) {\n throw new WorkflowError(`agent() could not start a child: ${renderThrown(error)}`, \"AGENT_START\", { cause: error });\n }\n const info = {\n seq,\n label,\n ...phase !== void 0 ? { phase } : {},\n childId: brandString(run.id)\n };\n this.observer.agentStart(info);\n try {\n let result;\n try {\n result = await run.result;\n } catch (error) {\n this.observer.agentEnd({\n ...info,\n outcome: \"failed\"\n });\n throw new WorkflowError(`child agent run failed: ${renderThrown(error)}`, \"AGENT_RESULT\", { cause: error });\n }\n if (result.stopReason === \"completed\") {\n if (opts.schema !== void 0) {\n if (result.structured === void 0) {\n this.observer.agentEnd({\n ...info,\n outcome: \"failed\"\n });\n return null;\n }\n this.observer.agentEnd({\n ...info,\n outcome: \"completed\"\n });\n return result.structured;\n }\n this.observer.agentEnd({\n ...info,\n outcome: \"completed\"\n });\n return outputText(result.output);\n }\n this.observer.agentEnd({\n ...info,\n outcome: \"failed\"\n });\n return null;\n } finally {\n await run.dispose();\n }\n } finally {\n this.releaseSlot();\n }\n }\n /** Materialize + validate the `agent()` options bag from the realm. */\n readAgentOptions(rawOpts) {\n if (rawOpts === void 0) return {};\n let opts;\n try {\n opts = materializeFromRealm(rawOpts, \"agent() options\");\n } catch (error) {\n /* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n if (!(error instanceof MaterializeError)) throw error;\n throw new WorkflowError(`agent() options must be plain JSON data — ${error.message}`, \"INVALID_ARGUMENT\", { cause: error });\n }\n if (typeof opts !== \"object\" || opts === null || Array.isArray(opts)) throw new WorkflowError(\"agent() options must be an object\", \"INVALID_ARGUMENT\");\n const record = opts;\n for (const key of Object.keys(record)) {\n if (SUPPORTED_AGENT_OPTIONS.has(key)) continue;\n if (DEFERRED_AGENT_OPTIONS.has(key)) throw new WorkflowError(`agent() option \"${key}\" is deferred and not supported by this engine (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n throw new WorkflowError(`agent() option \"${key}\" is not recognized (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n }\n for (const key of [\n \"label\",\n \"phase\",\n \"provider\",\n \"model\"\n ]) if (record[key] !== void 0 && typeof record[key] !== \"string\") throw new WorkflowError(`agent() option \"${key}\" must be a string`, \"INVALID_ARGUMENT\");\n let schema;\n if (record.schema !== void 0) try {\n assertObjectJsonSchema(record.schema);\n schema = record.schema;\n } catch (error) {\n /* v8 ignore next -- defensive rethrow arm: assertObjectJsonSchema only throws JsonSchemaError */\n if (!(error instanceof JsonSchemaError)) throw error;\n throw new WorkflowError(`agent() schema is outside the supported subset — ${error.message}`, \"UNSUPPORTED_SCHEMA\", { cause: error });\n }\n return {\n ...record.label !== void 0 ? { label: record.label } : {},\n ...record.phase !== void 0 ? { phase: record.phase } : {},\n ...record.provider !== void 0 ? { provider: record.provider } : {},\n ...record.model !== void 0 ? { model: record.model } : {},\n ...schema !== void 0 ? { schema } : {}\n };\n }\n /** The `parallel(thunks)` hook: each thunk caught → `null`; fatal errors propagate. */\n async parallel(rawThunks) {\n if (!Array.isArray(rawThunks)) throw new WorkflowError(\"parallel() requires an array of zero-argument functions\", \"INVALID_ARGUMENT\");\n this.assertItemCap(rawThunks.length, \"parallel()\");\n const thunks = rawThunks.map((thunk, index) => {\n if (typeof thunk !== \"function\") throw new WorkflowError(`parallel() item ${index} is not a function`, \"INVALID_ARGUMENT\");\n return thunk;\n });\n return Promise.all(thunks.map(async (thunk) => {\n try {\n return await thunk();\n } catch (error) {\n if (isFatalWorkflowError(error)) throw error;\n return null;\n }\n }));\n }\n /** The `pipeline(items, ...stages)` hook: per-item stage chains, NO cross-stage barrier. */\n async pipeline(rawItems, rawStages) {\n if (!Array.isArray(rawItems)) throw new WorkflowError(\"pipeline() requires an items array\", \"INVALID_ARGUMENT\");\n this.assertItemCap(rawItems.length, \"pipeline()\");\n if (rawStages.length === 0) throw new WorkflowError(\"pipeline() requires at least one stage function\", \"INVALID_ARGUMENT\");\n const stages = rawStages.map((stage, index) => {\n if (typeof stage !== \"function\") throw new WorkflowError(`pipeline() stage ${index} is not a function`, \"INVALID_ARGUMENT\");\n return stage;\n });\n return Promise.all(rawItems.map(async (item, index) => {\n let value = item;\n try {\n for (const stage of stages) value = await stage(value, item, index);\n return value;\n } catch (error) {\n if (isFatalWorkflowError(error)) throw error;\n return null;\n }\n }));\n }\n assertItemCap(length, hook) {\n if (length > this.limits.maxItemsPerCall) throw new WorkflowError(`${hook} received ${length} items — over the per-call cap (${this.limits.maxItemsPerCall}); split the work or raise maxItemsPerCall in the engine config`, \"ITEM_CAP\");\n }\n /** The `phase(title)` hook: sets the current label for subsequent `agent()` calls and notifies observers. */\n phase(title) {\n if (typeof title !== \"string\" || title.length === 0) throw new WorkflowError(\"phase() requires a non-empty title string\", \"INVALID_ARGUMENT\");\n this.currentPhase = title;\n this.observer.phase(title);\n }\n /** The `log(message)` hook: narration to observers. */\n log(message) {\n if (typeof message !== \"string\") throw new WorkflowError(\"log() requires a message string\", \"INVALID_ARGUMENT\");\n this.observer.log(message);\n }\n};\n//#endregion\n//#region packages/workflow/workflow-ptc/src/guest.ts\n/**\n* Run a workflow with one progress batch in flight. Drain progress before child\n* disposal and the terminal result; PTC and the host own cancellation and cleanup.\n* @param host - JSON callbacks owned by this workflow run.\n* @returns The script result after progress delivery; initialization failures reject.\n*/\nasync function runWorkflowGuest(host) {\n const init = await host.begin({});\n let queued = [];\n let inFlight;\n let progressError;\n const flush = () => {\n if (inFlight !== void 0 || queued.length === 0) return;\n const batch = queued;\n queued = [];\n inFlight = host.progress(batch).then(() => {\n inFlight = void 0;\n flush();\n }, (error) => {\n progressError = renderThrown(error);\n queued = [];\n inFlight = void 0;\n });\n };\n const send = (event) => {\n if (progressError !== void 0) return;\n queued.push(event);\n flush();\n };\n const drain = async () => {\n while (inFlight !== void 0) await inFlight;\n };\n const result = await new WorkflowExecution(init.meta, init.body, init.args, init.limits, {\n phase: (title) => {\n send({\n type: \"phase\",\n title\n });\n },\n log: (message) => {\n send({\n type: \"log\",\n message\n });\n },\n agentStart: (info) => {\n send({\n type: \"agent-start\",\n info\n });\n },\n agentEnd: (info) => {\n send({\n type: \"agent-end\",\n info\n });\n }\n }, { async startAgent(request) {\n const { callId, childId } = await host.startChild(request);\n const result = host.childResult({ callId });\n result.catch(() => {});\n return {\n id: childId,\n result,\n async dispose() {\n await drain();\n await host.disposeChild({ callId });\n }\n };\n } }).drive();\n await drain();\n return progressError === void 0 ? result : {\n value: null,\n stopReason: \"error\",\n error: progressError,\n agentsStarted: result.agentsStarted\n };\n}\n//#endregion\nexport { runWorkflowGuest };\n//# sourceURL=dsh-workflow-guest.js\n";
|
|
12
|
+
const WORKFLOW_GUEST_SOURCE = "import * as vm from \"node:vm\";\n//#region packages/workflow/workflow-ptc/src/realm.ts\n/**\n* Materializes script VM values as plain JSON and renders thrown values.\n* Getters and proxy traps may execute inside the confined Node process;\n* process isolation and cancellation belong to PTC, not the VM.\n* @module @deepseek-ai/dsh-workflow-ptc/realm\n*/\n/** Thrown by {@link materializeFromRealm}; the caller wraps it into the right `WorkflowError` code. */\nvar MaterializeError = class extends Error {\n path;\n reason;\n constructor(path, reason) {\n super(`${path}: ${reason}`);\n this.path = path;\n this.reason = reason;\n this.name = \"MaterializeError\";\n }\n};\n/**\n* Render a thrown value to failure text without ever throwing: prefer the\n* `stack` (host or realm — a realm error's `stack` is a plain string read),\n* fall back to `message`, then `String()`. Reading those properties MAY run\n* script code; if that code itself throws, a fixed label is returned instead.\n* @param error - any value thrown in the host or guest realm.\n* @returns human-readable text for the failure report; prefers the stack.\n*/\nfunction renderThrown(error) {\n try {\n const stack = error?.stack;\n if (typeof stack === \"string\" && stack.length > 0) return stack;\n const message = error?.message;\n if (typeof message === \"string\" && message.length > 0) return message;\n return String(error);\n } catch {\n return \"[unrenderable thrown value]\";\n }\n}\n/**\n* Whether an object's prototype chain represents a plain data object: `null`, or a prototype\n* whose own prototype is `null` (the realm's `Object.prototype` — which we\n* cannot compare by identity across realms). A `Date`/`Map`/class instance\n* has a longer chain and is rejected.\n*/\nfunction hasPlainPrototype(value) {\n const proto = Object.getPrototypeOf(value);\n if (proto === null) return true;\n return Object.getPrototypeOf(proto) === null;\n}\n/**\n* Copy `value` (typically from the vm realm) into plain host JSON data. Root `undefined` is\n* returned unchanged; nested `undefined` and values JSON cannot represent losslessly fail\n* with the offending path. Property accessors run normally, and a throwing read is wrapped\n* with its rendered failure.\n*\n* @param value - the realm value to materialize.\n* @param root - the path label for the root value (error messages).\n* @returns the host-realm copy (plain objects/arrays/scalars only).\n* @throws {@link MaterializeError} for unsupported values, cycles, sparse arrays, exotic\n* prototypes, or property reads that throw.\n*/\nfunction materializeFromRealm(value, root = \"value\") {\n if (value === void 0) return void 0;\n try {\n return materialize(value, root, /* @__PURE__ */ new Set());\n } catch (error) {\n if (error instanceof MaterializeError) throw error;\n throw new MaterializeError(root, `reading the value threw: ${renderThrown(error)}`);\n }\n}\nfunction materialize(value, path, seen) {\n switch (typeof value) {\n case \"boolean\":\n case \"string\": return value;\n case \"number\":\n if (!Number.isFinite(value)) throw new MaterializeError(path, \"non-finite numbers are not JSON data\");\n return value;\n case \"bigint\": throw new MaterializeError(path, \"bigints are not JSON data\");\n case \"function\": throw new MaterializeError(path, \"functions are not plain JSON data\");\n case \"symbol\": throw new MaterializeError(path, \"symbols are not plain JSON data\");\n case \"undefined\": throw new MaterializeError(path, \"undefined is not JSON data\");\n case \"object\": break;\n }\n if (value === null) return null;\n const objectValue = value;\n if (seen.has(objectValue)) throw new MaterializeError(path, \"circular references are not JSON data\");\n seen.add(objectValue);\n try {\n if (Array.isArray(objectValue)) return materializeArray(objectValue, path, seen);\n return materializeObject(objectValue, path, seen);\n } finally {\n seen.delete(objectValue);\n }\n}\nfunction materializeArray(value, path, seen) {\n const out = [];\n for (let index = 0; index < value.length; index++) {\n if (!(index in value)) throw new MaterializeError(`${path}[${index}]`, \"sparse arrays are not JSON data\");\n out.push(materialize(value[index], `${path}[${index}]`, seen));\n }\n for (const key of Object.keys(value)) {\n const index = Number(key);\n if (!Number.isInteger(index) || index < 0 || index >= value.length) throw new MaterializeError(`${path}.${key}`, \"arrays with non-index properties are not JSON data\");\n }\n if (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n return out;\n}\nfunction materializeObject(value, path, seen) {\n if (!hasPlainPrototype(value)) throw new MaterializeError(path, \"only plain objects and arrays are JSON data (exotic prototype)\");\n if (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n const out = {};\n for (const key of Object.keys(value)) Object.defineProperty(out, key, {\n value: materialize(value[key], `${path}.${key}`, seen),\n enumerable: true,\n writable: true,\n configurable: true\n });\n return out;\n}\n//#endregion\n//#region packages/util/brand/src/index.ts\n/**\n* Apply a compile-time string brand without changing the value.\n* @param value - string admitted by the domain that owns the target brand.\n* @returns the same string with the requested compile-time brand.\n*/\nfunction brandString(value) {\n return value;\n}\n//#endregion\n//#region packages/llm/llm/src/error.ts\n/**\n* Harness error base with a stable machine-routable code and chained cause.\n* Package errors extend it so tool results and replay can retain failure class.\n* @module @deepseek-ai/dsh-llm/error\n*/\n/**\n* Base class for all harness errors. Carries a `code` (stable, programmatic —\n* e.g. `NO_ADAPTER`, `INVALID_ARGS`, `INVARIANT`) distinct from the\n* human-readable `message`, and supports `cause` chaining via the standard\n* `ErrorOptions`. `name` defaults to the subclass constructor name.\n*/\nvar HarnessError = class extends Error {\n /** Stable machine-routable failure class (e.g. `RATE_LIMIT`); route on this, never by parsing `message`. */\n code;\n constructor(message, code, options) {\n super(message, options);\n this.code = code;\n this.name = new.target.name;\n }\n};\nnew RegExp(String.raw`(?:^|[^a-z0-9])context[\\s_-](?:length|window)[\\s_-]` + String.raw`(?:exceed(?:ed|s)?|overflow(?:ed)?|limit[\\s_-]exceeded)(?:$|[^a-z0-9])`, \"i\");\nnew RegExp(String.raw`\\b(?:request|prompt|input|messages?)\\s+(?:is\\s+|are\\s+)?` + String.raw`too\\s+(?:large|long)\\s+for\\s+(?:(?:this|the)\\s+)?` + String.raw`(?:model(?:'s)?\\s+)?context(?:\\s+window)?\\b`, \"i\");\nnew RegExp(String.raw`\\b(?:input|prompt|request|messages?)\\b.{0,40}` + String.raw`\\b(?:exceed(?:s|ed)?|overflows?|is\\s+larger\\s+than)\\b.{0,40}` + String.raw`\\b(?:the\\s+)?(?:model(?:'s)?\\s+)?context(?:\\s+(?:length|window))?\\b`, \"i\");\n//#endregion\n//#region packages/util/values/src/index.ts\n/**\n* Mark an unreachable closed-union branch.\n* @param value - impossible value; an unhandled typed variant fails at the call site.\n* @param context - optional switch-site label included in the failure message.\n* @returns never; a runtime value that escaped its type always throws.\n*/\nfunction assertNever(value, context) {\n const rendered = JSON.stringify(value) ?? String(value);\n throw new Error(`unreachable variant${context ? ` in ${context}` : \"\"}: ${rendered}`);\n}\n/** Whether a realm-owned intrinsic prototype has a native constructor matching this engine's representation. */\nfunction hasIntrinsicConstructor$1(prototype, name) {\n const constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n if (typeof constructor !== \"function\") return false;\n try {\n return constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === Function.prototype.toString.call(name === \"Array\" ? Array : Object);\n } catch {\n return false;\n }\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype$1(value) {\n return Object.getPrototypeOf(value) === null && hasIntrinsicConstructor$1(value, \"Object\");\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */\nfunction hasPlainArrayPrototype$1(value) {\n const prototype = Object.getPrototypeOf(value);\n if (!Array.isArray(prototype) || !hasIntrinsicConstructor$1(prototype, \"Array\")) return false;\n const objectPrototype = Object.getPrototypeOf(prototype);\n return typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype$1(objectPrototype);\n}\n/** Whether an object is a plain or null-prototype record from any JavaScript realm. */\nfunction hasPlainObjectPrototype(value) {\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype$1(prototype);\n}\n/** Return every JSON-visible object key, or reject own data JSON would discard. */\nfunction enumerableStringKeys(value) {\n const keys = Reflect.ownKeys(value);\n if (keys.some((key) => typeof key !== \"string\" || !Object.prototype.propertyIsEnumerable.call(value, key))) return void 0;\n return keys;\n}\n/** Validate lossless JSON iteratively, optionally materializing a detached snapshot. */\nfunction walkJsonValue(value, detach) {\n const ancestors = /* @__PURE__ */ new Set();\n let root;\n const assign = (destination, item) => {\n if (destination === void 0) return;\n if (destination.kind === \"root\") root = item;\n else if (destination.kind === \"array\") destination.target[destination.index] = item;\n else Object.defineProperty(destination.target, destination.key, {\n value: item,\n enumerable: true,\n configurable: true,\n writable: true\n });\n };\n const tasks = [{\n kind: \"visit\",\n value,\n ...detach ? { destination: { kind: \"root\" } } : {}\n }];\n for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n if (task.kind === \"leave\") {\n ancestors.delete(task.source);\n continue;\n }\n if (task.kind === \"array-item\") {\n if (!Object.prototype.hasOwnProperty.call(task.source, task.index)) return void 0;\n tasks.push({\n kind: \"visit\",\n value: task.source[task.index],\n ...task.target === void 0 ? {} : { destination: {\n kind: \"array\",\n target: task.target,\n index: task.index\n } }\n });\n continue;\n }\n if (task.kind === \"object-property\") {\n tasks.push({\n kind: \"visit\",\n value: task.source[task.key],\n ...task.target === void 0 ? {} : { destination: {\n kind: \"object\",\n target: task.target,\n key: task.key\n } }\n });\n continue;\n }\n const current = task.value;\n if (current === null) {\n assign(task.destination, null);\n continue;\n }\n if (typeof current === \"boolean\" || typeof current === \"string\") {\n assign(task.destination, current);\n continue;\n }\n if (typeof current === \"number\") {\n if (!Number.isFinite(current) || Object.is(current, -0)) return void 0;\n assign(task.destination, current);\n continue;\n }\n if (typeof current !== \"object\") return void 0;\n if (ancestors.has(current)) return void 0;\n if (Array.isArray(current)) {\n if (!hasPlainArrayPrototype$1(current)) return void 0;\n const length = current.length;\n if (Reflect.ownKeys(current).length !== length + 1) return void 0;\n const target = detach ? [] : void 0;\n if (target !== void 0) assign(task.destination, target);\n ancestors.add(current);\n tasks.push({\n kind: \"leave\",\n source: current\n });\n for (let index = length - 1; index >= 0; index--) tasks.push({\n kind: \"array-item\",\n source: current,\n index,\n ...target === void 0 ? {} : { target }\n });\n continue;\n }\n if (!hasPlainObjectPrototype(current)) return void 0;\n const keys = enumerableStringKeys(current);\n if (keys === void 0) return void 0;\n const target = detach ? {} : void 0;\n if (target !== void 0) assign(task.destination, target);\n ancestors.add(current);\n tasks.push({\n kind: \"leave\",\n source: current\n });\n for (let index = keys.length - 1; index >= 0; index--) {\n const key = keys[index];\n /* v8 ignore next -- the loop is bounded by the captured key count. */\n if (key === void 0) return void 0;\n tasks.push({\n kind: \"object-property\",\n source: current,\n key,\n ...target === void 0 ? {} : { target }\n });\n }\n }\n return detach ? root : true;\n}\n/**\n* Test the same lossless JSON rules as {@link snapshotJsonValue} without detaching the value.\n* @param value - candidate value to test.\n* @returns whether the value survives a JSON round trip without loss.\n*/\nfunction isJsonValue(value) {\n return walkJsonValue(value, false) === true;\n}\n//#endregion\n//#region packages/core/tools/src/json-schema.ts\n/**\n* Enforced JSON Schema subset shared by tool outputs, generated PTC mode\n* types, subagents, and workflows. The subset accepts any JSON root, an\n* annotation-only schema for unconstrained JSON, one scalar `type`, object\n* `properties`/`required`/boolean `additionalProperties`, array `items`,\n* type-correct scalar `enum`/`const`, and exact-one `oneOf`.\n*\n* Unsupported or misplaced keywords reject rather than being accepted without\n* enforcement. Consumers that require an object root apply\n* {@link assertObjectJsonSchema} before accepting input.\n* @module dsh-tools/json-schema\n*/\n/**\n* Thrown when a raw schema falls outside the enforced subset. `violations`\n* lists every offending path instead of stopping at the first author error.\n*/\nvar JsonSchemaError = class extends HarnessError {\n /** Individual schema violations in walk order. */\n violations;\n constructor(violations) {\n super(`unsupported JSON schema: ${violations.join(\"; \")}`, \"UNSUPPORTED_SCHEMA\");\n this.name = \"JsonSchemaError\";\n this.violations = violations;\n }\n};\nconst CONSTRAINT_KEYWORDS = new Set([\n \"type\",\n \"oneOf\",\n \"properties\",\n \"required\",\n \"additionalProperties\",\n \"items\",\n \"enum\",\n \"const\"\n]);\nconst ANNOTATION_KEYWORDS = new Set([\n \"description\",\n \"title\",\n \"default\",\n \"examples\"\n]);\nconst SCHEMA_TYPES = [\n \"object\",\n \"array\",\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"null\"\n];\n/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */\nfunction hasIntrinsicConstructor(prototype, name) {\n const constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n if (typeof constructor !== \"function\") return false;\n try {\n return constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === `function ${name}() { [native code] }`;\n } catch {\n return false;\n }\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype(value) {\n return Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, \"Object\");\n}\n/**\n* Test for a realm-agnostic plain JSON record without accepting arrays or\n* exotic objects.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the value has a plain-object prototype chain.\n*/\nfunction isPlainJsonRecord(value) {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n try {\n const prototype = Object.getPrototypeOf(value);\n return prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype(prototype);\n } catch {\n return false;\n }\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`. */\nfunction hasPlainArrayPrototype(value) {\n const prototype = Object.getPrototypeOf(value);\n if (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, \"Array\")) return false;\n const objectPrototype = Object.getPrototypeOf(prototype);\n return typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype(objectPrototype);\n}\n/** Return whether a record contains only own enumerable string keys. */\nfunction hasOnlyEnumerableStringKeys(value) {\n try {\n return Reflect.ownKeys(value).every((key) => typeof key === \"string\" && Object.prototype.propertyIsEnumerable.call(value, key));\n } catch {\n return false;\n }\n}\n/**\n* Test for an ordinary schema record whose keys survive JSON projection.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the record has an intrinsic prototype and only own enumerable string keys.\n*/\nfunction isJsonSchemaRecord(value) {\n return isPlainJsonRecord(value) && hasOnlyEnumerableStringKeys(value);\n}\n/**\n* Test for a dense ordinary array with no JSON-invisible decorations.\n* @param value - candidate array from any JavaScript realm.\n* @returns Whether the array is intrinsic, dense, and undecorated.\n*/\nfunction isPlainJsonArray(value) {\n if (!Array.isArray(value)) return false;\n try {\n if (!hasPlainArrayPrototype(value) || Reflect.ownKeys(value).length !== value.length + 1) return false;\n for (let index = 0; index < value.length; index++) if (!Object.hasOwn(value, index)) return false;\n return true;\n } catch {\n return false;\n }\n}\n/** Lossless finite JSON number, excluding negative zero. */\nfunction isJsonNumber(value) {\n return typeof value === \"number\" && Number.isFinite(value) && !Object.is(value, -0);\n}\n/** Whether a scalar is valid for one declared schema type. */\nfunction scalarMatches(type, value) {\n switch (type) {\n case \"string\": return typeof value === \"string\";\n case \"number\": return isJsonNumber(value);\n case \"integer\": return isJsonNumber(value) && Number.isInteger(value);\n case \"boolean\": return typeof value === \"boolean\";\n case \"null\": return value === null;\n /* v8 ignore next -- JsonSchemaScalarType is closed; this retains compile-time exhaustiveness. */\n default: return assertNever(type, \"JsonSchemaType\");\n }\n}\n/** Keywords that are invalid beside `oneOf`. */\nconst ONE_OF_SIBLING_KEYWORDS = [\n \"properties\",\n \"required\",\n \"additionalProperties\",\n \"items\",\n \"enum\",\n \"const\"\n];\n/** Validate object-only fields after its property schemas have been visited. */\nfunction checkObjectSchemaTail(node, path, properties, violations) {\n const hasRequired = Object.hasOwn(node, \"required\");\n const required = hasRequired ? node.required : void 0;\n if (hasRequired) if (!isPlainJsonArray(required) || required.some((entry) => typeof entry !== \"string\")) violations.push(`${path}.required must be an array of strings`);\n else {\n const declared = isJsonSchemaRecord(properties) ? properties : {};\n for (const key of required) if (!Object.hasOwn(declared, key)) violations.push(`${path}.required names \"${key}\" which is not in properties`);\n }\n if (Object.hasOwn(node, \"additionalProperties\") && typeof node.additionalProperties !== \"boolean\") violations.push(`${path}.additionalProperties must be a boolean`);\n}\n/** Collect every violation for one raw schema tree without using the JavaScript call stack. */\nfunction checkSchemaNode(root, rootPath, violations, seen) {\n const tasks = [{\n kind: \"enter\",\n node: root,\n path: rootPath\n }];\n for (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n if (task.kind === \"leave\") {\n seen.delete(task.node);\n continue;\n }\n if (task.kind === \"one-of-tail\") {\n for (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(task.node, key)) violations.push(`${task.path}.${key} is not supported beside oneOf`);\n continue;\n }\n if (task.kind === \"object-tail\") {\n checkObjectSchemaTail(task.node, task.path, task.properties, violations);\n continue;\n }\n const { node, path } = task;\n if (!isJsonSchemaRecord(node)) {\n violations.push(`${path} must be a schema object`);\n continue;\n }\n if (seen.has(node)) {\n violations.push(`${path} is circular`);\n continue;\n }\n seen.add(node);\n tasks.push({\n kind: \"leave\",\n node\n });\n for (const key of Object.keys(node)) {\n if (CONSTRAINT_KEYWORDS.has(key)) continue;\n if (ANNOTATION_KEYWORDS.has(key)) {\n try {\n if (!isJsonValue(node[key])) violations.push(`${path}.${key} annotation must be lossless JSON data`);\n } catch {\n violations.push(`${path}.${key} annotation must be lossless JSON data`);\n }\n continue;\n }\n violations.push(`${path}.${key} is not a supported keyword (subset: type/oneOf/properties/required/additionalProperties/items/enum/const + annotations)`);\n }\n if (Object.hasOwn(node, \"description\") && typeof node.description !== \"string\") violations.push(`${path}.description must be a string`);\n if (Object.hasOwn(node, \"title\") && typeof node.title !== \"string\") violations.push(`${path}.title must be a string`);\n const hasType = Object.hasOwn(node, \"type\");\n const hasOneOf = Object.hasOwn(node, \"oneOf\");\n if (hasType && hasOneOf) {\n violations.push(`${path} cannot declare both type and oneOf`);\n continue;\n }\n if (!hasType && !hasOneOf) {\n for (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(node, key)) violations.push(`${path}.${key} requires type or oneOf`);\n continue;\n }\n if (hasOneOf) {\n const oneOf = node.oneOf;\n tasks.push({\n kind: \"one-of-tail\",\n node,\n path\n });\n if (!isPlainJsonArray(oneOf) || oneOf.length < 2) violations.push(`${path}.oneOf must be an array of at least two schemas`);\n else for (let index = oneOf.length - 1; index >= 0; index--) tasks.push({\n kind: \"enter\",\n node: oneOf[index],\n path: `${path}.oneOf[${index}]`\n });\n continue;\n }\n const type = node.type;\n if (typeof type !== \"string\" || !SCHEMA_TYPES.includes(type)) {\n violations.push(Array.isArray(type) ? `${path}.type must be a single type string (type arrays are not supported)` : `${path}.type must be one of ${SCHEMA_TYPES.join(\"/\")}`);\n continue;\n }\n const schemaType = type;\n for (const [key, types] of Object.entries({\n properties: [\"object\"],\n required: [\"object\"],\n additionalProperties: [\"object\"],\n items: [\"array\"],\n enum: [\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"null\"\n ],\n const: [\n \"string\",\n \"number\",\n \"integer\",\n \"boolean\",\n \"null\"\n ]\n })) if (Object.hasOwn(node, key) && !types.includes(schemaType)) violations.push(`${path}.${key} is not supported on type \"${schemaType}\"`);\n switch (schemaType) {\n case \"object\": {\n const properties = Object.hasOwn(node, \"properties\") ? node.properties : void 0;\n tasks.push({\n kind: \"object-tail\",\n node,\n path,\n properties\n });\n if (Object.hasOwn(node, \"properties\")) if (!isJsonSchemaRecord(properties)) violations.push(`${path}.properties must be an object of schemas`);\n else {\n const entries = Object.entries(properties);\n for (let index = entries.length - 1; index >= 0; index--) {\n const entry = entries[index];\n /* v8 ignore next -- the loop is bounded by the captured entry count. */\n if (entry === void 0) continue;\n tasks.push({\n kind: \"enter\",\n node: entry[1],\n path: `${path}.properties.${entry[0]}`\n });\n }\n }\n break;\n }\n case \"array\":\n if (Object.hasOwn(node, \"items\")) tasks.push({\n kind: \"enter\",\n node: node.items,\n path: `${path}.items`\n });\n break;\n case \"string\":\n case \"number\":\n case \"integer\":\n case \"boolean\":\n case \"null\": {\n const hasEnum = Object.hasOwn(node, \"enum\");\n const allowed = hasEnum ? node.enum : void 0;\n const enumValid = isPlainJsonArray(allowed) && allowed.length > 0 && allowed.every((entry) => scalarMatches(schemaType, entry));\n if (hasEnum && !enumValid) violations.push(`${path}.enum must be a non-empty array of ${schemaType} values`);\n const hasConst = Object.hasOwn(node, \"const\");\n const declaredConst = hasConst ? node.const : void 0;\n const constValid = scalarMatches(schemaType, declaredConst);\n if (hasConst) {\n if (!constValid) violations.push(`${path}.const must be a ${schemaType} value`);\n else if (enumValid && !allowed.includes(declaredConst)) violations.push(`${path}.const must be one of ${path}.enum when both are declared`);\n }\n break;\n }\n /* v8 ignore next -- schemaType was narrowed from the closed SCHEMA_TYPES table above. */\n default: assertNever(schemaType, \"JsonSchemaType\");\n }\n }\n}\n/**\n* Assert the enforced subset plus the object-root constraint retained by\n* subagent and workflow structured outputs.\n* @param schema - untrusted caller-supplied schema.\n* @returns Assertion that the schema belongs to the supported subset and has an object root.\n*/\nfunction assertObjectJsonSchema(schema) {\n const violations = [];\n checkSchemaNode(schema, \"schema\", violations, /* @__PURE__ */ new Set());\n if (violations.length === 0 && (!isJsonSchemaRecord(schema) || !Object.hasOwn(schema, \"type\") || schema.type !== \"object\")) violations.push(\"schema.type must be \\\"object\\\" (structured output is object-rooted)\");\n if (violations.length > 0) throw new JsonSchemaError(violations);\n}\n//#endregion\n//#region packages/workflow/workflow/src/index.ts\n/**\n* Typed error for workflow-seam failures. Extends {@link HarnessError}, so the\n* `code` is machine-routable taxonomy. `fatal` drives the combinator\n* discipline: `parallel()`/`pipeline()` re-throw a fatal error (a typo'd\n* option or a tripped cap must kill the script loudly), and reserve the\n* per-item `null` for child-run failures and ordinary in-stage script errors.\n* Every {@link WorkflowErrorCode} is fatal; the flag exists so the\n* distinction is explicit at every catch site rather than implied.\n*/\nvar WorkflowError = class extends HarnessError {\n /** Whether combinators must propagate this error instead of nulling the item. */\n fatal;\n constructor(message, code, options) {\n super(message, code, options);\n this.name = \"WorkflowError\";\n this.fatal = options?.fatal ?? true;\n }\n};\n/**\n* Whether combinators must re-throw `error` instead of mapping the item to `null`.\n* @param error - any thrown value; fatality is host `instanceof` (unforgeable from a script realm).\n* @returns true iff `error` is a {@link WorkflowError} whose `fatal` flag is set.\n*/\nfunction isFatalWorkflowError(error) {\n return error instanceof WorkflowError && error.fatal;\n}\n//#endregion\n//#region packages/workflow/workflow-ptc/src/runtime.ts\n/**\n* Workflow VM hooks, child callbacks, ordinary concurrency limits and result serialization.\n* PTC owns process confinement and cancellation. Fatal hook and provider failures propagate\n* through combinators; ordinary child failures and stage errors become per-item nulls.\n* @module @deepseek-ai/dsh-workflow-ptc/runtime\n*/\n/** The `agent()` options the script may pass; everything else rejects loud. */\nconst SUPPORTED_AGENT_OPTIONS = new Set([\n \"label\",\n \"phase\",\n \"schema\",\n \"provider\",\n \"model\"\n]);\n/** Deferred Claude Code options we name explicitly in the rejection message. */\nconst DEFERRED_AGENT_OPTIONS = new Set([\n \"effort\",\n \"isolation\",\n \"agentType\"\n]);\n/** Flatten a child's final output blocks to text (the non-schema `agent()` result). */\nfunction outputText(blocks) {\n return blocks.filter((block) => block.type === \"text\").map((block) => block.text).join(\"\");\n}\n/** A short display label derived from the prompt when the script passes none. */\nfunction defaultLabel(prompt) {\n const newline = prompt.indexOf(\"\\n\");\n const line = newline === -1 ? prompt : prompt.slice(0, newline);\n return line.length <= 48 ? line : `${line.slice(0, 47)}…`;\n}\n/**\n* One script execution inside the confined Node process. The host owns\n* cancellation and cleanup of any dropped child work.\n*/\nvar WorkflowExecution = class {\n limits;\n observer;\n children;\n /** 1-based count of `agent()` calls started (the `agentsStarted` result field). */\n started = 0;\n activeSlots = 0;\n slotWaiters = [];\n currentPhase;\n context;\n compiled;\n constructor(meta, body, args, limits, observer, children) {\n this.limits = limits;\n this.observer = observer;\n this.children = children;\n try {\n this.compiled = new vm.Script(`(async () => {\\n${body}\\n})()`, {\n filename: `workflow:${meta.name}`,\n lineOffset: -1\n });\n } catch (error) {\n throw new WorkflowError(`workflow script does not parse: ${String(error)}`, \"SCRIPT_PARSE\", { cause: error });\n }\n this.context = vm.createContext({}, { name: `workflow:${meta.name}` });\n const globals = {\n agent: (prompt, opts) => this.contain(this.agent(prompt, opts)),\n parallel: (thunks) => this.contain(this.parallel(thunks)),\n pipeline: (items, ...stages) => this.contain(this.pipeline(items, stages)),\n phase: (title) => {\n this.phase(title);\n },\n log: (message) => {\n this.log(message);\n },\n args\n };\n for (const [key, value] of Object.entries(globals)) this.context[key] = typeof value === \"function\" ? Object.freeze(value) : value;\n }\n /**\n * Run the script and materialize its JSON return value.\n * @returns A completed or error result; script failures never reject.\n */\n async drive() {\n try {\n const scriptPromise = this.compiled.runInContext(this.context, { timeout: this.limits.syncTimeoutMs });\n const raw = await this.contain(Promise.resolve(scriptPromise));\n return {\n value: raw === void 0 ? null : this.materializeResult(raw),\n stopReason: \"completed\",\n agentsStarted: this.started\n };\n } catch (error) {\n return {\n value: null,\n stopReason: \"error\",\n error: renderThrown(error),\n agentsStarted: this.started\n };\n }\n }\n /**\n * Attach a no-op rejection consumer WITHOUT changing what the caller\n * receives: if the script drops the promise, a host rejection cannot become\n * an unhandled rejection that kills the process; if\n * the script does await it, it still observes the rejection.\n */\n contain(promise) {\n promise.catch(() => {});\n return promise;\n }\n /** Materialize the script's return value; violations become RESULT_UNSERIALIZABLE. */\n materializeResult(raw) {\n try {\n return materializeFromRealm(raw, \"workflow result\");\n } catch (error) {\n /* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n if (!(error instanceof MaterializeError)) throw error;\n throw new WorkflowError(`the workflow's return value is not plain JSON data — ${error.message}. Return only JSON-serializable objects/arrays/scalars.`, \"RESULT_UNSERIALIZABLE\", { cause: error });\n }\n }\n /** Acquire one concurrency slot in FIFO order. */\n acquireSlot() {\n if (this.activeSlots < this.limits.maxConcurrentAgents) {\n this.activeSlots += 1;\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n this.slotWaiters.push(() => {\n this.activeSlots += 1;\n resolve();\n });\n });\n }\n releaseSlot() {\n this.activeSlots -= 1;\n const next = this.slotWaiters.shift();\n if (next) next();\n }\n /** The `agent(prompt, opts)` hook. */\n async agent(rawPrompt, rawOpts) {\n if (typeof rawPrompt !== \"string\" || rawPrompt.length === 0) throw new WorkflowError(\"agent() requires a non-empty prompt string\", \"INVALID_ARGUMENT\");\n const opts = this.readAgentOptions(rawOpts);\n if (this.started >= this.limits.maxTotalAgents) throw new WorkflowError(`this run reached its total agent cap (${this.limits.maxTotalAgents}) — a runaway-loop backstop; raise the applicable maxTotalAgents limit if the scale is intentional`, \"AGENT_CAP\");\n this.started += 1;\n const seq = this.started;\n const label = opts.label ?? defaultLabel(rawPrompt);\n const phase = opts.phase ?? this.currentPhase;\n await this.acquireSlot();\n try {\n let run;\n try {\n run = await this.children.startAgent({\n prompt: rawPrompt,\n ...opts.schema !== void 0 ? { schema: opts.schema } : {},\n ...opts.provider !== void 0 ? { provider: opts.provider } : {},\n ...opts.model !== void 0 ? { model: opts.model } : {}\n });\n } catch (error) {\n throw new WorkflowError(`agent() could not start a child: ${renderThrown(error)}`, \"AGENT_START\", { cause: error });\n }\n const info = {\n seq,\n label,\n ...phase !== void 0 ? { phase } : {},\n childId: brandString(run.id)\n };\n this.observer.agentStart(info);\n try {\n let result;\n try {\n result = await run.result;\n } catch (error) {\n this.observer.agentEnd({\n ...info,\n outcome: \"failed\"\n });\n throw new WorkflowError(`child agent run failed: ${renderThrown(error)}`, \"AGENT_RESULT\", { cause: error });\n }\n if (result.stopReason === \"completed\") {\n if (opts.schema !== void 0) {\n if (result.structured === void 0) {\n this.observer.agentEnd({\n ...info,\n outcome: \"failed\"\n });\n return null;\n }\n this.observer.agentEnd({\n ...info,\n outcome: \"completed\"\n });\n return result.structured;\n }\n this.observer.agentEnd({\n ...info,\n outcome: \"completed\"\n });\n return outputText(result.output);\n }\n this.observer.agentEnd({\n ...info,\n outcome: \"failed\"\n });\n return null;\n } finally {\n await run.dispose();\n }\n } finally {\n this.releaseSlot();\n }\n }\n /** Materialize + validate the `agent()` options bag from the realm. */\n readAgentOptions(rawOpts) {\n if (rawOpts === void 0) return {};\n let opts;\n try {\n opts = materializeFromRealm(rawOpts, \"agent() options\");\n } catch (error) {\n /* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n if (!(error instanceof MaterializeError)) throw error;\n throw new WorkflowError(`agent() options must be plain JSON data — ${error.message}`, \"INVALID_ARGUMENT\", { cause: error });\n }\n if (typeof opts !== \"object\" || opts === null || Array.isArray(opts)) throw new WorkflowError(\"agent() options must be an object\", \"INVALID_ARGUMENT\");\n const record = opts;\n for (const key of Object.keys(record)) {\n if (SUPPORTED_AGENT_OPTIONS.has(key)) continue;\n if (DEFERRED_AGENT_OPTIONS.has(key)) throw new WorkflowError(`agent() option \"${key}\" is deferred and not supported by this engine (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n throw new WorkflowError(`agent() option \"${key}\" is not recognized (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n }\n for (const key of [\n \"label\",\n \"phase\",\n \"provider\",\n \"model\"\n ]) if (record[key] !== void 0 && typeof record[key] !== \"string\") throw new WorkflowError(`agent() option \"${key}\" must be a string`, \"INVALID_ARGUMENT\");\n let schema;\n if (record.schema !== void 0) try {\n assertObjectJsonSchema(record.schema);\n schema = record.schema;\n } catch (error) {\n /* v8 ignore next -- defensive rethrow arm: assertObjectJsonSchema only throws JsonSchemaError */\n if (!(error instanceof JsonSchemaError)) throw error;\n throw new WorkflowError(`agent() schema is outside the supported subset — ${error.message}`, \"UNSUPPORTED_SCHEMA\", { cause: error });\n }\n return {\n ...record.label !== void 0 ? { label: record.label } : {},\n ...record.phase !== void 0 ? { phase: record.phase } : {},\n ...record.provider !== void 0 ? { provider: record.provider } : {},\n ...record.model !== void 0 ? { model: record.model } : {},\n ...schema !== void 0 ? { schema } : {}\n };\n }\n /** The `parallel(thunks)` hook: each thunk caught → `null`; fatal errors propagate. */\n async parallel(rawThunks) {\n if (!Array.isArray(rawThunks)) throw new WorkflowError(\"parallel() requires an array of zero-argument functions\", \"INVALID_ARGUMENT\");\n this.assertItemCap(rawThunks.length, \"parallel()\");\n const thunks = rawThunks.map((thunk, index) => {\n if (typeof thunk !== \"function\") throw new WorkflowError(`parallel() item ${index} is not a function`, \"INVALID_ARGUMENT\");\n return thunk;\n });\n return Promise.all(thunks.map(async (thunk) => {\n try {\n return await thunk();\n } catch (error) {\n if (isFatalWorkflowError(error)) throw error;\n return null;\n }\n }));\n }\n /** The `pipeline(items, ...stages)` hook: per-item stage chains, NO cross-stage barrier. */\n async pipeline(rawItems, rawStages) {\n if (!Array.isArray(rawItems)) throw new WorkflowError(\"pipeline() requires an items array\", \"INVALID_ARGUMENT\");\n this.assertItemCap(rawItems.length, \"pipeline()\");\n if (rawStages.length === 0) throw new WorkflowError(\"pipeline() requires at least one stage function\", \"INVALID_ARGUMENT\");\n const stages = rawStages.map((stage, index) => {\n if (typeof stage !== \"function\") throw new WorkflowError(`pipeline() stage ${index} is not a function`, \"INVALID_ARGUMENT\");\n return stage;\n });\n return Promise.all(rawItems.map(async (item, index) => {\n let value = item;\n try {\n for (const stage of stages) value = await stage(value, item, index);\n return value;\n } catch (error) {\n if (isFatalWorkflowError(error)) throw error;\n return null;\n }\n }));\n }\n assertItemCap(length, hook) {\n if (length > this.limits.maxItemsPerCall) throw new WorkflowError(`${hook} received ${length} items — over the per-call cap (${this.limits.maxItemsPerCall}); split the work or raise maxItemsPerCall in the engine config`, \"ITEM_CAP\");\n }\n /** The `phase(title)` hook: sets the current label for subsequent `agent()` calls and notifies observers. */\n phase(title) {\n if (typeof title !== \"string\" || title.length === 0) throw new WorkflowError(\"phase() requires a non-empty title string\", \"INVALID_ARGUMENT\");\n this.currentPhase = title;\n this.observer.phase(title);\n }\n /** The `log(message)` hook: narration to observers. */\n log(message) {\n if (typeof message !== \"string\") throw new WorkflowError(\"log() requires a message string\", \"INVALID_ARGUMENT\");\n this.observer.log(message);\n }\n};\n//#endregion\n//#region packages/workflow/workflow-ptc/src/guest.ts\n/**\n* Run a workflow with one progress batch in flight. Drain progress before child\n* disposal and the terminal result; PTC and the host own cancellation and cleanup.\n* @param host - JSON callbacks owned by this workflow run.\n* @returns The script result after progress delivery; initialization failures reject.\n*/\nasync function runWorkflowGuest(host) {\n const init = await host.begin({});\n let queued = [];\n let inFlight;\n let progressError;\n const flush = () => {\n if (inFlight !== void 0 || queued.length === 0) return;\n const batch = queued;\n queued = [];\n inFlight = host.progress(batch).then(() => {\n inFlight = void 0;\n flush();\n }, (error) => {\n progressError = renderThrown(error);\n queued = [];\n inFlight = void 0;\n });\n };\n const send = (event) => {\n if (progressError !== void 0) return;\n queued.push(event);\n flush();\n };\n const drain = async () => {\n while (inFlight !== void 0) await inFlight;\n };\n const result = await new WorkflowExecution(init.meta, init.body, init.args, init.limits, {\n phase: (title) => {\n send({\n type: \"phase\",\n title\n });\n },\n log: (message) => {\n send({\n type: \"log\",\n message\n });\n },\n agentStart: (info) => {\n send({\n type: \"agent-start\",\n info\n });\n },\n agentEnd: (info) => {\n send({\n type: \"agent-end\",\n info\n });\n }\n }, { async startAgent(request) {\n const { callId, childId } = await host.startChild(request);\n const result = host.childResult({ callId });\n result.catch(() => {});\n return {\n id: childId,\n result,\n async dispose() {\n await drain();\n await host.disposeChild({ callId });\n }\n };\n } }).drive();\n await drain();\n return progressError === void 0 ? result : {\n value: null,\n stopReason: \"error\",\n error: progressError,\n agentsStarted: result.agentsStarted\n };\n}\n//#endregion\nexport { runWorkflowGuest };\n//# sourceURL=dsh-workflow-guest.js\n";
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region lib/types/realm.js
|
|
15
15
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Generated by scripts/gen-workflow-guest.ts. Do not edit directly. */
|
|
2
2
|
/** Self-contained ESM guest transported into the mounted PTC runtime. */
|
|
3
|
-
export declare const WORKFLOW_GUEST_SOURCE = "import * as vm from \"node:vm\";\n//#region packages/workflow/workflow-ptc/src/realm.ts\n/**\n* Materializes script VM values as plain JSON and renders thrown values.\n* Getters and proxy traps may execute inside the confined Node process;\n* process isolation and cancellation belong to PTC, not the VM.\n* @module @deepseek-ai/dsh-workflow-ptc/realm\n*/\n/** Thrown by {@link materializeFromRealm}; the caller wraps it into the right `WorkflowError` code. */\nvar MaterializeError = class extends Error {\n\tpath;\n\treason;\n\tconstructor(path, reason) {\n\t\tsuper(`${path}: ${reason}`);\n\t\tthis.path = path;\n\t\tthis.reason = reason;\n\t\tthis.name = \"MaterializeError\";\n\t}\n};\n/**\n* Render a thrown value to failure text without ever throwing: prefer the\n* `stack` (host or realm \u2014 a realm error's `stack` is a plain string read),\n* fall back to `message`, then `String()`. Reading those properties MAY run\n* script code; if that code itself throws, a fixed label is returned instead.\n* @param error - any value thrown in the host or guest realm.\n* @returns human-readable text for the failure report; prefers the stack.\n*/\nfunction renderThrown(error) {\n\ttry {\n\t\tconst stack = error?.stack;\n\t\tif (typeof stack === \"string\" && stack.length > 0) return stack;\n\t\tconst message = error?.message;\n\t\tif (typeof message === \"string\" && message.length > 0) return message;\n\t\treturn String(error);\n\t} catch {\n\t\treturn \"[unrenderable thrown value]\";\n\t}\n}\n/**\n* Whether an object's prototype chain represents a plain data object: `null`, or a prototype\n* whose own prototype is `null` (the realm's `Object.prototype` \u2014 which we\n* cannot compare by identity across realms). A `Date`/`Map`/class instance\n* has a longer chain and is rejected.\n*/\nfunction hasPlainPrototype(value) {\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto === null) return true;\n\treturn Object.getPrototypeOf(proto) === null;\n}\n/**\n* Copy `value` (typically from the vm realm) into plain host JSON data. Root `undefined` is\n* returned unchanged; nested `undefined` and values JSON cannot represent losslessly fail\n* with the offending path. Property accessors run normally, and a throwing read is wrapped\n* with its rendered failure.\n*\n* @param value - the realm value to materialize.\n* @param root - the path label for the root value (error messages).\n* @returns the host-realm copy (plain objects/arrays/scalars only).\n* @throws {@link MaterializeError} for unsupported values, cycles, sparse arrays, exotic\n* prototypes, or property reads that throw.\n*/\nfunction materializeFromRealm(value, root = \"value\") {\n\tif (value === void 0) return void 0;\n\ttry {\n\t\treturn materialize(value, root, /* @__PURE__ */ new Set());\n\t} catch (error) {\n\t\tif (error instanceof MaterializeError) throw error;\n\t\tthrow new MaterializeError(root, `reading the value threw: ${renderThrown(error)}`);\n\t}\n}\nfunction materialize(value, path, seen) {\n\tswitch (typeof value) {\n\t\tcase \"boolean\":\n\t\tcase \"string\": return value;\n\t\tcase \"number\":\n\t\t\tif (!Number.isFinite(value)) throw new MaterializeError(path, \"non-finite numbers are not JSON data\");\n\t\t\treturn value;\n\t\tcase \"bigint\": throw new MaterializeError(path, \"bigints are not JSON data\");\n\t\tcase \"function\": throw new MaterializeError(path, \"functions are not plain JSON data\");\n\t\tcase \"symbol\": throw new MaterializeError(path, \"symbols are not plain JSON data\");\n\t\tcase \"undefined\": throw new MaterializeError(path, \"undefined is not JSON data\");\n\t\tcase \"object\": break;\n\t}\n\tif (value === null) return null;\n\tconst objectValue = value;\n\tif (seen.has(objectValue)) throw new MaterializeError(path, \"circular references are not JSON data\");\n\tseen.add(objectValue);\n\ttry {\n\t\tif (Array.isArray(objectValue)) return materializeArray(objectValue, path, seen);\n\t\treturn materializeObject(objectValue, path, seen);\n\t} finally {\n\t\tseen.delete(objectValue);\n\t}\n}\nfunction materializeArray(value, path, seen) {\n\tconst out = [];\n\tfor (let index = 0; index < value.length; index++) {\n\t\tif (!(index in value)) throw new MaterializeError(`${path}[${index}]`, \"sparse arrays are not JSON data\");\n\t\tout.push(materialize(value[index], `${path}[${index}]`, seen));\n\t}\n\tfor (const key of Object.keys(value)) {\n\t\tconst index = Number(key);\n\t\tif (!Number.isInteger(index) || index < 0 || index >= value.length) throw new MaterializeError(`${path}.${key}`, \"arrays with non-index properties are not JSON data\");\n\t}\n\tif (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n\treturn out;\n}\nfunction materializeObject(value, path, seen) {\n\tif (!hasPlainPrototype(value)) throw new MaterializeError(path, \"only plain objects and arrays are JSON data (exotic prototype)\");\n\tif (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n\tconst out = {};\n\tfor (const key of Object.keys(value)) Object.defineProperty(out, key, {\n\t\tvalue: materialize(value[key], `${path}.${key}`, seen),\n\t\tenumerable: true,\n\t\twritable: true,\n\t\tconfigurable: true\n\t});\n\treturn out;\n}\n//#endregion\n//#region packages/util/brand/src/index.ts\n/**\n* Apply a compile-time string brand without changing the value.\n* @param value - string admitted by the domain that owns the target brand.\n* @returns the same string with the requested compile-time brand.\n*/\nfunction brandString(value) {\n\treturn value;\n}\n//#endregion\n//#region packages/llm/llm/src/error.ts\n/**\n* Harness error base with a stable machine-routable code and chained cause.\n* Package errors extend it so tool results and replay can retain failure class.\n* @module @deepseek-ai/dsh-llm/error\n*/\n/**\n* Base class for all harness errors. Carries a `code` (stable, programmatic \u2014\n* e.g. `NO_ADAPTER`, `INVALID_ARGS`, `INVARIANT`) distinct from the\n* human-readable `message`, and supports `cause` chaining via the standard\n* `ErrorOptions`. `name` defaults to the subclass constructor name.\n*/\nvar HarnessError = class extends Error {\n\t/** Stable machine-routable failure class (e.g. `RATE_LIMIT`); route on this, never by parsing `message`. */\n\tcode;\n\tconstructor(message, code, options) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t\tthis.name = new.target.name;\n\t}\n};\nnew RegExp(String.raw`(?:^|[^a-z0-9])context[\\s_-](?:length|window)[\\s_-]` + String.raw`(?:exceed(?:ed|s)?|overflow(?:ed)?|limit[\\s_-]exceeded)(?:$|[^a-z0-9])`, \"i\");\nnew RegExp(String.raw`\\b(?:request|prompt|input|messages?)\\s+(?:is\\s+|are\\s+)?` + String.raw`too\\s+(?:large|long)\\s+for\\s+(?:(?:this|the)\\s+)?` + String.raw`(?:model(?:'s)?\\s+)?context(?:\\s+window)?\\b`, \"i\");\nnew RegExp(String.raw`\\b(?:input|prompt|request|messages?)\\b.{0,40}` + String.raw`\\b(?:exceed(?:s|ed)?|overflows?|is\\s+larger\\s+than)\\b.{0,40}` + String.raw`\\b(?:the\\s+)?(?:model(?:'s)?\\s+)?context(?:\\s+(?:length|window))?\\b`, \"i\");\n//#endregion\n//#region packages/util/values/src/index.ts\n/**\n* Mark an unreachable closed-union branch.\n* @param value - impossible value; an unhandled typed variant fails at the call site.\n* @param context - optional switch-site label included in the failure message.\n* @returns never; a runtime value that escaped its type always throws.\n*/\nfunction assertNever(value, context) {\n\tconst rendered = JSON.stringify(value) ?? String(value);\n\tthrow new Error(`unreachable variant${context ? ` in ${context}` : \"\"}: ${rendered}`);\n}\n/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */\nfunction hasIntrinsicConstructor$1(prototype, name) {\n\tconst constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n\tif (typeof constructor !== \"function\") return false;\n\ttry {\n\t\treturn constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === `function ${name}() { [native code] }`;\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype$1(value) {\n\treturn Object.getPrototypeOf(value) === null && hasIntrinsicConstructor$1(value, \"Object\");\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */\nfunction hasPlainArrayPrototype$1(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (!Array.isArray(prototype) || !hasIntrinsicConstructor$1(prototype, \"Array\")) return false;\n\tconst objectPrototype = Object.getPrototypeOf(prototype);\n\treturn typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype$1(objectPrototype);\n}\n/** Whether an object is a plain or null-prototype record from any JavaScript realm. */\nfunction hasPlainObjectPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype$1(prototype);\n}\n/** Return every JSON-visible object key, or reject own data JSON would discard. */\nfunction enumerableStringKeys(value) {\n\tconst keys = Reflect.ownKeys(value);\n\tif (keys.some((key) => typeof key !== \"string\" || !Object.prototype.propertyIsEnumerable.call(value, key))) return void 0;\n\treturn keys;\n}\n/** Validate lossless JSON iteratively, optionally materializing a detached snapshot. */\nfunction walkJsonValue(value, detach) {\n\tconst ancestors = /* @__PURE__ */ new Set();\n\tlet root;\n\tconst assign = (destination, item) => {\n\t\tif (destination === void 0) return;\n\t\tif (destination.kind === \"root\") root = item;\n\t\telse if (destination.kind === \"array\") destination.target[destination.index] = item;\n\t\telse Object.defineProperty(destination.target, destination.key, {\n\t\t\tvalue: item,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t\twritable: true\n\t\t});\n\t};\n\tconst tasks = [{\n\t\tkind: \"visit\",\n\t\tvalue,\n\t\t...detach ? { destination: { kind: \"root\" } } : {}\n\t}];\n\tfor (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n\t\tif (task.kind === \"leave\") {\n\t\t\tancestors.delete(task.source);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"array-item\") {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(task.source, task.index)) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.index],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"array\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tindex: task.index\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"object-property\") {\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.key],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"object\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tkey: task.key\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst current = task.value;\n\t\tif (current === null) {\n\t\t\tassign(task.destination, null);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"boolean\" || typeof current === \"string\") {\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"number\") {\n\t\t\tif (!Number.isFinite(current) || Object.is(current, -0)) return void 0;\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current !== \"object\") return void 0;\n\t\tif (ancestors.has(current)) return void 0;\n\t\tif (Array.isArray(current)) {\n\t\t\tif (!hasPlainArrayPrototype$1(current)) return void 0;\n\t\t\tconst length = current.length;\n\t\t\tif (Reflect.ownKeys(current).length !== length + 1) return void 0;\n\t\t\tconst target = detach ? [] : void 0;\n\t\t\tif (target !== void 0) assign(task.destination, target);\n\t\t\tancestors.add(current);\n\t\t\ttasks.push({\n\t\t\t\tkind: \"leave\",\n\t\t\t\tsource: current\n\t\t\t});\n\t\t\tfor (let index = length - 1; index >= 0; index--) tasks.push({\n\t\t\t\tkind: \"array-item\",\n\t\t\t\tsource: current,\n\t\t\t\tindex,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasPlainObjectPrototype(current)) return void 0;\n\t\tconst keys = enumerableStringKeys(current);\n\t\tif (keys === void 0) return void 0;\n\t\tconst target = detach ? {} : void 0;\n\t\tif (target !== void 0) assign(task.destination, target);\n\t\tancestors.add(current);\n\t\ttasks.push({\n\t\t\tkind: \"leave\",\n\t\t\tsource: current\n\t\t});\n\t\tfor (let index = keys.length - 1; index >= 0; index--) {\n\t\t\tconst key = keys[index];\n\t\t\t/* v8 ignore next -- the loop is bounded by the captured key count. */\n\t\t\tif (key === void 0) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"object-property\",\n\t\t\t\tsource: current,\n\t\t\t\tkey,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t}\n\t}\n\treturn detach ? root : true;\n}\n/**\n* Test the same lossless JSON rules as {@link snapshotJsonValue} without detaching the value.\n* @param value - candidate value to test.\n* @returns whether the value survives a JSON round trip without loss.\n*/\nfunction isJsonValue(value) {\n\treturn walkJsonValue(value, false) === true;\n}\n//#endregion\n//#region packages/core/tools/src/json-schema.ts\n/**\n* Enforced JSON Schema subset shared by tool outputs, generated PTC mode\n* types, subagents, and workflows. The subset accepts any JSON root, an\n* annotation-only schema for unconstrained JSON, one scalar `type`, object\n* `properties`/`required`/boolean `additionalProperties`, array `items`,\n* type-correct scalar `enum`/`const`, and exact-one `oneOf`.\n*\n* Unsupported or misplaced keywords reject rather than being accepted without\n* enforcement. Consumers that require an object root apply\n* {@link assertObjectJsonSchema} before accepting input.\n* @module dsh-tools/json-schema\n*/\n/**\n* Thrown when a raw schema falls outside the enforced subset. `violations`\n* lists every offending path instead of stopping at the first author error.\n*/\nvar JsonSchemaError = class extends HarnessError {\n\t/** Individual schema violations in walk order. */\n\tviolations;\n\tconstructor(violations) {\n\t\tsuper(`unsupported JSON schema: ${violations.join(\"; \")}`, \"UNSUPPORTED_SCHEMA\");\n\t\tthis.name = \"JsonSchemaError\";\n\t\tthis.violations = violations;\n\t}\n};\nconst CONSTRAINT_KEYWORDS = new Set([\n\t\"type\",\n\t\"oneOf\",\n\t\"properties\",\n\t\"required\",\n\t\"additionalProperties\",\n\t\"items\",\n\t\"enum\",\n\t\"const\"\n]);\nconst ANNOTATION_KEYWORDS = new Set([\n\t\"description\",\n\t\"title\",\n\t\"default\",\n\t\"examples\"\n]);\nconst SCHEMA_TYPES = [\n\t\"object\",\n\t\"array\",\n\t\"string\",\n\t\"number\",\n\t\"integer\",\n\t\"boolean\",\n\t\"null\"\n];\n/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */\nfunction hasIntrinsicConstructor(prototype, name) {\n\tconst constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n\tif (typeof constructor !== \"function\") return false;\n\ttry {\n\t\treturn constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === `function ${name}() { [native code] }`;\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype(value) {\n\treturn Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, \"Object\");\n}\n/**\n* Test for a realm-agnostic plain JSON record without accepting arrays or\n* exotic objects.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the value has a plain-object prototype chain.\n*/\nfunction isPlainJsonRecord(value) {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n\ttry {\n\t\tconst prototype = Object.getPrototypeOf(value);\n\t\treturn prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype(prototype);\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`. */\nfunction hasPlainArrayPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, \"Array\")) return false;\n\tconst objectPrototype = Object.getPrototypeOf(prototype);\n\treturn typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype(objectPrototype);\n}\n/** Return whether a record contains only own enumerable string keys. */\nfunction hasOnlyEnumerableStringKeys(value) {\n\ttry {\n\t\treturn Reflect.ownKeys(value).every((key) => typeof key === \"string\" && Object.prototype.propertyIsEnumerable.call(value, key));\n\t} catch {\n\t\treturn false;\n\t}\n}\n/**\n* Test for an ordinary schema record whose keys survive JSON projection.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the record has an intrinsic prototype and only own enumerable string keys.\n*/\nfunction isJsonSchemaRecord(value) {\n\treturn isPlainJsonRecord(value) && hasOnlyEnumerableStringKeys(value);\n}\n/**\n* Test for a dense ordinary array with no JSON-invisible decorations.\n* @param value - candidate array from any JavaScript realm.\n* @returns Whether the array is intrinsic, dense, and undecorated.\n*/\nfunction isPlainJsonArray(value) {\n\tif (!Array.isArray(value)) return false;\n\ttry {\n\t\tif (!hasPlainArrayPrototype(value) || Reflect.ownKeys(value).length !== value.length + 1) return false;\n\t\tfor (let index = 0; index < value.length; index++) if (!Object.hasOwn(value, index)) return false;\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Lossless finite JSON number, excluding negative zero. */\nfunction isJsonNumber(value) {\n\treturn typeof value === \"number\" && Number.isFinite(value) && !Object.is(value, -0);\n}\n/** Whether a scalar is valid for one declared schema type. */\nfunction scalarMatches(type, value) {\n\tswitch (type) {\n\t\tcase \"string\": return typeof value === \"string\";\n\t\tcase \"number\": return isJsonNumber(value);\n\t\tcase \"integer\": return isJsonNumber(value) && Number.isInteger(value);\n\t\tcase \"boolean\": return typeof value === \"boolean\";\n\t\tcase \"null\": return value === null;\n\t\t/* v8 ignore next -- JsonSchemaScalarType is closed; this retains compile-time exhaustiveness. */\n\t\tdefault: return assertNever(type, \"JsonSchemaType\");\n\t}\n}\n/** Keywords that are invalid beside `oneOf`. */\nconst ONE_OF_SIBLING_KEYWORDS = [\n\t\"properties\",\n\t\"required\",\n\t\"additionalProperties\",\n\t\"items\",\n\t\"enum\",\n\t\"const\"\n];\n/** Validate object-only fields after its property schemas have been visited. */\nfunction checkObjectSchemaTail(node, path, properties, violations) {\n\tconst hasRequired = Object.hasOwn(node, \"required\");\n\tconst required = hasRequired ? node.required : void 0;\n\tif (hasRequired) if (!isPlainJsonArray(required) || required.some((entry) => typeof entry !== \"string\")) violations.push(`${path}.required must be an array of strings`);\n\telse {\n\t\tconst declared = isJsonSchemaRecord(properties) ? properties : {};\n\t\tfor (const key of required) if (!Object.hasOwn(declared, key)) violations.push(`${path}.required names \"${key}\" which is not in properties`);\n\t}\n\tif (Object.hasOwn(node, \"additionalProperties\") && typeof node.additionalProperties !== \"boolean\") violations.push(`${path}.additionalProperties must be a boolean`);\n}\n/** Collect every violation for one raw schema tree without using the JavaScript call stack. */\nfunction checkSchemaNode(root, rootPath, violations, seen) {\n\tconst tasks = [{\n\t\tkind: \"enter\",\n\t\tnode: root,\n\t\tpath: rootPath\n\t}];\n\tfor (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n\t\tif (task.kind === \"leave\") {\n\t\t\tseen.delete(task.node);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"one-of-tail\") {\n\t\t\tfor (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(task.node, key)) violations.push(`${task.path}.${key} is not supported beside oneOf`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"object-tail\") {\n\t\t\tcheckObjectSchemaTail(task.node, task.path, task.properties, violations);\n\t\t\tcontinue;\n\t\t}\n\t\tconst { node, path } = task;\n\t\tif (!isJsonSchemaRecord(node)) {\n\t\t\tviolations.push(`${path} must be a schema object`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (seen.has(node)) {\n\t\t\tviolations.push(`${path} is circular`);\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(node);\n\t\ttasks.push({\n\t\t\tkind: \"leave\",\n\t\t\tnode\n\t\t});\n\t\tfor (const key of Object.keys(node)) {\n\t\t\tif (CONSTRAINT_KEYWORDS.has(key)) continue;\n\t\t\tif (ANNOTATION_KEYWORDS.has(key)) {\n\t\t\t\ttry {\n\t\t\t\t\tif (!isJsonValue(node[key])) violations.push(`${path}.${key} annotation must be lossless JSON data`);\n\t\t\t\t} catch {\n\t\t\t\t\tviolations.push(`${path}.${key} annotation must be lossless JSON data`);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tviolations.push(`${path}.${key} is not a supported keyword (subset: type/oneOf/properties/required/additionalProperties/items/enum/const + annotations)`);\n\t\t}\n\t\tif (Object.hasOwn(node, \"description\") && typeof node.description !== \"string\") violations.push(`${path}.description must be a string`);\n\t\tif (Object.hasOwn(node, \"title\") && typeof node.title !== \"string\") violations.push(`${path}.title must be a string`);\n\t\tconst hasType = Object.hasOwn(node, \"type\");\n\t\tconst hasOneOf = Object.hasOwn(node, \"oneOf\");\n\t\tif (hasType && hasOneOf) {\n\t\t\tviolations.push(`${path} cannot declare both type and oneOf`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasType && !hasOneOf) {\n\t\t\tfor (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(node, key)) violations.push(`${path}.${key} requires type or oneOf`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (hasOneOf) {\n\t\t\tconst oneOf = node.oneOf;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"one-of-tail\",\n\t\t\t\tnode,\n\t\t\t\tpath\n\t\t\t});\n\t\t\tif (!isPlainJsonArray(oneOf) || oneOf.length < 2) violations.push(`${path}.oneOf must be an array of at least two schemas`);\n\t\t\telse for (let index = oneOf.length - 1; index >= 0; index--) tasks.push({\n\t\t\t\tkind: \"enter\",\n\t\t\t\tnode: oneOf[index],\n\t\t\t\tpath: `${path}.oneOf[${index}]`\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst type = node.type;\n\t\tif (typeof type !== \"string\" || !SCHEMA_TYPES.includes(type)) {\n\t\t\tviolations.push(Array.isArray(type) ? `${path}.type must be a single type string (type arrays are not supported)` : `${path}.type must be one of ${SCHEMA_TYPES.join(\"/\")}`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst schemaType = type;\n\t\tfor (const [key, types] of Object.entries({\n\t\t\tproperties: [\"object\"],\n\t\t\trequired: [\"object\"],\n\t\t\tadditionalProperties: [\"object\"],\n\t\t\titems: [\"array\"],\n\t\t\tenum: [\n\t\t\t\t\"string\",\n\t\t\t\t\"number\",\n\t\t\t\t\"integer\",\n\t\t\t\t\"boolean\",\n\t\t\t\t\"null\"\n\t\t\t],\n\t\t\tconst: [\n\t\t\t\t\"string\",\n\t\t\t\t\"number\",\n\t\t\t\t\"integer\",\n\t\t\t\t\"boolean\",\n\t\t\t\t\"null\"\n\t\t\t]\n\t\t})) if (Object.hasOwn(node, key) && !types.includes(schemaType)) violations.push(`${path}.${key} is not supported on type \"${schemaType}\"`);\n\t\tswitch (schemaType) {\n\t\t\tcase \"object\": {\n\t\t\t\tconst properties = Object.hasOwn(node, \"properties\") ? node.properties : void 0;\n\t\t\t\ttasks.push({\n\t\t\t\t\tkind: \"object-tail\",\n\t\t\t\t\tnode,\n\t\t\t\t\tpath,\n\t\t\t\t\tproperties\n\t\t\t\t});\n\t\t\t\tif (Object.hasOwn(node, \"properties\")) if (!isJsonSchemaRecord(properties)) violations.push(`${path}.properties must be an object of schemas`);\n\t\t\t\telse {\n\t\t\t\t\tconst entries = Object.entries(properties);\n\t\t\t\t\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\t\t\t\t\tconst entry = entries[index];\n\t\t\t\t\t\t/* v8 ignore next -- the loop is bounded by the captured entry count. */\n\t\t\t\t\t\tif (entry === void 0) continue;\n\t\t\t\t\t\ttasks.push({\n\t\t\t\t\t\t\tkind: \"enter\",\n\t\t\t\t\t\t\tnode: entry[1],\n\t\t\t\t\t\t\tpath: `${path}.properties.${entry[0]}`\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"array\":\n\t\t\t\tif (Object.hasOwn(node, \"items\")) tasks.push({\n\t\t\t\t\tkind: \"enter\",\n\t\t\t\t\tnode: node.items,\n\t\t\t\t\tpath: `${path}.items`\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"string\":\n\t\t\tcase \"number\":\n\t\t\tcase \"integer\":\n\t\t\tcase \"boolean\":\n\t\t\tcase \"null\": {\n\t\t\t\tconst hasEnum = Object.hasOwn(node, \"enum\");\n\t\t\t\tconst allowed = hasEnum ? node.enum : void 0;\n\t\t\t\tconst enumValid = isPlainJsonArray(allowed) && allowed.length > 0 && allowed.every((entry) => scalarMatches(schemaType, entry));\n\t\t\t\tif (hasEnum && !enumValid) violations.push(`${path}.enum must be a non-empty array of ${schemaType} values`);\n\t\t\t\tconst hasConst = Object.hasOwn(node, \"const\");\n\t\t\t\tconst declaredConst = hasConst ? node.const : void 0;\n\t\t\t\tconst constValid = scalarMatches(schemaType, declaredConst);\n\t\t\t\tif (hasConst) {\n\t\t\t\t\tif (!constValid) violations.push(`${path}.const must be a ${schemaType} value`);\n\t\t\t\t\telse if (enumValid && !allowed.includes(declaredConst)) violations.push(`${path}.const must be one of ${path}.enum when both are declared`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* v8 ignore next -- schemaType was narrowed from the closed SCHEMA_TYPES table above. */\n\t\t\tdefault: assertNever(schemaType, \"JsonSchemaType\");\n\t\t}\n\t}\n}\n/**\n* Assert the enforced subset plus the object-root constraint retained by\n* subagent and workflow structured outputs.\n* @param schema - untrusted caller-supplied schema.\n* @returns Assertion that the schema belongs to the supported subset and has an object root.\n*/\nfunction assertObjectJsonSchema(schema) {\n\tconst violations = [];\n\tcheckSchemaNode(schema, \"schema\", violations, /* @__PURE__ */ new Set());\n\tif (violations.length === 0 && (!isJsonSchemaRecord(schema) || !Object.hasOwn(schema, \"type\") || schema.type !== \"object\")) violations.push(\"schema.type must be \\\"object\\\" (structured output is object-rooted)\");\n\tif (violations.length > 0) throw new JsonSchemaError(violations);\n}\n//#endregion\n//#region packages/workflow/workflow/src/index.ts\n/**\n* Typed error for workflow-seam failures. Extends {@link HarnessError}, so the\n* `code` is machine-routable taxonomy. `fatal` drives the combinator\n* discipline: `parallel()`/`pipeline()` re-throw a fatal error (a typo'd\n* option or a tripped cap must kill the script loudly), and reserve the\n* per-item `null` for child-run failures and ordinary in-stage script errors.\n* Every {@link WorkflowErrorCode} is fatal; the flag exists so the\n* distinction is explicit at every catch site rather than implied.\n*/\nvar WorkflowError = class extends HarnessError {\n\t/** Whether combinators must propagate this error instead of nulling the item. */\n\tfatal;\n\tconstructor(message, code, options) {\n\t\tsuper(message, code, options);\n\t\tthis.name = \"WorkflowError\";\n\t\tthis.fatal = options?.fatal ?? true;\n\t}\n};\n/**\n* Whether combinators must re-throw `error` instead of mapping the item to `null`.\n* @param error - any thrown value; fatality is host `instanceof` (unforgeable from a script realm).\n* @returns true iff `error` is a {@link WorkflowError} whose `fatal` flag is set.\n*/\nfunction isFatalWorkflowError(error) {\n\treturn error instanceof WorkflowError && error.fatal;\n}\n//#endregion\n//#region packages/workflow/workflow-ptc/src/runtime.ts\n/**\n* Workflow VM hooks, child callbacks, ordinary concurrency limits and result serialization.\n* PTC owns process confinement and cancellation. Fatal hook and provider failures propagate\n* through combinators; ordinary child failures and stage errors become per-item nulls.\n* @module @deepseek-ai/dsh-workflow-ptc/runtime\n*/\n/** The `agent()` options the script may pass; everything else rejects loud. */\nconst SUPPORTED_AGENT_OPTIONS = new Set([\n\t\"label\",\n\t\"phase\",\n\t\"schema\",\n\t\"provider\",\n\t\"model\"\n]);\n/** Deferred Claude Code options we name explicitly in the rejection message. */\nconst DEFERRED_AGENT_OPTIONS = new Set([\n\t\"effort\",\n\t\"isolation\",\n\t\"agentType\"\n]);\n/** Flatten a child's final output blocks to text (the non-schema `agent()` result). */\nfunction outputText(blocks) {\n\treturn blocks.filter((block) => block.type === \"text\").map((block) => block.text).join(\"\");\n}\n/** A short display label derived from the prompt when the script passes none. */\nfunction defaultLabel(prompt) {\n\tconst newline = prompt.indexOf(\"\\n\");\n\tconst line = newline === -1 ? prompt : prompt.slice(0, newline);\n\treturn line.length <= 48 ? line : `${line.slice(0, 47)}\u2026`;\n}\n/**\n* One script execution inside the confined Node process. The host owns\n* cancellation and cleanup of any dropped child work.\n*/\nvar WorkflowExecution = class {\n\tlimits;\n\tobserver;\n\tchildren;\n\t/** 1-based count of `agent()` calls started (the `agentsStarted` result field). */\n\tstarted = 0;\n\tactiveSlots = 0;\n\tslotWaiters = [];\n\tcurrentPhase;\n\tcontext;\n\tcompiled;\n\tconstructor(meta, body, args, limits, observer, children) {\n\t\tthis.limits = limits;\n\t\tthis.observer = observer;\n\t\tthis.children = children;\n\t\ttry {\n\t\t\tthis.compiled = new vm.Script(`(async () => {\\n${body}\\n})()`, {\n\t\t\t\tfilename: `workflow:${meta.name}`,\n\t\t\t\tlineOffset: -1\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new WorkflowError(`workflow script does not parse: ${String(error)}`, \"SCRIPT_PARSE\", { cause: error });\n\t\t}\n\t\tthis.context = vm.createContext({}, { name: `workflow:${meta.name}` });\n\t\tconst globals = {\n\t\t\tagent: (prompt, opts) => this.contain(this.agent(prompt, opts)),\n\t\t\tparallel: (thunks) => this.contain(this.parallel(thunks)),\n\t\t\tpipeline: (items, ...stages) => this.contain(this.pipeline(items, stages)),\n\t\t\tphase: (title) => {\n\t\t\t\tthis.phase(title);\n\t\t\t},\n\t\t\tlog: (message) => {\n\t\t\t\tthis.log(message);\n\t\t\t},\n\t\t\targs\n\t\t};\n\t\tfor (const [key, value] of Object.entries(globals)) this.context[key] = typeof value === \"function\" ? Object.freeze(value) : value;\n\t}\n\t/**\n\t* Run the script and materialize its JSON return value.\n\t* @returns A completed or error result; script failures never reject.\n\t*/\n\tasync drive() {\n\t\ttry {\n\t\t\tconst scriptPromise = this.compiled.runInContext(this.context, { timeout: this.limits.syncTimeoutMs });\n\t\t\tconst raw = await this.contain(Promise.resolve(scriptPromise));\n\t\t\treturn {\n\t\t\t\tvalue: raw === void 0 ? null : this.materializeResult(raw),\n\t\t\t\tstopReason: \"completed\",\n\t\t\t\tagentsStarted: this.started\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tvalue: null,\n\t\t\t\tstopReason: \"error\",\n\t\t\t\terror: renderThrown(error),\n\t\t\t\tagentsStarted: this.started\n\t\t\t};\n\t\t}\n\t}\n\t/**\n\t* Attach a no-op rejection consumer WITHOUT changing what the caller\n\t* receives: if the script drops the promise, a host rejection cannot become\n\t* an unhandled rejection that kills the process; if\n\t* the script does await it, it still observes the rejection.\n\t*/\n\tcontain(promise) {\n\t\tpromise.catch(() => {});\n\t\treturn promise;\n\t}\n\t/** Materialize the script's return value; violations become RESULT_UNSERIALIZABLE. */\n\tmaterializeResult(raw) {\n\t\ttry {\n\t\t\treturn materializeFromRealm(raw, \"workflow result\");\n\t\t} catch (error) {\n\t\t\t/* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n\t\t\tif (!(error instanceof MaterializeError)) throw error;\n\t\t\tthrow new WorkflowError(`the workflow's return value is not plain JSON data \u2014 ${error.message}. Return only JSON-serializable objects/arrays/scalars.`, \"RESULT_UNSERIALIZABLE\", { cause: error });\n\t\t}\n\t}\n\t/** Acquire one concurrency slot in FIFO order. */\n\tacquireSlot() {\n\t\tif (this.activeSlots < this.limits.maxConcurrentAgents) {\n\t\t\tthis.activeSlots += 1;\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\treturn new Promise((resolve) => {\n\t\t\tthis.slotWaiters.push(() => {\n\t\t\t\tthis.activeSlots += 1;\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\treleaseSlot() {\n\t\tthis.activeSlots -= 1;\n\t\tconst next = this.slotWaiters.shift();\n\t\tif (next) next();\n\t}\n\t/** The `agent(prompt, opts)` hook. */\n\tasync agent(rawPrompt, rawOpts) {\n\t\tif (typeof rawPrompt !== \"string\" || rawPrompt.length === 0) throw new WorkflowError(\"agent() requires a non-empty prompt string\", \"INVALID_ARGUMENT\");\n\t\tconst opts = this.readAgentOptions(rawOpts);\n\t\tif (this.started >= this.limits.maxTotalAgents) throw new WorkflowError(`this run reached its total agent cap (${this.limits.maxTotalAgents}) \u2014 a runaway-loop backstop; raise the applicable maxTotalAgents limit if the scale is intentional`, \"AGENT_CAP\");\n\t\tthis.started += 1;\n\t\tconst seq = this.started;\n\t\tconst label = opts.label ?? defaultLabel(rawPrompt);\n\t\tconst phase = opts.phase ?? this.currentPhase;\n\t\tawait this.acquireSlot();\n\t\ttry {\n\t\t\tlet run;\n\t\t\ttry {\n\t\t\t\trun = await this.children.startAgent({\n\t\t\t\t\tprompt: rawPrompt,\n\t\t\t\t\t...opts.schema !== void 0 ? { schema: opts.schema } : {},\n\t\t\t\t\t...opts.provider !== void 0 ? { provider: opts.provider } : {},\n\t\t\t\t\t...opts.model !== void 0 ? { model: opts.model } : {}\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tthrow new WorkflowError(`agent() could not start a child: ${renderThrown(error)}`, \"AGENT_START\", { cause: error });\n\t\t\t}\n\t\t\tconst info = {\n\t\t\t\tseq,\n\t\t\t\tlabel,\n\t\t\t\t...phase !== void 0 ? { phase } : {},\n\t\t\t\tchildId: brandString(run.id)\n\t\t\t};\n\t\t\tthis.observer.agentStart(info);\n\t\t\ttry {\n\t\t\t\tlet result;\n\t\t\t\ttry {\n\t\t\t\t\tresult = await run.result;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t...info,\n\t\t\t\t\t\toutcome: \"failed\"\n\t\t\t\t\t});\n\t\t\t\t\tthrow new WorkflowError(`child agent run failed: ${renderThrown(error)}`, \"AGENT_RESULT\", { cause: error });\n\t\t\t\t}\n\t\t\t\tif (result.stopReason === \"completed\") {\n\t\t\t\t\tif (opts.schema !== void 0) {\n\t\t\t\t\t\tif (result.structured === void 0) {\n\t\t\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\t\toutcome: \"failed\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\toutcome: \"completed\"\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn result.structured;\n\t\t\t\t\t}\n\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t...info,\n\t\t\t\t\t\toutcome: \"completed\"\n\t\t\t\t\t});\n\t\t\t\t\treturn outputText(result.output);\n\t\t\t\t}\n\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t...info,\n\t\t\t\t\toutcome: \"failed\"\n\t\t\t\t});\n\t\t\t\treturn null;\n\t\t\t} finally {\n\t\t\t\tawait run.dispose();\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.releaseSlot();\n\t\t}\n\t}\n\t/** Materialize + validate the `agent()` options bag from the realm. */\n\treadAgentOptions(rawOpts) {\n\t\tif (rawOpts === void 0) return {};\n\t\tlet opts;\n\t\ttry {\n\t\t\topts = materializeFromRealm(rawOpts, \"agent() options\");\n\t\t} catch (error) {\n\t\t\t/* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n\t\t\tif (!(error instanceof MaterializeError)) throw error;\n\t\t\tthrow new WorkflowError(`agent() options must be plain JSON data \u2014 ${error.message}`, \"INVALID_ARGUMENT\", { cause: error });\n\t\t}\n\t\tif (typeof opts !== \"object\" || opts === null || Array.isArray(opts)) throw new WorkflowError(\"agent() options must be an object\", \"INVALID_ARGUMENT\");\n\t\tconst record = opts;\n\t\tfor (const key of Object.keys(record)) {\n\t\t\tif (SUPPORTED_AGENT_OPTIONS.has(key)) continue;\n\t\t\tif (DEFERRED_AGENT_OPTIONS.has(key)) throw new WorkflowError(`agent() option \"${key}\" is deferred and not supported by this engine (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n\t\t\tthrow new WorkflowError(`agent() option \"${key}\" is not recognized (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n\t\t}\n\t\tfor (const key of [\n\t\t\t\"label\",\n\t\t\t\"phase\",\n\t\t\t\"provider\",\n\t\t\t\"model\"\n\t\t]) if (record[key] !== void 0 && typeof record[key] !== \"string\") throw new WorkflowError(`agent() option \"${key}\" must be a string`, \"INVALID_ARGUMENT\");\n\t\tlet schema;\n\t\tif (record.schema !== void 0) try {\n\t\t\tassertObjectJsonSchema(record.schema);\n\t\t\tschema = record.schema;\n\t\t} catch (error) {\n\t\t\t/* v8 ignore next -- defensive rethrow arm: assertObjectJsonSchema only throws JsonSchemaError */\n\t\t\tif (!(error instanceof JsonSchemaError)) throw error;\n\t\t\tthrow new WorkflowError(`agent() schema is outside the supported subset \u2014 ${error.message}`, \"UNSUPPORTED_SCHEMA\", { cause: error });\n\t\t}\n\t\treturn {\n\t\t\t...record.label !== void 0 ? { label: record.label } : {},\n\t\t\t...record.phase !== void 0 ? { phase: record.phase } : {},\n\t\t\t...record.provider !== void 0 ? { provider: record.provider } : {},\n\t\t\t...record.model !== void 0 ? { model: record.model } : {},\n\t\t\t...schema !== void 0 ? { schema } : {}\n\t\t};\n\t}\n\t/** The `parallel(thunks)` hook: each thunk caught \u2192 `null`; fatal errors propagate. */\n\tasync parallel(rawThunks) {\n\t\tif (!Array.isArray(rawThunks)) throw new WorkflowError(\"parallel() requires an array of zero-argument functions\", \"INVALID_ARGUMENT\");\n\t\tthis.assertItemCap(rawThunks.length, \"parallel()\");\n\t\tconst thunks = rawThunks.map((thunk, index) => {\n\t\t\tif (typeof thunk !== \"function\") throw new WorkflowError(`parallel() item ${index} is not a function`, \"INVALID_ARGUMENT\");\n\t\t\treturn thunk;\n\t\t});\n\t\treturn Promise.all(thunks.map(async (thunk) => {\n\t\t\ttry {\n\t\t\t\treturn await thunk();\n\t\t\t} catch (error) {\n\t\t\t\tif (isFatalWorkflowError(error)) throw error;\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}));\n\t}\n\t/** The `pipeline(items, ...stages)` hook: per-item stage chains, NO cross-stage barrier. */\n\tasync pipeline(rawItems, rawStages) {\n\t\tif (!Array.isArray(rawItems)) throw new WorkflowError(\"pipeline() requires an items array\", \"INVALID_ARGUMENT\");\n\t\tthis.assertItemCap(rawItems.length, \"pipeline()\");\n\t\tif (rawStages.length === 0) throw new WorkflowError(\"pipeline() requires at least one stage function\", \"INVALID_ARGUMENT\");\n\t\tconst stages = rawStages.map((stage, index) => {\n\t\t\tif (typeof stage !== \"function\") throw new WorkflowError(`pipeline() stage ${index} is not a function`, \"INVALID_ARGUMENT\");\n\t\t\treturn stage;\n\t\t});\n\t\treturn Promise.all(rawItems.map(async (item, index) => {\n\t\t\tlet value = item;\n\t\t\ttry {\n\t\t\t\tfor (const stage of stages) value = await stage(value, item, index);\n\t\t\t\treturn value;\n\t\t\t} catch (error) {\n\t\t\t\tif (isFatalWorkflowError(error)) throw error;\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}));\n\t}\n\tassertItemCap(length, hook) {\n\t\tif (length > this.limits.maxItemsPerCall) throw new WorkflowError(`${hook} received ${length} items \u2014 over the per-call cap (${this.limits.maxItemsPerCall}); split the work or raise maxItemsPerCall in the engine config`, \"ITEM_CAP\");\n\t}\n\t/** The `phase(title)` hook: sets the current label for subsequent `agent()` calls and notifies observers. */\n\tphase(title) {\n\t\tif (typeof title !== \"string\" || title.length === 0) throw new WorkflowError(\"phase() requires a non-empty title string\", \"INVALID_ARGUMENT\");\n\t\tthis.currentPhase = title;\n\t\tthis.observer.phase(title);\n\t}\n\t/** The `log(message)` hook: narration to observers. */\n\tlog(message) {\n\t\tif (typeof message !== \"string\") throw new WorkflowError(\"log() requires a message string\", \"INVALID_ARGUMENT\");\n\t\tthis.observer.log(message);\n\t}\n};\n//#endregion\n//#region packages/workflow/workflow-ptc/src/guest.ts\n/**\n* Run a workflow with one progress batch in flight. Drain progress before child\n* disposal and the terminal result; PTC and the host own cancellation and cleanup.\n* @param host - JSON callbacks owned by this workflow run.\n* @returns The script result after progress delivery; initialization failures reject.\n*/\nasync function runWorkflowGuest(host) {\n\tconst init = await host.begin({});\n\tlet queued = [];\n\tlet inFlight;\n\tlet progressError;\n\tconst flush = () => {\n\t\tif (inFlight !== void 0 || queued.length === 0) return;\n\t\tconst batch = queued;\n\t\tqueued = [];\n\t\tinFlight = host.progress(batch).then(() => {\n\t\t\tinFlight = void 0;\n\t\t\tflush();\n\t\t}, (error) => {\n\t\t\tprogressError = renderThrown(error);\n\t\t\tqueued = [];\n\t\t\tinFlight = void 0;\n\t\t});\n\t};\n\tconst send = (event) => {\n\t\tif (progressError !== void 0) return;\n\t\tqueued.push(event);\n\t\tflush();\n\t};\n\tconst drain = async () => {\n\t\twhile (inFlight !== void 0) await inFlight;\n\t};\n\tconst result = await new WorkflowExecution(init.meta, init.body, init.args, init.limits, {\n\t\tphase: (title) => {\n\t\t\tsend({\n\t\t\t\ttype: \"phase\",\n\t\t\t\ttitle\n\t\t\t});\n\t\t},\n\t\tlog: (message) => {\n\t\t\tsend({\n\t\t\t\ttype: \"log\",\n\t\t\t\tmessage\n\t\t\t});\n\t\t},\n\t\tagentStart: (info) => {\n\t\t\tsend({\n\t\t\t\ttype: \"agent-start\",\n\t\t\t\tinfo\n\t\t\t});\n\t\t},\n\t\tagentEnd: (info) => {\n\t\t\tsend({\n\t\t\t\ttype: \"agent-end\",\n\t\t\t\tinfo\n\t\t\t});\n\t\t}\n\t}, { async startAgent(request) {\n\t\tconst { callId, childId } = await host.startChild(request);\n\t\tconst result = host.childResult({ callId });\n\t\tresult.catch(() => {});\n\t\treturn {\n\t\t\tid: childId,\n\t\t\tresult,\n\t\t\tasync dispose() {\n\t\t\t\tawait drain();\n\t\t\t\tawait host.disposeChild({ callId });\n\t\t\t}\n\t\t};\n\t} }).drive();\n\tawait drain();\n\treturn progressError === void 0 ? result : {\n\t\tvalue: null,\n\t\tstopReason: \"error\",\n\t\terror: progressError,\n\t\tagentsStarted: result.agentsStarted\n\t};\n}\n//#endregion\nexport { runWorkflowGuest };\n//# sourceURL=dsh-workflow-guest.js\n";
|
|
3
|
+
export declare const WORKFLOW_GUEST_SOURCE = "import * as vm from \"node:vm\";\n//#region packages/workflow/workflow-ptc/src/realm.ts\n/**\n* Materializes script VM values as plain JSON and renders thrown values.\n* Getters and proxy traps may execute inside the confined Node process;\n* process isolation and cancellation belong to PTC, not the VM.\n* @module @deepseek-ai/dsh-workflow-ptc/realm\n*/\n/** Thrown by {@link materializeFromRealm}; the caller wraps it into the right `WorkflowError` code. */\nvar MaterializeError = class extends Error {\n\tpath;\n\treason;\n\tconstructor(path, reason) {\n\t\tsuper(`${path}: ${reason}`);\n\t\tthis.path = path;\n\t\tthis.reason = reason;\n\t\tthis.name = \"MaterializeError\";\n\t}\n};\n/**\n* Render a thrown value to failure text without ever throwing: prefer the\n* `stack` (host or realm \u2014 a realm error's `stack` is a plain string read),\n* fall back to `message`, then `String()`. Reading those properties MAY run\n* script code; if that code itself throws, a fixed label is returned instead.\n* @param error - any value thrown in the host or guest realm.\n* @returns human-readable text for the failure report; prefers the stack.\n*/\nfunction renderThrown(error) {\n\ttry {\n\t\tconst stack = error?.stack;\n\t\tif (typeof stack === \"string\" && stack.length > 0) return stack;\n\t\tconst message = error?.message;\n\t\tif (typeof message === \"string\" && message.length > 0) return message;\n\t\treturn String(error);\n\t} catch {\n\t\treturn \"[unrenderable thrown value]\";\n\t}\n}\n/**\n* Whether an object's prototype chain represents a plain data object: `null`, or a prototype\n* whose own prototype is `null` (the realm's `Object.prototype` \u2014 which we\n* cannot compare by identity across realms). A `Date`/`Map`/class instance\n* has a longer chain and is rejected.\n*/\nfunction hasPlainPrototype(value) {\n\tconst proto = Object.getPrototypeOf(value);\n\tif (proto === null) return true;\n\treturn Object.getPrototypeOf(proto) === null;\n}\n/**\n* Copy `value` (typically from the vm realm) into plain host JSON data. Root `undefined` is\n* returned unchanged; nested `undefined` and values JSON cannot represent losslessly fail\n* with the offending path. Property accessors run normally, and a throwing read is wrapped\n* with its rendered failure.\n*\n* @param value - the realm value to materialize.\n* @param root - the path label for the root value (error messages).\n* @returns the host-realm copy (plain objects/arrays/scalars only).\n* @throws {@link MaterializeError} for unsupported values, cycles, sparse arrays, exotic\n* prototypes, or property reads that throw.\n*/\nfunction materializeFromRealm(value, root = \"value\") {\n\tif (value === void 0) return void 0;\n\ttry {\n\t\treturn materialize(value, root, /* @__PURE__ */ new Set());\n\t} catch (error) {\n\t\tif (error instanceof MaterializeError) throw error;\n\t\tthrow new MaterializeError(root, `reading the value threw: ${renderThrown(error)}`);\n\t}\n}\nfunction materialize(value, path, seen) {\n\tswitch (typeof value) {\n\t\tcase \"boolean\":\n\t\tcase \"string\": return value;\n\t\tcase \"number\":\n\t\t\tif (!Number.isFinite(value)) throw new MaterializeError(path, \"non-finite numbers are not JSON data\");\n\t\t\treturn value;\n\t\tcase \"bigint\": throw new MaterializeError(path, \"bigints are not JSON data\");\n\t\tcase \"function\": throw new MaterializeError(path, \"functions are not plain JSON data\");\n\t\tcase \"symbol\": throw new MaterializeError(path, \"symbols are not plain JSON data\");\n\t\tcase \"undefined\": throw new MaterializeError(path, \"undefined is not JSON data\");\n\t\tcase \"object\": break;\n\t}\n\tif (value === null) return null;\n\tconst objectValue = value;\n\tif (seen.has(objectValue)) throw new MaterializeError(path, \"circular references are not JSON data\");\n\tseen.add(objectValue);\n\ttry {\n\t\tif (Array.isArray(objectValue)) return materializeArray(objectValue, path, seen);\n\t\treturn materializeObject(objectValue, path, seen);\n\t} finally {\n\t\tseen.delete(objectValue);\n\t}\n}\nfunction materializeArray(value, path, seen) {\n\tconst out = [];\n\tfor (let index = 0; index < value.length; index++) {\n\t\tif (!(index in value)) throw new MaterializeError(`${path}[${index}]`, \"sparse arrays are not JSON data\");\n\t\tout.push(materialize(value[index], `${path}[${index}]`, seen));\n\t}\n\tfor (const key of Object.keys(value)) {\n\t\tconst index = Number(key);\n\t\tif (!Number.isInteger(index) || index < 0 || index >= value.length) throw new MaterializeError(`${path}.${key}`, \"arrays with non-index properties are not JSON data\");\n\t}\n\tif (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n\treturn out;\n}\nfunction materializeObject(value, path, seen) {\n\tif (!hasPlainPrototype(value)) throw new MaterializeError(path, \"only plain objects and arrays are JSON data (exotic prototype)\");\n\tif (Object.getOwnPropertySymbols(value).length > 0) throw new MaterializeError(path, \"symbol-keyed properties are not plain JSON data\");\n\tconst out = {};\n\tfor (const key of Object.keys(value)) Object.defineProperty(out, key, {\n\t\tvalue: materialize(value[key], `${path}.${key}`, seen),\n\t\tenumerable: true,\n\t\twritable: true,\n\t\tconfigurable: true\n\t});\n\treturn out;\n}\n//#endregion\n//#region packages/util/brand/src/index.ts\n/**\n* Apply a compile-time string brand without changing the value.\n* @param value - string admitted by the domain that owns the target brand.\n* @returns the same string with the requested compile-time brand.\n*/\nfunction brandString(value) {\n\treturn value;\n}\n//#endregion\n//#region packages/llm/llm/src/error.ts\n/**\n* Harness error base with a stable machine-routable code and chained cause.\n* Package errors extend it so tool results and replay can retain failure class.\n* @module @deepseek-ai/dsh-llm/error\n*/\n/**\n* Base class for all harness errors. Carries a `code` (stable, programmatic \u2014\n* e.g. `NO_ADAPTER`, `INVALID_ARGS`, `INVARIANT`) distinct from the\n* human-readable `message`, and supports `cause` chaining via the standard\n* `ErrorOptions`. `name` defaults to the subclass constructor name.\n*/\nvar HarnessError = class extends Error {\n\t/** Stable machine-routable failure class (e.g. `RATE_LIMIT`); route on this, never by parsing `message`. */\n\tcode;\n\tconstructor(message, code, options) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t\tthis.name = new.target.name;\n\t}\n};\nnew RegExp(String.raw`(?:^|[^a-z0-9])context[\\s_-](?:length|window)[\\s_-]` + String.raw`(?:exceed(?:ed|s)?|overflow(?:ed)?|limit[\\s_-]exceeded)(?:$|[^a-z0-9])`, \"i\");\nnew RegExp(String.raw`\\b(?:request|prompt|input|messages?)\\s+(?:is\\s+|are\\s+)?` + String.raw`too\\s+(?:large|long)\\s+for\\s+(?:(?:this|the)\\s+)?` + String.raw`(?:model(?:'s)?\\s+)?context(?:\\s+window)?\\b`, \"i\");\nnew RegExp(String.raw`\\b(?:input|prompt|request|messages?)\\b.{0,40}` + String.raw`\\b(?:exceed(?:s|ed)?|overflows?|is\\s+larger\\s+than)\\b.{0,40}` + String.raw`\\b(?:the\\s+)?(?:model(?:'s)?\\s+)?context(?:\\s+(?:length|window))?\\b`, \"i\");\n//#endregion\n//#region packages/util/values/src/index.ts\n/**\n* Mark an unreachable closed-union branch.\n* @param value - impossible value; an unhandled typed variant fails at the call site.\n* @param context - optional switch-site label included in the failure message.\n* @returns never; a runtime value that escaped its type always throws.\n*/\nfunction assertNever(value, context) {\n\tconst rendered = JSON.stringify(value) ?? String(value);\n\tthrow new Error(`unreachable variant${context ? ` in ${context}` : \"\"}: ${rendered}`);\n}\n/** Whether a realm-owned intrinsic prototype has a native constructor matching this engine's representation. */\nfunction hasIntrinsicConstructor$1(prototype, name) {\n\tconst constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n\tif (typeof constructor !== \"function\") return false;\n\ttry {\n\t\treturn constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === Function.prototype.toString.call(name === \"Array\" ? Array : Object);\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype$1(value) {\n\treturn Object.getPrototypeOf(value) === null && hasIntrinsicConstructor$1(value, \"Object\");\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */\nfunction hasPlainArrayPrototype$1(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (!Array.isArray(prototype) || !hasIntrinsicConstructor$1(prototype, \"Array\")) return false;\n\tconst objectPrototype = Object.getPrototypeOf(prototype);\n\treturn typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype$1(objectPrototype);\n}\n/** Whether an object is a plain or null-prototype record from any JavaScript realm. */\nfunction hasPlainObjectPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype$1(prototype);\n}\n/** Return every JSON-visible object key, or reject own data JSON would discard. */\nfunction enumerableStringKeys(value) {\n\tconst keys = Reflect.ownKeys(value);\n\tif (keys.some((key) => typeof key !== \"string\" || !Object.prototype.propertyIsEnumerable.call(value, key))) return void 0;\n\treturn keys;\n}\n/** Validate lossless JSON iteratively, optionally materializing a detached snapshot. */\nfunction walkJsonValue(value, detach) {\n\tconst ancestors = /* @__PURE__ */ new Set();\n\tlet root;\n\tconst assign = (destination, item) => {\n\t\tif (destination === void 0) return;\n\t\tif (destination.kind === \"root\") root = item;\n\t\telse if (destination.kind === \"array\") destination.target[destination.index] = item;\n\t\telse Object.defineProperty(destination.target, destination.key, {\n\t\t\tvalue: item,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t\twritable: true\n\t\t});\n\t};\n\tconst tasks = [{\n\t\tkind: \"visit\",\n\t\tvalue,\n\t\t...detach ? { destination: { kind: \"root\" } } : {}\n\t}];\n\tfor (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n\t\tif (task.kind === \"leave\") {\n\t\t\tancestors.delete(task.source);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"array-item\") {\n\t\t\tif (!Object.prototype.hasOwnProperty.call(task.source, task.index)) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.index],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"array\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tindex: task.index\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"object-property\") {\n\t\t\ttasks.push({\n\t\t\t\tkind: \"visit\",\n\t\t\t\tvalue: task.source[task.key],\n\t\t\t\t...task.target === void 0 ? {} : { destination: {\n\t\t\t\t\tkind: \"object\",\n\t\t\t\t\ttarget: task.target,\n\t\t\t\t\tkey: task.key\n\t\t\t\t} }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst current = task.value;\n\t\tif (current === null) {\n\t\t\tassign(task.destination, null);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"boolean\" || typeof current === \"string\") {\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current === \"number\") {\n\t\t\tif (!Number.isFinite(current) || Object.is(current, -0)) return void 0;\n\t\t\tassign(task.destination, current);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof current !== \"object\") return void 0;\n\t\tif (ancestors.has(current)) return void 0;\n\t\tif (Array.isArray(current)) {\n\t\t\tif (!hasPlainArrayPrototype$1(current)) return void 0;\n\t\t\tconst length = current.length;\n\t\t\tif (Reflect.ownKeys(current).length !== length + 1) return void 0;\n\t\t\tconst target = detach ? [] : void 0;\n\t\t\tif (target !== void 0) assign(task.destination, target);\n\t\t\tancestors.add(current);\n\t\t\ttasks.push({\n\t\t\t\tkind: \"leave\",\n\t\t\t\tsource: current\n\t\t\t});\n\t\t\tfor (let index = length - 1; index >= 0; index--) tasks.push({\n\t\t\t\tkind: \"array-item\",\n\t\t\t\tsource: current,\n\t\t\t\tindex,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasPlainObjectPrototype(current)) return void 0;\n\t\tconst keys = enumerableStringKeys(current);\n\t\tif (keys === void 0) return void 0;\n\t\tconst target = detach ? {} : void 0;\n\t\tif (target !== void 0) assign(task.destination, target);\n\t\tancestors.add(current);\n\t\ttasks.push({\n\t\t\tkind: \"leave\",\n\t\t\tsource: current\n\t\t});\n\t\tfor (let index = keys.length - 1; index >= 0; index--) {\n\t\t\tconst key = keys[index];\n\t\t\t/* v8 ignore next -- the loop is bounded by the captured key count. */\n\t\t\tif (key === void 0) return void 0;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"object-property\",\n\t\t\t\tsource: current,\n\t\t\t\tkey,\n\t\t\t\t...target === void 0 ? {} : { target }\n\t\t\t});\n\t\t}\n\t}\n\treturn detach ? root : true;\n}\n/**\n* Test the same lossless JSON rules as {@link snapshotJsonValue} without detaching the value.\n* @param value - candidate value to test.\n* @returns whether the value survives a JSON round trip without loss.\n*/\nfunction isJsonValue(value) {\n\treturn walkJsonValue(value, false) === true;\n}\n//#endregion\n//#region packages/core/tools/src/json-schema.ts\n/**\n* Enforced JSON Schema subset shared by tool outputs, generated PTC mode\n* types, subagents, and workflows. The subset accepts any JSON root, an\n* annotation-only schema for unconstrained JSON, one scalar `type`, object\n* `properties`/`required`/boolean `additionalProperties`, array `items`,\n* type-correct scalar `enum`/`const`, and exact-one `oneOf`.\n*\n* Unsupported or misplaced keywords reject rather than being accepted without\n* enforcement. Consumers that require an object root apply\n* {@link assertObjectJsonSchema} before accepting input.\n* @module dsh-tools/json-schema\n*/\n/**\n* Thrown when a raw schema falls outside the enforced subset. `violations`\n* lists every offending path instead of stopping at the first author error.\n*/\nvar JsonSchemaError = class extends HarnessError {\n\t/** Individual schema violations in walk order. */\n\tviolations;\n\tconstructor(violations) {\n\t\tsuper(`unsupported JSON schema: ${violations.join(\"; \")}`, \"UNSUPPORTED_SCHEMA\");\n\t\tthis.name = \"JsonSchemaError\";\n\t\tthis.violations = violations;\n\t}\n};\nconst CONSTRAINT_KEYWORDS = new Set([\n\t\"type\",\n\t\"oneOf\",\n\t\"properties\",\n\t\"required\",\n\t\"additionalProperties\",\n\t\"items\",\n\t\"enum\",\n\t\"const\"\n]);\nconst ANNOTATION_KEYWORDS = new Set([\n\t\"description\",\n\t\"title\",\n\t\"default\",\n\t\"examples\"\n]);\nconst SCHEMA_TYPES = [\n\t\"object\",\n\t\"array\",\n\t\"string\",\n\t\"number\",\n\t\"integer\",\n\t\"boolean\",\n\t\"null\"\n];\n/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */\nfunction hasIntrinsicConstructor(prototype, name) {\n\tconst constructor = Object.getOwnPropertyDescriptor(prototype, \"constructor\")?.value;\n\tif (typeof constructor !== \"function\") return false;\n\ttry {\n\t\treturn constructor.name === name && constructor.prototype === prototype && Function.prototype.toString.call(constructor) === `function ${name}() { [native code] }`;\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether a candidate is one realm's intrinsic `Object.prototype`. */\nfunction isIntrinsicObjectPrototype(value) {\n\treturn Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, \"Object\");\n}\n/**\n* Test for a realm-agnostic plain JSON record without accepting arrays or\n* exotic objects.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the value has a plain-object prototype chain.\n*/\nfunction isPlainJsonRecord(value) {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n\ttry {\n\t\tconst prototype = Object.getPrototypeOf(value);\n\t\treturn prototype === null || typeof prototype === \"object\" && isIntrinsicObjectPrototype(prototype);\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Whether an array uses one realm's intrinsic `Array.prototype`. */\nfunction hasPlainArrayPrototype(value) {\n\tconst prototype = Object.getPrototypeOf(value);\n\tif (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, \"Array\")) return false;\n\tconst objectPrototype = Object.getPrototypeOf(prototype);\n\treturn typeof objectPrototype === \"object\" && objectPrototype !== null && isIntrinsicObjectPrototype(objectPrototype);\n}\n/** Return whether a record contains only own enumerable string keys. */\nfunction hasOnlyEnumerableStringKeys(value) {\n\ttry {\n\t\treturn Reflect.ownKeys(value).every((key) => typeof key === \"string\" && Object.prototype.propertyIsEnumerable.call(value, key));\n\t} catch {\n\t\treturn false;\n\t}\n}\n/**\n* Test for an ordinary schema record whose keys survive JSON projection.\n* @param value - candidate record from any JavaScript realm.\n* @returns Whether the record has an intrinsic prototype and only own enumerable string keys.\n*/\nfunction isJsonSchemaRecord(value) {\n\treturn isPlainJsonRecord(value) && hasOnlyEnumerableStringKeys(value);\n}\n/**\n* Test for a dense ordinary array with no JSON-invisible decorations.\n* @param value - candidate array from any JavaScript realm.\n* @returns Whether the array is intrinsic, dense, and undecorated.\n*/\nfunction isPlainJsonArray(value) {\n\tif (!Array.isArray(value)) return false;\n\ttry {\n\t\tif (!hasPlainArrayPrototype(value) || Reflect.ownKeys(value).length !== value.length + 1) return false;\n\t\tfor (let index = 0; index < value.length; index++) if (!Object.hasOwn(value, index)) return false;\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n/** Lossless finite JSON number, excluding negative zero. */\nfunction isJsonNumber(value) {\n\treturn typeof value === \"number\" && Number.isFinite(value) && !Object.is(value, -0);\n}\n/** Whether a scalar is valid for one declared schema type. */\nfunction scalarMatches(type, value) {\n\tswitch (type) {\n\t\tcase \"string\": return typeof value === \"string\";\n\t\tcase \"number\": return isJsonNumber(value);\n\t\tcase \"integer\": return isJsonNumber(value) && Number.isInteger(value);\n\t\tcase \"boolean\": return typeof value === \"boolean\";\n\t\tcase \"null\": return value === null;\n\t\t/* v8 ignore next -- JsonSchemaScalarType is closed; this retains compile-time exhaustiveness. */\n\t\tdefault: return assertNever(type, \"JsonSchemaType\");\n\t}\n}\n/** Keywords that are invalid beside `oneOf`. */\nconst ONE_OF_SIBLING_KEYWORDS = [\n\t\"properties\",\n\t\"required\",\n\t\"additionalProperties\",\n\t\"items\",\n\t\"enum\",\n\t\"const\"\n];\n/** Validate object-only fields after its property schemas have been visited. */\nfunction checkObjectSchemaTail(node, path, properties, violations) {\n\tconst hasRequired = Object.hasOwn(node, \"required\");\n\tconst required = hasRequired ? node.required : void 0;\n\tif (hasRequired) if (!isPlainJsonArray(required) || required.some((entry) => typeof entry !== \"string\")) violations.push(`${path}.required must be an array of strings`);\n\telse {\n\t\tconst declared = isJsonSchemaRecord(properties) ? properties : {};\n\t\tfor (const key of required) if (!Object.hasOwn(declared, key)) violations.push(`${path}.required names \"${key}\" which is not in properties`);\n\t}\n\tif (Object.hasOwn(node, \"additionalProperties\") && typeof node.additionalProperties !== \"boolean\") violations.push(`${path}.additionalProperties must be a boolean`);\n}\n/** Collect every violation for one raw schema tree without using the JavaScript call stack. */\nfunction checkSchemaNode(root, rootPath, violations, seen) {\n\tconst tasks = [{\n\t\tkind: \"enter\",\n\t\tnode: root,\n\t\tpath: rootPath\n\t}];\n\tfor (let task = tasks.pop(); task !== void 0; task = tasks.pop()) {\n\t\tif (task.kind === \"leave\") {\n\t\t\tseen.delete(task.node);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"one-of-tail\") {\n\t\t\tfor (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(task.node, key)) violations.push(`${task.path}.${key} is not supported beside oneOf`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (task.kind === \"object-tail\") {\n\t\t\tcheckObjectSchemaTail(task.node, task.path, task.properties, violations);\n\t\t\tcontinue;\n\t\t}\n\t\tconst { node, path } = task;\n\t\tif (!isJsonSchemaRecord(node)) {\n\t\t\tviolations.push(`${path} must be a schema object`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (seen.has(node)) {\n\t\t\tviolations.push(`${path} is circular`);\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(node);\n\t\ttasks.push({\n\t\t\tkind: \"leave\",\n\t\t\tnode\n\t\t});\n\t\tfor (const key of Object.keys(node)) {\n\t\t\tif (CONSTRAINT_KEYWORDS.has(key)) continue;\n\t\t\tif (ANNOTATION_KEYWORDS.has(key)) {\n\t\t\t\ttry {\n\t\t\t\t\tif (!isJsonValue(node[key])) violations.push(`${path}.${key} annotation must be lossless JSON data`);\n\t\t\t\t} catch {\n\t\t\t\t\tviolations.push(`${path}.${key} annotation must be lossless JSON data`);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tviolations.push(`${path}.${key} is not a supported keyword (subset: type/oneOf/properties/required/additionalProperties/items/enum/const + annotations)`);\n\t\t}\n\t\tif (Object.hasOwn(node, \"description\") && typeof node.description !== \"string\") violations.push(`${path}.description must be a string`);\n\t\tif (Object.hasOwn(node, \"title\") && typeof node.title !== \"string\") violations.push(`${path}.title must be a string`);\n\t\tconst hasType = Object.hasOwn(node, \"type\");\n\t\tconst hasOneOf = Object.hasOwn(node, \"oneOf\");\n\t\tif (hasType && hasOneOf) {\n\t\t\tviolations.push(`${path} cannot declare both type and oneOf`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!hasType && !hasOneOf) {\n\t\t\tfor (const key of ONE_OF_SIBLING_KEYWORDS) if (Object.hasOwn(node, key)) violations.push(`${path}.${key} requires type or oneOf`);\n\t\t\tcontinue;\n\t\t}\n\t\tif (hasOneOf) {\n\t\t\tconst oneOf = node.oneOf;\n\t\t\ttasks.push({\n\t\t\t\tkind: \"one-of-tail\",\n\t\t\t\tnode,\n\t\t\t\tpath\n\t\t\t});\n\t\t\tif (!isPlainJsonArray(oneOf) || oneOf.length < 2) violations.push(`${path}.oneOf must be an array of at least two schemas`);\n\t\t\telse for (let index = oneOf.length - 1; index >= 0; index--) tasks.push({\n\t\t\t\tkind: \"enter\",\n\t\t\t\tnode: oneOf[index],\n\t\t\t\tpath: `${path}.oneOf[${index}]`\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst type = node.type;\n\t\tif (typeof type !== \"string\" || !SCHEMA_TYPES.includes(type)) {\n\t\t\tviolations.push(Array.isArray(type) ? `${path}.type must be a single type string (type arrays are not supported)` : `${path}.type must be one of ${SCHEMA_TYPES.join(\"/\")}`);\n\t\t\tcontinue;\n\t\t}\n\t\tconst schemaType = type;\n\t\tfor (const [key, types] of Object.entries({\n\t\t\tproperties: [\"object\"],\n\t\t\trequired: [\"object\"],\n\t\t\tadditionalProperties: [\"object\"],\n\t\t\titems: [\"array\"],\n\t\t\tenum: [\n\t\t\t\t\"string\",\n\t\t\t\t\"number\",\n\t\t\t\t\"integer\",\n\t\t\t\t\"boolean\",\n\t\t\t\t\"null\"\n\t\t\t],\n\t\t\tconst: [\n\t\t\t\t\"string\",\n\t\t\t\t\"number\",\n\t\t\t\t\"integer\",\n\t\t\t\t\"boolean\",\n\t\t\t\t\"null\"\n\t\t\t]\n\t\t})) if (Object.hasOwn(node, key) && !types.includes(schemaType)) violations.push(`${path}.${key} is not supported on type \"${schemaType}\"`);\n\t\tswitch (schemaType) {\n\t\t\tcase \"object\": {\n\t\t\t\tconst properties = Object.hasOwn(node, \"properties\") ? node.properties : void 0;\n\t\t\t\ttasks.push({\n\t\t\t\t\tkind: \"object-tail\",\n\t\t\t\t\tnode,\n\t\t\t\t\tpath,\n\t\t\t\t\tproperties\n\t\t\t\t});\n\t\t\t\tif (Object.hasOwn(node, \"properties\")) if (!isJsonSchemaRecord(properties)) violations.push(`${path}.properties must be an object of schemas`);\n\t\t\t\telse {\n\t\t\t\t\tconst entries = Object.entries(properties);\n\t\t\t\t\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\t\t\t\t\tconst entry = entries[index];\n\t\t\t\t\t\t/* v8 ignore next -- the loop is bounded by the captured entry count. */\n\t\t\t\t\t\tif (entry === void 0) continue;\n\t\t\t\t\t\ttasks.push({\n\t\t\t\t\t\t\tkind: \"enter\",\n\t\t\t\t\t\t\tnode: entry[1],\n\t\t\t\t\t\t\tpath: `${path}.properties.${entry[0]}`\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"array\":\n\t\t\t\tif (Object.hasOwn(node, \"items\")) tasks.push({\n\t\t\t\t\tkind: \"enter\",\n\t\t\t\t\tnode: node.items,\n\t\t\t\t\tpath: `${path}.items`\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"string\":\n\t\t\tcase \"number\":\n\t\t\tcase \"integer\":\n\t\t\tcase \"boolean\":\n\t\t\tcase \"null\": {\n\t\t\t\tconst hasEnum = Object.hasOwn(node, \"enum\");\n\t\t\t\tconst allowed = hasEnum ? node.enum : void 0;\n\t\t\t\tconst enumValid = isPlainJsonArray(allowed) && allowed.length > 0 && allowed.every((entry) => scalarMatches(schemaType, entry));\n\t\t\t\tif (hasEnum && !enumValid) violations.push(`${path}.enum must be a non-empty array of ${schemaType} values`);\n\t\t\t\tconst hasConst = Object.hasOwn(node, \"const\");\n\t\t\t\tconst declaredConst = hasConst ? node.const : void 0;\n\t\t\t\tconst constValid = scalarMatches(schemaType, declaredConst);\n\t\t\t\tif (hasConst) {\n\t\t\t\t\tif (!constValid) violations.push(`${path}.const must be a ${schemaType} value`);\n\t\t\t\t\telse if (enumValid && !allowed.includes(declaredConst)) violations.push(`${path}.const must be one of ${path}.enum when both are declared`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/* v8 ignore next -- schemaType was narrowed from the closed SCHEMA_TYPES table above. */\n\t\t\tdefault: assertNever(schemaType, \"JsonSchemaType\");\n\t\t}\n\t}\n}\n/**\n* Assert the enforced subset plus the object-root constraint retained by\n* subagent and workflow structured outputs.\n* @param schema - untrusted caller-supplied schema.\n* @returns Assertion that the schema belongs to the supported subset and has an object root.\n*/\nfunction assertObjectJsonSchema(schema) {\n\tconst violations = [];\n\tcheckSchemaNode(schema, \"schema\", violations, /* @__PURE__ */ new Set());\n\tif (violations.length === 0 && (!isJsonSchemaRecord(schema) || !Object.hasOwn(schema, \"type\") || schema.type !== \"object\")) violations.push(\"schema.type must be \\\"object\\\" (structured output is object-rooted)\");\n\tif (violations.length > 0) throw new JsonSchemaError(violations);\n}\n//#endregion\n//#region packages/workflow/workflow/src/index.ts\n/**\n* Typed error for workflow-seam failures. Extends {@link HarnessError}, so the\n* `code` is machine-routable taxonomy. `fatal` drives the combinator\n* discipline: `parallel()`/`pipeline()` re-throw a fatal error (a typo'd\n* option or a tripped cap must kill the script loudly), and reserve the\n* per-item `null` for child-run failures and ordinary in-stage script errors.\n* Every {@link WorkflowErrorCode} is fatal; the flag exists so the\n* distinction is explicit at every catch site rather than implied.\n*/\nvar WorkflowError = class extends HarnessError {\n\t/** Whether combinators must propagate this error instead of nulling the item. */\n\tfatal;\n\tconstructor(message, code, options) {\n\t\tsuper(message, code, options);\n\t\tthis.name = \"WorkflowError\";\n\t\tthis.fatal = options?.fatal ?? true;\n\t}\n};\n/**\n* Whether combinators must re-throw `error` instead of mapping the item to `null`.\n* @param error - any thrown value; fatality is host `instanceof` (unforgeable from a script realm).\n* @returns true iff `error` is a {@link WorkflowError} whose `fatal` flag is set.\n*/\nfunction isFatalWorkflowError(error) {\n\treturn error instanceof WorkflowError && error.fatal;\n}\n//#endregion\n//#region packages/workflow/workflow-ptc/src/runtime.ts\n/**\n* Workflow VM hooks, child callbacks, ordinary concurrency limits and result serialization.\n* PTC owns process confinement and cancellation. Fatal hook and provider failures propagate\n* through combinators; ordinary child failures and stage errors become per-item nulls.\n* @module @deepseek-ai/dsh-workflow-ptc/runtime\n*/\n/** The `agent()` options the script may pass; everything else rejects loud. */\nconst SUPPORTED_AGENT_OPTIONS = new Set([\n\t\"label\",\n\t\"phase\",\n\t\"schema\",\n\t\"provider\",\n\t\"model\"\n]);\n/** Deferred Claude Code options we name explicitly in the rejection message. */\nconst DEFERRED_AGENT_OPTIONS = new Set([\n\t\"effort\",\n\t\"isolation\",\n\t\"agentType\"\n]);\n/** Flatten a child's final output blocks to text (the non-schema `agent()` result). */\nfunction outputText(blocks) {\n\treturn blocks.filter((block) => block.type === \"text\").map((block) => block.text).join(\"\");\n}\n/** A short display label derived from the prompt when the script passes none. */\nfunction defaultLabel(prompt) {\n\tconst newline = prompt.indexOf(\"\\n\");\n\tconst line = newline === -1 ? prompt : prompt.slice(0, newline);\n\treturn line.length <= 48 ? line : `${line.slice(0, 47)}\u2026`;\n}\n/**\n* One script execution inside the confined Node process. The host owns\n* cancellation and cleanup of any dropped child work.\n*/\nvar WorkflowExecution = class {\n\tlimits;\n\tobserver;\n\tchildren;\n\t/** 1-based count of `agent()` calls started (the `agentsStarted` result field). */\n\tstarted = 0;\n\tactiveSlots = 0;\n\tslotWaiters = [];\n\tcurrentPhase;\n\tcontext;\n\tcompiled;\n\tconstructor(meta, body, args, limits, observer, children) {\n\t\tthis.limits = limits;\n\t\tthis.observer = observer;\n\t\tthis.children = children;\n\t\ttry {\n\t\t\tthis.compiled = new vm.Script(`(async () => {\\n${body}\\n})()`, {\n\t\t\t\tfilename: `workflow:${meta.name}`,\n\t\t\t\tlineOffset: -1\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthrow new WorkflowError(`workflow script does not parse: ${String(error)}`, \"SCRIPT_PARSE\", { cause: error });\n\t\t}\n\t\tthis.context = vm.createContext({}, { name: `workflow:${meta.name}` });\n\t\tconst globals = {\n\t\t\tagent: (prompt, opts) => this.contain(this.agent(prompt, opts)),\n\t\t\tparallel: (thunks) => this.contain(this.parallel(thunks)),\n\t\t\tpipeline: (items, ...stages) => this.contain(this.pipeline(items, stages)),\n\t\t\tphase: (title) => {\n\t\t\t\tthis.phase(title);\n\t\t\t},\n\t\t\tlog: (message) => {\n\t\t\t\tthis.log(message);\n\t\t\t},\n\t\t\targs\n\t\t};\n\t\tfor (const [key, value] of Object.entries(globals)) this.context[key] = typeof value === \"function\" ? Object.freeze(value) : value;\n\t}\n\t/**\n\t* Run the script and materialize its JSON return value.\n\t* @returns A completed or error result; script failures never reject.\n\t*/\n\tasync drive() {\n\t\ttry {\n\t\t\tconst scriptPromise = this.compiled.runInContext(this.context, { timeout: this.limits.syncTimeoutMs });\n\t\t\tconst raw = await this.contain(Promise.resolve(scriptPromise));\n\t\t\treturn {\n\t\t\t\tvalue: raw === void 0 ? null : this.materializeResult(raw),\n\t\t\t\tstopReason: \"completed\",\n\t\t\t\tagentsStarted: this.started\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tvalue: null,\n\t\t\t\tstopReason: \"error\",\n\t\t\t\terror: renderThrown(error),\n\t\t\t\tagentsStarted: this.started\n\t\t\t};\n\t\t}\n\t}\n\t/**\n\t* Attach a no-op rejection consumer WITHOUT changing what the caller\n\t* receives: if the script drops the promise, a host rejection cannot become\n\t* an unhandled rejection that kills the process; if\n\t* the script does await it, it still observes the rejection.\n\t*/\n\tcontain(promise) {\n\t\tpromise.catch(() => {});\n\t\treturn promise;\n\t}\n\t/** Materialize the script's return value; violations become RESULT_UNSERIALIZABLE. */\n\tmaterializeResult(raw) {\n\t\ttry {\n\t\t\treturn materializeFromRealm(raw, \"workflow result\");\n\t\t} catch (error) {\n\t\t\t/* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n\t\t\tif (!(error instanceof MaterializeError)) throw error;\n\t\t\tthrow new WorkflowError(`the workflow's return value is not plain JSON data \u2014 ${error.message}. Return only JSON-serializable objects/arrays/scalars.`, \"RESULT_UNSERIALIZABLE\", { cause: error });\n\t\t}\n\t}\n\t/** Acquire one concurrency slot in FIFO order. */\n\tacquireSlot() {\n\t\tif (this.activeSlots < this.limits.maxConcurrentAgents) {\n\t\t\tthis.activeSlots += 1;\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\treturn new Promise((resolve) => {\n\t\t\tthis.slotWaiters.push(() => {\n\t\t\t\tthis.activeSlots += 1;\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\treleaseSlot() {\n\t\tthis.activeSlots -= 1;\n\t\tconst next = this.slotWaiters.shift();\n\t\tif (next) next();\n\t}\n\t/** The `agent(prompt, opts)` hook. */\n\tasync agent(rawPrompt, rawOpts) {\n\t\tif (typeof rawPrompt !== \"string\" || rawPrompt.length === 0) throw new WorkflowError(\"agent() requires a non-empty prompt string\", \"INVALID_ARGUMENT\");\n\t\tconst opts = this.readAgentOptions(rawOpts);\n\t\tif (this.started >= this.limits.maxTotalAgents) throw new WorkflowError(`this run reached its total agent cap (${this.limits.maxTotalAgents}) \u2014 a runaway-loop backstop; raise the applicable maxTotalAgents limit if the scale is intentional`, \"AGENT_CAP\");\n\t\tthis.started += 1;\n\t\tconst seq = this.started;\n\t\tconst label = opts.label ?? defaultLabel(rawPrompt);\n\t\tconst phase = opts.phase ?? this.currentPhase;\n\t\tawait this.acquireSlot();\n\t\ttry {\n\t\t\tlet run;\n\t\t\ttry {\n\t\t\t\trun = await this.children.startAgent({\n\t\t\t\t\tprompt: rawPrompt,\n\t\t\t\t\t...opts.schema !== void 0 ? { schema: opts.schema } : {},\n\t\t\t\t\t...opts.provider !== void 0 ? { provider: opts.provider } : {},\n\t\t\t\t\t...opts.model !== void 0 ? { model: opts.model } : {}\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tthrow new WorkflowError(`agent() could not start a child: ${renderThrown(error)}`, \"AGENT_START\", { cause: error });\n\t\t\t}\n\t\t\tconst info = {\n\t\t\t\tseq,\n\t\t\t\tlabel,\n\t\t\t\t...phase !== void 0 ? { phase } : {},\n\t\t\t\tchildId: brandString(run.id)\n\t\t\t};\n\t\t\tthis.observer.agentStart(info);\n\t\t\ttry {\n\t\t\t\tlet result;\n\t\t\t\ttry {\n\t\t\t\t\tresult = await run.result;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t...info,\n\t\t\t\t\t\toutcome: \"failed\"\n\t\t\t\t\t});\n\t\t\t\t\tthrow new WorkflowError(`child agent run failed: ${renderThrown(error)}`, \"AGENT_RESULT\", { cause: error });\n\t\t\t\t}\n\t\t\t\tif (result.stopReason === \"completed\") {\n\t\t\t\t\tif (opts.schema !== void 0) {\n\t\t\t\t\t\tif (result.structured === void 0) {\n\t\t\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\t\toutcome: \"failed\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\toutcome: \"completed\"\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn result.structured;\n\t\t\t\t\t}\n\t\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t\t...info,\n\t\t\t\t\t\toutcome: \"completed\"\n\t\t\t\t\t});\n\t\t\t\t\treturn outputText(result.output);\n\t\t\t\t}\n\t\t\t\tthis.observer.agentEnd({\n\t\t\t\t\t...info,\n\t\t\t\t\toutcome: \"failed\"\n\t\t\t\t});\n\t\t\t\treturn null;\n\t\t\t} finally {\n\t\t\t\tawait run.dispose();\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.releaseSlot();\n\t\t}\n\t}\n\t/** Materialize + validate the `agent()` options bag from the realm. */\n\treadAgentOptions(rawOpts) {\n\t\tif (rawOpts === void 0) return {};\n\t\tlet opts;\n\t\ttry {\n\t\t\topts = materializeFromRealm(rawOpts, \"agent() options\");\n\t\t} catch (error) {\n\t\t\t/* v8 ignore next -- defensive rethrow arm: materializeFromRealm only throws MaterializeError */\n\t\t\tif (!(error instanceof MaterializeError)) throw error;\n\t\t\tthrow new WorkflowError(`agent() options must be plain JSON data \u2014 ${error.message}`, \"INVALID_ARGUMENT\", { cause: error });\n\t\t}\n\t\tif (typeof opts !== \"object\" || opts === null || Array.isArray(opts)) throw new WorkflowError(\"agent() options must be an object\", \"INVALID_ARGUMENT\");\n\t\tconst record = opts;\n\t\tfor (const key of Object.keys(record)) {\n\t\t\tif (SUPPORTED_AGENT_OPTIONS.has(key)) continue;\n\t\t\tif (DEFERRED_AGENT_OPTIONS.has(key)) throw new WorkflowError(`agent() option \"${key}\" is deferred and not supported by this engine (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n\t\t\tthrow new WorkflowError(`agent() option \"${key}\" is not recognized (supported: label, phase, schema, provider, model)`, \"UNSUPPORTED_OPTION\");\n\t\t}\n\t\tfor (const key of [\n\t\t\t\"label\",\n\t\t\t\"phase\",\n\t\t\t\"provider\",\n\t\t\t\"model\"\n\t\t]) if (record[key] !== void 0 && typeof record[key] !== \"string\") throw new WorkflowError(`agent() option \"${key}\" must be a string`, \"INVALID_ARGUMENT\");\n\t\tlet schema;\n\t\tif (record.schema !== void 0) try {\n\t\t\tassertObjectJsonSchema(record.schema);\n\t\t\tschema = record.schema;\n\t\t} catch (error) {\n\t\t\t/* v8 ignore next -- defensive rethrow arm: assertObjectJsonSchema only throws JsonSchemaError */\n\t\t\tif (!(error instanceof JsonSchemaError)) throw error;\n\t\t\tthrow new WorkflowError(`agent() schema is outside the supported subset \u2014 ${error.message}`, \"UNSUPPORTED_SCHEMA\", { cause: error });\n\t\t}\n\t\treturn {\n\t\t\t...record.label !== void 0 ? { label: record.label } : {},\n\t\t\t...record.phase !== void 0 ? { phase: record.phase } : {},\n\t\t\t...record.provider !== void 0 ? { provider: record.provider } : {},\n\t\t\t...record.model !== void 0 ? { model: record.model } : {},\n\t\t\t...schema !== void 0 ? { schema } : {}\n\t\t};\n\t}\n\t/** The `parallel(thunks)` hook: each thunk caught \u2192 `null`; fatal errors propagate. */\n\tasync parallel(rawThunks) {\n\t\tif (!Array.isArray(rawThunks)) throw new WorkflowError(\"parallel() requires an array of zero-argument functions\", \"INVALID_ARGUMENT\");\n\t\tthis.assertItemCap(rawThunks.length, \"parallel()\");\n\t\tconst thunks = rawThunks.map((thunk, index) => {\n\t\t\tif (typeof thunk !== \"function\") throw new WorkflowError(`parallel() item ${index} is not a function`, \"INVALID_ARGUMENT\");\n\t\t\treturn thunk;\n\t\t});\n\t\treturn Promise.all(thunks.map(async (thunk) => {\n\t\t\ttry {\n\t\t\t\treturn await thunk();\n\t\t\t} catch (error) {\n\t\t\t\tif (isFatalWorkflowError(error)) throw error;\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}));\n\t}\n\t/** The `pipeline(items, ...stages)` hook: per-item stage chains, NO cross-stage barrier. */\n\tasync pipeline(rawItems, rawStages) {\n\t\tif (!Array.isArray(rawItems)) throw new WorkflowError(\"pipeline() requires an items array\", \"INVALID_ARGUMENT\");\n\t\tthis.assertItemCap(rawItems.length, \"pipeline()\");\n\t\tif (rawStages.length === 0) throw new WorkflowError(\"pipeline() requires at least one stage function\", \"INVALID_ARGUMENT\");\n\t\tconst stages = rawStages.map((stage, index) => {\n\t\t\tif (typeof stage !== \"function\") throw new WorkflowError(`pipeline() stage ${index} is not a function`, \"INVALID_ARGUMENT\");\n\t\t\treturn stage;\n\t\t});\n\t\treturn Promise.all(rawItems.map(async (item, index) => {\n\t\t\tlet value = item;\n\t\t\ttry {\n\t\t\t\tfor (const stage of stages) value = await stage(value, item, index);\n\t\t\t\treturn value;\n\t\t\t} catch (error) {\n\t\t\t\tif (isFatalWorkflowError(error)) throw error;\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}));\n\t}\n\tassertItemCap(length, hook) {\n\t\tif (length > this.limits.maxItemsPerCall) throw new WorkflowError(`${hook} received ${length} items \u2014 over the per-call cap (${this.limits.maxItemsPerCall}); split the work or raise maxItemsPerCall in the engine config`, \"ITEM_CAP\");\n\t}\n\t/** The `phase(title)` hook: sets the current label for subsequent `agent()` calls and notifies observers. */\n\tphase(title) {\n\t\tif (typeof title !== \"string\" || title.length === 0) throw new WorkflowError(\"phase() requires a non-empty title string\", \"INVALID_ARGUMENT\");\n\t\tthis.currentPhase = title;\n\t\tthis.observer.phase(title);\n\t}\n\t/** The `log(message)` hook: narration to observers. */\n\tlog(message) {\n\t\tif (typeof message !== \"string\") throw new WorkflowError(\"log() requires a message string\", \"INVALID_ARGUMENT\");\n\t\tthis.observer.log(message);\n\t}\n};\n//#endregion\n//#region packages/workflow/workflow-ptc/src/guest.ts\n/**\n* Run a workflow with one progress batch in flight. Drain progress before child\n* disposal and the terminal result; PTC and the host own cancellation and cleanup.\n* @param host - JSON callbacks owned by this workflow run.\n* @returns The script result after progress delivery; initialization failures reject.\n*/\nasync function runWorkflowGuest(host) {\n\tconst init = await host.begin({});\n\tlet queued = [];\n\tlet inFlight;\n\tlet progressError;\n\tconst flush = () => {\n\t\tif (inFlight !== void 0 || queued.length === 0) return;\n\t\tconst batch = queued;\n\t\tqueued = [];\n\t\tinFlight = host.progress(batch).then(() => {\n\t\t\tinFlight = void 0;\n\t\t\tflush();\n\t\t}, (error) => {\n\t\t\tprogressError = renderThrown(error);\n\t\t\tqueued = [];\n\t\t\tinFlight = void 0;\n\t\t});\n\t};\n\tconst send = (event) => {\n\t\tif (progressError !== void 0) return;\n\t\tqueued.push(event);\n\t\tflush();\n\t};\n\tconst drain = async () => {\n\t\twhile (inFlight !== void 0) await inFlight;\n\t};\n\tconst result = await new WorkflowExecution(init.meta, init.body, init.args, init.limits, {\n\t\tphase: (title) => {\n\t\t\tsend({\n\t\t\t\ttype: \"phase\",\n\t\t\t\ttitle\n\t\t\t});\n\t\t},\n\t\tlog: (message) => {\n\t\t\tsend({\n\t\t\t\ttype: \"log\",\n\t\t\t\tmessage\n\t\t\t});\n\t\t},\n\t\tagentStart: (info) => {\n\t\t\tsend({\n\t\t\t\ttype: \"agent-start\",\n\t\t\t\tinfo\n\t\t\t});\n\t\t},\n\t\tagentEnd: (info) => {\n\t\t\tsend({\n\t\t\t\ttype: \"agent-end\",\n\t\t\t\tinfo\n\t\t\t});\n\t\t}\n\t}, { async startAgent(request) {\n\t\tconst { callId, childId } = await host.startChild(request);\n\t\tconst result = host.childResult({ callId });\n\t\tresult.catch(() => {});\n\t\treturn {\n\t\t\tid: childId,\n\t\t\tresult,\n\t\t\tasync dispose() {\n\t\t\t\tawait drain();\n\t\t\t\tawait host.disposeChild({ callId });\n\t\t\t}\n\t\t};\n\t} }).drive();\n\tawait drain();\n\treturn progressError === void 0 ? result : {\n\t\tvalue: null,\n\t\tstopReason: \"error\",\n\t\terror: progressError,\n\t\tagentsStarted: result.agentsStarted\n\t};\n}\n//#endregion\nexport { runWorkflowGuest };\n//# sourceURL=dsh-workflow-guest.js\n";
|
|
4
4
|
//# sourceMappingURL=guest-source.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-workflow-ptc",
|
|
3
3
|
"description": "Workflow orchestration in the shared sandboxed Node PTC runtime",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-rc.1",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -28,45 +28,45 @@
|
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@deepseek-ai/cordis": "~4.0.4",
|
|
31
|
-
"@deepseek-ai/dsh-
|
|
32
|
-
"@deepseek-ai/dsh-
|
|
33
|
-
"@deepseek-ai/dsh-
|
|
34
|
-
"@deepseek-ai/dsh-
|
|
35
|
-
"@deepseek-ai/dsh-
|
|
36
|
-
"@deepseek-ai/dsh-
|
|
37
|
-
"@deepseek-ai/dsh-
|
|
38
|
-
"@deepseek-ai/dsh-
|
|
39
|
-
"@deepseek-ai/dsh-
|
|
31
|
+
"@deepseek-ai/dsh-agent": "0.2.0-rc.1",
|
|
32
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.1",
|
|
33
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.1",
|
|
34
|
+
"@deepseek-ai/dsh-subagent": "0.2.0-rc.1",
|
|
35
|
+
"@deepseek-ai/dsh-workflow": "0.2.0-rc.1",
|
|
36
|
+
"@deepseek-ai/dsh-ptc-runtime": "0.2.0-rc.1",
|
|
37
|
+
"@deepseek-ai/dsh-sandbox": "0.2.0-rc.1",
|
|
38
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.1",
|
|
39
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.1"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@deepseek-ai/dsh-brand": "0.
|
|
43
|
-
"@deepseek-ai/dsh-util-values": "0.
|
|
42
|
+
"@deepseek-ai/dsh-brand": "0.2.0-rc.1",
|
|
43
|
+
"@deepseek-ai/dsh-util-values": "0.2.0-rc.1",
|
|
44
44
|
"@deepseek-ai/schemastery": "~3.18.4"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@deepseek-ai/cordis": "~4.0.4",
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-
|
|
50
|
-
"@deepseek-ai/dsh-agent-loop": "0.
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
52
|
-
"@deepseek-ai/dsh-
|
|
53
|
-
"@deepseek-ai/dsh-
|
|
54
|
-
"@deepseek-ai/dsh-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-sandbox": "0.
|
|
63
|
-
"@deepseek-ai/dsh-ptc-runtime": "0.
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"@deepseek-ai/dsh-
|
|
66
|
-
"@deepseek-ai/dsh-sandbox-
|
|
67
|
-
"@deepseek-ai/dsh-
|
|
68
|
-
"@deepseek-ai/dsh-
|
|
69
|
-
"@deepseek-ai/dsh-
|
|
70
|
-
"@deepseek-ai/dsh-
|
|
48
|
+
"@deepseek-ai/dsh-llm-deepseek-api-key": "0.2.0-rc.1",
|
|
49
|
+
"@deepseek-ai/dsh-agent": "0.2.0-rc.1",
|
|
50
|
+
"@deepseek-ai/dsh-agent-loop": "0.2.0-rc.1",
|
|
51
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.1",
|
|
52
|
+
"@deepseek-ai/dsh-session-projection": "0.2.0-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-subagent": "0.2.0-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-subagent-spawn-in-process": "0.2.0-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.0-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.0-rc.1",
|
|
58
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.1",
|
|
59
|
+
"@deepseek-ai/dsh-http-proxy": "0.2.0-rc.1",
|
|
60
|
+
"@deepseek-ai/dsh-ptc-runtime": "0.2.0-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-sandbox": "0.2.0-rc.1",
|
|
62
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.0-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-ptc-runtime-node": "0.2.0-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-subprocess": "0.2.0-rc.1",
|
|
65
|
+
"@deepseek-ai/dsh-subprocess-local": "0.2.0-rc.1",
|
|
66
|
+
"@deepseek-ai/dsh-sandbox-local": "0.2.0-rc.1",
|
|
67
|
+
"@deepseek-ai/dsh-invariants": "0.2.0-rc.1",
|
|
68
|
+
"@deepseek-ai/dsh-fs": "0.2.0-rc.1",
|
|
69
|
+
"@deepseek-ai/dsh-workflow": "0.2.0-rc.1",
|
|
70
|
+
"@deepseek-ai/dsh-fs-local": "0.2.0-rc.1"
|
|
71
71
|
}
|
|
72
72
|
}
|