@agent-compose/sdk 0.7.0 → 0.8.1

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.
Files changed (119) hide show
  1. package/README.md +66 -39
  2. package/dist/agent/__tests__/runtime-json-schema.test.d.ts +10 -0
  3. package/dist/agent/agent-context.d.ts +21 -1
  4. package/dist/agent/agent-loop.d.ts +32 -1
  5. package/dist/agent/run-agent.d.ts +4 -0
  6. package/dist/client.d.ts +382 -534
  7. package/dist/directives.d.ts +112 -0
  8. package/dist/display.d.ts +258 -0
  9. package/dist/errors.d.ts +24 -1
  10. package/dist/index.d.ts +26 -14
  11. package/dist/index.js +3774 -1679
  12. package/dist/pause/wrappers.d.ts +31 -9
  13. package/dist/runtimes/_acp-client.d.ts +46 -1
  14. package/dist/runtimes/_cli-agent.d.ts +51 -4
  15. package/dist/runtimes/_jsonl-guard.d.ts +103 -0
  16. package/dist/runtimes/amp.d.ts +2 -2
  17. package/dist/runtimes/claude-code.d.ts +61 -0
  18. package/dist/runtimes/claude-code.test.d.ts +14 -0
  19. package/dist/runtimes/claude.d.ts +16 -0
  20. package/dist/runtimes/claude.test.d.ts +8 -0
  21. package/dist/runtimes/codex.d.ts +12 -3
  22. package/dist/runtimes/cursor.d.ts +2 -2
  23. package/dist/runtimes/droid.d.ts +2 -2
  24. package/dist/runtimes/jsonl-guard.test.d.ts +19 -0
  25. package/dist/runtimes/openai-desktop.js +3718 -1680
  26. package/dist/runtimes/opencode.d.ts +2 -2
  27. package/dist/runtimes/vercel.js +12 -1
  28. package/dist/sandbox/devbox.d.ts +42 -0
  29. package/dist/sandbox/exec-stream.d.ts +14 -0
  30. package/dist/sandbox/network-policy.d.ts +100 -0
  31. package/dist/sandbox/provider-def.d.ts +79 -0
  32. package/dist/sandbox/providers/desktop.d.ts +10 -0
  33. package/dist/sandbox/providers/e2b.d.ts +17 -0
  34. package/dist/sandbox/providers/local.d.ts +11 -0
  35. package/dist/sandbox/providers/vercel.d.ts +18 -0
  36. package/dist/sandbox/registry.d.ts +45 -0
  37. package/dist/sandbox/sizes.d.ts +68 -0
  38. package/dist/sandbox.d.ts +24 -299
  39. package/dist/step-invocation/__tests__/foreground-recovery.test.d.ts +1 -0
  40. package/dist/step-invocation/invoker.d.ts +10 -0
  41. package/dist/step-invocation/protocol.d.ts +5 -0
  42. package/dist/types/api-compliance.d.ts +71 -0
  43. package/dist/types/api-conversations.d.ts +523 -0
  44. package/dist/types/api-factory.d.ts +334 -0
  45. package/dist/types/api-projects.d.ts +131 -0
  46. package/dist/types/api-runs.d.ts +422 -0
  47. package/dist/types/api-scopes.d.ts +102 -0
  48. package/dist/types/conversation-stream.d.ts +191 -0
  49. package/dist/types/execution-context.d.ts +12 -2
  50. package/dist/types/protocol.d.ts +38 -1
  51. package/dist/types/sandbox-environment.d.ts +8 -5
  52. package/dist/types/sandbox.d.ts +74 -4
  53. package/dist/types/workflow-metadata.d.ts +41 -8
  54. package/dist/types/workflow-plan.d.ts +10 -0
  55. package/dist/types/workflow.d.ts +18 -205
  56. package/dist/utils/bundler.d.ts +68 -1
  57. package/dist/workflow-steps/index.d.ts +1 -1
  58. package/dist/workflow-steps/observability.d.ts +8 -1
  59. package/dist/workflow-steps/runner.d.ts +3 -3
  60. package/dist/workflow-steps/step.d.ts +15 -1
  61. package/dist/workflow-steps/types.d.ts +19 -5
  62. package/dist/workflow-steps/workflow.d.ts +29 -1
  63. package/dist/workflows/engine.d.ts +3 -2
  64. package/dist/workflows/invoke-child.d.ts +20 -2
  65. package/dist/workflows/invoke-child.test.d.ts +9 -0
  66. package/package.json +2 -2
  67. package/src/agent/agent-context.ts +186 -3
  68. package/src/agent/agent-loop.ts +40 -2
  69. package/src/agent/run-agent.ts +5 -0
  70. package/src/client.ts +1048 -625
  71. package/src/directives.ts +184 -0
  72. package/src/display.ts +834 -0
  73. package/src/errors.ts +39 -0
  74. package/src/index.ts +114 -12
  75. package/src/pause/wrappers.ts +44 -9
  76. package/src/runtimes/_acp-client.ts +72 -3
  77. package/src/runtimes/_cli-agent.ts +161 -36
  78. package/src/runtimes/_jsonl-guard.ts +219 -0
  79. package/src/runtimes/claude-code.ts +256 -0
  80. package/src/runtimes/claude.ts +32 -2
  81. package/src/runtimes/codex.ts +63 -3
  82. package/src/runtimes/openai-desktop.ts +59 -14
  83. package/src/sandbox/devbox.ts +48 -0
  84. package/src/sandbox/exec-stream.ts +48 -0
  85. package/src/sandbox/network-policy.ts +181 -0
  86. package/src/sandbox/provider-def.ts +94 -0
  87. package/src/sandbox/providers/desktop.ts +57 -0
  88. package/src/sandbox/providers/e2b.ts +354 -0
  89. package/src/sandbox/providers/local.ts +106 -0
  90. package/src/sandbox/providers/vercel.ts +331 -0
  91. package/src/sandbox/registry.ts +198 -0
  92. package/src/sandbox/sizes.ts +95 -0
  93. package/src/sandbox.ts +59 -1275
  94. package/src/step-invocation/invoker.ts +151 -28
  95. package/src/step-invocation/protocol.ts +8 -0
  96. package/src/types/api-compliance.ts +79 -0
  97. package/src/types/api-conversations.ts +547 -0
  98. package/src/types/api-factory.ts +368 -0
  99. package/src/types/api-projects.ts +140 -0
  100. package/src/types/api-runs.ts +459 -0
  101. package/src/types/api-scopes.ts +102 -0
  102. package/src/types/conversation-stream.ts +231 -0
  103. package/src/types/execution-context.ts +10 -2
  104. package/src/types/protocol.ts +41 -0
  105. package/src/types/sandbox-environment.ts +28 -9
  106. package/src/types/sandbox.ts +73 -4
  107. package/src/types/workflow-metadata.ts +44 -8
  108. package/src/types/workflow-plan.ts +11 -0
  109. package/src/types/workflow.ts +25 -292
  110. package/src/utils/bundler.ts +245 -8
  111. package/src/utils/errors.ts +16 -1
  112. package/src/workflow-steps/index.ts +1 -0
  113. package/src/workflow-steps/observability.ts +19 -8
  114. package/src/workflow-steps/runner.ts +4 -4
  115. package/src/workflow-steps/step.ts +49 -1
  116. package/src/workflow-steps/types.ts +20 -5
  117. package/src/workflow-steps/workflow.ts +29 -1
  118. package/src/workflows/engine.ts +3 -2
  119. package/src/workflows/invoke-child.ts +49 -13
