@xneog/dsh-workflow-worker-thread 0.1.0 → 0.1.3-alpha.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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/workflow/workflow-worker-thread/README.md
5
- README.md: ba32c9dab4e870dd52c8f8acba3cfa627fa78000
6
- README.zh.md: 99107aec40a45c8460f10082f2b75b908e3e8692
5
+ README.md: 954682f166b7aa51f07d14dae3046bb40dbc52a6
6
+ README.zh.md: 2252616d4d58c3a543ead79246973037be498a8c
package/README.md CHANGED
@@ -1,90 +1,132 @@
1
+ ---
2
+ description: "The worker-thread workflow engine: executes model-written orchestration scripts off the host event loop, for users and maintainers choosing or configuring execution isolation."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @xneog/dsh-workflow-worker-thread
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- This package implements `WorkflowEngine` with one Node worker thread per run. The worker executes the orchestration script; child agents remain on the host and are reached through `ctx.subagents` over a typed host/worker protocol.
10
+ ## Summary
6
11
 
7
- The package root exports the default engine plugin and its `Config`; the worker protocol, runtime, and session modules stay private to the implementation. The operational `./worker` entry remains the engine's spawn target.
12
+ `dsh-workflow-worker-thread` implements the workflow engine with one Node worker thread per run: the orchestration script executes inside a fresh worker while its `agent()` calls reach host subagents over a typed host/worker protocol. A synchronous script loop cannot block the harness event loop, and a script that ignores cancellation can be terminated with its worker. The isolation is containment, not a security boundary — a model-written script has the same trust premise as the model's existing bash access, and escaping the `node:vm` context recovers the worker's process authority. Mount this engine to give `ctx.workflowEngine` a concrete implementation; a composition that loads it with `dsh-tool-workflow` gives the model the `workflow` tool.
8
13
 
9
- The split has one primary purpose: a synchronous script loop cannot block the harness event loop, and a script that ignores cancellation can be terminated with its worker. It is not a security sandbox.
14
+ ## Table of Contents
10
15
 
11
- ## Trust and isolation boundary
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
12
22
 
13
- Workflow scripts are model-written and have the same trust premise as the model's existing bash access. `node:vm` inside a worker is an API-shaping mechanism, not a security boundary: an escaped script can recover Node capabilities with the host process's privileges.
23
+ -----
14
24
 
15
- The worker still provides useful containment:
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
16
27
 
17
- - Script CPU work and synchronous spins stay off the host event loop.
18
- - `worker.terminate()` gives disposal a real final stop.
19
- - The worker starts with an empty environment, except unbuilt loader plumbing, so ambient credentials do not cross through `process.env`.
20
- - Host/worker messages use structured-clone data, with plain-JSON validation at the script boundary.
28
+ Mount this engine when a composition needs the workflow capability: each orchestration script runs in its own worker thread, off the host event loop, and the `workflow` and `ralph` tools in the shipped composition execute on it. Do not use it as a sandbox for genuinely untrusted scripts — hostile code needs a separate-process or container engine.
21
29
 
22
- A genuinely untrusted-script sandbox would require a different engine behind the same workflow seam.
30
+ ### Minimal configuration
23
31
 
24
- ## Script contract
32
+ Loading the engine registers `ctx.workflowEngine`; adding `dsh-tool-workflow` on top gives the model the `workflow` tool. Every config field is optional:
25
33
 
26
- The workflow's `meta` is host-provided data, not evaluated script text. The engine validates its required `name` and `description`, rejects unknown fields, and parse-checks the body before returning a run.
34
+ ```yaml
35
+ - name: '@xneog/dsh-workflow-worker-thread'
36
+ - name: '@xneog/dsh-tool-workflow'
37
+ ```
27
38
 
28
- Inside the worker, the script receives `args` and these hooks:
39
+ | Field | Default | Meaning |
40
+ |---|---|---|
41
+ | `provider` | `spawn` | Host-side subagent provider used by `agent()` calls. |
42
+ | `maxConcurrentAgents` | `0` | Concurrent `agent()` ceiling; `0` resolves from available CPU parallelism. |
43
+ | `maxTotalAgents` | `1000` | Total `agent()` calls one run may start — the runaway-loop backstop. |
44
+ | `maxItemsPerCall` | `4096` | Items accepted by one `parallel()` or `pipeline()` call. |
45
+ | `syncTimeoutMs` | `5000` | VM timeout for the script's initial synchronous slice, in milliseconds. |
46
+ | `disposeGraceMs` | `5000` | Bound before force-settlement and worker termination; also bounds `dispose()`. |
29
47
 
