@automatalabs/workflows 0.1.2 → 0.3.0

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.md CHANGED
@@ -137,10 +137,24 @@ try {
137
137
  ```
138
138
 
139
139
  `run(prompt, options?)` accepts the seam's `RunOptions`: `schema`, `model`, `tier`, `cwd`,
140
- `instructions`, `label`, `toolNames` / `disallowedToolNames`, `signal`, `mcpServers`, and the
141
- out-of-band telemetry callbacks `onUsage` / `onModelResolved` / `onModelFallback` / `onHistory`.
142
- Token/cost usage is delivered via `onUsage` (it may never fire — ACP usage is experimental), never
143
- via the return value.
140
+ `instructions`, `label`, `toolNames` / `disallowedToolNames`, `signal`, `mcpServers`,
141
+ `baseInstructions` / `developerInstructions` (Codex-only), and the out-of-band telemetry callbacks
142
+ `onUsage` / `onModelResolved` / `onModelFallback` / `onHistory`. Token/cost usage is delivered via
143
+ `onUsage` (it may never fire — ACP usage is experimental), never via the return value.
144
+
145
+ > **Codex session instructions.** When the run routes to the Codex backend, `baseInstructions`
146
+ > **replaces** Codex's built-in base system prompt and `developerInstructions` adds developer-role
147
+ > instructions for the session. They ride ACP `session/new` `_meta` into Codex `thread/start` and
148
+ > are **ignored by the Claude backend** (which has no analog) — unlike `instructions`, which is
149
+ > folded into the prompt text for either backend.
150
+ >
151
+ > ```ts
152
+ > await runner.run("Cut the release.", {
153
+ > model: "gpt-5-codex",
154
+ > baseInstructions: "You are a release bot. Only touch CHANGELOG.md.",
155
+ > developerInstructions: "Prefer conventional-commit summaries.",
156
+ > });
157
+ > ```
144
158
 
145
159
  > The ACP server **process** is pooled and reused across `run()` calls; each `run()` opens and
146
160
  > closes one **session** on it. Call `dispose()` once at shutdown to tear the pool down. Pool size
@@ -208,6 +222,60 @@ testable without a live agent — pass a stub runner.
208
222
 
209
223
  ---
210
224
 
225
+ ## Listening in on the live ACP stream (events)
226
+
227
+ `createAcpRunner()` returns an `AcpAgentRunner` with a **typed event bus**. Subscribe with
228
+ `runner.on(name, listener)` to observe the live ACP stream of every run on that runner — streaming
229
+ assistant text, tool calls, usage, permissions — without touching the `run()` return value or the
230
+ `AgentRunner` seam.
231
+
232
+ ```ts
233
+ import { createAcpRunner } from "@automatalabs/workflows";
234
+
235
+ const runner = createAcpRunner();
236
+
237
+ // ACP `sessionUpdate` discriminants are the event names; the listener payload is typed to each.
238
+ runner.on("agent_message_chunk", (e) => {
239
+ if (e.content.type === "text") process.stdout.write(e.content.text); // stream tokens as they land
240
+ });
241
+ runner.on("tool_call", (e) => console.error(`[${e.label}] tool: ${e.title}`));
242
+ runner.on("usage_update", (e) => console.error(`ctx ${e.used}/${e.size} tokens`));
243
+
244
+ // One catch-all for "everything": fires for EVERY session/update, carrying the raw update.
245
+ const off = runner.on("session_update", (e) => console.error(e.update.sessionUpdate));
246
+
247
+ await runner.run("Refactor this module and run the tests.", { label: "refactor", cwd });
248
+ off(); // on()/once() return an unsubscribe thunk; off(name, listener) and removeAllListeners() also exist
249
+ await runner.dispose();
250
+ ```
251
+
252
+ **Event names.** The ACP `sessionUpdate` discriminants verbatim — `user_message_chunk`,
253
+ `agent_message_chunk`, `agent_thought_chunk`, `tool_call`, `tool_call_update`, `plan`,
254
+ `plan_update`, `plan_removed`, `available_commands_update`, `current_mode_update`,
255
+ `config_option_update`, `session_info_update`, `usage_update` — plus a few cross-cutting events:
256
+
257
+ | event | payload |
258
+ |-------|---------|
259
+ | `session_update` | `{ update }` — catch-all for **every** update, regardless of kind |
260
+ | `permission_request` | `{ request, outcome }` — a tool permission the runner auto-answered |
261
+ | `raw_message` | `{ method, message }` — a vendor extension notification (e.g. Claude `_claude/sdkMessage`) |
262
+ | `session_open` / `session_close` | a session opened / was released on a pooled connection |
263
+ | `backend_error` | `{ backendId, error }` — a pooled backend process crashed |
264
+
265
+ **Context envelope.** A pooled runner multiplexes many concurrent runs over one process, so every
266
+ event (except `backend_error`) carries `{ sessionId, backendId, label?, runId? }` — filter by
267
+ `label`/`runId` (from the run's `RunOptions`) to attribute an event to a specific run.
268
+
269
+ **Best-effort.** Listeners are observers: a throwing listener is isolated and never breaks the run,
270
+ the update drain, or sibling listeners.
271
+
272
+ **With `runDynamicWorkflow` / `WorkflowManager`.** Construct the runner yourself, subscribe, then
273
+ inject it: `runDynamicWorkflow(script, { runner })` or `new WorkflowManager({ agent: runner })`.
274
+ Every `agent()` call in the script then streams through your listeners (filter by `label` to tell
275
+ agents apart).
276
+
277
+ ---
278
+
211
279
  ## The in-script DSL
212
280
 
213
281
  The orchestration primitives are **not importable symbols**. They are **globals injected into the
@@ -310,11 +378,12 @@ parseWorkflowScript, // parse a script's meta + body
310
378
  WorkflowManager, // stateful / resumable run manager
311
379
 
312
380
  // ── ACP backend ──
313
- createAcpRunner, // () => AcpAgentRunner (the default AgentRunner)
381
+ createAcpRunner, // () => AcpAgentRunner (the default AgentRunner; has .on(...) events)
314
382
  AcpAgentRunner, // class — implements AgentRunner over ACP
315
383
  selectBackend, // pick Claude vs Codex from a model/tier spec
316
384
  ClaudeBackend, CodexBackend, // the concrete backends
317
385
  toJsonSchema, toStrictJsonSchema,
386
+ TypedEventEmitter, // the tiny typed emitter backing runner.on(...)
318
387
 
319
388
  // ── Errors ──
320
389
  WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit,
@@ -323,6 +392,9 @@ WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit,
323
392
  RunDynamicWorkflowOptions, WorkflowRunOptions, AgentOptions, ExecOptions,
324
393
  WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, WorkflowSnapshot,
325
394
  AcpPoolOptions, AgentRunner, RunOptions, AgentResult, AgentUsage, JournalEntry,
395
+ // ACP events: the runner.on(...) surface
396
+ AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext,
397
+ AcpSessionUpdate, AcpUpdateKind, AcpPermissionEvent, AcpRawMessageEvent, AcpBackendErrorEvent,
326
398
  ```
327
399
 
328
400
  (The DSL globals — `agent`, `parallel`, `pipeline`, … — are **not** exported; they are realm
package/dist/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export type { WorkflowRunOptions, AgentOptions, ExecOptions, WorkflowManagerOpti
5
5
  export { WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit, } from "@automatalabs/workflow-engine";
6
6
  export { createAcpRunner, AcpAgentRunner, selectBackend, ClaudeBackend, CodexBackend, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
7
7
  export type { AcpPoolOptions } from "@automatalabs/acp-agents";
8
+ export { TypedEventEmitter } from "@automatalabs/acp-agents";
9
+ export type { AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext, AcpSessionUpdate, AcpUpdateKind, AcpPermissionEvent, AcpRawMessageEvent, AcpBackendErrorEvent, } from "@automatalabs/acp-agents";
8
10
  export type { AgentRunner, RunOptions, AgentResult, AgentUsage } from "@automatalabs/shared-types";
9
11
  export type { JournalEntry } from "@automatalabs/shared-types";
10
12
  /** Options for {@link runDynamicWorkflow}. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIjF,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAClG,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAI/D,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACnG,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,8CAA8C;AAC9C,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kGAAkG;IAClG,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAE5B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIjF,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAClG,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAM/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAIlC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACnG,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,8CAA8C;AAC9C,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kGAAkG;IAClG,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAE5B"}
package/dist/index.js CHANGED
@@ -18,6 +18,11 @@ export { WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit
18
18
  // ── ACP backend: the default AgentRunner implementation, backend selection, the
19
19
  // concrete backends, the pool options, and the JSON-Schema helpers. ──
20
20
  export { createAcpRunner, AcpAgentRunner, selectBackend, ClaudeBackend, CodexBackend, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
21
+ // ── Live ACP events: `createAcpRunner().on("tool_call", evt => …)` to listen in on the
22
+ // stream of a run. The event map keys are ACP `sessionUpdate` discriminants plus a few
23
+ // cross-cutting events; each payload carries a `{ sessionId, backendId, label?, runId? }`
24
+ // context envelope so a pooled runner's concurrent runs are disambiguable. ──
25
+ export { TypedEventEmitter } from "@automatalabs/acp-agents";
21
26
  /**
22
27
  * Run a dynamic workflow script to a TERMINAL result, with the AgentRunner seam
23
28
  * defaulted to the ACP backend.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automatalabs/workflows",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,9 +24,9 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "@automatalabs/shared-types": "0.1.2",
28
- "@automatalabs/workflow-engine": "0.1.2",
29
- "@automatalabs/acp-agents": "0.1.2"
27
+ "@automatalabs/shared-types": "0.2.0",
28
+ "@automatalabs/workflow-engine": "0.1.3",
29
+ "@automatalabs/acp-agents": "0.3.0"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsc -b",