@automatalabs/workflows 0.1.1 → 0.1.2

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 ADDED
@@ -0,0 +1,342 @@
1
+ # @automatalabs/workflows
2
+
3
+ The programmatic **SDK** for AgentPrism — run dynamic, multi-agent **workflow scripts**
4
+ (`agent()` / `parallel()` / `pipeline()` / …) over real coding-agent backends through the
5
+ [Agent Client Protocol](https://agentclientprotocol.com) (ACP).
6
+
7
+ You author a small JavaScript **script** (a string), the engine runs it in a deterministic,
8
+ journaled, resumable realm, and every `agent()` call inside it is fanned out to a pooled ACP
9
+ backend — **Claude** (`claude-agent-acp`) or **Codex** (`codex-acp`) — driving the actual agent
10
+ subprocess to completion.
11
+
12
+ This package is the **canonical SDK** that the stdio MCP server
13
+ [`@automatalabs/mcp-server`](https://www.npmjs.com/package/@automatalabs/mcp-server) is built on.
14
+ If you want to expose a `workflow` tool to an MCP host (Claude Code, Zed, …), use that package; if
15
+ you want to embed the runner in your own program, use this one.
16
+
17
+ It is a **pure library**: it pulls in neither `@modelcontextprotocol/sdk` nor `zod`. It is a thin
18
+ facade that re-exports the clean public surface of the engine + ACP packages and adds one
19
+ convenience helper, `runDynamicWorkflow`, which defaults the agent backend to ACP.
20
+
21
+ ---
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pnpm add @automatalabs/workflows
27
+ ```
28
+
29
+ > The backend ACP servers ship as transitive dependencies and are spawned for you on demand; you
30
+ > do not install or start them separately.
31
+
32
+ ---
33
+
34
+ ## Requirements
35
+
36
+ - **Node.js ≥ 22.**
37
+ - **Backend auth** — the SDK spawns the ACP backend as a child process that inherits your
38
+ `process.env`, so it uses whatever credentials those agents already use:
39
+ - **Claude** — a logged-in Claude Code install (`~/.claude`) **or** `ANTHROPIC_API_KEY` in the
40
+ environment.
41
+ - **Codex** — a logged-in Codex install (`~/.codex`).
42
+
43
+ You only need auth for the backend(s) your scripts actually route to. The default backend is
44
+ Claude (override with `AGENTPRISM_DEFAULT_BACKEND`; see [Backend selection](#backend-selection)).
45
+
46
+ ---
47
+
48
+ ## Core API
49
+
50
+ ### a) `runDynamicWorkflow(script, opts?)` — run a script to a terminal result
51
+
52
+ The one-call entry point. It builds a one-off `WorkflowManager` whose agent backend defaults to
53
+ `createAcpRunner()` and runs the script to a **terminal** `WorkflowRunResult`. It never throws for
54
+ an ordinary pause/fail/abort — read `result.status` directly.
55
+
56
+ ```ts
57
+ import { runDynamicWorkflow } from "@automatalabs/workflows";
58
+
59
+ const script = `
60
+ export const meta = {
61
+ name: "repo-scan",
62
+ description: "describe a repo as JSON, two ways in parallel",
63
+ phases: [{ title: "Fan" }],
64
+ };
65
+
66
+ const SCHEMA = {
67
+ type: "object",
68
+ additionalProperties: false,
69
+ required: ["repo", "fileCount"],
70
+ properties: { repo: { type: "string" }, fileCount: { type: "number" } },
71
+ };
72
+
73
+ phase("Fan");
74
+ log("scanning " + args.repo);
75
+ return await parallel([
76
+ () => agent("Report this repo as JSON {repo, fileCount}.", { label: "a1", schema: SCHEMA }),
77
+ () => agent("Report this repo as JSON {repo, fileCount}.", { label: "a2", schema: SCHEMA }),
78
+ ]);
79
+ `;
80
+
81
+ const run = await runDynamicWorkflow(script, { args: { repo: "agentprism" } });
82
+
83
+ run.status; // "completed" | "paused" | "failed" | "aborted"
84
+ run.result; // [{ repo, fileCount }, …] — the script's return value (schema-validated)
85
+ run.tokenUsage; // { input, output, total, cost, … } | undefined
86
+ run.runId; // stable id; pass back to resume a paused run from its journal
87
+ ```
88
+
89
+ Options (`RunDynamicWorkflowOptions`):
90
+
91
+ | field | type | meaning |
92
+ |----------|----------------|---------|
93
+ | `args` | `unknown` | The value handed to the script's `args` global. |
94
+ | `runner` | `AgentRunner` | Swap the backend (or stub it in tests). Omitted ⇒ `createAcpRunner()`. |
95
+ | `exec` | `ExecOptions` | Per-run controls forwarded to the manager: `tokenBudget`, `agentTimeoutMs`, `concurrency`, `agentRetries`, `signal`, `onProgress`, `confirm`, … |
96
+
97
+ ```ts
98
+ const run = await runDynamicWorkflow(script, {
99
+ args: { repo: "agentprism" },
100
+ exec: {
101
+ tokenBudget: 200_000,
102
+ concurrency: 4,
103
+ onProgress: (snapshot) => console.error(snapshot.doneCount, "/", snapshot.agentCount),
104
+ },
105
+ });
106
+ ```
107
+
108
+ Every script **must** begin with `export const meta = { name, description, phases? }` as its first
109
+ statement, and must be **deterministic** — `Date.now()`, `Math.random()`, and `new Date()` are
110
+ unavailable inside the realm (they would break journal replay on resume).
111
+
112
+ ### b) `createAcpRunner().run(...)` — drive a single agent
113
+
114
+ Skip the script realm entirely and call one agent directly. The runner is the default ACP
115
+ `AgentRunner`. With a `schema`, `run()` returns the **validated object**; without one, it returns
116
+ the assistant's final **text**.
117
+
118
+ ```ts
119
+ import { createAcpRunner } from "@automatalabs/workflows";
120
+
121
+ const runner = createAcpRunner(); // optional: { size } pool option, default 1
122
+ try {
123
+ const data = await runner.run("Summarize this repo as JSON {summary}.", {
124
+ schema: {
125
+ type: "object", additionalProperties: false,
126
+ required: ["summary"], properties: { summary: { type: "string" } },
127
+ },
128
+ model: "opus", // routes to Claude; e.g. "gpt-5-codex" routes to Codex
129
+ cwd: process.cwd(), // absolute working dir for the agent's session
130
+ });
131
+ // data is the schema-validated object (not text)
132
+
133
+ const text = await runner.run("Name this repo in one word."); // no schema ⇒ string
134
+ } finally {
135
+ await runner.dispose(); // close the pooled backend processes when you're done
136
+ }
137
+ ```
138
+
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.
144
+
145
+ > The ACP server **process** is pooled and reused across `run()` calls; each `run()` opens and
146
+ > closes one **session** on it. Call `dispose()` once at shutdown to tear the pool down. Pool size
147
+ > is `AcpPoolOptions.size` (default 1) or `AGENTPRISM_ACP_POOL_SIZE`.
148
+
149
+ ### c) `WorkflowManager` — stateful / resumable runs
150
+
151
+ `runDynamicWorkflow` is a thin wrapper over a fresh `WorkflowManager`. Construct one yourself to
152
+ keep run state across calls, persist journals, and **resume** a paused run.
153
+
154
+ ```ts
155
+ import { WorkflowManager, createAcpRunner } from "@automatalabs/workflows";
156
+
157
+ const manager = new WorkflowManager({ agent: createAcpRunner() });
158
+
159
+ const run = await manager.runSync(script, { repo: "agentprism" }, { tokenBudget: 200_000 });
160
+
161
+ if (run.status === "paused") {
162
+ // A pause carries a journal of every completed agent() call. Re-hydrate it and re-run the
163
+ // SAME script: the unchanged prefix is replayed from the journal, the rest runs live.
164
+ const persisted = manager.getPersistence().load(run.runId);
165
+ const resumeJournal = new Map(persisted?.journal?.map((e) => [e.index, e]) ?? []);
166
+ const finished = await manager.runSync(script, { repo: "agentprism" }, { resumeJournal });
167
+ console.log(finished.status); // "completed", typically
168
+ }
169
+ ```
170
+
171
+ `runSync(script, args?, exec?)` always resolves to a terminal `WorkflowRunResult`. A run **pauses**
172
+ (rather than fails) on a provider usage limit or a headless `checkpoint()`; both are resumable as
173
+ above. `WorkflowManagerOptions` lets you set a default `agent`, `concurrency`, `cwd`, a
174
+ `loadSavedWorkflow` resolver (enables nested `workflow('name')`), and per-agent timeout/retry
175
+ defaults.
176
+
177
+ ### d) Bring your own backend — implement the `AgentRunner` seam
178
+
179
+ `AgentRunner` is the single, frozen coupling point between the engine and any backend. Implement
180
+ its one method and inject it anywhere a runner is accepted (`runDynamicWorkflow({ runner })`,
181
+ `new WorkflowManager({ agent })`, or `runSync(script, args, { agent })`).
182
+
183
+ ```ts
184
+ import {
185
+ runDynamicWorkflow,
186
+ type AgentRunner,
187
+ type RunOptions,
188
+ type AgentResult,
189
+ } from "@automatalabs/workflows";
190
+ import type { TSchema } from "typebox";
191
+
192
+ const echoRunner: AgentRunner = {
193
+ async run<S extends TSchema | undefined>(prompt: string, options?: RunOptions<S>) {
194
+ // schema present ⇒ return the validated object; absent ⇒ return text.
195
+ options?.onUsage?.({ input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0, cost: 0 });
196
+ return `echo: ${prompt}` as AgentResult<S>;
197
+ },
198
+ };
199
+
200
+ const run = await runDynamicWorkflow(script, { runner: echoRunner });
201
+ ```
202
+
203
+ Seam contract (summarized): `run()` returns the **raw** value (schema ⇒ validated object, no schema
204
+ ⇒ string) — never an envelope; usage flows out-of-band via `options.onUsage`; on failure **throw**
205
+ (ideally a `WorkflowError` so `instanceof` holds across packages); honor `options.signal` but do
206
+ **not** implement your own timeout (the engine owns timeout/abort). This makes the SDK fully
207
+ testable without a live agent — pass a stub runner.
208
+
209
+ ---
210
+
211
+ ## The in-script DSL
212
+
213
+ The orchestration primitives are **not importable symbols**. They are **globals injected into the
214
+ script's `vm` realm**, available only **inside** the script string you pass to
215
+ `runDynamicWorkflow` / `runSync`. There is nothing to import to obtain them. Their shapes are
216
+ documented for editor IntelliSense by the **ambient `dsl.d.ts`** shipped with this package (it
217
+ ships no runtime code).
218
+
219
+ | global | what it does |
220
+ |--------|--------------|
221
+ | `agent(prompt, options?)` | Run ONE subagent to completion; returns its result (text, or the validated object with `options.schema`). |
222
+ | `parallel(thunks)` | Run an array of **thunks** (`() => Promise`) concurrently; resolves in input order. |
223
+ | `pipeline(items, ...stages)` | Map `items` through sequential async stages, concurrently across items. |
224
+ | `workflow(nameOrScript, args?)` | Run a saved (or inline) workflow nested in this run, sharing its limiter/budget. |
225
+ | `verify(item, options?)` | Adversarial verification panel — N reviewers vote whether `item` is real/correct. |
226
+ | `judgePanel(attempts, options?)` | LLM-judge panel — score candidates against a rubric, return the best. |
227
+ | `loopUntilDry(options)` | Repeat a round, collecting deduped new items until it dries up. |
228
+ | `completenessCheck(args, results)` | Ask a critic what is still missing. |
229
+ | `retry(thunk, options?)` | Bounded retry until `until(result)` holds. |
230
+ | `gate(thunk, validator, options?)` | Validate-and-feed-back loop until it passes. |
231
+ | `checkpoint(text, options?)` | Deterministic, journaled human gate (headless takes a default). |
232
+ | `phase(title, options?)` | Open a named phase (optional soft token sub-budget). |
233
+ | `log(message)` | Append a line to the run log. |
234
+ | `args` | The input bag passed in via `{ args }`. |
235
+ | `budget` | Live token-budget view: `budget.total`, `budget.spent()`, `budget.remaining()`. |
236
+
237
+ (`console.log/info/warn/error` route to `log` too.) Pass these primitives **thunks**, not
238
+ promises — `parallel([() => agent("a"), () => agent("b")])`, not `parallel([agent("a"), …])`.
239
+
240
+ ---
241
+
242
+ ## Structured output
243
+
244
+ Pass a JSON Schema to `agent({ schema })` (in a script) or `runner.run(prompt, { schema })` (direct)
245
+ and the result is a **validated object** instead of text. The backend constrains output natively
246
+ (Claude `outputFormat`; Codex strict `outputSchema`), then the value is coerced and validated
247
+ client-side (typebox `Convert` → `Check`); on a miss the runner re-prompts a bounded number of
248
+ times before failing with a non-recoverable `SCHEMA_NONCOMPLIANCE`.
249
+
250
+ A **plain JSON Schema object literal** works everywhere (this is the only option inside a script —
251
+ no schema-builder is injected into the realm):
252
+
253
+ ```json
254
+ {
255
+ "type": "object",
256
+ "additionalProperties": false,
257
+ "required": ["title", "score"],
258
+ "properties": {
259
+ "title": { "type": "string" },
260
+ "score": { "type": "number" }
261
+ }
262
+ }
263
+ ```
264
+
265
+ In TypeScript you may instead build the schema with [typebox](https://github.com/sinclairzx81/typebox)
266
+ (`Type.Object({ … })`) for static result typing. Two helpers convert a typebox schema to the exact
267
+ wire JSON Schema each backend expects:
268
+
269
+ ```ts
270
+ import { toJsonSchema, toStrictJsonSchema } from "@automatalabs/workflows";
271
+ import { Type } from "typebox";
272
+
273
+ const schema = Type.Object({ title: Type.String(), score: Type.Number() });
274
+ toJsonSchema(schema); // plain JSON Schema (Claude outputFormat)
275
+ toStrictJsonSchema(schema); // OpenAI-strict-normalized (Codex outputSchema)
276
+ ```
277
+
278
+ ---
279
+
280
+ ## Backend selection
281
+
282
+ The backend for each agent is chosen from its `model` (preferred) or `tier` string:
283
+
284
+ - **Provider prefix** — `anthropic/…` or `claude/…` ⇒ Claude; `openai/…` or `codex/…` ⇒ Codex.
285
+ - **Bare id** — matched by pattern: `codex` / `gpt` / `openai` / `o<digit>` ⇒ Codex;
286
+ `claude` / `opus` / `sonnet` / `haiku` / `anthropic` ⇒ Claude.
287
+ - **No match / no spec** — the default backend: `AGENTPRISM_DEFAULT_BACKEND` (`claude` | `codex`,
288
+ default `claude`).
289
+
290
+ ```ts
291
+ import { selectBackend } from "@automatalabs/workflows";
292
+
293
+ selectBackend({ model: "opus" }).id; // "claude"
294
+ selectBackend({ model: "gpt-5-codex" }).id; // "codex"
295
+ selectBackend({ model: "anthropic/claude-sonnet" }).id; // "claude"
296
+ ```
297
+
298
+ Within a provider, the model spec selects the concrete model on the session (Claude `_meta` model /
299
+ Codex config). Per-backend pool size is `AGENTPRISM_ACP_POOL_SIZE` (or `AcpPoolOptions.size`).
300
+
301
+ ---
302
+
303
+ ## Exports
304
+
305
+ ```ts
306
+ // ── Run entry & helper ──
307
+ runDynamicWorkflow, // (script, { args?, runner?, exec? }) => Promise<WorkflowRunResult>
308
+ runWorkflow, // the bare engine run (no status trio)
309
+ parseWorkflowScript, // parse a script's meta + body
310
+ WorkflowManager, // stateful / resumable run manager
311
+
312
+ // ── ACP backend ──
313
+ createAcpRunner, // () => AcpAgentRunner (the default AgentRunner)
314
+ AcpAgentRunner, // class — implements AgentRunner over ACP
315
+ selectBackend, // pick Claude vs Codex from a model/tier spec
316
+ ClaudeBackend, CodexBackend, // the concrete backends
317
+ toJsonSchema, toStrictJsonSchema,
318
+
319
+ // ── Errors ──
320
+ WorkflowError, WorkflowErrorCode, isWorkflowError, isProviderUsageLimit,
321
+
322
+ // ── Types ──
323
+ RunDynamicWorkflowOptions, WorkflowRunOptions, AgentOptions, ExecOptions,
324
+ WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, WorkflowSnapshot,
325
+ AcpPoolOptions, AgentRunner, RunOptions, AgentResult, AgentUsage, JournalEntry,
326
+ ```
327
+
328
+ (The DSL globals — `agent`, `parallel`, `pipeline`, … — are **not** exported; they are realm
329
+ globals documented by the ambient `dsl.d.ts`.)
330
+
331
+ ---
332
+
333
+ ## See also
334
+
335
+ - **[`@automatalabs/mcp-server`](https://www.npmjs.com/package/@automatalabs/mcp-server)** — the
336
+ stdio MCP server built on this SDK. It wraps the same engine + ACP backend behind a single
337
+ `workflow` tool (bin: `agentprism-workflow`) for any MCP host. Use it when you want the
338
+ **MCP-tool route** instead of embedding the runner in code.
339
+
340
+ ## License
341
+
342
+ Apache-2.0
package/dist/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import type { ExecOptions } from "@automatalabs/workflow-engine";
2
2
  import type { AgentRunner, WorkflowRunResult } from "@automatalabs/shared-types";
3
3
  export { runWorkflow, parseWorkflowScript, WorkflowManager } from "@automatalabs/workflow-engine";
4
- export type { WorkflowRunOptions, AgentOptions, ExecOptions, WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, } from "@automatalabs/workflow-engine";
4
+ export type { WorkflowRunOptions, AgentOptions, ExecOptions, WorkflowManagerOptions, CheckpointOptions, WorkflowRunResult, WorkflowSnapshot, } from "@automatalabs/workflow-engine";
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
8
  export type { AgentRunner, RunOptions, AgentResult, AgentUsage } from "@automatalabs/shared-types";
9
+ export type { JournalEntry } from "@automatalabs/shared-types";
9
10
  /** Options for {@link runDynamicWorkflow}. */
10
11
  export interface RunDynamicWorkflowOptions {
11
12
  /**
@@ -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,GAClB,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;AAEnG,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;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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automatalabs/workflows",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
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.1",
28
- "@automatalabs/workflow-engine": "0.1.1",
29
- "@automatalabs/acp-agents": "0.1.1"
27
+ "@automatalabs/shared-types": "0.1.2",
28
+ "@automatalabs/workflow-engine": "0.1.2",
29
+ "@automatalabs/acp-agents": "0.1.2"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsc -b",