@automatalabs/workflows 0.5.0 → 0.6.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
@@ -177,6 +177,14 @@ return value.
177
177
  > programmatic option wins per name). A `schema` is forwarded to custom backends as turn-level
178
178
  > `_meta.outputSchema` and the result is JSON-parsed off the final message — agents that ignore the
179
179
  > schema channel still work via the validate/re-prompt ladder.
180
+ >
181
+ > A workflow **script** can also declare backends itself via `meta.backends` (same config shape,
182
+ > keyed by name). Because script-declared backends spawn commands on your machine, they are inert
183
+ > unless you approve them: pass `allowScriptBackends: true` to `runDynamicWorkflow`, or a callback
184
+ > `(backend) => boolean | Promise<boolean>` to decide per backend — an unapproved declaration
185
+ > throws with guidance, and a declined backend aborts the run (it would otherwise silently reroute
186
+ > its `agent()` calls to the default backend). Host-registered names always win over script
187
+ > declarations. Lower-level callers can thread a pre-approved registry via `exec.scriptBackends`.
180
188
 
181
189
  ### c) `WorkflowManager` — stateful / resumable runs
182
190
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { ExecOptions } from "@automatalabs/workflow-engine";
2
- import type { AgentRunner, WorkflowRunResult } from "@automatalabs/shared-types";
2
+ import type { AgentRunner, WorkflowBackendConfig, WorkflowRunResult } from "@automatalabs/shared-types";
3
3
  export { runWorkflow, parseWorkflowScript, WorkflowManager } from "@automatalabs/workflow-engine";