@@ -1,229 +1,42 @@
1
1
  /**
2
- * Workflow types — the context and function signature for authoring workflows.
2
+ * Workflow authoring types — `defineWorkflow` and the shared author-facing
3
+ * type surface.
3
4
  *
4
- * A workflow is `async (ctx, sandbox) => T`. Two positional args by design:
5
- *
6
- * - `ctx` carries facts + observability about THIS run (id, input,
7
- * setMetadata, step). Metadata bag.
8
- * - `sandbox` is a capability handed to you by the engine for doing work
9
- * (exec commands, write files). Pass it to `agent({ sandbox, ... })`
10
- * and to any helper that takes a SandboxProvider (git utilities, file
11
- * writers). Constructed once per run; reuse it.
5
+ * Workflows are STEP-FORM only: a builder of discrete, durable steps —
6
+ * `defineWorkflow({ id, input, output }).step(defineStep(...)).build()`.
7
+ * Every step is a replay checkpoint; pause/resume works at step
8
+ * granularity. The legacy run-form (`defineWorkflow({ run(ctx, sandbox)
9
+ * { … } })`) has been removed — passing a `run` key throws at
10
+ * definition time (i.e. at registration, loud and early).
12
11
  *
13
12
  * LLM agent loops live in `agent(opts)` (sdk/src/agent/run-agent.ts).
14
13
  * Invoking other workflows uses `AgentComposeClient.invoke[AndWait](...)`.
15
14
  */
16
- import { z } from "zod";
17
- import type { SandboxNetworkPolicy } from "../sandbox.js";
18
- import type { SandboxProvider } from "./sandbox.js";
19
15
  import type { AgentLifecycleEvent } from "../agent/agent-loop.js";
20
- import type { Processor } from "../processors/processor.js";
21
- import type { StepWorkflowDefinition } from "../workflow-steps/workflow.js";
22
- import type { Workflow } from "../workflow-steps/types.js";
23
- import type { BaseExecutionContext } from "./execution-context.js";
24
- import { type ConnectorRequirements, type ConnectorOperationTag, type InvokePolicy } from "./workflow-metadata.js";
16
+ import type { StepWorkflowDefinition, WorkflowBuilder } from "../workflow-steps/workflow.js";
25
17
  export type { WorkflowRun, InvokeChild, BaseExecutionContext } from "./execution-context.js";
26
- export type { WorkflowMetadata } from "./workflow-metadata.js";
18
+ export type { WorkflowMetadata, SnapshotConfig, BootSnapshot, ReuseSnapshot, IOSchema, OutputSchema, SandboxResources } from "./workflow-metadata.js";
27
19
  export interface AgentEventSink {
28
20
  emit(event: AgentLifecycleEvent): void | Promise<void>;
29
21
  }
30
- import type { SnapshotConfig, BootSnapshot, ReuseSnapshot, IOSchema, OutputSchema, SandboxResources } from "./workflow-metadata.js";
31
- export type { SnapshotConfig, BootSnapshot, ReuseSnapshot, IOSchema, OutputSchema, SandboxResources };
32
22
  /** Turn/iteration budget for `agent(opts)`. Re-exported here so authors
33
23
  * can type per-invoke budget overrides they pass as workflow input. */
34
24
  export interface AgentBudget {
35
25
  turnsPerIteration: number;
36
26
  maxIterations: number;
37
27
  }