30
- - `agent(prompt, { label, phase, schema, model })` starts one host-side subagent. With a schema it returns the structured value; otherwise it returns final text. An ordinary failed child yields `null`.
31
- - `parallel(thunks)` runs thunks under the configured concurrency limit.
32
- - `pipeline(items, ...stages)` passes `(previous, item, index)` without a cross-stage barrier.
33
- - `phase(title)` and `log(message)` emit observer narration.
48
+ An owning consumer may set `WorkflowStartRequest.subagentProvider` and `WorkflowStartRequest.maxTotalAgents` for one run — engine-level policy, not script hooks; the ordinary `workflow` tool leaves both unset, and a per-run total-child cap may lower but never raise the configured ceiling. The generated [configuration catalog](../../../docs/config-catalog.md#xneogdsh-workflow-worker-thread) is the exhaustive source for every accepted field.
34
49
 
35
- Unknown options, malformed arguments, unsupported schemas, tripped caps, provider-start failures, and infrastructure result failures are fatal workflow errors. No timers, filesystem API, or Node globals are intentionally injected, though the trust caveat above still applies.
50
+ ### What a run gives you
36
51
 
37
- ## Run sequence
52
+ When a run starts, the script body executes in the worker with top-level `await` and the hooks `agent()`, `parallel()`, `pipeline()`, `phase()`, and `log()`; `meta` and `args` arrive as plain JSON data, never evaluated code. Every `agent()` call starts a host-side subagent under the configured provider, with the run's parent as the parent of every child. The run settles with the script's final JSON value; an ordinary child failure resolves `agent()` to `null` so the script can handle it.
38
53
 
39
- `start()` validates meta, parses the body, resolves a registered normalized provider route, and resolves any per-run total-child cap before creating a worker or publishing `workflow/start`. A requested `maxTotalAgents` must be a positive safe integer no greater than the engine's configured deployment ceiling. Source mode installs TypeScript transforms through a data-URL bootstrap; built mode passes sibling `lib/worker.cjs` as a filesystem path because pkg's VFS hook expects CommonJS. Both work under ordinary Node. A ready/go handshake prevents a start-signal cancellation racing worker boot from executing the script's initial synchronous slice.
54
+ A malformed meta block, a body that does not parse, an unavailable provider route, or a per-run cap above the ceiling is rejected synchronously before a worker exists, so the caller sees a violation list and can correct the call. During execution, hook misuse and tripped caps kill the script with a fatal workflow error. Cancellation is bounded: a script that ignores it is force-settled as cancelled and its worker terminated after `disposeGraceMs`.
40
55
 
41
- For each `agent()` call:
56
+ ### Trust expectations
42
57
 
43
- 1. The worker sends `child-start` with a plain-data prompt and options.
44
- 2. The host calls the start request's provider override, or otherwise the configured provider, through async `SubagentRuntime.start`, passing the workflow's parent and one canonical per-run abort signal. Provider choice applies to every child in that run and is not visible to the script.
45
- 3. If start rejects, the host sends `child-start-error`; provider startup has already reached quiescence and no child lifecycle event is emitted.
46
- 4. If start fulfills while the workflow still admits work, the host records the run, observes `result`, then sends `child-started`. Even an already-settled result is forwarded afterward, preserving start-before-result order.
47
- 5. The worker emits paired `workflow/agent-start` and `workflow/agent-end` narration and requests child disposal after collection.
58
+ Script CPU work and synchronous spins stay off the host event loop, `worker.terminate()` gives disposal a real final stop, and the worker starts with a scrubbed environment — only platform temp paths and, in source mode, `TSX_TSCONFIG_PATH` — so ambient credentials do not cross through `process.env`. Host/worker messages use structured-clone data with plain-JSON validation at the script boundary.
48
59
 
49
- Provider starts are tracked separately from published children. If cancellation, worker death, or normal workflow settlement closes admission while a start is pending, the shared signal aborts it. A provider that nevertheless fulfills after closure is disposed by the host and never announced to the worker.
60
+ None of this is a security boundary: no timers, filesystem API, or Node globals are intentionally injected, but escaped code can still reach Node with the worker's process authority.
50
61
 
51
- ## Value boundary
62
+ -----
52
63
 
53
- Values leaving the script pass through `materializeFromRealm`, which accepts plain, lossless JSON data and rejects exotic prototypes, functions, symbols, cycles, sparse arrays, non-finite numbers, and nested `undefined`. The walk runs in the worker, and defines object keys as data properties so `__proto__` cannot mutate a prototype.
64
+ <a id="understand-the-implementation"></a>
65
+ ## Understand the implementation
54
66
 
55
- Child results are projected and snapshotted before crossing from the host to the worker. This is a real process-like serialization boundary; it is deliberately different from trusted same-process workflow and subagent event payloads, which are borrowed immutable values.
67
+ <details>
68
+ <summary>Implementation internals — click to expand</summary>
56
69
 
57
- ## Cancellation and disposal
70
+ This section explains the engine's isolation design and run mechanics; observable behavior is fully covered in [Use this package](#use-this-package).
58
71
 
59
- `WorkflowRun.cancel()` records the first reason, tells the worker to cancel, aborts the one signal shared by every pending and published child, and arms the `disposeGraceMs` timer. Worker hooks then throw `CANCELLED` at their next await. If the run remains unsettled at the deadline, the host resolves it as cancelled, pairs stranded child lifecycle events, and terminates the worker.
72
+ ### Design concept
60
73
 
61
- The subagent seam has one cancellation channel: the request signal. There is no separate child-cancel RPC. Published child teardown uses `run.dispose()`; pending provider starts remain provider-owned until their promise rejects or fulfills.
74
+ One worker thread per run keeps a misbehaving script from stalling the host and makes force termination possible: the script runs in an escapable `node:vm` context inside the worker, and `agent()` calls cross a typed host/worker protocol back to `ctx.subagents`. The vm context shapes the script's API surface; it is not a security sandbox.
62
75
 
63
- Normal settlement also aborts pending starts and begins disposing any published fire-and-forget children before the result becomes externally settled. The host's quiescence condition includes both pending starts and published child disposals, so cleanup does not forget an async startup transaction.
76
+ ### Source map
64
77
 
65
- `dispose()` is idempotent. It cancels the run, starts host-driven disposal immediately, waits for result plus child quiescence up to the same grace, terminates the worker unconditionally, and performs a final survivor sweep. Per-child disposal is memoized so worker RPC, host cancellation, death cleanup, and public disposal all join one operation.
78
+ | File | Role |
79
+ |---|---|
80
+ | [`src/index.ts`](src/index.ts) | Plugin entry: `Config` schema, up-front validation, `start()` wiring |
81
+ | [`src/host.ts`](src/host.ts) | Host side of a run: worker spawn, child orchestration, settlement, disposal |
82
+ | [`src/worker.ts`](src/worker.ts) | Worker entry: script execution, hook implementation, value materialization |
83
+ | [`src/runtime.ts`](src/runtime.ts) | Script runtime: hook contracts, `parallel()` and `pipeline()` combinators |
84
+ | [`src/realm.ts`](src/realm.ts) | Cross-realm materialization: plain-JSON acceptance and rejection rules |
85
+ | [`src/protocol.ts`](src/protocol.ts) | Typed host/worker message protocol |
86
+ | [`src/meta.ts`](src/meta.ts) | `meta` shape validation and normalization |
87
+ | [`src/session.ts`](src/session.ts) | Child run projection and snapshotting before crossing to the worker |
88
+ | — | No runtime invariant companion is published; this process-boundary implementation exposes no same-process event relation; worker protocol and built-worker tests cover it. |
66
89
 
67
- ## Outcome and event guarantees
90
+ ### Run sequence
68
91
 
69
- Terminal outcome is first-wins at host claim points. An accepted external cancellation overrides a later non-cancelled worker result; a result or worker death that claims first cannot be rewritten by reentrant cleanup callbacks.
92
+ `start()` validates the meta block, parses the body, resolves the provider route, and resolves the per-run total-child cap before creating a worker or publishing `workflow/start`. A ready/go handshake prevents a start-signal cancellation racing worker boot from executing the script's initial synchronous slice; source mode installs TypeScript transforms through a data-URL bootstrap, while built mode passes the sibling `lib/worker.cjs` bundle.
70
93
 
71
- Worker error, message failure, or premature exit closes message admission before cleanup, then resolves `error` unless cancellation already owns the run. Late queued messages cannot create children or narrate after that logical boundary.
94
+ For each `agent()` call the worker sends a `child-start`; the host starts the provider (the request's override, or the configured provider) through the subagent seam, attributes the child to the run's parent, and reports start or start-error back. Provider choice applies to every child in the run and is not visible to the script. Provider starts are tracked separately from published children, so a pending start is aborted by the shared signal when cancellation, worker death, or normal settlement closes admission.
72
95
 
73
- The host keeps a ledger of forwarded child starts. A graceful worker supplies their ends; death or force termination synthesizes any missing end as cancelled. Every forwarded `workflow/agent-start` is therefore paired exactly once, although cleanup after an already-arrived workflow result may complete afterward.
96
+ ### Value boundary
74
97
 
75
- ## Config
98
+ Values leaving the script pass through realm materialization, which accepts plain lossless JSON data and rejects exotic prototypes, functions, symbols, cycles, sparse arrays, non-finite numbers, and nested `undefined`. Child results are projected and snapshotted before crossing from host to worker — a real process-like serialization boundary, deliberately different from the borrowed immutable values of same-process workflow events.
76
99
 
77
- | Key | Default | Meaning |
78
- |---|---|---|
79
- | `provider` | `spawn` | Host-side subagent provider used by `agent()`. |
80
- | `maxConcurrentAgents` | `0` | Concurrent `agent()` ceiling; `0` resolves from available CPU parallelism. |
81
- | `maxTotalAgents` | `1000` | Total `agent()` calls in one run. |
82
- | `maxItemsPerCall` | `4096` | Items accepted by one `parallel()` or `pipeline()` call. |
83
- | `syncTimeoutMs` | `5000` | VM timeout for the script's initial synchronous slice. |
84
- | `disposeGraceMs` | `5000` | Bound before force-settlement/termination and for public disposal. |
100
+ ### Cancellation and disposal
101
+
102
+ `cancel()` records the first reason, tells the worker to cancel, aborts the one signal shared by every pending and published child, and arms the `disposeGraceMs` timer; worker hooks then throw `CANCELLED` at their next await. If the run remains unsettled at the deadline, the host resolves it as cancelled, pairs stranded child lifecycle events, and terminates the worker.
103
+
104
+ `dispose()` is idempotent: it cancels the run, starts host-driven disposal immediately, waits for result and child quiescence up to the same grace, terminates the worker unconditionally, and performs a final survivor sweep. Per-child disposal is memoized so worker RPC, host cancellation, death cleanup, and public disposal all join one operation.
105
+
106
+ ### Outcome and event guarantees
107
+
108
+ Terminal outcome is first-wins at host claim points: an accepted external cancellation overrides a later non-cancelled worker result, and a result or worker death that claims first cannot be rewritten by reentrant cleanup callbacks. Worker error, message failure, or premature exit closes message admission before cleanup, then resolves `error` unless cancellation already owns the run.
109
+
110
+ The host keeps a ledger of forwarded child starts; a graceful worker supplies their ends, while death or force termination synthesizes any missing end as cancelled — every forwarded `workflow/agent-start` is paired exactly once.
111
+
112
+ </details>
85
113
 
86
- An owning consumer may set `WorkflowStartRequest.subagentProvider` and `WorkflowStartRequest.maxTotalAgents` for one run. These are engine-level policy, not script hooks or model-facing options; the ordinary `workflow` tool leaves both unset. A per-run total-child cap may lower but never raise the configured `maxTotalAgents` ceiling.
114
+ -----
87
115
 
116
+ <a id="further-exploration"></a>
117
+ ## Further Exploration
118
+
119
+ Read these pages when the engine-level contract is not enough. They move from the seam contract to the model-facing consumers and the design decisions.
120
+
121
+ - [Workflow subsystem](../../../docs/subsystems/workflow.md) — the seam contract this engine implements.
122
+ - [Workflow seam](../workflow/README.md) — the run and result vocabulary behind `ctx.workflowEngine`.
123
+ - [workflow tool](../tool-workflow/README.md) — the model-facing consumer that runs scripts on this engine.
124
+ - [Group map](../README.md) — the workflow capability family and its packages.
125
+ - [Dynamic workflows Agent Note](../../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.md) — the seam design and its decisions.
126
+
127
+ -----
128
+
129
+ <a id="model-experience"></a>
88
130
  ## Model Experience
89
131
 
90
132
  ### Child-agent requests
@@ -105,7 +147,7 @@ Independent of the parent request cache and of sibling children. Each child can
105
147
 
106
148
  #### What the model sees
107
149
 
108
- Through [`dsh-tool-workflow`](../tool-workflow/README.md), success exposes only the materialized final JSON value and child count in that consumer's wrapper. This engine supplies stable errors including `workflow script does not parse: <error>`, `invalid meta: <violations>`, `agent() requires a non-empty prompt string`, `agent() could not start a child: <error>`, `child agent run failed: <error>`, and its exact `parallel()`, `pipeline()`, `phase()`, option, schema, and JSON-boundary validation messages. Intermediate child outputs are available to the script but not the parent model.
150
+ Through [`dsh-tool-workflow`](../tool-workflow/README.md), success exposes only the materialized final JSON value and child count in that consumer's wrapper. This engine supplies stable errors including `workflow script does not parse: <error>`, `invalid meta: <violations>`, `agent() requires a non-empty prompt string`, `agent() could not start a child: <error>`, and `child agent run failed: <error>`, plus its exact `parallel()`, `pipeline()`, `phase()`, option, schema, and JSON-boundary validation messages. Intermediate child outputs are available to the script but not the parent model.
109
151
 
110
152
  #### Token effect
111
153
 
@@ -117,8 +159,25 @@ Append-only; newly visible content follows the reusable request prefix and does
117
159
 
118
160
  ## Known Limitations and Deferred Work
119
161
 
120
- - **The worker/vm is not a security boundary** — model-written code can escape `node:vm` and reach the worker's process authority; a hostile-code deployment needs a separate-process or container engine.
162
+ <a id="known-limitations-and-deferred-work"></a>
163
+
164
+
165
+ These limits define when the engine is a poor fit or needs special operational care. They are current constraints, not a task backlog.
166
+
167
+ - **The worker and vm are not a security boundary** — model-written code can escape `node:vm` and reach the worker's process authority; a hostile-code deployment needs a separate-process or container engine.
121
168
  - **One worker thread is paid per run** — there is no pool, warm runtime, or cross-run script cache.
122
- - **No ambient timers, filesystem, or network are injected, but escaped code can still reach Node** — the missing globals are portability API, not containment.
169
+ - **No ambient timers, filesystem, or network are injected, but escaped code can still reach Node** — the missing globals are a portability API, not containment.
123
170
  - **Termination can only report host-observed starts** — `agentsStarted` excludes worker-side calls still queued behind concurrency when a forced termination makes them unknowable.
124
171
  - **Cross-realm errors fail `instanceof Error` inside scripts** — workflow authors must branch on stable fields such as `name` and `code`.
172
+
173
+ <a id="dev-note"></a>
174
+ ### Dev Note
175
+
176
+ <details>
177
+ <summary>Working context for maintainers — click to expand</summary>
178
+
179
+ This Dev Note is working context for maintainers: measured artifacts and directions that are not decided. It is explicitly non-authoritative — shipped behavior, limits, and accepted rationale live in the sections above, the package code, and the linked Agent Notes.
180
+
181
+ Open directions: a pooled or warm runtime and a cross-run script cache to avoid one worker per run; a genuine process or container engine for untrusted scripts behind the same seam. The built `./worker` entry ships as a CommonJS bundle because pkg's VFS hook expects CommonJS; source mode installs tsx transforms through a data-URL bootstrap.
182
+
183
+ </details>
package/README.zh.md CHANGED
@@ -1,111 +1,153 @@
1
+ ---
2
+ description: "worker-thread 工作流引擎:在宿主事件循环之外执行由模型编写的编排脚本,供选择或配置执行隔离的用户与维护者阅读。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @xneog/dsh-workflow-worker-thread
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 本包为 `WorkflowEngine` 提供实现,每次运行使用一个 Node worker thread。worker 执行编排脚本;子 agent(智能体)留在宿主上,脚本通过带类型的宿主/worker 协议经由 `ctx.subagents` 访问它们。
10
+ ## 概述
6
11
 
7
- 包根目录默认导出引擎插件及其 `Config`;worker 协议、运行时和会话模块均为实现私有。操作入口 `./worker` 仍是引擎的 spawn 目标。
12
+ `dsh-workflow-worker-thread` 以每次运行一个 Node worker thread 的方式实现工作流引擎:编排脚本在一个全新 worker 内执行,其 `agent()` 调用通过带类型的宿主/worker 协议触达宿主 subagent。同步脚本循环不会阻塞 harness 事件循环,忽略取消的脚本可以连同其 worker 一起终止。这种隔离只是 containment(隔离),不是安全边界——由模型编写的脚本与模型已有的 bash 访问具有相同的信任前提,逃逸 `node:vm` 上下文即可重新取得 worker 的进程权限。挂载本引擎即为 `ctx.workflowEngine` 提供具体实现;与 `dsh-tool-workflow` 一起加载的组合会把 `workflow` 工具交给模型。
8
13
 
9
- 这种拆分只有一个主要目的:同步脚本循环不能阻塞 harness 事件循环,忽略取消的脚本可以连同其 worker 一起终止。它不是安全沙箱。
14
+ ## 目录
10
15
 
11
- ## 信任与隔离边界
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
12
22
 
13
- 工作流脚本由模型编写,信任前提与模型已有的 bash 访问相同。worker 内的 `node:vm` 是塑造 API 的机制,不是安全边界:逃逸的脚本可以用宿主进程权限重新取得 Node 能力。
23
+ -----
14
24
 
15
- worker 仍提供实用的隔离:
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
16
27
 
17
- - 脚本 CPU 工作和同步自旋不会占用宿主事件循环;
18
- - `worker.terminate()` 为 dispose(资源释放)提供真实的最终停止手段;
19
- - 除未构建 loader 所需的衔接配置外,worker 以空环境启动,因此环境凭据不会通过 `process.env` 跨越边界;
20
- - 宿主/worker 消息使用结构化克隆数据,并在脚本边界执行普通 JSON 校验。
28
+ 当组合需要工作流能力时挂载本引擎:每个编排脚本都在独立 worker thread 中、宿主事件循环之外运行,已发布组合中的 `workflow` 与 `ralph` 工具都在其上执行。不要把它当作真正不可信脚本的沙箱——恶意代码需要独立进程或容器引擎。
21
29
 
22
- 真正的不可信脚本沙箱需要在同一工作流 seam 背后采用不同引擎。
30
+ ### 最小配置
23
31
 
24
- ## 脚本约定
32
+ 加载本引擎即注册 `ctx.workflowEngine`;在其上添加 `dsh-tool-workflow` 会把 `workflow` 工具交给模型。每个配置字段都是可选的:
25
33
 
26
- 工作流的 `meta` 是宿主提供的数据,而不是待求值的脚本文本。引擎会校验必需的 `name` 和 `description`、拒绝未知字段,并在返回运行前检查脚本正文能否解析。
34
+ ```yaml
35
+ - name: '@xneog/dsh-workflow-worker-thread'
36
+ - name: '@xneog/dsh-tool-workflow'
37
+ ```
27
38
 
28
- worker 内,脚本会收到 `args` 以及以下钩子:
39
+ | 字段 | 默认值 | 含义 |
40
+ |---|---|---|
41
+ | `provider` | `spawn` | `agent()` 调用使用的宿主侧 subagent 提供方。 |
42
+ | `maxConcurrentAgents` | `0` | 并发 `agent()` 上限;`0` 会根据可用 CPU 并行度解析。 |
43
+ | `maxTotalAgents` | `1000` | 一次运行最多启动的 `agent()` 调用总数——失控循环的后备闸。 |
44
+ | `maxItemsPerCall` | `4096` | 一次 `parallel()` 或 `pipeline()` 调用接受的条目数。 |
45
+ | `syncTimeoutMs` | `5000` | 脚本最初同步片段的 VM 超时时间,单位为毫秒。 |
46
+ | `disposeGraceMs` | `5000` | 强制结算与终止 worker 前的期限;同时约束 `dispose()`。 |
29
47
 
30
- - `agent(prompt, { label, phase, schema, model })` 启动一个宿主侧 subagent。提供 schema 时返回结构化值,否则返回最终文本。普通子 agent 失败会产生 `null`;
31
- - `parallel(thunks)` 在已配置的并发限制下运行 thunk;
32
- - `pipeline(items, ...stages)` 在没有跨阶段屏障的情况下传递 `(previous, item, index)`;
33
- - `phase(title)` 和 `log(message)` 发出观察器叙述。
48
+ 负责该引擎的消费方可以为一次运行设置 `WorkflowStartRequest.subagentProvider` `WorkflowStartRequest.maxTotalAgents`——这是引擎级策略,不是脚本钩子;普通 `workflow` 工具两者都不设置,单次运行的子 agent 总数上限可以降低、但绝不能提高已配置的上限。生成的[配置目录](../../../docs/config-catalog.zh.md#xneogdsh-workflow-worker-thread)是每个受支持字段的穷尽式真源。
34
49
 
35
- 未知选项、格式错误的参数、不支持的 schema、超出上限、提供方启动失败和基础设施结果失败都属于致命工作流错误。有意不注入 timer、文件系统 API 或 Node 全局变量,但上述信任注意事项仍然适用。
50
+ ### 运行会得到什么
36
51
 
37
- ## 运行顺序
52
+ 运行启动后,脚本正文在 worker 中以顶层 `await` 执行,并可使用钩子 `agent()`、`parallel()`、`pipeline()`、`phase()` 与 `log()`;`meta` 与 `args` 以普通 JSON 数据到达,绝不作为代码求值。每次 `agent()` 调用都会在配置的提供方下启动一个宿主侧 subagent,并以运行的父级作为每个子 agent 的父级。运行以脚本的最终 JSON 值结算;普通子 agent 失败会把 `agent()` 兑现为 `null`,由脚本处理。
38
53
 
39
- `start()` 会校验 meta、解析脚本正文、解析一个已注册且规范化的提供方路由,并解析每次运行的子 agent 总数上限,然后才创建 worker 或发布 `workflow/start`。请求的 `maxTotalAgents` 必须是正安全整数,且不能超过引擎配置的部署上限。源代码模式通过 data URL bootstrap 安装 TypeScript 转换;构建模式把同级 `lib/worker.cjs` 作为文件系统路径传入,因为 pkg 的虚拟文件系统(VFS)钩子要求 CommonJS。两者都能在普通 Node 下运行。ready/go 握手可以避免启动信号取消与 worker 启动发生竞态,导致脚本最初的同步片段被执行。
54
+ 格式错误的 meta 块、无法解析的正文、不可用的提供方路由或高于上限的单次运行上限,都会在 worker 存在之前被同步拒绝,调用方因此看到违规清单并可以修正调用。执行期间,钩子误用与超出上限会用致命工作流错误终止脚本。取消是有界的:忽略取消的脚本会在 `disposeGraceMs` 后被强制以 cancelled 结算,其 worker 被终止。
40
55
 
41
- 对于每次 `agent()` 调用:
56
+ ### 信任预期
42
57
 
43
- 1. worker 发送 `child-start`,其中包含普通数据提示词和选项。
44
- 2. 宿主通过异步 `SubagentRuntime.start` 调用启动请求中指定的提供方,否则调用已配置的提供方;调用会传入工作流父级和该次运行共用的唯一中止信号。提供方选择应用于该次运行的每个子 agent,对脚本不可见。
45
- 3. 如果启动被拒绝,宿主会发送 `child-start-error`;提供方启动已经完全停稳,不会发出子 agent 生命周期事件。
46
- 4. 如果启动兑现时工作流仍接纳工作,宿主会记录该运行、观察 `result`,然后发送 `child-started`。即使结果已经结算,也只会随后转发,以保持先启动、后结果的顺序。
47
- 5. worker 发出成对的 `workflow/agent-start` 和 `workflow/agent-end` 叙述,并在收集后请求 dispose 子 agent。
58
+ 脚本的 CPU 工作与同步自旋不会占用宿主事件循环,`worker.terminate()` 为 dispose(资源释放)提供真实的最终停止手段,worker 以清理后的环境启动——只注入平台临时路径以及(源码模式下)`TSX_TSCONFIG_PATH`——因此环境凭据不会通过 `process.env` 跨越边界。宿主/worker 消息使用结构化克隆数据,并在脚本边界执行普通 JSON 校验。
48
59
 
49
- 提供方启动与已发布子 agent 分开跟踪。如果启动仍在等待,而取消、worker 死亡或正常工作流结算关闭了接纳,共享信号会中止该启动。即便提供方随后兑现,宿主也会 dispose 它,且绝不向 worker 通知。
60
+ 以上都不是安全边界:有意不注入 timer、文件系统 API Node 全局变量,但逃逸代码仍可以 worker 的进程权限触达 Node。
50
61
 
51
- ## 值边界
62
+ -----
52
63
 
53
- 离开脚本的值会经过 `materializeFromRealm`;该函数接受普通的无损 JSON 数据,并拒绝特殊原型、函数、symbol、循环、稀疏数组、非有限数和嵌套 `undefined`。遍历在 worker 内执行,并把对象键定义为数据属性,使 `__proto__` 无法改变原型。
64
+ <a id="understand-the-implementation"></a>
65
+ ## 理解实现
54
66
 
55
- 子 agent 结果从宿主跨越到 worker 之前,会先投影并制作快照。这是真正近似进程的序列化边界;它有意不同于可信的同进程工作流和 subagent 事件 payload,后者以不可变方式借用值。
67
+ <details>
68
+ <summary>实现细节——点击展开</summary>
56
69
 
57
- ## 取消与 dispose
70
+ 本节解释引擎的隔离设计与运行机制;可观察行为已在[使用本包](#use-this-package)中完整说明。
58
71
 
59
- `WorkflowRun.cancel()` 会记录第一个原因、通知 worker 取消、中止每个待处理及已发布子 agent 共享的唯一信号,并启动 `disposeGraceMs` 定时器。worker 钩子会在下次 await 时抛出 `CANCELLED`。如果运行到期限仍未结算,宿主会将其以已取消状态兑现、为悬空的子 agent 生命周期事件配对,并终止 worker。
72
+ ### 设计理念
60
73
 
61
- subagent seam 只有一个取消通道:请求信号。不存在单独的子 agent 取消 RPC。已发布子 agent 使用 `run.dispose()` 清理;待处理的提供方启动在其 promise 拒绝或兑现前仍由提供方负责。
74
+ 每次运行一个 worker thread,让行为异常的脚本无法拖垮宿主,并使强制终止成为可能:脚本在 worker 内可逃逸的 `node:vm` 上下文中运行,`agent()` 调用通过带类型的宿主/worker 协议回到 `ctx.subagents`。vm 上下文塑造脚本的 API 表面;它不是安全沙箱。
62
75
 
63
- 正常结算也会中止待处理启动,并在结果对外结算前开始 dispose 所有已发布但无需等待的子 agent。宿主的完全停稳条件同时包括待处理启动和已发布子 agent 的 dispose,因此清理不会遗漏异步启动事务。
76
+ ### 源码地图
64
77
 
65
- `dispose()` 是幂等的。它会取消运行、立即启动宿主驱动的 dispose、在同一宽限时间内等待结果和子 agent 完全停稳、无条件终止 worker,并执行最后一次幸存项扫描。每个子 agent 的 dispose 都会记忆化,使 worker RPC、宿主取消、死亡清理和公开 dispose 都汇入同一操作。
78
+ | 文件 | 职责 |
79
+ |---|---|
80
+ | [`src/index.ts`](src/index.ts) | 插件入口:`Config` schema、前置校验、`start()` 接线 |
81
+ | [`src/host.ts`](src/host.ts) | 一次运行的宿主侧:worker 启动、子 agent 编排、结算、dispose |
82
+ | [`src/worker.ts`](src/worker.ts) | worker 入口:脚本执行、钩子实现、值物化 |
83
+ | [`src/runtime.ts`](src/runtime.ts) | 脚本运行时:钩子契约、`parallel()` 与 `pipeline()` 组合器 |
84
+ | [`src/realm.ts`](src/realm.ts) | 跨 realm 物化:普通 JSON 的接受与拒绝规则 |
85
+ | [`src/protocol.ts`](src/protocol.ts) | 带类型的宿主/worker 消息协议 |
86
+ | [`src/meta.ts`](src/meta.ts) | `meta` 形状校验与规范化 |
87
+ | [`src/session.ts`](src/session.ts) | 子 agent 运行在跨入 worker 前的投影与快照 |
88
+ | — | 不发布运行时不变式伴生入口;worker 测试覆盖该边界。 |
66
89
 
67
- ## 结果与事件保证
90
+ ### 运行顺序
68
91
 
69
- 在宿主的结果确认点,终态结果遵循先到者胜。已接受的外部取消会覆盖后到的非取消 worker 结果;先完成确认的结果或 worker 死亡不能被可重入清理回调改写。
92
+ `start()` 在创建 worker 或发布 `workflow/start` 之前校验 meta 块、解析正文、解析提供方路由并解析单次运行的子 agent 总数上限。ready/go 握手可以避免启动信号取消与 worker 启动发生竞态、导致脚本最初的同步片段被执行;源代码模式通过 data URL bootstrap 安装 TypeScript 转换,构建模式则传入同级 `lib/worker.cjs` 包。
70
93
 
71
- worker 错误、消息失败或提前退出会在清理前关闭消息接纳,然后以 `error` 兑现;如果取消已经接管该运行,则不覆盖取消。后到的排队消息无法在该逻辑边界后创建子 agent 或发出叙述。
94
+ 每次 `agent()` 调用,worker 都会发送 `child-start`;宿主通过 subagent seam 启动提供方(请求的覆盖值,或配置的提供方),把子 agent 归属于运行的父级,并回报启动成功或启动错误。提供方选择应用于该运行的每个子 agent,对脚本不可见。提供方启动与已发布子 agent 分开跟踪,因此当取消、worker 死亡或正常结算关闭接纳时,待处理启动会被共享信号中止。
72
95
 
73
- 宿主会维护已转发子 agent 启动的台账。优雅退出的 worker 会提供对应的结束事件;死亡或强制终止会把缺失的结束事件合成为已取消。因此,每个已转发的 `workflow/agent-start` 都会且只会配对一次,不过已经到达的工作流结果之后的清理可能稍后才完成。
96
+ ### 值边界
74
97
 
75
- ## 配置
98
+ 离开脚本的值会经过 realm 物化;该过程接受普通无损 JSON 数据,拒绝特殊原型、函数、symbol、循环、稀疏数组、非有限数与嵌套 `undefined`。子 agent 结果在从宿主跨入 worker 之前先投影并快照——这是真正近似进程的序列化边界,刻意区别于同进程工作流事件以不可变方式借用的值。
76
99
 
77
- | | 默认值 | 含义 |
78
- |---|---|---|
79
- | `provider` | `spawn` | `agent()` 使用的宿主侧 subagent 提供方。 |
80
- | `maxConcurrentAgents` | `0` | 并发 `agent()` 上限;`0` 会根据可用 CPU 并行度解析。 |
81
- | `maxTotalAgents` | `1000` | 一次运行中的 `agent()` 调用总数。 |
82
- | `maxItemsPerCall` | `4096` | 一次 `parallel()` 或 `pipeline()` 调用接受的条目数。 |
83
- | `syncTimeoutMs` | `5000` | 脚本最初同步片段的 VM 超时时间。 |
84
- | `disposeGraceMs` | `5000` | 强制结算/终止之前的期限,也是公开 dispose 的期限。 |
100
+ ### 取消与 dispose
101
+
102
+ `cancel()` 记录第一个原因、通知 worker 取消、中止所有待处理与已发布子 agent 共享的唯一信号,并启动 `disposeGraceMs` 定时器;worker 钩子随后在下次 await 时抛出 `CANCELLED`。如果运行到期限仍未结算,宿主会将其以 cancelled 兑现、为悬空的子 agent 生命周期事件配对,并终止 worker。
103
+
104
+ `dispose()` 是幂等的:它取消运行、立即启动宿主驱动的 dispose、在同一宽限期内等待结果与子 agent 完全停稳、无条件终止 worker,并执行最后一次幸存项扫描。每个子 agent dispose 都会记忆化,使 worker RPC、宿主取消、死亡清理与公开 dispose 都汇入同一操作。
105
+
106
+ ### 结果与事件保证
107
+
108
+ 在宿主的认领点,终态结果遵循先到者胜:已接受的外部取消会覆盖后到的非取消 worker 结果,先认领的结果或 worker 死亡不能被可重入清理回调改写。worker 错误、消息失败或提前退出会在清理前关闭消息接纳,然后以 `error` 兑现;除非取消已接管该运行。
109
+
110
+ 宿主维护已转发子 agent 启动的台账;优雅退出的 worker 提供对应的结束事件,死亡或强制终止则把缺失的结束事件合成为已取消——每个已转发的 `workflow/agent-start` 都会且只会配对一次。
111
+
112
+ </details>
85
113
 
86
- 负责该引擎的消费方可以为一次运行设置 `WorkflowStartRequest.subagentProvider` 和 `WorkflowStartRequest.maxTotalAgents`。它们属于引擎级策略,不是脚本钩子或面向模型的选项;普通 `workflow` 工具不会设置两者。每次运行的子 agent 总数上限可以降低、但绝不能提高已配置的 `maxTotalAgents` 上限。
114
+ -----
87
115
 
116
+ <a id="further-exploration"></a>
117
+ ## 进一步探索
118
+
119
+ 当引擎级契约不够用时阅读以下页面。它们从 seam 契约逐步进入面向模型的消费方与设计决策。
120
+
121
+ - [工作流子系统](../../../docs/subsystems/workflow.zh.md)——本引擎实现的 seam 契约。
122
+ - [工作流 seam](../workflow/README.zh.md)——`ctx.workflowEngine` 背后的运行与结果词汇。
123
+ - [workflow 工具](../tool-workflow/README.zh.md)——在本引擎上运行脚本的模型侧消费方。
124
+ - [组地图](../README.zh.md)——工作流能力家族及其包。
125
+ - [动态工作流 Agent Note](../../../.agents/notes/implemented/feature/2026-07-05-dynamic-workflows.zh.md)——seam 设计及其决策。
126
+
127
+ -----
128
+
129
+ <a id="model-experience"></a>
88
130
  ## 模型体验
89
131
 
90
132
  ### 子 agent 请求
91
133
 
92
- #### 模型看到的内容
134
+ #### 模型看到什么
93
135
 
94
- 脚本每次调用 `agent()`,都会把提示词原样发送给 subagent 提供方,并附带可选模型或结构化输出 schema。每个子 agent 看到该提供方自己的上下文;phase log 叙述只留在观察器事件中。
136
+ 脚本每次调用 `agent()`,都会把提示词原样发送给 subagent 提供方,并附带可选模型或结构化输出 schema。每个子 agent 看到该提供方自己的上下文;phase log 叙述只留在观察器事件中。
95
137
 
96
138
  #### Token 影响
97
139
 
98
- 可能需要为许多独立子 agent 上下文支付 token 成本,数量受 `maxConcurrentAgents`、`maxTotalAgents` `maxItemsPerCall` 限制;这些上下文绝不会直接加入父级历史。
140
+ 可能需要为许多独立子 agent 上下文支付 token,数量受 `maxConcurrentAgents`、`maxTotalAgents` `maxItemsPerCall` 限制;这些上下文绝不会直接加入父级历史。
99
141
 
100
142
  #### KV Cache 影响
101
143
 
102
- 与父级请求缓存和同级子 agent 缓存相互独立。每个子 agent 只能在其自身提供方、模型、提示词和 schema 下复用逐字节相同的前缀;其后续历史仅追加增长。
144
+ 与父级请求缓存及同级子 agent 相互独立。每个子 agent 只能在其自身提供方、模型、提示词与 schema 下复用逐字节相同的前缀;其后续历史仅追加增长。
103
145
 
104
146
  ### 父级工具结果(间接)
105
147
 
106
- #### 模型看到的内容
148
+ #### 模型看到什么
107
149
 
108
- 通过 [`dsh-tool-workflow`](../tool-workflow/README.md),成功结果只会在该消费方的包装层中公开实体化的最终 JSON 值和子 agent 数量。本引擎提供稳定错误,包括 `workflow script does not parse: <error>`、`invalid meta: <violations>`、`agent() requires a non-empty prompt string`、`agent() could not start a child: <error>`、`child agent run failed: <error>`,以及其精确的 `parallel()`、`pipeline()`、`phase()`、选项、schema JSON 边界校验消息。中间子 agent 输出可供脚本使用,但不提供给父模型。
150
+ 通过 [`dsh-tool-workflow`](../tool-workflow/README.zh.md),成功结果只会在该消费方的包装层中公开实体化的最终 JSON 值与子 agent 数量。本引擎提供稳定错误,包括 `workflow script does not parse: <error>`、`invalid meta: <violations>`、`agent() requires a non-empty prompt string`、`agent() could not start a child: <error>` 与 `child agent run failed: <error>`,以及其精确的 `parallel()`、`pipeline()`、`phase()`、选项、schema JSON 边界校验消息。中间子 agent 输出可供脚本使用,但不提供给父模型。
109
151
 
110
152
  #### Token 影响
111
153
 
@@ -115,10 +157,27 @@ worker 错误、消息失败或提前退出会在清理前关闭消息接纳,
115
157
 
116
158
  仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
117
159
 
118
- ## 已知限制与暂缓事项
160
+ ## 已知限制与延期工作
161
+
162
+ <a id="known-limitations-and-deferred-work"></a>
163
+
164
+
165
+ 这些限制说明本引擎何时不合适,或何时需要特别的运维注意。它们是当前约束,不是任务积压。
166
+
167
+ - **worker 与 vm 不是安全边界**——模型编写的代码可以逃逸 `node:vm` 并取得 worker 的进程权限;不可信代码部署需要独立进程或容器引擎。
168
+ - **每次运行都要支付一个 worker thread**——没有池、预热运行时或跨运行脚本缓存。
169
+ - **不注入默认可用的定时器、文件系统或网络,但逃逸代码仍可触达 Node**——缺失的全局变量属于可移植性 API,而非隔离措施。
170
+ - **终止只能报告宿主观察到的启动**——`agentsStarted` 不包括因并发限制仍在 worker 侧排队、且在强制终止后无法得知的调用。
171
+ - **跨 realm 错误在脚本内无法通过 `instanceof Error`**——工作流作者必须根据 `name` 与 `code` 等稳定字段分支。
172
+
173
+ <a id="dev-note"></a>
174
+ ### 开发备注
175
+
176
+ <details>
177
+ <summary>维护者的工作上下文——点击展开</summary>
178
+
179
+ 本开发备注是维护者的工作上下文:实测产物与尚未决定的探索方向。它明确不具权威性——已交付的行为、限制与既定理由以上文、包代码与相关 Agent Note 为准。
180
+
181
+ 开放方向:用池化或预热运行时与跨运行脚本缓存来避免每次运行一个 worker;在同一 seam 背后为不可信脚本提供真正的进程或容器引擎。构建产物 `./worker` 入口以 CommonJS 包形式发布,因为 pkg 的虚拟文件系统(VFS)钩子要求 CommonJS;源代码模式通过 data URL bootstrap 安装 tsx 转换。
119
182
 
120
- - **worker/vm 不是安全边界**:模型编写的代码可以逃逸 `node:vm` 并取得 worker 的进程权限;不可信代码部署需要独立进程或容器引擎。
121
- - **每次运行都要支付一个 worker thread 的成本**:没有池、预热运行时或跨运行脚本缓存。
122
- - **不注入默认可用的定时器、文件系统或网络,但逃逸代码仍可访问 Node**:这些缺失的全局变量属于可移植性 API 设计,而非隔离措施。
123
- - **终止只能报告宿主观察到的启动**:`agentsStarted` 不包括因并发限制仍在 worker 侧排队、且在强制终止后无法得知的调用。
124
- - **跨 realm 错误在脚本内无法通过 `instanceof Error`**:工作流作者必须根据 `name` 和 `code` 等稳定字段分支。
183
+ </details>
package/lib/index.js CHANGED
@@ -5,8 +5,7 @@ import z from "@xneog/schemastery";
5
5
  import WorkflowEngine, { WorkflowError, WorkflowRunId } from "@xneog/dsh-workflow";
6
6
  import { Worker } from "node:worker_threads";
7
7
  import { fileURLToPath } from "node:url";
8
- import { assertNever } from "@xneog/dsh-llm";
9
- import { snapshotJsonValue } from "@xneog/dsh-session";
8
+ import { assertNever, snapshotJsonValue } from "@xneog/dsh-util-values";
10
9
  //#region lib/types/realm.js
11
10
  /**
12
11
  * Materializes values leaving the script vm into plain JSON before they cross the worker
@@ -187,7 +186,11 @@ var HostToWorkerType;
187
186
  * @module @xneog/dsh-workflow-worker-thread/host
188
187
  */
189
188
  /**
190
- * The scrubbed worker environment: no ambient credentials, no loader flags.
189
+ * The scrubbed worker environment: no ambient credentials, no loader flags, and deliberately no
190
+ * proxy policy. A worker thread does not inherit the host's global dispatcher, so a workflow's own
191
+ * requests go direct — the alternative is handing the worker a proxy URL that may carry
192
+ * `user:password`, and this worker executes the model-authored script body. That is the same
193
+ * containment the code runtime keeps, and `docs/defensive-patterns.md` requires it.
191
194
  * Windows derives `os.tmpdir()` from `TMP`/`TEMP` and falls back to the
192
195
  * literal relative path `undefined\temp` when the environment is empty, so
193
196
  * tsx's transform cache would land in a cwd-relative `undefined/temp`
@@ -12,7 +12,11 @@ import type { WorkflowMeta, WorkflowResult, WorkflowRun, WorkflowRunId } from '@
12
12
  import type { ExecutionObserver } from './runtime.ts';
13
13
  import type { WorkerInit } from './types.ts';
14
14
  /**
15
- * The scrubbed worker environment: no ambient credentials, no loader flags.
15
+ * The scrubbed worker environment: no ambient credentials, no loader flags, and deliberately no
16
+ * proxy policy. A worker thread does not inherit the host's global dispatcher, so a workflow's own
17
+ * requests go direct — the alternative is handing the worker a proxy URL that may carry
18
+ * `user:password`, and this worker executes the model-authored script body. That is the same
19
+ * containment the code runtime keeps, and `docs/defensive-patterns.md` requires it.
16
20
  * Windows derives `os.tmpdir()` from `TMP`/`TEMP` and falls back to the
17
21
  * literal relative path `undefined\temp` when the environment is empty, so
18
22
  * tsx's transform cache would land in a cwd-relative `undefined/temp`
package/lib/worker.cjs CHANGED
@@ -21,10 +21,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  }) : target, mod));
22
22
  //#endregion
23
23
  let node_worker_threads = require("node:worker_threads");
24
- let _xneog_dsh_llm = require("@xneog/dsh-llm");
24
+ let _xneog_dsh_util_values = require("@xneog/dsh-util-values");
25
25
  let node_vm = require("node:vm");
26
26
  node_vm = __toESM(node_vm, 1);
27
- let _xneog_dsh_session = require("@xneog/dsh-session");
27
+ let _xneog_dsh_brand = require("@xneog/dsh-brand");
28
28
  let _xneog_dsh_tools = require("@xneog/dsh-tools");
29
29
  let _xneog_dsh_workflow = require("@xneog/dsh-workflow");
30
30
  //#region lib/types/protocol.js
@@ -433,7 +433,7 @@ var WorkflowExecution = class {
433
433
  seq,
434
434
  label,
435
435
  ...phase !== void 0 ? { phase } : {},
436
- childId: (0, _xneog_dsh_session.SessionId)(run.id)
436
+ childId: (0, _xneog_dsh_brand.brandString)(run.id)
437
437
  };
438
438
  this.observer.agentStart(info);
439
439
  try {
@@ -763,7 +763,7 @@ async function runWorkerSession(port, init) {
763
763
  children.onChildDisposed(message.callId);
764
764
  break;
765
765
  /* v8 ignore next 2 -- closed engine-owned union; the arm only makes adding a message type a compile error */
766
- default: (0, _xneog_dsh_llm.assertNever)(message, "host-to-worker message");
766
+ default: (0, _xneog_dsh_util_values.assertNever)(message, "host-to-worker message");
767
767
  }
768
768
  });
769
769
  post(WorkerToHostType.Ready, {});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xneog/dsh-workflow-worker-thread",
3
3
  "description": "worker-thread workflow engine: executes model-written orchestration scripts off the host event loop, bridging agent() calls back to ctx.subagents",
4
- "version": "0.1.0",
4
+ "version": "0.1.3-alpha.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -18,10 +18,6 @@
18
18
  "types": "./lib/types/index.d.ts",
19
19
  "default": "./lib/index.js"
20
20
  },