4
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";
@@ -8,7 +8,19 @@ export type { AcpPoolOptions, AcpRunnerOptions, BackendRegistry, CustomBackendCo
8
8
  export { TypedEventEmitter } from "@automatalabs/acp-agents";
9
9
  export type { AcpRunnerEventMap, AcpEventName, AcpEventListener, AcpEventContext, AcpSessionUpdate, AcpUpdateKind, AcpPermissionEvent, AcpRawMessageEvent, AcpBackendErrorEvent, } from "@automatalabs/acp-agents";
10
10
  export type { AgentRunner, RunOptions, AgentResult, AgentUsage } from "@automatalabs/shared-types";
11
- export type { JournalEntry } from "@automatalabs/shared-types";
11
+ export type { JournalEntry, WorkflowBackendConfig, WorkflowMeta } from "@automatalabs/shared-types";
12
+ /**
13
+ * Approval policy for SCRIPT-DECLARED custom ACP backends (`meta.backends`). Script backends
14
+ * spawn arbitrary commands on this machine, so they are INERT unless the embedder approves
15
+ * them: `true` approves everything the script declares; a callback is asked per backend (and
16
+ * a single decline aborts the run — a declined backend would otherwise silently reroute its
17
+ * agent() calls to the default backend). Omitted/false + a script that declares backends =>
18
+ * runDynamicWorkflow THROWS with guidance rather than running a script whose declared
19
+ * dependencies were dropped.
20
+ */
21
+ export type ScriptBackendApproval = boolean | ((backend: {
22
+ name: string;
23
+ } & WorkflowBackendConfig) => boolean | Promise<boolean>);
12
24
  /** Options for {@link runDynamicWorkflow}. */
13
25
  export interface RunDynamicWorkflowOptions {
14
26
  /**
@@ -21,6 +33,8 @@ export interface RunDynamicWorkflowOptions {
21
33
  args?: unknown;
22
34
  /** Per-execution options forwarded to `WorkflowManager.runSync` (timeouts, signal, budget, …). */
23
35
  exec?: ExecOptions;
36
+ /** Approval policy for script-declared `meta.backends` (see {@link ScriptBackendApproval}). */
37
+ allowScriptBackends?: ScriptBackendApproval;
24
38
  }
25
39
  /**
26
40
  * Run a dynamic workflow script to a TERMINAL result, with the AgentRunner seam
@@ -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;AAOvC,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,YAAY,EACZ,YAAY,EACZ,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAMlC,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"}
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,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIxG,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;AAOvC,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,YAAY,EACZ,YAAY,EACZ,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAMlC,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,qBAAqB,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAEpG;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAC7B,OAAO,GACP,CAAC,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,qBAAqB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAExF,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;IACnB,+FAA+F;IAC/F,mBAAmB,CAAC,EAAE,qBAAqB,CAAC;CAC7C;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,yBAA8B,GACnC,OAAO,CAAC,iBAAiB,CAAC,CAe5B"}
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@
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
12
  import { createAcpRunner } from "@automatalabs/acp-agents";
13
- import { WorkflowManager } from "@automatalabs/workflow-engine";
13
+ import { parseWorkflowScript, WorkflowError, WorkflowErrorCode, WorkflowManager } 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
16
  export { runWorkflow, parseWorkflowScript, WorkflowManager } from "@automatalabs/workflow-engine";
@@ -36,6 +36,39 @@ export { TypedEventEmitter } from "@automatalabs/acp-agents";
36
36
  * `WorkflowRunResult` (status `completed | paused | failed | aborted`) — never throwing
37
37
  * for an ordinary pause/fail — so the caller can read `result.status` directly.
38
38
  */
39
- export function runDynamicWorkflow(script, opts = {}) {
40
- return new WorkflowManager({ agent: opts.runner ?? createAcpRunner() }).runSync(script, opts.args, opts.exec);
39
+ export async function runDynamicWorkflow(script, opts = {}) {
40
+ // Script-declared backends need explicit approval BEFORE the run. A malformed script is
41
+ // deliberately not diagnosed here — runSync re-parses and throws the engine's own parse
42
+ // error (its pre-existing contract), so the approval gate never masks a parse message.
43
+ let declared;
44
+ try {
45
+ declared = parseWorkflowScript(script).meta.backends;
46
+ }
47
+ catch {
48
+ declared = undefined;
49
+ }
50
+ let exec = opts.exec;
51
+ if (declared && Object.keys(declared).length > 0) {
52
+ exec = { ...(exec ?? {}), scriptBackends: await approveScriptBackends(declared, opts.allowScriptBackends) };
53
+ }
54
+ return new WorkflowManager({ agent: opts.runner ?? createAcpRunner() }).runSync(script, opts.args, exec);
55
+ }
56
+ /** Resolve the embedder's approval policy over the declared backends; throw with guidance when
57
+ * approval is missing or any backend is declined (an unapproved dependency must abort, never
58
+ * silently reroute). */
59
+ async function approveScriptBackends(declared, approval) {
60
+ const names = Object.keys(declared).join(", ");
61
+ if (approval === undefined || approval === false) {
62
+ throw new WorkflowError(`script declares custom ACP backends (meta.backends: ${names}) — these spawn commands on this machine and require explicit approval. ` +
63
+ `Pass allowScriptBackends: true (or a per-backend approval callback) to runDynamicWorkflow, ` +
64
+ `or thread an approved registry yourself via exec.scriptBackends.`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false });
65
+ }
66
+ if (approval === true)
67
+ return declared;
68
+ for (const [name, config] of Object.entries(declared)) {
69
+ if (!(await approval({ name, ...config }))) {
70
+ throw new WorkflowError(`script backend "${name}" (command: ${config.command}) was declined by the allowScriptBackends callback — aborting the run`, WorkflowErrorCode.SCRIPT_VALIDATION_ERROR, { recoverable: false });
71
+ }
72
+ }
73
+ return declared;
41
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automatalabs/workflows",
3
- "version": "0.5.0",
3
+ "version": "0.6.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.4.0",
28
- "@automatalabs/workflow-engine": "0.2.0",
29
- "@automatalabs/acp-agents": "0.5.0"
27
+ "@automatalabs/shared-types": "0.5.0",
28
+ "@automatalabs/workflow-engine": "0.3.0",
29
+ "@automatalabs/acp-agents": "0.6.0"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsc -b",