38
- /** Context passed to a workflow function — facts + observability for this run. */
39
- export interface WorkflowCtx<TInput extends Record<string, unknown> = Record<string, unknown>> extends Omit<BaseExecutionContext, "sandbox"> {
40
- input?: TInput;
41
- /** Persist key-value metadata on the run record (e.g. prUrl, planUrl). */
42
- setMetadata: (data: Record<string, unknown>) => Promise<void>;
43
- /**
44
- * Durable named step (ADR-0012). Runs `fn` once and memoises its result to
45
- * the sandbox state-dir; on a pause-resume re-entry the recorded value is
46
- * returned and `fn` is NOT re-run (a duration-0 "restored" sub-step). Also
47
- * emits substep_started / substep_completed / substep_failed lifecycle
48
- * events with duration — use for long phases you want both durable and
49
- * visible on the run's timeline (setup, external API calls, submit).
50
- *
51
- * Names must be unique within a step body (they key the memoise file).
52
- * A body that pauses is never memoised — the resume re-runs it. For
53
- * cross-process side effects (DB writes, emails) use `invokeChild`.
54
- */
55
- step<T>(name: string, fn: () => Promise<T>): Promise<T>;
56
- /** Pass to `agent({ events: ctx.agentEvents })` to stream agent lifecycle events. */
57
- agentEvents: AgentEventSink;
58
- /**
59
- * Workflow-level processors registered via `defineWorkflow({ processors })`.
60
- * Read-only here. Authors merge with agent-specific lists when calling
61
- * `agent({ processors: [...ctx.processors, mySpecific] })`.
62
- *
63
- * Empty array when the workflow declared no processors.
64
- */
65
- processors: readonly Processor[];
66
- }
67
- /** A workflow is `async (ctx, sandbox) => TOutput`. */
68
- export type WorkflowFn<TOutput = unknown, TInput extends Record<string, unknown> = Record<string, unknown>> = (ctx: WorkflowCtx<TInput>, sandbox: SandboxProvider) => Promise<TOutput>;
69
28
  /**
70
- * Declare a workflow with server-side metadata.
71
- * Use `export default defineWorkflow({ run, networkPolicy, ... })` to attach
72
- * a runner network policy so the server brokers credentials for the workflow
73
- * sandbox.
29
+ * Declare a workflow — the typed step builder. Multiple steps with
30
+ * explicit input/output schemas, durability + replay at every step
31
+ * boundary:
74
32
  *
75
- * Without defineWorkflow, a plain `export default async (ctx) => {...}` still
76
- * works — the workflow just runs with secrets passed directly in env.
77
- */
78
- export interface WorkflowDefinition<TOutput = unknown, TInput extends Record<string, unknown> = Record<string, unknown>> {
79
- /** One-line, human-readable description of what this workflow does.
80
- * Surfaced on the dashboard template tile + run page header. */
81
- description?: string;
82
- /** Zod schema for the workflow's `input`. When declared, the SDK
83
- * bundler captures it as JSON-Schema-shaped `inputSchema` in
84
- * template metadata, the dashboard playground renders a typed
85
- * form, and the engine validates dispatched payloads against it
86
- * at the step boundary. Omit to leave inputs as `unknown` (the
87
- * legacy default — playground falls back to a freeform JSON
88
- * textarea). */
89
- input?: z.ZodType<TInput>;
90
- /** Same as `input`, for the workflow's return value. Captured into
91
- * `outputSchema` metadata and rendered in the IO panel. */
92
- output?: z.ZodType<TOutput>;
93
- /**
94
- * @deprecated Legacy run-form. Prefer step-form — the
95
- * `.step(defineStep(...))` builder — for per-step durability/replay and
96
- * working pause. A run-form body compiles to one opaque step
97
- * (`compileRunForm`), so any failure/resume re-runs the whole body.
98
- */
99
- run: WorkflowFn<TOutput, TInput>;
100
- /**
101
- * All snapshot config — boot source plus capture mode.
102
- *
103
- * `snapshots.bootFrom`: the runner restores from this exact provider
104
- * snapshot id at run start. Omit to boot a fresh sandbox.
105
- *
106
- * `snapshots.saveLatest`: `true` captures one snapshot after each
107
- * successful step (latest-only — prior is freed).
108
- * `{ saveLatest: true, retainSteps: true }` keeps every step's
109
- * snapshot for fork / replay / time-travel.
110
- *
111
- * Snapshots are long-lived (never auto-expire). List + delete via
112
- * `agentc snapshot list/delete`. Per-invocation
113
- * `invoke({ snapshots })` overrides this default.
114
- */
115
- snapshots?: SnapshotConfig;
116
- /**
117
- * Sandbox resources — machine SKU (`size`, a `SandboxSize` vCPU string:
118
- * `2vcpu-4gb` | `4vcpu-8gb` | `8vcpu-16gb` | `32vcpu-64gb`) and `provider`
119
- * (`vercel` | `e2b`). `size` maps to provider machine specs at create
120
- * (Vercel: vCPUs, 2048 MB RAM per vCPU); E2B sizing is template-defined and
121
- * ignores it. Optional; omit → smallest SKU on the default provider.
122
- * Per-invocation `invoke({ size })` overrides the size.
123
- */
124
- resources?: SandboxResources;
125
- /**
126
- * Outbound network policy for the runner sandbox.
127
- * Use "*": [] to allow all traffic while still injecting headers for specific domains.
128
- * Secret values are referenced as $VARIABLE and resolved from GCP at dispatch time.
129
- * Vercel only — E2B ignores.
130
- *
131
- * @example
132
- * networkPolicy: {
133
- * allow: {
134
- * "*": [],
135
- * "api.github.com": [{ transform: [{ headers: { "Authorization": "basic:$GITHUB_TOKEN" } }] }],
136
- * }
137
- * }
138
- */
139
- networkPolicy?: SandboxNetworkPolicy;
140
- /**
141
- * Workflow-level processor chain — runs around every `agent(...)` loop the
142
- * workflow body launches, ahead of any agent-specific processors. Use for
143
- * org-wide gating (deny destructive tools, require scopes). Authors merge
144
- * with agent-specific lists via `[...ctx.processors, ...]`.
145
- */
146
- processors?: readonly Processor[];
147
- /**
148
- * Optional placeholder env var values for secrets referenced in the network policy.
149
- * By default, brokered secrets are removed from the runner env entirely — the real
150
- * values are only ever present inside the Vercel firewall config, never in the VM.
151
- * Only set this if a tool or SDK validates the env var format on startup before
152
- * making any requests (e.g. some CLIs check that ANTHROPIC_API_KEY looks like a
153
- * real key). The placeholder is a syntactically valid but non-functional stand-in.
154
- *
155
- * @example
156
- * placeholders: {
157
- * ANTHROPIC_API_KEY: `sk-ant-api03-${"a".repeat(95)}`,
158
- * }
159
- */
160
- placeholders?: Record<string, string>;
161
- /**
162
- * Connector requirements (ADR-0007). Declaring a provider makes the
163
- * server resolve an authorized OAuth grant for the calling principal at
164
- * dispatch time and inject a fresh access token at the network layer —
165
- * workflow code talks to the provider API with plain fetch/SDKs and
166
- * never holds the credential.
167
- *
168
- * @example
169
- * connectors: { github: { scopes: ["repo"] } }
170
- */
171
- connectors?: ConnectorRequirements;
172
- /**
173
- * Marks this workflow as a catalogue OPERATION of a connector — e.g.
174
- * the `create-issue` operation of the `github` connector. Pair with
175
- * `description` + `input`/`output` schemas so the operation is fully
176
- * self-describing (MCP-tool-like) to humans and agents browsing the
177
- * connector catalogue.
178
- *
179
- * @example
180
- * connectorOperation: { provider: "github", operation: "create-issue" }
181
- */
182
- connectorOperation?: ConnectorOperationTag;
183
- /**
184
- * Tier-1 invoke ACL (connector credential boundary). When this workflow
185
- * declares `connectors` (it brokers a credential) AND an `invokePolicy`,
186
- * the server evaluates the calling principal against the policy BEFORE
187
- * binding any grant — a caller matching no clause is refused with HTTP
188
- * 403. Has no effect on workflows that declare no connectors. Omit to
189
- * leave the workflow invokable by the whole team.
190
- *
191
- * @example
192
- * connectors: { github: { access: "read" } },
193
- * invokePolicy: { users: "owner", workflows: ["nightly-orchestrator"] }
194
- */
195
- invokePolicy?: InvokePolicy;
196
- /**
197
- * Internal — set by `defineSandboxEnvironment`, not by workflow authors.
198
- * Marks the workflow as an environment build (base-env / agent-env) so the
199
- * server skips mounting the shared factory drive for its runs (#13). See
200
- * `WorkflowMetadata.environmentBuild`.
201
- */
202
- environmentBuild?: boolean;
203
- }
204
- /**
205
- * Declare a workflow. Two forms; both return a `Workflow` whose
206
- * `metadata` field carries the server-readable declarations.
33
+ * defineWorkflow({ id, input, output }).step(defineStep(...)).build()
207
34
  *
208
- * Run form — wraps the legacy `(ctx, sandbox) => T` body as a single
209
- * step internally. Lifecycle granularity is workflow-level (one step).
210
- *
211
- * Step form — the typed builder. Multiple steps with explicit input/
212
- * output schemas, durability + replay at every step boundary.
213
- *
214
- * Both forms produce the same downstream shape: the bundler reads
215
- * `workflow.metadata.networkPolicy` / `placeholders` / etc.; the server
216
- * stores the step plan; runner subprocesses execute one step at a time
217
- * via the StepInvocation seam.
218
- */
219
- /**
220
- * @deprecated Run-form is legacy. Use the step-form overload —
221
- * `defineWorkflow({ id, input, output }).step(defineStep(...)).build()` — for
222
- * durable, replayable steps and working pause. Run-form compiles to a single
223
- * opaque step (`compileRunForm`); there is no per-step replay.
35
+ * The bundler reads `workflow.metadata.networkPolicy` / `placeholders` /
36
+ * etc. off the built `Workflow`; the server stores the step plan; runner
37
+ * subprocesses execute one step at a time via the StepInvocation seam.
224
38
  */