21
- "./invariant": {
22
- "types": "./lib/types/invariant.d.ts",
23
- "default": "./lib/invariant.js"
24
- },
25
21
  "./worker": {
26
22
  "types": "./lib/types/worker.d.ts",
27
23
  "default": "./lib/worker.cjs"
@@ -31,39 +27,39 @@
31
27
  },
32
28
  "files": [
33
29
  "lib/index.js",
34
- "lib/invariant.js",
35
30
  "lib/worker.cjs",
36
31
  "lib/types/**/*.d.ts"
37
32
  ],
38
33
  "license": "MIT",
39
34
  "peerDependencies": {
40
- "@xneog/dsh-agent": "0.1.0",
41
- "@xneog/dsh-brand": "0.1.0",
42
- "@xneog/dsh-invariants": "0.1.0",
43
- "@xneog/dsh-llm": "0.1.0",
44
- "@xneog/dsh-session": "0.1.0",
45
- "@xneog/dsh-subagent": "0.1.0",
46
- "@xneog/dsh-tools": "0.1.0",
47
- "@xneog/dsh-workflow": "0.1.0",
48
- "@xneog/cordis": "0.1.0"
35
+ "@xneog/cordis": "^4.0.2",
36
+ "@xneog/dsh-agent": "^0.1.3-alpha.1",
37
+ "@xneog/dsh-llm": "^0.1.3-alpha.1",
38
+ "@xneog/dsh-subagent": "^0.1.3-alpha.1",
39
+ "@xneog/dsh-workflow": "^0.1.3-alpha.1",
40
+ "@xneog/dsh-tools": "^0.1.3-alpha.1",
41
+ "@xneog/dsh-session": "^0.1.3-alpha.1"
49
42
  },
