@automatalabs/workflows 0.6.2 → 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 +30 -7
- package/dist/index.d.ts +55 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +141 -14
- package/package.json +3 -3
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
|
|
@@ -283,9 +295,10 @@ await runner.dispose();
|
|
|
283
295
|
| event | payload |
|
|
284
296
|
|-------|---------|
|
|
285
297
|
| `session_update` | `{ update }` — catch-all for **every** update, regardless of kind |
|
|
286
|
-
| `
|
|
298
|
+
| `permission_pending` | `{ request }` — resolver-only; emitted after the request is parked and before the resolver is invoked |
|
|
299
|
+
| `permission_request` | `{ request, outcome }` — the final permission outcome returned to the agent |
|
|
287
300
|
| `raw_message` | `{ method, message }` — a vendor extension notification (e.g. Claude `_claude/sdkMessage`) |
|
|
288
|
-
| `session_open` / `session_close` |
|
|
301
|
+
| `session_open` / `session_close` | an ACP session opened / was released |
|
|
289
302
|
| `backend_error` | `{ backendId, error }` — a pooled backend process crashed |
|
|
290
303
|
|
|
291
304
|
**Context envelope.** A pooled runner multiplexes many concurrent runs over one process, so every
|
|
@@ -295,10 +308,11 @@ event (except `backend_error`) carries `{ sessionId, backendId, label?, runId? }
|
|
|
295
308
|
**Best-effort.** Listeners are observers: a throwing listener is isolated and never breaks the run,
|
|
296
309
|
the update drain, or sibling listeners.
|
|
297
310
|
|
|
298
|
-
**With `runDynamicWorkflow` / `WorkflowManager`.**
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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.
|
|
302
316
|
|
|
303
317
|
---
|
|
304
318
|
|
|
@@ -406,21 +420,30 @@ WorkflowManager, // stateful / resumable run manager
|
|
|
406
420
|
// ── ACP backend ──
|
|
407
421
|
createAcpRunner, // () => AcpAgentRunner (the default AgentRunner; has .on(...) events)
|
|
408
422
|
AcpAgentRunner, // class — implements AgentRunner over ACP
|
|
423
|
+
InteractiveSession, // held-open multi-turn ACP session returned by openSession()
|
|
409
424
|
selectBackend, // pick Claude vs Codex from a model/tier spec
|
|
410
425
|
ClaudeBackend, CodexBackend, // the concrete backends
|
|
426
|
+
clientCapabilitiesFor, adaptPromptContent,
|
|
411
427
|
toJsonSchema, toStrictJsonSchema,
|
|
412
428
|
TypedEventEmitter, // the tiny typed emitter backing runner.on(...)
|
|
413
429
|
|
|
414
430
|
// ── Errors ──
|
|
415
431
|
WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit,
|
|
416
432
|
|
|
433
|
+
// ── Persistence paths ──
|
|
434
|
+
AGENTPRISM_PERSISTENCE_ROOT_ENV,
|
|
435
|
+
|
|
417
436
|
// ── Types ──
|
|
418
437
|
RunDynamicWorkflowOptions, WorkflowRunOptions, AgentOptions, ExecOptions,
|
|
419
438
|
WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, WorkflowSnapshot,
|
|
439
|
+
WorkflowPathOptions, RunPersistenceOptions,
|
|
420
440
|
AcpPoolOptions, AgentRunner, RunOptions, AgentResult, AgentUsage, JournalEntry,
|
|
441
|
+
InteractiveSessionOptions, InteractiveTurn, PermissionResolver,
|
|
442
|
+
ClientHandlers, FsHandlers, TerminalHandlers, AcpSessionContext, NegotiatedCapabilities,
|
|
421
443
|
// ACP events: the runner.on(...) surface
|
|
422
444
|
AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext,
|
|
423
|
-
AcpSessionUpdate, AcpUpdateKind,
|
|
445
|
+
AcpSessionUpdate, AcpUpdateKind, AcpPermissionPendingEvent, AcpPermissionEvent,
|
|
446
|
+
AcpRawMessageEvent, AcpBackendErrorEvent,
|
|
424
447
|
```
|
|
425
448
|
|
|
426
449
|
(The DSL globals — `agent`, `parallel`, `pipeline`, … — are **not** exported; they are realm
|
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";
|
|
6
|
-
export { createAcpRunner, AcpAgentRunner, selectBackend, ClaudeBackend, CodexBackend, CustomAcpBackend, resolveBackendRegistry, BACKENDS_ENV, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
|
|
7
|
-
export type { AcpPoolOptions, AcpRunnerOptions, BackendRegistry, CustomBackendConfig, RegisteredBackend, } from "@automatalabs/acp-agents";
|
|
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";
|
|
8
|
+
export { createAcpRunner, AcpAgentRunner, InteractiveSession, selectBackend, ClaudeBackend, CodexBackend, CustomAcpBackend, clientCapabilitiesFor, adaptPromptContent, resolveBackendRegistry, BACKENDS_ENV, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
|
|
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
|
-
export type { AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext, AcpSessionUpdate, AcpUpdateKind, AcpPermissionEvent, AcpRawMessageEvent, AcpBackendErrorEvent, } from "@automatalabs/acp-agents";
|
|
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,31 +1,152 @@
|
|
|
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";
|
|
18
|
-
// ── ACP backend: the default AgentRunner implementation,
|
|
19
|
-
// concrete backends (built-in + custom registry), the pool/runner options,
|
|
20
|
-
//
|
|
16
|
+
export { runWorkflow, parseWorkflowScript } from "@automatalabs/workflow-engine";
|
|
17
|
+
export { AGENTPRISM_PERSISTENCE_ROOT_ENV, WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit, } from "@automatalabs/workflow-engine";
|
|
18
|
+
// ── ACP backend: the default AgentRunner implementation, interactive sessions, backend
|
|
19
|
+
// selection, the concrete backends (built-in + custom registry), the pool/runner options,
|
|
20
|
+
// capability helpers, client handlers, permission resolvers, and JSON-Schema helpers.
|
|
21
|
+
// Custom backends let ANY ACP agent serve agent() calls:
|
|
21
22
|
// `createAcpRunner({ backends: { browser: { command: "…" } } })` (or the
|
|
22
23
|
// AGENTPRISM_BACKENDS env var), then route with `agent(p, { model: "browser" })`. ──
|
|
23
|
-
export { createAcpRunner, AcpAgentRunner, selectBackend, ClaudeBackend, CodexBackend, CustomAcpBackend, resolveBackendRegistry, BACKENDS_ENV, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
|
|
24
|
+
export { createAcpRunner, AcpAgentRunner, InteractiveSession, selectBackend, ClaudeBackend, CodexBackend, CustomAcpBackend, clientCapabilitiesFor, adaptPromptContent, resolveBackendRegistry, BACKENDS_ENV, toJsonSchema, toStrictJsonSchema, } from "@automatalabs/acp-agents";
|
|
24
25
|
// ── Live ACP events: `createAcpRunner().on("tool_call", evt => …)` to listen in on the
|
|
25
26
|
// stream of a run. The event map keys are ACP `sessionUpdate` discriminants plus a few
|
|
26
27
|
// cross-cutting events; each payload carries a `{ sessionId, backendId, label?, runId? }`
|
|
27
28
|
// context envelope so a pooled runner's concurrent runs are disambiguable. ──
|
|
28
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
|
+
}
|
|
29
150
|
/**
|
|
30
151
|
* Run a dynamic workflow script to a TERMINAL result, with the AgentRunner seam
|
|
31
152
|
* defaulted to the ACP backend.
|
|
@@ -51,7 +172,13 @@ export async function runDynamicWorkflow(script, opts = {}) {
|
|
|
51
172
|
if (declared && Object.keys(declared).length > 0) {
|
|
52
173
|
exec = { ...(exec ?? {}), scriptBackends: await approveScriptBackends(declared, opts.allowScriptBackends) };
|
|
53
174
|
}
|
|
54
|
-
|
|
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
|
+
}
|
|
55
182
|
}
|
|
56
183
|
/** Resolve the embedder's approval policy over the declared backends; throw with guidance when
|
|
57
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,8 +25,8 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@automatalabs/shared-types": "0.7.0",
|
|
28
|
-
"@automatalabs/workflow-engine": "0.
|
|
29
|
-
"@automatalabs/acp-agents": "0.
|
|
28
|
+
"@automatalabs/workflow-engine": "0.4.0",
|
|
29
|
+
"@automatalabs/acp-agents": "0.9.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsc -b",
|