225
- export declare function defineWorkflow<TOutput = unknown, TInput extends Record<string, unknown> = Record<string, unknown>>(def: WorkflowDefinition<TOutput, TInput>): Workflow<TInput, TOutput>;
226
- export declare function defineWorkflow<TInput, TOutput>(def: StepWorkflowDefinition<TInput, TOutput>): import("../workflow-steps/workflow.js").WorkflowBuilder<TInput, TInput>;
39
+ export declare function defineWorkflow<TInput, TOutput>(def: StepWorkflowDefinition<TInput, TOutput>): WorkflowBuilder<TInput, TInput>;
227
40
  /** Observability-only lifecycle hooks — passed to the workflow engine, not workflow authors. */
228
41
  export interface WorkflowHooks {
229
42
  onStepStart?: (step: string) => void;
@@ -18,10 +18,24 @@
18
18
  * parses or imports user source — it only validates the structured manifest
19
19
  * this function returns alongside the bundled bytes, and cross-checks the
20
20
  * manifest's `sourceHash` against the source it received.
21
+ *
22
+ * Module resolution carries two more layers, because most workflow source is
23
+ * now written by an AGENT and the bundler's error is the only feedback it
24
+ * gets (the Workflow Studio's agent authored `import … from "agentc/sdk"`
25
+ * and prod answered with bun's `Maybe you need to "bun install"?` — advice
26
+ * nobody could act on inside a sandbox with no package.json):
27
+ *
28
+ * - TOLERATE (`SDK_SPECIFIER_ALIASES` + `sdkAliasPlugin`) — near-miss
29
+ * spellings of `@agent-compose/sdk` resolve to the real package, so a
30
+ * draft already written with the wrong one builds unedited.
31
+ * - SELF-CORRECT (`explainBundleFailure`) — anything that still fails to
32
+ * resolve produces an error NAMING the real package, which an agent
33
+ * reading its own tool error can fix on the next turn.
21
34
  */
22
35
  import type { SnapshotConfig } from "../types/workflow.js";
23
- import type { IOSchema, ConnectorRequirements, ConnectorOperationTag, InvokePolicy, SandboxResources } from "../types/workflow-metadata.js";
36
+ import type { IOSchema, ConnectorRequirements, ConnectorOperationTag, InvokePolicy, SandboxResources, DriveMergePolicy } from "../types/workflow-metadata.js";
24
37
  import type { SandboxNetworkPolicy } from "../sandbox.js";
38
+ import type { Workflow } from "../workflow-steps/types.js";
25
39
  import { type WorkflowPlan } from "../types/workflow-plan.js";
26
40
  /** Bumped when the manifest contract changes in a way the server should
27
41
  * notice. The server pins its manifest schema to this exact value (no
@@ -87,6 +101,9 @@ export interface BundledWorkflow {
87
101
  /** Sandbox resources declared via `defineWorkflow({ resources })` — machine
88
102
  * SKU (`size`) and `provider` (`vercel` | `e2b`). */
89
103
  resources?: SandboxResources;
104
+ /** Run-branch merge policy declared via `defineWorkflow({ mergePolicy })`.
105
+ * Absent ⇒ `"auto"` (today's behaviour). */
106
+ mergePolicy?: DriveMergePolicy;
90
107
  workflowPlan: WorkflowPlan;
91
108
  /** Compact JSON-Schema-shaped description of the workflow's input
92
109
  * type. Extracted from the workflow's declared `input` zod schema
@@ -104,7 +121,50 @@ export interface BundledWorkflow {
104
121
  /** Set by `defineSandboxEnvironment` — marks an environment build so the
105
122
  * server skips the /factory mount for its runs (#13). */
106
123
  environmentBuild?: boolean;
124
+ /** Drive requirement declared via `defineWorkflow({ factoryDrive })`.
125
+ * Absent ⇒ `"required"` (a failed /factory mount fails the run);
126
+ * `"none"` = explicit no-drive opt-out. */
127
+ factoryDrive?: "required" | "none";
107
128
  }