50
43
  "dependencies": {
51
- "@xneog/schemastery": "0.1.0"
44
+ "@xneog/dsh-brand": "^0.1.3-alpha.1",
45
+ "@xneog/dsh-util-values": "^0.1.3-alpha.1",
46
+ "@xneog/schemastery": "^3.18.2"
52
47
  },
53
48
  "devDependencies": {
54
- "@xneog/dsh-agent": "0.1.0",
55
- "@xneog/dsh-agent-loop": "0.1.0",
56
- "@xneog/dsh-agent-loop-testkit": "0.1.0",
57
- "@xneog/dsh-brand": "0.1.0",
58
- "@xneog/dsh-invariants": "0.1.0",
59
- "@xneog/dsh-llm": "0.1.0",
60
- "@xneog/dsh-session": "0.1.0",
61
- "@xneog/dsh-subagent": "0.1.0",
62
- "@xneog/dsh-subagent-spawn-in-process": "0.1.0",
63
- "@xneog/dsh-system-prompt": "0.1.0",
64
- "@xneog/dsh-tools": "0.1.0",
65
- "@xneog/dsh-workflow": "0.1.0",
66
- "@xneog/cordis": "0.1.0",
67
- "tsx": "^4.19.2"
49
+ "tsx": "^4.19.2",
50
+ "@xneog/cordis": "^4.0.2",
51
+ "@xneog/dsh-agent": "^0.1.3-alpha.1",
52
+ "@xneog/dsh-agent-loop-testkit": "^0.1.3-alpha.1",
53
+ "@xneog/dsh-llm": "^0.1.3-alpha.1",
54
+ "@xneog/dsh-session": "^0.1.3-alpha.1",
55
+ "@xneog/dsh-subagent": "^0.1.3-alpha.1",
56
+ "@xneog/dsh-subagent-spawn-in-process": "^0.1.3-alpha.1",
57
+ "@xneog/dsh-session-projection": "^0.1.3-alpha.1",
58
+ "@xneog/dsh-agent-loop": "^0.1.3-alpha.1",
59
+ "@xneog/dsh-invariants": "^0.1.3-alpha.1",
60
+ "@xneog/dsh-system-prompt": "^0.1.3-alpha.1",
61
+ "@xneog/dsh-tools": "^0.1.3-alpha.1",
62
+ "@xneog/dsh-workflow": "^0.1.3-alpha.1",
63
+ "@xneog/dsh-http-proxy": "^0.1.3-alpha.1"
68
64
  }
