@automatalabs/workflows 0.7.0 → 0.8.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 +21 -4
- package/dist/index.d.ts +52 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +136 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -214,6 +214,18 @@ above. `WorkflowManagerOptions` lets you set a default `agent`, `concurrency`, `
|
|
|
214
214
|
`loadSavedWorkflow` resolver (enables nested `workflow('name')`), and per-agent timeout/retry
|
|
215
215
|
defaults.
|
|
216
216
|
|
|
217
|
+
Manager events are Node `EventEmitter` notifications: `agentStart`, `agentEnd`, `agentHistory`,
|
|
218
|
+
`tokenUsage`, `log`, `phase`, `complete`, `paused`, `resumed`, `stopped`, `error`, and
|
|
219
|
+
`agentEvent`. `agentEvent` forwards the live ACP stream from an ACP-capable runner with `name`,
|
|
220
|
+
`event`, and the runner context fields (`runId`, `label`, `sessionId`, `backendId`) when the event
|
|
221
|
+
carries them; `backend_error` is connection-scoped and carries `backendId` only. ACP
|
|
222
|
+
`session/update` traffic is emitted once under its inner discriminant name, while
|
|
223
|
+
permission/session/raw/backend events keep their runner names.
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
manager.on("agentEvent", ({ runId, label, name }) => console.error(runId, label, name));
|
|
227
|
+
```
|
|
228
|
+
|
|
217
229
|
### d) Bring your own backend — implement the `AgentRunner` seam
|
|
218
230
|
|
|
219
231
|
`AgentRunner` is the single, frozen coupling point between the engine and any backend. Implement
|
|
@@ -296,10 +308,11 @@ event (except `backend_error`) carries `{ sessionId, backendId, label?, runId? }
|
|
|
296
308
|
**Best-effort.** Listeners are observers: a throwing listener is isolated and never breaks the run,
|
|
297
309
|
the update drain, or sibling listeners.
|
|
298
310
|
|
|
299
|
-
**With `runDynamicWorkflow` / `WorkflowManager`.**
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
311
|
+
**With `runDynamicWorkflow` / `WorkflowManager`.** Subscribe at the manager layer:
|
|
312
|
+
`manager.on("agentEvent", ({ runId, label, name, event }) => …)`. Every `agent()` call in the
|
|
313
|
+
script then streams live ACP events through the manager; ACP `session/update` traffic is forwarded
|
|
314
|
+
once under `name = event.sessionUpdate`, so hosts do not receive both the catch-all and the
|
|
315
|
+
per-discriminant runner event.
|
|
303
316
|
|
|
304
317
|
---
|
|
305
318
|
|
|
@@ -417,9 +430,13 @@ TypedEventEmitter, // the tiny typed emitter backing runner.on(...)
|
|
|
417
430
|
// ── Errors ──
|
|
418
431
|
WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit,
|
|
419
432
|
|
|
433
|
+
// ── Persistence paths ──
|
|
434
|
+
AGENTPRISM_PERSISTENCE_ROOT_ENV,
|
|
435
|
+
|
|
420
436
|
// ── Types ──
|
|
421
437
|
RunDynamicWorkflowOptions, WorkflowRunOptions, AgentOptions, ExecOptions,
|
|
422
438
|
WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, WorkflowSnapshot,
|
|
439
|
+
WorkflowPathOptions, RunPersistenceOptions,
|
|
423
440
|
AcpPoolOptions, AgentRunner, RunOptions, AgentResult, AgentUsage, JournalEntry,
|
|
424
441
|
InteractiveSessionOptions, InteractiveTurn, PermissionResolver,
|
|
425
442
|
ClientHandlers, FsHandlers, TerminalHandlers, AcpSessionContext, NegotiatedCapabilities,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,62 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { WorkflowManager as EngineWorkflowManager } from "@automatalabs/workflow-engine";
|
|
2
|
+
import type { AcpEventName, AcpRunnerEventMap } from "@automatalabs/acp-agents";
|
|
3
|
+
import type { ExecOptions, WorkflowManagerOptions } from "@automatalabs/workflow-engine";
|
|
2
4
|
import type { AgentRunner, WorkflowBackendConfig, WorkflowRunResult } from "@automatalabs/shared-types";
|
|
3
|
-
export { runWorkflow, parseWorkflowScript
|
|
4
|
-
export type { WorkflowRunOptions, AgentOptions, ExecOptions, WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, WorkflowSnapshot, } from "@automatalabs/workflow-engine";
|
|
5
|
-
export { WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit, } from "@automatalabs/workflow-engine";
|
|
5
|
+
export { runWorkflow, parseWorkflowScript } from "@automatalabs/workflow-engine";
|
|
6
|
+
export type { WorkflowRunOptions, AgentOptions, ExecOptions, WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, WorkflowSnapshot, WorkflowPathOptions, RunPersistenceOptions, } from "@automatalabs/workflow-engine";
|
|
7
|
+
export { AGENTPRISM_PERSISTENCE_ROOT_ENV, WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit, } from "@automatalabs/workflow-engine";
|
|
6
8
|
export { createAcpRunner, AcpAgentRunner, InteractiveSession, selectBackend, ClaudeBackend, CodexBackend, CustomAcpBackend, clientCapabilitiesFor, adaptPromptContent, resolveBackendRegistry, BACKENDS_ENV, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
|
|
7
9
|
export type { AcpPoolOptions, AcpRunnerOptions, InteractiveSessionOptions, InteractiveTurn, BackendRegistry, CustomBackendConfig, RegisteredBackend, ClientHandlers, FsHandlers, TerminalHandlers, AcpSessionContext, NegotiatedCapabilities, PermissionResolver, } from "@automatalabs/acp-agents";
|
|
8
10
|
export { TypedEventEmitter } from "@automatalabs/acp-agents";
|
|
9
11
|
export type { AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext, AcpSessionUpdate, AcpUpdateKind, AcpPermissionPendingEvent, AcpPermissionEvent, AcpRawMessageEvent, AcpBackendErrorEvent, } from "@automatalabs/acp-agents";
|
|
10
12
|
export type { AgentRunner, RunOptions, AgentResult, AgentUsage } from "@automatalabs/shared-types";
|
|
11
13
|
export type { JournalEntry, WorkflowBackendConfig, WorkflowMeta } from "@automatalabs/shared-types";
|
|
14
|
+
type ContextProperty<T, K extends PropertyKey> = K extends keyof T ? T[K] : never;
|
|
15
|
+
type OptionalContextProperty<T, K extends PropertyKey> = K extends keyof T ? T[K] : undefined;
|
|
16
|
+
/** Payload of `WorkflowManager`'s `agentEvent` observer. `event` is the verbatim runner event
|
|
17
|
+
* payload; the top-level envelope repeats the ACP context fields hosts filter on. `backend_error`
|
|
18
|
+
* is connection-scoped in acp-agents and therefore has no session/run context to repeat. */
|
|
19
|
+
type AgentEventPayloadMap = {
|
|
20
|
+
[K in AcpEventName]: {
|
|
21
|
+
name: K;
|
|
22
|
+
event: AcpRunnerEventMap[K];
|
|
23
|
+
backendId: ContextProperty<AcpRunnerEventMap[K], "backendId">;
|
|
24
|
+
} & ("sessionId" extends keyof AcpRunnerEventMap[K] ? {
|
|
25
|
+
sessionId: ContextProperty<AcpRunnerEventMap[K], "sessionId">;
|
|
26
|
+
} : {
|
|
27
|
+
sessionId?: undefined;
|
|
28
|
+
}) & {
|
|
29
|
+
label?: OptionalContextProperty<AcpRunnerEventMap[K], "label">;
|
|
30
|
+
runId?: OptionalContextProperty<AcpRunnerEventMap[K], "runId">;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export type AgentEventPayload<K extends AcpEventName = AcpEventName> = AgentEventPayloadMap[K];
|
|
34
|
+
/**
|
|
35
|
+
* Stateful workflow manager exported by the SDK facade. It is the workflow-engine manager plus
|
|
36
|
+
* ONE composition-root bridge for ACP-capable runners: when the injected AgentRunner also exposes
|
|
37
|
+
* the acp-agents `.on(name, listener)` bus, the manager forwards that live stream as `agentEvent`.
|
|
38
|
+
*
|
|
39
|
+
* The engine package stays backend-agnostic; this facade already owns the ACP default runner and
|
|
40
|
+
* ACP event types, so the bridge belongs here. Forwarding is OBSERVABILITY ONLY: manager
|
|
41
|
+
* `agentEvent` listeners are isolated from each other and from the run, and `dispose()` removes
|
|
42
|
+
* only the manager's runner subscriptions (runner process ownership stays with the caller).
|
|
43
|
+
*/
|
|
44
|
+
export declare class WorkflowManager extends EngineWorkflowManager {
|
|
45
|
+
private readonly acpBridges;
|
|
46
|
+
constructor(options?: WorkflowManagerOptions);
|
|
47
|
+
startInBackground(script: string, args?: unknown, exec?: ExecOptions): {
|
|
48
|
+
runId: string;
|
|
49
|
+
promise: Promise<WorkflowRunResult>;
|
|
50
|
+
};
|
|
51
|
+
runSync(script: string, args?: unknown, exec?: ExecOptions): Promise<WorkflowRunResult>;
|
|
52
|
+
resume(runId: string, exec?: ExecOptions): Promise<boolean>;
|
|
53
|
+
/** Detach manager-owned ACP event subscriptions. The manager does NOT dispose the runner: the
|
|
54
|
+
* caller may share one runner across managers or own its process lifetime explicitly. */
|
|
55
|
+
dispose(): void;
|
|
56
|
+
/** Node-style alias for hosts that tear down managers through close hooks. */
|
|
57
|
+
close(): void;
|
|
58
|
+
private acquireAcpRunnerBridge;
|
|
59
|
+
}
|
|
12
60
|
/**
|
|
13
61
|
* Approval policy for SCRIPT-DECLARED custom ACP backends (`meta.backends`). Script backends
|
|
14
62
|
* spawn arbitrary commands on this machine, so they are INERT unless the embedder approves
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/// <reference path="./dsl.d.ts" />
|
|
2
2
|
// @automatalabs/workflows — the importable SDK for the AgentPrism dynamic-workflow
|
|
3
|
-
// orchestrator. A
|
|
4
|
-
//
|
|
5
|
-
// convenience helper (`runDynamicWorkflow`) that defaults the AgentRunner seam
|
|
6
|
-
// ACP backend. It is SEPARATE from @automatalabs/mcp-server (the stdio MCP server)
|
|
7
|
-
// stays a PURE library — it pulls in neither @modelcontextprotocol/sdk nor zod.
|
|
3
|
+
// orchestrator. A FACADE re-export barrel: it re-exports the clean public surface of
|
|
4
|
+
// the three engine packages, adds the SDK-level WorkflowManager ACP-event bridge, and
|
|
5
|
+
// adds ONE convenience helper (`runDynamicWorkflow`) that defaults the AgentRunner seam
|
|
6
|
+
// to the ACP backend. It is SEPARATE from @automatalabs/mcp-server (the stdio MCP server)
|
|
7
|
+
// and stays a PURE library — it pulls in neither @modelcontextprotocol/sdk nor zod.
|
|
8
8
|
//
|
|
9
9
|
// The DSL globals available INSIDE a workflow script (agent, parallel, pipeline, …) are
|
|
10
10
|
// vm-realm globals, NOT importable symbols; they are documented for author IntelliSense
|
|
11
11
|
// in ./dsl.d.ts (referenced above), not exported here.
|
|
12
|
-
import { createAcpRunner } from "@automatalabs/acp-agents";
|
|
13
|
-
import { parseWorkflowScript, WorkflowError, WorkflowErrorCode, WorkflowManager } from "@automatalabs/workflow-engine";
|
|
12
|
+
import { ACP_CROSS_CUTTING_EVENT_NAMES, createAcpRunner } from "@automatalabs/acp-agents";
|
|
13
|
+
import { parseWorkflowScript, WorkflowError, WorkflowErrorCode, WorkflowManager as EngineWorkflowManager, } from "@automatalabs/workflow-engine";
|
|
14
14
|
// ── Engine: run entry, script parsing, the managed-run lifecycle, and the
|
|
15
15
|
// option/result + error types the host composes against. ──
|
|
16
|
-
export { runWorkflow, parseWorkflowScript
|
|
17
|
-
export { WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit, } from "@automatalabs/workflow-engine";
|
|
16
|
+
export { runWorkflow, parseWorkflowScript } from "@automatalabs/workflow-engine";
|
|
17
|
+
export { AGENTPRISM_PERSISTENCE_ROOT_ENV, WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit, } from "@automatalabs/workflow-engine";
|
|
18
18
|
// ── ACP backend: the default AgentRunner implementation, interactive sessions, backend
|
|
19
19
|
// selection, the concrete backends (built-in + custom registry), the pool/runner options,
|
|
20
20
|
// capability helpers, client handlers, permission resolvers, and JSON-Schema helpers.
|
|
@@ -27,6 +27,126 @@ export { createAcpRunner, AcpAgentRunner, InteractiveSession, selectBackend, Cla
|
|
|
27
27
|
// cross-cutting events; each payload carries a `{ sessionId, backendId, label?, runId? }`
|
|
28
28
|
// context envelope so a pooled runner's concurrent runs are disambiguable. ──
|
|
29
29
|
export { TypedEventEmitter } from "@automatalabs/acp-agents";
|
|
30
|
+
const MANAGER_ACP_CROSS_CUTTING_EVENT_NAMES = ACP_CROSS_CUTTING_EVENT_NAMES;
|
|
31
|
+
/**
|
|
32
|
+
* Stateful workflow manager exported by the SDK facade. It is the workflow-engine manager plus
|
|
33
|
+
* ONE composition-root bridge for ACP-capable runners: when the injected AgentRunner also exposes
|
|
34
|
+
* the acp-agents `.on(name, listener)` bus, the manager forwards that live stream as `agentEvent`.
|
|
35
|
+
*
|
|
36
|
+
* The engine package stays backend-agnostic; this facade already owns the ACP default runner and
|
|
37
|
+
* ACP event types, so the bridge belongs here. Forwarding is OBSERVABILITY ONLY: manager
|
|
38
|
+
* `agentEvent` listeners are isolated from each other and from the run, and `dispose()` removes
|
|
39
|
+
* only the manager's runner subscriptions (runner process ownership stays with the caller).
|
|
40
|
+
*/
|
|
41
|
+
export class WorkflowManager extends EngineWorkflowManager {
|
|
42
|
+
acpBridges = new Map();
|
|
43
|
+
constructor(options = {}) {
|
|
44
|
+
super(options);
|
|
45
|
+
this.acquireAcpRunnerBridge(options.agent);
|
|
46
|
+
}
|
|
47
|
+
startInBackground(script, args, exec = {}) {
|
|
48
|
+
const releaseBridge = this.acquireAcpRunnerBridge(exec.agent);
|
|
49
|
+
try {
|
|
50
|
+
const started = super.startInBackground(script, args, exec);
|
|
51
|
+
void started.promise.then(releaseBridge, releaseBridge);
|
|
52
|
+
return started;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
releaseBridge();
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
async runSync(script, args, exec = {}) {
|
|
60
|
+
const releaseBridge = this.acquireAcpRunnerBridge(exec.agent);
|
|
61
|
+
try {
|
|
62
|
+
return await super.runSync(script, args, exec);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
releaseBridge();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async resume(runId, exec = {}) {
|
|
69
|
+
const releaseBridge = this.acquireAcpRunnerBridge(exec.agent);
|
|
70
|
+
try {
|
|
71
|
+
return await super.resume(runId, exec);
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
releaseBridge();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Detach manager-owned ACP event subscriptions. The manager does NOT dispose the runner: the
|
|
78
|
+
* caller may share one runner across managers or own its process lifetime explicitly. */
|
|
79
|
+
dispose() {
|
|
80
|
+
for (const bridge of this.acpBridges.values()) {
|
|
81
|
+
for (const unsubscribe of bridge.unsubscribers)
|
|
82
|
+
unsubscribe();
|
|
83
|
+
}
|
|
84
|
+
this.acpBridges.clear();
|
|
85
|
+
}
|
|
86
|
+
/** Node-style alias for hosts that tear down managers through close hooks. */
|
|
87
|
+
close() {
|
|
88
|
+
this.dispose();
|
|
89
|
+
}
|
|
90
|
+
acquireAcpRunnerBridge(agent) {
|
|
91
|
+
if (!isAcpEventBusRunner(agent))
|
|
92
|
+
return () => { };
|
|
93
|
+
let bridge = this.acpBridges.get(agent);
|
|
94
|
+
if (!bridge) {
|
|
95
|
+
bridge = {
|
|
96
|
+
refs: 0,
|
|
97
|
+
unsubscribers: [
|
|
98
|
+
agent.on("session_update", (event) => {
|
|
99
|
+
this.emit("agentEvent", toSessionUpdateAgentEventPayload(event));
|
|
100
|
+
}),
|
|
101
|
+
...MANAGER_ACP_CROSS_CUTTING_EVENT_NAMES.map((name) => agent.on(name, (event) => {
|
|
102
|
+
this.emit("agentEvent", toAgentEventPayload(name, event));
|
|
103
|
+
})),
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
this.acpBridges.set(agent, bridge);
|
|
107
|
+
}
|
|
108
|
+
bridge.refs++;
|
|
109
|
+
let active = true;
|
|
110
|
+
return () => {
|
|
111
|
+
if (!active)
|
|
112
|
+
return;
|
|
113
|
+
active = false;
|
|
114
|
+
const current = this.acpBridges.get(agent);
|
|
115
|
+
if (current !== bridge)
|
|
116
|
+
return;
|
|
117
|
+
current.refs--;
|
|
118
|
+
if (current.refs > 0)
|
|
119
|
+
return;
|
|
120
|
+
for (const unsubscribe of current.unsubscribers)
|
|
121
|
+
unsubscribe();
|
|
122
|
+
this.acpBridges.delete(agent);
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function isAcpEventBusRunner(agent) {
|
|
127
|
+
return typeof agent?.on === "function";
|
|
128
|
+
}
|
|
129
|
+
function toSessionUpdateAgentEventPayload(event) {
|
|
130
|
+
const name = event.update.sessionUpdate;
|
|
131
|
+
return toAgentEventPayload(name, {
|
|
132
|
+
...event.update,
|
|
133
|
+
sessionId: event.sessionId,
|
|
134
|
+
backendId: event.backendId,
|
|
135
|
+
label: event.label,
|
|
136
|
+
runId: event.runId,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function toAgentEventPayload(name, event) {
|
|
140
|
+
const context = event;
|
|
141
|
+
return {
|
|
142
|
+
name,
|
|
143
|
+
event,
|
|
144
|
+
backendId: context.backendId,
|
|
145
|
+
...(context.sessionId !== undefined ? { sessionId: context.sessionId } : {}),
|
|
146
|
+
...(context.label !== undefined ? { label: context.label } : {}),
|
|
147
|
+
...(context.runId !== undefined ? { runId: context.runId } : {}),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
30
150
|
/**
|
|
31
151
|
* Run a dynamic workflow script to a TERMINAL result, with the AgentRunner seam
|
|
32
152
|
* defaulted to the ACP backend.
|
|
@@ -52,7 +172,13 @@ export async function runDynamicWorkflow(script, opts = {}) {
|
|
|
52
172
|
if (declared && Object.keys(declared).length > 0) {
|
|
53
173
|
exec = { ...(exec ?? {}), scriptBackends: await approveScriptBackends(declared, opts.allowScriptBackends) };
|
|
54
174
|
}
|
|
55
|
-
|
|
175
|
+
const manager = new WorkflowManager({ agent: opts.runner ?? createAcpRunner() });
|
|
176
|
+
try {
|
|
177
|
+
return await manager.runSync(script, opts.args, exec);
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
manager.dispose();
|
|
181
|
+
}
|
|
56
182
|
}
|
|
57
183
|
/** Resolve the embedder's approval policy over the declared backends; throw with guidance when
|
|
58
184
|
* approval is missing or any backend is declined (an unapproved dependency must abort, never
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automatalabs/workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@automatalabs/shared-types": "0.7.0",
|
|
28
|
-
"@automatalabs/workflow-engine": "0.
|
|
28
|
+
"@automatalabs/workflow-engine": "0.4.0",
|
|
29
29
|
"@automatalabs/acp-agents": "0.9.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|