129
+ /** The one true import specifier for the platform SDK. */
130
+ export declare const SDK_PACKAGE = "@agent-compose/sdk";
131
+ /**
132
+ * Import specifiers that can only have MEANT `@agent-compose/sdk`, rewritten
133
+ * to it at bundle time so a draft written with the wrong spelling builds
134
+ * unedited.
135
+ *
136
+ * Every entry carries an `sdk` segment or suffix, so none of them can be a
137
+ * real third-party package a workflow might legitimately depend on: `a/b`
138
+ * forms are subpaths of packages that don't exist, and the `*-sdk` forms
139
+ * name this platform explicitly. Bare `agentc` / `agent-compose` are
140
+ * deliberately NOT aliased — those are plausible npm package names, and
141
+ * silently redirecting a real dependency is worse than a clear error.
142
+ *
143
+ * Exported for the unit test that pins the table.
144
+ */
145
+ export declare const SDK_SPECIFIER_ALIASES: readonly string[];
146
+ /** `@agent-compose/sdk` when `specifier` is a known near-miss for it, else
147
+ * null. The single authority: the plugin's regex filter is only a fast
148
+ * pre-filter, and this decides. */
149
+ export declare function resolveSdkAlias(specifier: string): string | null;
150
+ /**
151
+ * The SELF-CORRECTING layer. Turns a Bun bundle failure into a message that
152
+ * names the real fix instead of leaking Bun's internals.
153
+ *
154
+ * An unresolved import is almost always one thing: workflow source naming
155
+ * the platform SDK by a specifier that isn't its package name. Bun answers
156
+ * that with `Could not resolve: "agentc/sdk". Maybe you need to "bun
157
+ * install"?` — advice the author cannot act on (there is no package.json to
158
+ * install into; the drive holds one file). The rewritten message says the
159
+ * package name, so an agent reading its own tool error can fix the import on
160
+ * the next turn.
161
+ *
162
+ * Non-resolve failures (syntax errors, transform failures) keep their
163
+ * verbatim diagnostics — those are already actionable.
164
+ *
165
+ * Exported for the unit test; `bundleWorkflow` is the supported entrypoint.
166
+ */
167
+ export declare function explainBundleFailure(err: unknown, label: string): string;
108
168
  /**
109
169
  * Parse the bundled source and assert the default export is a CallExpression
110
170
  * to an identifier named `defineWorkflow` (or to a `.step(...).build()` chain
@@ -123,6 +183,13 @@ export interface BundledWorkflow {
123
183
  * from outside the SDK — `bundleWorkflow` is the supported entrypoint.
124
184
  */