69
65
  }
package/lib/invariant.js DELETED
@@ -1,23 +0,0 @@
1
- //#region lib/types/invariant.js
2
- /**
3
- * Package-owned invariant companion for `@xneog/dsh-workflow-worker-thread`.
4
- * @module @xneog/dsh-workflow-worker-thread/invariant
5
- */
6
- const PACKAGE_NAME = "@xneog/dsh-workflow-worker-thread";
7
- /** Cordis companion plugin name. */
8
- const name = "workflow-worker-thread-invariant";
9
- /** Service required before the companion can reserve package ownership. */
10
- const inject = ["invariants"];
11
- /**
12
- * No runtime invariant: this process-boundary implementation exposes no same-process event relation;
13
- * worker protocol and built-worker tests cover it.
14
- */
15
- const install = () => {};
16
- /**
17
- * Register this package's invariant companion.
18
- * @param ctx - Cordis context carrying the invariant service.
19
- * @returns the installed registration's disposer after setup succeeds.
20
- */
21
- const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
22
- //#endregion
23
- export { apply, inject, name };
@@ -1,16 +0,0 @@
1
- /**
2
- * Package-owned invariant companion for `@xneog/dsh-workflow-worker-thread`.
3
- * @module @xneog/dsh-workflow-worker-thread/invariant
4
- */
5
- import type { Context } from '@xneog/cordis';
6
- /** Cordis companion plugin name. */
7
- export declare const name = "workflow-worker-thread-invariant";
8
- /** Service required before the companion can reserve package ownership. */
9
- export declare const inject: string[];
10
- /**
11
- * Register this package's invariant companion.
12
- * @param ctx - Cordis context carrying the invariant service.
13
- * @returns the installed registration's disposer after setup succeeds.
14
- */
15
- export declare const apply: (ctx: Context) => Promise<() => void>;
16
- //# sourceMappingURL=invariant.d.ts.map