125
185
  export declare function assertDefaultExportIsDefineWorkflow(source: string, label: string): void;
186
+ /**
187
+ * The registration-time step plan read off an (already evaluated) workflow
188
+ * object. Narrative fields (`summary`, `deliverables`) ride along additively;
189
+ * conditional spreads keep absent fields ABSENT — the plan travels as JSON,
190
+ * so no `undefined` keys. Exported for tests.
191
+ */
192
+ export declare function extractWorkflowPlan(workflow: Workflow<unknown, unknown>): WorkflowPlan;
126
193
  /** Bundle a workflow from source. */
127
194
  export declare function bundleWorkflow(workflowPath: string, overrides?: {
128
195
  networkPolicy?: SandboxNetworkPolicy;
@@ -4,7 +4,7 @@ export { createStepWorkflow, isWorkflow } from "./workflow.js";
4
4
  export type { StepWorkflowDefinition, WorkflowBuilder } from "./workflow.js";
5
5
  export { runWorkflowSteps, runWorkflowSingleStep, StepValidationError, WorkflowInputValidationError, WorkflowOutputValidationError, } from "./runner.js";
6
6
  export type { RunWorkflowStepsOpts, RunWorkflowStepsResult, RunWorkflowSingleStepOpts, RunWorkflowSingleStepResult, } from "./runner.js";
7
- export type { Step, StepContext, StepRunResult, Workflow, } from "./types.js";
7
+ export type { Step, StepContext, StepDeliverable, StepRunResult, Workflow, } from "./types.js";
8
8
  export { WORKFLOW_BRAND } from "./types.js";
9
9
  export { StepObservabilityCollector } from "./observability.js";
10
10
  export type { StepObservability, SubStepEvent } from "./observability.js";
@@ -52,7 +52,14 @@ export interface SubStepEvent {
52
52
  * empty snapshot (and the wire payload omits the field entirely). */
53
53
  export interface StepObservability {
54
54
  metadata?: Record<string, unknown>;
55
- events?: AgentLifecycleEvent[];
55
+ /** Residual events that failed live delivery, each carrying its ORIGINAL
56
+ * emit-time `seq`. The server keys its idempotency on that seq — the SAME
57
+ * key the live route used — so a live write whose ack was lost collapses
58
+ * on redelivery instead of duplicating. Array position is NOT the seq:
59
+ * acked events are stripped, so indices shift. */
60
+ events?: Array<AgentLifecycleEvent & {
61
+ seq: number;
62
+ }>;
56
63
  subSteps?: SubStepEvent[];
57
64
  }
58
65
  /**
@@ -25,7 +25,7 @@ import { z } from "zod";
25
25
  import type { Workflow, StepRunResult } from "./types.js";
26
26
  import type { RequestContext } from "../request-context/request-context.js";
27
27
  import type { SandboxProvider } from "../types/sandbox.js";
28
- import type { WorkflowRun, WorkflowCtx } from "../types/workflow.js";
28
+ import type { WorkflowRun, InvokeChild } from "../types/execution-context.js";
29
29
  import { type StepObservability } from "./observability.js";
30
30
  import type { LiveAgentEventEmitter } from "./run-callback.js";
31
31
  export declare class StepValidationError extends Error {
@@ -67,7 +67,7 @@ export interface RunWorkflowStepsOpts<TInput, TOutput> {
67
67
  /** Fire before a step runs (after cache check / before input validation). */
68
68
  onStepStarted?(stepIndex: number, stepName: string): void | Promise<void>;
69
69
  /** Child workflow invocation implementation. Defaults to a clear unsupported error. */
70
- invokeChild?: WorkflowCtx["invokeChild"];
70
+ invokeChild?: InvokeChild;
71
71
  /** Optional live-stream emitter for agent lifecycle events. The runner
72
72
  * passes a fetch-based emitter wired to the per-run callback token so
73
73
  * the dashboard sees events as the agent loop produces them; tests
@@ -89,7 +89,7 @@ export interface RunWorkflowSingleStepOpts {
89
89
  requestContext: RequestContext;
90
90
  sandbox?: SandboxProvider;
91
91
  abortSignal?: AbortSignal;
92
- invokeChild?: WorkflowCtx["invokeChild"];
92
+ invokeChild?: InvokeChild;
93
93
  /** Optional live-stream emitter — see `RunWorkflowStepsOpts.liveAgentEventEmitter`. */
94
94
  liveAgentEventEmitter?: LiveAgentEventEmitter;
95
95
  }
@@ -7,19 +7,33 @@
7
7
  * - `output` Zod schema; validated against `run`'s return value
8
8
  * - `run` step body
9
9
  *
10
+ * Optional narrative fields (rendered on the dashboard workflow graph):
11
+ * - `summary` one plain sentence of what the step actually does
12
+ * - `deliverables` files the step promises to produce
13
+ *
10
14
  * Validation is required (not optional) because the durability story rides
11
15
  * on every step boundary being a recordable, replayable JSON value. A step
12
16
  * without a schema is invisible to the engine's persistence layer.
13
17
  *
18
+ * Narrative caps are enforced HERE, at construction — the bundler evaluates
19
+ * the module at registration, so this is the "length-capped at registration"
20
+ * point and the error names the step in the author's own environment. The
21
+ * server's manifest zod re-checks the same caps (untrusted input).
22
+ *
14
23
  * Type inference flows: `defineStep` infers TInput/TOutput from the schemas
15
24
  * so `run(ctx)` is fully typed via `ctx.input` at the call site.
16
25
  */
17
26
  import type { z } from "zod";
18
- import type { Step, StepContext } from "./types.js";
27
+ import type { Step, StepContext, StepDeliverable } from "./types.js";
19
28
  export interface DefineStepOpts<TInput, TOutput> {
20
29
  name: string;
21
30
  input: z.ZodType<TInput>;
22
31
  output: z.ZodType<TOutput>;
23
32
  run(ctx: StepContext<TInput>): TOutput | Promise<TOutput>;
33
+ /** One plain sentence of what the step actually does. 1-200 chars, no
34
+ * control characters (so no newlines). */
35
+ summary?: string;
36
+ /** Files the step promises to produce. At most 8. */
37
+ deliverables?: StepDeliverable[];
24
38
  }
25
39
  export declare function defineStep<TInput, TOutput>(opts: DefineStepOpts<TInput, TOutput>): Step<TInput, TOutput>;
@@ -14,6 +14,7 @@ import type { z } from "zod";
14
14
  import type { BaseExecutionContext } from "../types/execution-context.js";
15
15
  import type { AgentEventSink } from "../types/workflow.js";
16
16
  import type { WorkflowMetadata } from "../types/workflow-metadata.js";
17
+ import type { StepObservability } from "./observability.js";
17
18
  /**
18
19
  * Per-step execution context. Threaded into every step's `execute(...)` so
19
20
  * the step can read tenant identity and run identity, log progress, and
@@ -59,6 +60,14 @@ export interface StepContext<TInput = unknown> extends BaseExecutionContext {
59
60
  */
60
61
  agentEvents: AgentEventSink;
61
62
  }
63
+ /** One artifact a step promises to produce. `path` is workspace/drive-relative
64
+ * (e.g. "out/report.html"); the dashboard derives the format tag from the
65
+ * extension client-side — no `format` field here. */
66
+ export interface StepDeliverable {
67
+ path: string;
68
+ /** Optional one-line description of the artifact. */
69
+ description?: string;
70
+ }
62
71
  /**
63
72
  * Step definition — a single typed unit of work in a workflow chain.
64
73
  *
@@ -77,6 +86,11 @@ export interface Step<TInput, TOutput> {
77
86
  readonly output: z.ZodType<TOutput>;
78
87
  /** Step body. Receives a `StepContext<TInput>` and returns the typed output. */
79
88
  run(ctx: StepContext<TInput>): TOutput | Promise<TOutput>;
89
+ /** One plain sentence of what the step actually does — rendered on the
90
+ * dashboard workflow graph. ≤200 chars, no newlines. */
91
+ readonly summary?: string;
92
+ /** Files the step promises to produce. ≤8 entries. */
93
+ readonly deliverables?: readonly StepDeliverable[];
80
94
  }
81
95
  /**
82
96
  * The result of running one step. Engine adapters persist these into the
@@ -89,18 +103,18 @@ export type StepRunResult<TOutput = unknown> = {
89
103
  status: "completed";
90
104
  output: TOutput;
91
105
  durationMs: number;
92
- observability?: import("./observability.js").StepObservability;
106
+ observability?: StepObservability;
93
107
  } | {
94
108
  status: "failed";
95
109
  error: string;
96
110
  durationMs: number;
97
- observability?: import("./observability.js").StepObservability;
111
+ observability?: StepObservability;
98
112
  };
99
113
  /**
100
114
  * Workflow — a list of typed steps plus the workflow's input/output
101
- * schemas plus its server-side metadata bag. Returned by `defineWorkflow(...)`
102
- * (run form) and `defineWorkflow(...).step(...)...build()` (step form).
103
- * Engine adapters consume this shape.
115
+ * schemas plus its server-side metadata bag. Returned by
116
+ * `defineWorkflow(...).step(...)...build()`. Engine adapters consume
117
+ * this shape.
104
118
  *
105
119
  * `input` validates the workflow input before the first step runs.
106
120
  * `output` validates the final step's output before the workflow
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import type { z } from "zod";
22
22
  import type { Step, Workflow } from "./types.js";
23
- import type { SnapshotConfig, SandboxResources } from "../types/workflow-metadata.js";
23
+ import type { SnapshotConfig, SandboxResources, ConnectorRequirements, ConnectorOperationTag, InvokePolicy, DriveMergePolicy } from "../types/workflow-metadata.js";
24
24
  import type { SandboxNetworkPolicy } from "../sandbox.js";
25
25
  import type { Processor } from "../processors/processor.js";
26
26
  export interface WorkflowBuilder<TInput, TCurrent> {
@@ -50,7 +50,35 @@ export interface StepWorkflowDefinition<TInput, TOutput> {
50
50
  * and `provider` (`vercel` | `e2b`). Vercel maps `size` to vCPUs; E2B
51
51
  * sizing is template-defined. Omit → smallest SKU on the default provider. */
52
52
  resources?: SandboxResources;
53
+ /** What happens to this workflow's drive branch when a run ends:
54
+ * `"auto"` (the default when omitted — today's behaviour) folds it into
55
+ * `main`; `"manual"` proposes a merge approval at the same terminus
56
+ * instead, leaving the branch durable until a human clicks approve. A
57
+ * cancelled run neither merges nor proposes under either policy. */
58
+ mergePolicy?: DriveMergePolicy;
53
59
  processors?: readonly Processor[];
60
+ /** Connector requirements (ADR-0007) — providers whose APIs this workflow
61
+ * calls. Dispatch resolves an authorized grant per provider and injects a
62
+ * fresh access token at the network layer. */
63
+ connectors?: ConnectorRequirements;
64
+ /** Marks this workflow as a catalogue OPERATION of a connector — e.g. the
65
+ * `create-issue` operation of the `github` connector. */
66
+ connectorOperation?: ConnectorOperationTag;
67
+ /** Tier-1 invoke ACL — who may dispatch this connector-brokering workflow.
68
+ * See `InvokePolicy`. */
69
+ invokePolicy?: InvokePolicy;
70
+ /** Internal — set by `defineSandboxEnvironment`, not by workflow authors.
71
+ * Marks the workflow as an environment build (base-env / agent-env) so the
72
+ * server skips mounting the shared factory drive for its runs (#13). See
73
+ * `WorkflowMetadata.environmentBuild`. */
74
+ environmentBuild?: boolean;
75
+ /** Whether this workflow's runs need the factory drive. Omit (⇒
76
+ * `"required"`) for any workflow that reads or writes /factory: a failed
77
+ * mount then FAILS the run instead of silently proceeding drive-less.
78
+ * Declare `"none"` for a drive-agnostic workflow — the server skips the
79
+ * /factory mount entirely for its runs. See
80
+ * `WorkflowMetadata.factoryDrive`. */
81
+ factoryDrive?: "required" | "none";
54
82
  }
55
83
  export declare function createStepWorkflow<TInput, TOutput>(opts: StepWorkflowDefinition<TInput, TOutput>): WorkflowBuilder<TInput, TInput>;
56
84
  /** Type guard — true when `value` is a `Workflow`. */
@@ -8,7 +8,8 @@
8
8
  * Errors classified into `WorkflowError` (user code threw) vs `EngineError`
9
9
  * (platform problem) for the runner harness to surface upstream.
10
10
  */
11
- import type { WorkflowHooks, WorkflowCtx } from "../types/workflow.js";
11
+ import type { WorkflowHooks } from "../types/workflow.js";
12
+ import type { InvokeChild } from "../types/execution-context.js";
12
13
  import { RequestContext } from "../request-context/request-context.js";
13
14
  import type { Workflow } from "../workflow-steps/types.js";
14
15
  import { type RunWorkflowStepsOpts } from "../workflow-steps/runner.js";
@@ -54,7 +55,7 @@ export interface RunWorkflowOptions {
54
55
  /** Provider-specific child workflow invocation. Temporal/Inngest providers
55
56
  * inject their native child-workflow primitive; the LocalProvider injects
56
57
  * the public Agent Compose API client. */
57
- invokeChild?: WorkflowCtx["invokeChild"];
58
+ invokeChild?: InvokeChild;
58
59
  }
59
60
  export declare function runWorkflow<TInput, TOutput>(wf: Workflow<TInput, TOutput>, ctx: {
60
61
  run: {
@@ -1,4 +1,22 @@
1
- import type { WorkflowCtx } from "../types/workflow.js";
1
+ import type { InvokeChild } from "../types/execution-context.js";
2
+ /**
3
+ * Derive the deterministic per-call `Idempotency-Key` for a `ctx.invokeChild`
4
+ * dispatch: `invoke-child:<parentRunId>:step<stepIndex>:<childName>:<ordinal>`.
5
+ *
6
+ * Replay safety: a replayed step re-runs its body from the top, so the k-th
7
+ * `invokeChild(name)` call in a step re-derives the SAME key (the per-scope
8
+ * ordinal counter lives on the active-step state, which resets identically on
9
+ * every (re-)entry — the `nextPauseOrdinalInActiveStep` pattern). The server's
10
+ * idempotency window then returns the original child run instead of
11
+ * double-dispatching. Outside step execution (local dev, tests) there is no
12
+ * stable coordinate to key on — returns null and the dispatch is unkeyed,
13
+ * exactly the old behavior.
14
+ *
15
+ * Key syntax matches the server's `Idempotency-Key` grammar
16
+ * (`[A-Za-z0-9_\-:.]{1,255}`): runId is a UUID, step index a number, and
17
+ * workflow names are kebab-case.
18
+ */
19
+ export declare function deriveInvokeChildIdempotencyKey(parentRunId: string, childName: string): string | null;
2
20
  /**
3
21
  * Build the public-API child workflow invoker used by legacy and sandboxed
4
22
  * workflow execution. Provider-backed engines may inject a different
@@ -7,4 +25,4 @@ import type { WorkflowCtx } from "../types/workflow.js";
7
25
  export declare function buildInvokeChild(runId: string, opts?: {
8
26
  fallbackBaseUrl?: string;
9
27
  defaultFactorySlug?: string;
10
- }): WorkflowCtx["invokeChild"];
28
+ }): InvokeChild;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Replay-safety pin for `ctx.invokeChild` (parity plan P3.3): the
3
+ * Idempotency-Key a child dispatch carries is DETERMINISTIC per
4
+ * (parentRunId, stepIndex, childName, call ordinal) — a step body re-run
5
+ * from the top (pause/resume re-entry, crash-replayed attempt) re-derives
6
+ * byte-identical keys, so the server's idempotency window collapses the
7
+ * replayed dispatch into the original child run instead of double-running.
8
+ */
9
+ export {};
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@agent-compose/sdk",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "Client library for agent-compose — define agents, runtimes, and workflows, and invoke them against an agent-compose server.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "git+https://github.com/Layr-Labs/agent-compose.git",
8
+ "url": "git+https://github.com/Chris-Moller/agent-compose.git",
9
9
  "directory": "sdk"
10
10
  },
11
11
  "type": "module",