@agent-compose/sdk 0.5.0 → 0.5.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.
Files changed (90) hide show
  1. package/dist/active-step.d.ts +60 -0
  2. package/dist/agent/agent-loop-steer.test.d.ts +1 -0
  3. package/dist/agent/agent-loop.d.ts +46 -0
  4. package/dist/agent/async-queue.d.ts +29 -0
  5. package/dist/agent/protocol.d.ts +9 -1
  6. package/dist/agent/resolve-agent-id.test.d.ts +1 -0
  7. package/dist/agent/run-agent.d.ts +16 -3
  8. package/dist/agent/steer-control.d.ts +57 -0
  9. package/dist/agent/steer-control.test.d.ts +1 -0
  10. package/dist/client.d.ts +161 -0
  11. package/dist/index.d.ts +7 -4
  12. package/dist/index.js +1341 -157
  13. package/dist/pause/__tests__/agent-loop-checkpoint.test.d.ts +1 -0
  14. package/dist/pause/__tests__/checkpoint.test.d.ts +1 -0
  15. package/dist/pause/__tests__/errors.test.d.ts +1 -0
  16. package/dist/pause/__tests__/manager.test.d.ts +1 -0
  17. package/dist/pause/__tests__/pause-core.test.d.ts +1 -0
  18. package/dist/pause/__tests__/state-dir.test.d.ts +1 -0
  19. package/dist/pause/__tests__/wrappers.test.d.ts +1 -0
  20. package/dist/pause/checkpoint.d.ts +28 -0
  21. package/dist/pause/errors.d.ts +52 -0
  22. package/dist/pause/manager.d.ts +63 -0
  23. package/dist/pause/pause-core.d.ts +101 -0
  24. package/dist/pause/state-dir.d.ts +80 -0
  25. package/dist/pause/wrappers.d.ts +41 -0
  26. package/dist/request-context/request-context.d.ts +12 -0
  27. package/dist/runtimes/claude.d.ts +6 -0
  28. package/dist/runtimes/openai-desktop.d.ts +2 -0
  29. package/dist/runtimes/openai-desktop.js +1338 -156
  30. package/dist/runtimes/vercel.d.ts +12 -0
  31. package/dist/runtimes/vercel.js +50 -7
  32. package/dist/runtimes/vercel.test.d.ts +1 -0
  33. package/dist/sse.d.ts +2 -3
  34. package/dist/step-invocation/index.d.ts +2 -2
  35. package/dist/step-invocation/invoker.d.ts +3 -0
  36. package/dist/step-invocation/protocol.d.ts +12 -0
  37. package/dist/step-invocation/server.d.ts +1 -0
  38. package/dist/step-invocation/types.d.ts +40 -5
  39. package/dist/types/events.d.ts +9 -0
  40. package/dist/types/execution-context.d.ts +25 -0
  41. package/dist/types/protocol.d.ts +8 -0
  42. package/dist/types/runtime.d.ts +55 -0
  43. package/dist/types/sandbox.d.ts +6 -1
  44. package/dist/utils/schemas.d.ts +2 -0
  45. package/dist/workflow-steps/__tests__/pause-wiring.test.d.ts +1 -0
  46. package/dist/workflow-steps/index.d.ts +2 -0
  47. package/dist/workflow-steps/observability.d.ts +43 -11
  48. package/dist/workflow-steps/run-callback.d.ts +39 -0
  49. package/dist/workflow-steps/runner.d.ts +8 -0
  50. package/package.json +1 -1
  51. package/src/active-step.ts +124 -0
  52. package/src/agent/agent-loop.ts +253 -19
  53. package/src/agent/async-queue.ts +61 -0
  54. package/src/agent/protocol.ts +12 -2
  55. package/src/agent/run-agent.ts +184 -8
  56. package/src/agent/steer-control.ts +125 -0
  57. package/src/client.ts +277 -0
  58. package/src/index.ts +18 -2
  59. package/src/pause/checkpoint.ts +44 -0
  60. package/src/pause/errors.ts +70 -0
  61. package/src/pause/manager.ts +177 -0
  62. package/src/pause/pause-core.ts +267 -0
  63. package/src/pause/state-dir.ts +262 -0
  64. package/src/pause/wrappers.ts +79 -0
  65. package/src/request-context/request-context.ts +17 -2
  66. package/src/runtimes/claude.ts +101 -6
  67. package/src/runtimes/openai-desktop.ts +11 -0
  68. package/src/runtimes/vercel.ts +26 -0
  69. package/src/sandbox.ts +45 -17
  70. package/src/sse.ts +8 -6
  71. package/src/step-invocation/index.ts +2 -1
  72. package/src/step-invocation/invoker.ts +107 -29
  73. package/src/step-invocation/protocol.ts +16 -0
  74. package/src/step-invocation/server.ts +45 -12
  75. package/src/step-invocation/types.ts +43 -7
  76. package/src/tools/coding.ts +16 -5
  77. package/src/types/events.ts +9 -0
  78. package/src/types/execution-context.ts +25 -0
  79. package/src/types/protocol.ts +8 -0
  80. package/src/types/runtime.ts +52 -0
  81. package/src/types/sandbox.ts +10 -1
  82. package/src/types/workflow.ts +6 -1
  83. package/src/utils/bundler.ts +8 -3
  84. package/src/utils/schemas.ts +2 -0
  85. package/src/workflow-steps/index.ts +3 -0
  86. package/src/workflow-steps/observability.ts +84 -13
  87. package/src/workflow-steps/run-callback.ts +72 -0
  88. package/src/workflow-steps/runner.ts +70 -8
  89. package/dist/utils/discovery.d.ts +0 -2
  90. package/src/utils/discovery.ts +0 -4
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The step currently executing in this runner subprocess.
3
+ *
4
+ * Step-mode derivations that must be byte-identical across a pause-resume
5
+ * re-entry — the agent loop's `agentId` (which names `agent-<id>.json`) and
6
+ * the pause primitive's `pauseId` — need the running step's index. They
7
+ * CANNOT read it from `process.env.AC_STEP_INDEX`: `serveStep` scrubs the
8
+ * transport envs (`AC_STEP_MODE`, `AC_STEP_INDEX`, the result token, …) from
9
+ * `process.env` *before* the user step body runs, so by the time `agent()` /
10
+ * `ctx.pause` execute those reads return `undefined`
11
+ * (`step-invocation/server.ts` `scrubProtocolEnvs`). Reading scrubbed env was
12
+ * a latent resume bug: `agentId` fell through to `randomUUID()` on every
13
+ * subprocess, so resume never matched the prior `agent-<id>.json`.
14
+ *
15
+ * Instead the step runner sets the index here from the un-scrubbed `stepIndex`
16
+ * it already holds, and the derivations read it from here.
17
+ *
18
+ * Async-local rather than process-global: public in-process execution can run
19
+ * multiple workflows concurrently, and ids must stay scoped to the async step
20
+ * body that is deriving them. A fresh subprocess on resume starts with a fresh
21
+ * async context, the runner re-sets the same `stepIndex`, and the per-step
22
+ * call-order counters re-derive identical ids — which is exactly what lets
23
+ * resume find its on-disk state.
24
+ */
25
+ export interface ActiveStep {
26
+ stepIndex: number;
27
+ }
28
+ interface ActiveStepState extends ActiveStep {
29
+ nextAgentCallIndex: number;
30
+ pauseOrdinalByScope: Map<string, number>;
31
+ }
32
+ /** Set (or clear, with `null`) the step currently running. Called by the
33
+ * step runner around `step.run(...)`. Prefer `runWithActiveStep` for real
34
+ * async execution; this setter exists for tests and small synchronous helpers. */
35
+ export declare function setActiveStep(step: ActiveStep | null): void;
36
+ /** Run `fn` with a step context scoped to this async call tree. */
37
+ export declare function runWithActiveStep<T>(step: ActiveStep, fn: () => Promise<T>): Promise<T>;
38
+ /** Publish (or clear, with `null`) the active step on the cross-instance bridge.
39
+ * Called ONLY by the sandbox step runner (`runWorkflowSingleStep`), which runs
40
+ * exactly one step per subprocess — so there is no concurrency to race the
41
+ * single global slot. The bundle's `agent()` reads this when its own ALS is
42
+ * empty. Returns the prior value so the caller can restore it. */
43
+ export declare function setActiveStepBridge(step: ActiveStep | null): {
44
+ state: ActiveStepState | null;
45
+ };
46
+ /** Restore a bridge value captured by `setActiveStepBridge`. */
47
+ export declare function restoreActiveStepBridge(prev: {
48
+ state: ActiveStepState | null;
49
+ }): void;
50
+ /** The step currently running, or `null` outside step execution (local
51
+ * tests, dev, between steps). */
52
+ export declare function getActiveStep(): ActiveStep | null;
53
+ /** Return the next implicit `agent()` call coordinate for the active step. */
54
+ export declare function nextAgentCallInActiveStep(): {
55
+ stepIndex: number;
56
+ callIndex: number;
57
+ } | null;
58
+ /** Return the next pause ordinal in `scope` for the active step invocation. */
59
+ export declare function nextPauseOrdinalInActiveStep(scope: string): number | null;
60
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -7,6 +7,7 @@ import { z } from "zod";
7
7
  import type { AgentStatus, AgentMessage } from "./protocol.js";
8
8
  import type { Processor } from "../processors/processor.js";
9
9
  import { RequestContext } from "../request-context/request-context.js";
10
+ import { type SteerPayload } from "./steer-control.js";
10
11
  export declare const DEFAULT_CLAUDE_MODEL = "claude-opus-4-7";
11
12
  export declare function parseAgentStatus(text: string): AgentStatus | null;
12
13
  export interface AgentLoopResult<TResponse = unknown> {
@@ -30,6 +31,7 @@ export type AgentMessageSummary = {
30
31
  type: "tool_use";
31
32
  toolName: string;
32
33
  toolUseId: string;
34
+ toolInput: Record<string, unknown>;
33
35
  toolInputPreview: string;
34
36
  } | {
35
37
  type: "tool_result";
@@ -58,6 +60,12 @@ export type AgentLifecycleEvent = {
58
60
  agentId: string;
59
61
  label: string;
60
62
  allowedTools?: string[];
63
+ /** Resolved model id used for this agent (e.g. `claude-sonnet-4-6`).
64
+ * Read off `client.model` after runtime construction. */
65
+ model?: string;
66
+ /** Short runtime self-identifier (`claude`, `openai-desktop`, …).
67
+ * Drives the per-agent runtime icon on the dashboard. */
68
+ runtimeKind?: string;
61
69
  } | {
62
70
  event: "agent.message";
63
71
  at: number;
@@ -101,5 +109,43 @@ export interface AgentLoopOpts<TResponse = unknown> {
101
109
  processors?: readonly Processor[];
102
110
  /** Per-run typed bag — propagated to every processor as `ctx.requestContext`. */
103
111
  requestContext?: RequestContext;
112
+ /**
113
+ * Mid-iteration user-message injection. When set, the agent loop
114
+ * builds a per-iteration AsyncQueue and hands it to the runtime as
115
+ * `inboxStream`. The runner-side inbox poller calls `push()` on
116
+ * `inbox` when a user message arrives; the runtime (streaming-input
117
+ * Claude Agent SDK) picks it up at the next safe boundary.
118
+ *
119
+ * The loop drains `inbox` into the per-iteration queue while the
120
+ * iteration is active and stops draining at iteration end — any
121
+ * messages that arrive between iterations are buffered on `inbox`
122
+ * and drain into the NEXT iteration's queue. So no message is lost,
123
+ * but mid-iteration injection requires the runtime to support
124
+ * streaming input (ignored otherwise — handled at the runtime).
125
+ */
126
+ inbox?: import("./async-queue.js").AsyncQueue<{
127
+ text: string;
128
+ senderName?: string | null;
129
+ }>;
130
+ /** PR 7 steer-pause: the boundary calls this to pause the workflow for a
131
+ * human steer. agent() builds it (a corePause closed over runId/stepIndex);
132
+ * the loop supplies the agentScope so the pauseId is stable across resume.
133
+ * Absent ⇒ no steer pause (local tests, non-sandbox callers). */
134
+ pause?: <T = unknown>(req: {
135
+ reason: string;
136
+ correlationKey?: string;
137
+ schema?: z.ZodType<T>;
138
+ }, agentScope: {
139
+ agentId: string;
140
+ iteration: number;
141
+ }) => Promise<T>;
142
+ /** PR 7: take-once read of this agent's pending steer (set by the control
143
+ * poller). Returns the steer's payload (reason / correlationKey) or null.
144
+ * The boundary consumes it once per check, and only when no steer is
145
+ * already staged. */
146
+ consumeSteerPending?: () => SteerPayload | null;
147
+ /** PR 7: `auto` (autonomous, default) or `hitl` (can be steer-paused). The
148
+ * boundary is inert unless `hitl`. */
149
+ mode?: "auto" | "hitl";
104
150
  }
105
151
  export declare function agentLoop<TResponse = unknown>(opts: AgentLoopOpts<TResponse>): Promise<AgentLoopResult<TResponse>>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * AsyncQueue — single-producer/single-consumer push-iterable.
3
+ *
4
+ * The Claude Agent SDK's streaming-input mode wants
5
+ * `prompt: AsyncIterable<SDKUserMessage>`. We need a primitive that:
6
+ * - lets the agent loop `push()` user turns from outside the iterator
7
+ * (initial prompt, plus async-arriving inbox messages)
8
+ * - lets the SDK's `for await` consume them in order, blocking until
9
+ * the next item arrives
10
+ * - terminates cleanly via `close()` so the SDK sees the iterable
11
+ * drain and finalises the assistant turn
12
+ *
13
+ * Why not an `EventEmitter` or RxJS — both are overkill for one shape.
14
+ * The implementation is ~30 lines of native Promise plumbing and stays
15
+ * inside the SDK package so it can be the canonical way agent-loop
16
+ * builds its prompt iterable.
17
+ */
18
+ export declare class AsyncQueue<T> implements AsyncIterable<T> {
19
+ private readonly buffer;
20
+ private readonly resolvers;
21
+ private done;
22
+ /** Push one item. If a consumer is awaiting, it wakes immediately;
23
+ * otherwise the item is buffered until the next `next()` call. */
24
+ push(value: T): void;
25
+ /** Signal end-of-stream. Any pending awaiters resolve as
26
+ * `{ done: true }`; subsequent `push()` calls are silent no-ops. */
27
+ close(): void;
28
+ [Symbol.asyncIterator](): AsyncIterator<T>;
29
+ }
@@ -4,4 +4,12 @@ import type { AgentMessage } from "../types/protocol.js";
4
4
  export type { AgentMessage, AgentMessageInit, AgentMessageText, AgentMessageThinking, AgentMessageToolUse, AgentMessageToolResult, AgentMessageDone, AgentMessageError, AgentMessageUsage, AgentStatus, } from "../types/protocol.js";
5
5
  export { AgentStatusSchema };
6
6
  export declare const AgentMessageSchema: z.ZodType<AgentMessage>;
7
- export declare function parseAgentResponse(text: string): unknown;
7
+ /** Parse the `<response>...</response>` block from agent text. Returns
8
+ * `null` if missing or malformed. Callers run schema validation on
9
+ * the returned `unknown` directly — the earlier generic overload that
10
+ * did the safeParse inline returned `null` on schema failure,
11
+ * swallowing the validation error without setting any breadcrumb on
12
+ * the loop's `lastResponseValidationError`. No caller used that
13
+ * overload; the dedicated `responseSchema` path in `agent-loop.ts`
14
+ * does the parse-with-error-capture itself. */
15
+ export declare function parseAgentResponse(text: string): unknown | null;
@@ -0,0 +1 @@
1
+ export {};
@@ -37,6 +37,11 @@ export interface AgentOpts<T = unknown> {
37
37
  tools?: string[];
38
38
  /** Turn/iteration caps. Defaults: 40 turns/iteration, 8 iterations. */
39
39
  budget?: AgentBudget;
40
+ /** Steerability (PR 7). `auto` (default) runs autonomously and ignores steer
41
+ * requests; `hitl` lets a human pause this agent mid-run via the steer route
42
+ * — the loop checks for a pending steer at each iteration boundary and only
43
+ * `hitl` agents run the control poller. */
44
+ mode?: "auto" | "hitl";
40
45
  /** If set, the loop demands a `<response>` block when `exit_signal=true`
41
46
  * and validates it against this schema. The response format appendix is
42
47
  * appended to the prompt on first iteration. */
@@ -76,8 +81,16 @@ export interface AgentOpts<T = unknown> {
76
81
  requestContext?: RequestContext;
77
82
  }
78
83
  /**
79
- * Run an agent loop inside a workflow. Returns the loop's final
80
- * `AgentLoopResult`, including `response` when a `responseSchema` was
81
- * supplied and the model validated against it.
84
+ * Resolve the `agentId` for an `agent()` call. Resolution order:
85
+ * 1. Caller-supplied `explicitId` (the workflow author owns the id).
86
+ * 2. Step-mode derivation `step<idx>-agent-<callOrder>` — deterministic
87
+ * across a pause-resume re-entry: the same step body re-executes in the
88
+ * same call order, so the same id recovers `agent-<id>.json`. The step
89
+ * index comes from the active-step context (set by the step runner),
90
+ * NOT `process.env.AC_STEP_INDEX` — `serveStep` scrubs that before the
91
+ * step body runs, which would orphan the state file on every resume
92
+ * (see `active-step.ts`).
93
+ * 3. `randomUUID()` outside step mode (local tests, dev).
82
94
  */
95
+ export declare function resolveAgentId(explicitId?: string): string;
83
96
  export declare function agent<T = unknown>(opts: AgentOpts<T>): Promise<AgentLoopResult<T>>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Steer-control (PR 7) — the in-sandbox half of "a human pauses a running
3
+ * agent." A `runControlPoller` long-polls the per-run control channel; when a
4
+ * `steer_pause` for this agent arrives it sets a per-agentId **take-once**
5
+ * flag. The agent loop consumes the flag at its next iteration boundary
6
+ * (`consumeSteerPending`) and takes a `ctx.pause` there (commit 6).
7
+ *
8
+ * Lives in its own module so both `run-agent.ts` (the poller, the signal) and
9
+ * `agent-loop.ts` (the consume) import it without a cycle.
10
+ *
11
+ * The flag is **transient** and best-effort: a steer NOTIFY that arrives while
12
+ * the poller is between long-poll requests is missed (no durable backing — the
13
+ * route writes no row). The human re-requests; the loop only commits a durable
14
+ * `run_pauses` row once it reaches a boundary and takes the pause.
15
+ */
16
+ import { z } from "zod";
17
+ /** What a steer/resume answer carries. Used as the boundary pause's `schema`
18
+ * so it is validated client-side in the re-spawned runner — a null/empty
19
+ * message is rejected (PauseSchemaError) so an agent never resumes on an
20
+ * empty steer. `message` becomes the agent's next user turn. */
21
+ export declare const SteerDecisionSchema: z.ZodObject<{
22
+ message: z.ZodString;
23
+ actor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
24
+ }, z.core.$strip>;
25
+ export type SteerDecision = z.infer<typeof SteerDecisionSchema>;
26
+ /** Metadata a pending steer carries from the control message to the boundary
27
+ * that turns it into a durable pause row. The flag store used to be a bare
28
+ * `Set<string>` carrying none of this, so the committed `run_pauses` row
29
+ * always had `correlation_key = null` and `reason = "human steer"` —
30
+ * `resumePauseByKey` could never match and the operator's reason was lost. */
31
+ export interface SteerPayload {
32
+ reason: string | null;
33
+ correlationKey: string | null;
34
+ }
35
+ /** Enqueue a pending steer-pause for `agentId` (called by the poller). A steer
36
+ * whose correlationKey matches one already queued replaces it (idempotent);
37
+ * a distinct key is appended. */
38
+ export declare function signalSteerPending(agentId: string, payload: SteerPayload): void;
39
+ /** Take-once read: dequeues and returns the next pending steer's payload for
40
+ * `agentId` (FIFO), else null. The boundary calls this exactly once per check
41
+ * so a single steer can't re-fire on the post-resume continuation; a second
42
+ * queued steer surfaces at the next boundary. */
43
+ export declare function consumeSteerPending(agentId: string): SteerPayload | null;
44
+ /**
45
+ * Long-poll the per-run control channel and set the steer flag for this agent.
46
+ * Mirrors `runInboxPoller`: same per-run HMAC token, same backoff, stops on
47
+ * 401/403 (token expired / wrong run). The server holds each request open
48
+ * until a control message lands or the long-poll window elapses, so this
49
+ * loops mostly blocked in `fetch`.
50
+ */
51
+ export declare function runControlPoller(opts: {
52
+ baseUrl: string;
53
+ token: string;
54
+ runId: string;
55
+ agentId: string;
56
+ signal: AbortSignal;
57
+ }): Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
package/dist/client.d.ts CHANGED
@@ -183,6 +183,95 @@ export interface RunStatus<TOutput = unknown> {
183
183
  status: RunState;
184
184
  output?: TOutput;
185
185
  }
186
+ /** ADR-0006 step 10 — actor record returned on a successful resume.
187
+ * Shape mirrors the server's `PauseResumeActor` type after the row
188
+ * has been stamped. Audit FKs (`userId` / `keyId` / `runId`) may be
189
+ * null when the referenced row was deleted between resume and the
190
+ * response render — the immutable `label` survives. */
191
+ export interface ResumePauseActor {
192
+ kind: "session_user" | "api_key" | "agent";
193
+ /** Better Auth user id when kind='session_user'. */
194
+ userId?: string | null;
195
+ /** api_keys.id when kind='api_key'. */
196
+ keyId?: string | null;
197
+ /** Caller-run id when kind='agent' (NOT the run being resumed). */
198
+ runId?: string | null;
199
+ /** Agent-instance within `runId` when kind='agent'. */
200
+ agentId?: string | null;
201
+ label: string;
202
+ }
203
+ /** Success branch of the resume HTTP response. The pause has reached
204
+ * a terminal state — `resolved` (workflow signal arrived), `expired`
205
+ * (TTL fired first), or `cancelled` (workflow terminated mid-pause).
206
+ * Only `resolved` carries the resume payload the user supplied. */
207
+ export interface ResumePauseSuccess {
208
+ status: "resolved" | "expired" | "cancelled";
209
+ pauseId: string;
210
+ resolvedAt: string | null;
211
+ resumePayload: unknown;
212
+ actor: ResumePauseActor | null;
213
+ }
214
+ /** Pending branch — the workflow accepted the signal but the row
215
+ * flip didn't observe within the route's 5s wait window. The
216
+ * operation is in-flight; retry with the same `Idempotency-Key`
217
+ * and the cache collapses the duplicate to a single canonical
218
+ * response. */
219
+ export interface ResumePausePending {
220
+ status: "pending";
221
+ pauseId: string;
222
+ timedOut: true;
223
+ }
224
+ export type ResumePauseResponse = ResumePauseSuccess | ResumePausePending;
225
+ export interface ResumePauseOptions {
226
+ /** Stripe-style retry-dedup key — same syntax as the workflow-invoke
227
+ * route: 1..255 chars of `[A-Za-z0-9_\-:.]`, no embedded CR/LF.
228
+ * Sent as the `Idempotency-Key` request header. (The server reads the
229
+ * header first, falling back to a body field for callers behind a
230
+ * header-stripping proxy; this client only sends the header.) */
231
+ idempotencyKey?: string;
232
+ /** Abort the HTTP request mid-wait (e.g. from a UI cancel button).
233
+ * The server's LISTEN tears down via the request's AbortSignal. */
234
+ signal?: AbortSignal;
235
+ }
236
+ export interface RequestAgentPauseOptions {
237
+ /** Human-readable note surfaced to the agent as the pause reason. */
238
+ reason?: string;
239
+ /** Your handle for answering this pause without the minted pauseId:
240
+ * pass the same value to `resumePauseByKey`. */
241
+ correlationKey?: string;
242
+ /** Abort the HTTP request. */
243
+ signal?: AbortSignal;
244
+ }
245
+ export interface AnswerSteerOptions extends ResumePauseOptions {
246
+ /** Who answered — surfaced to the agent as `[human steer from <actor>]`. */
247
+ actor?: string;
248
+ }
249
+ /** 202 envelope from a steer-pause request. The request is best-effort and
250
+ * fire-and-forget: it publishes a transient control message and returns
251
+ * immediately — the agent parks at its next iteration boundary (if it is
252
+ * `mode: "hitl"` and still running). Answer it via `answerSteerByKey`
253
+ * (pass the `correlationKey` you set here) or `answerSteer` (by pauseId). */
254
+ export interface RequestAgentPauseResponse {
255
+ status: "steer_requested";
256
+ runId: string;
257
+ agentId: string;
258
+ }
259
+ export interface SendAgentMessageOptions {
260
+ /** Transcript attribution. For non-session callers (API key, orchestrator)
261
+ * this names the sender; defaults to the caller's identity server-side. */
262
+ senderName?: string;
263
+ /** Abort the HTTP request. */
264
+ signal?: AbortSignal;
265
+ }
266
+ /** 202 envelope from a message-to-running-agent request. The message is queued
267
+ * durably and delivered mid-stream as the agent's next user turn — the workflow
268
+ * is NOT paused. `seq` is the message's per-run ordinal. */
269
+ export interface SendAgentMessageResponse {
270
+ status: "message_enqueued";
271
+ runId: string;
272
+ agentId: string;
273
+ seq: number;
274
+ }
186
275
  export interface RunDetail<TOutput = unknown> {
187
276
  runId: string;
188
277
  title: string;
@@ -408,6 +497,78 @@ export declare class AgentComposeClient {
408
497
  deleteRunSnapshot(runId: string, snapshotId: string): Promise<void>;
409
498
  /** Poll run status. */
410
499
  getStatus<TOutput = unknown>(runId: string): Promise<RunStatus<TOutput>>;
500
+ /** Resume a paused run by pause id.
501
+ *
502
+ * Returns the terminal state on success (200) or a pending
503
+ * envelope (202) if the server's 5s wait timed out. For the
504
+ * pending case, retry with the same `idempotencyKey` — the
505
+ * server-side cache collapses duplicates to a single canonical
506
+ * response once the workflow's row-flip lands.
507
+ *
508
+ * Throws `AgentComposeError` on 4xx/5xx — 404 when the run or
509
+ * pause doesn't exist, 403 when the caller lacks scope or the
510
+ * run-token cross-run/cross-agent gate fails, 409 when the
511
+ * `Idempotency-Key` was reused against a different operation.
512
+ */
513
+ resumePause(runId: string, pauseId: string, payload: unknown, opts?: ResumePauseOptions): Promise<ResumePauseResponse>;
514
+ /** Resume a paused run by correlation key. The correlation key is
515
+ * the second resume key set on `ctx.pause({ correlationKey })`;
516
+ * the server resolves it to a unique pending pause within the
517
+ * run, then delegates to the same handler as `resumePause`.
518
+ *
519
+ * The key is `encodeURIComponent`'d at the call site, so callers
520
+ * pass the literal value (containing `/`, `:`, etc. as written).
521
+ */
522
+ resumePauseByKey(runId: string, correlationKey: string, payload: unknown, opts?: ResumePauseOptions): Promise<ResumePauseResponse>;
523
+ /** Answer a steer-pause by its `correlationKey` (PR 7) — the typed,
524
+ * footgun-free way to resume a `requestAgentPause`.
525
+ *
526
+ * The steer boundary validates its resume payload against
527
+ * `SteerDecisionSchema` (`{ message }`) inside the re-spawned runner; a bare
528
+ * string or wrong-shaped payload passed to `resumePause`/`resumePauseByKey`
529
+ * fails that check and terminates the run. This wraps `message` in the
530
+ * expected shape so the answer is always well-formed. `message` becomes the
531
+ * agent's next user turn. Pass the `correlationKey` you gave
532
+ * `requestAgentPause`.
533
+ *
534
+ * Throws `AgentComposeError` on 4xx/5xx — 404 when no pending steer matches
535
+ * the key. Throws synchronously if `message` is empty. */
536
+ answerSteerByKey(runId: string, correlationKey: string, message: string, opts?: AnswerSteerOptions): Promise<ResumePauseResponse>;
537
+ /** Answer a steer-pause by its minted `pauseId`. Use this when you learned
538
+ * the pauseId out of band (e.g. from the `pause_requested` lifecycle event);
539
+ * otherwise prefer {@link answerSteerByKey}. Same `{ message }` wrapping and
540
+ * validation as `answerSteerByKey`. */
541
+ answerSteer(runId: string, pauseId: string, message: string, opts?: AnswerSteerOptions): Promise<ResumePauseResponse>;
542
+ /** Request that a running agent pause for human steering (PR 7).
543
+ *
544
+ * Three callers share this route — an operator (session/api-key), another
545
+ * agent or external orchestrator (run-callback token), and this method.
546
+ * It is fire-and-forget: the server publishes a transient control message
547
+ * and returns 202 immediately. The agent takes the pause at its next
548
+ * iteration boundary — but only if it was started `mode: "hitl"` and is
549
+ * still running; an `auto` agent ignores it. Delivery is best-effort (a
550
+ * steer arriving between the in-sandbox poller's long-polls is missed —
551
+ * re-request). Once the agent parks, answer it with `answerSteerByKey` (by
552
+ * the `correlationKey` you pass here) or `answerSteer` (by the minted
553
+ * pauseId) — these wrap the answer in the shape the steer boundary
554
+ * validates. The human's `message` becomes the agent's next user turn.
555
+ *
556
+ * Throws `AgentComposeError` on 4xx/5xx — 404 when the run doesn't exist,
557
+ * 403 when the caller lacks scope or the run-token gate fails.
558
+ */
559
+ requestAgentPause(runId: string, agentId: string, opts?: RequestAgentPauseOptions): Promise<RequestAgentPauseResponse>;
560
+ /** Send a message to a RUNNING agent — the lightweight steer (PR 7).
561
+ *
562
+ * Durable and **non-halting**: the message is queued and delivered to the
563
+ * agent mid-stream as its next user turn, *without* pausing the workflow.
564
+ * This is the efficient way to nudge or redirect an agent that should keep
565
+ * running — reserve `requestAgentPause` for when it must stop and wait. The
566
+ * message lands at the agent's next iteration boundary (it finishes the
567
+ * current model turn first). `senderName` sets the transcript attribution.
568
+ *
569
+ * Throws `AgentComposeError` on 4xx/5xx — 404 unknown run, 403 scope/gate.
570
+ */
571
+ sendAgentMessage(runId: string, agentId: string, message: string, opts?: SendAgentMessageOptions): Promise<SendAgentMessageResponse>;
411
572
  /** Full run detail, including input/output and lifecycle events. */
412
573
  getRun<TOutput = unknown>(runId: string): Promise<RunDetail<TOutput>>;
413
574
  /** Ordered lifecycle timeline for one run. */
package/dist/index.d.ts CHANGED
@@ -27,11 +27,10 @@ export type { Processor, ProcessorContext, ProcessorVerdict, ToolCall, } from ".
27
27
  export type { AgentMessage, AgentMessageInit, AgentMessageText, AgentMessageThinking, AgentMessageToolUse, AgentMessageToolResult, AgentMessageDone, AgentMessageError, AgentMessageUsage, AgentStatus, } from "./types/protocol.js";
28
28
  export type { SandboxProvider, DesktopSandboxProvider, } from "./types/sandbox.js";
29
29
  export { AgentComposeClient } from "./client.js";
30
- export type { RegisterResult, RegisterWorkflowInput, RuntimeSourceInput, InvokeWorkflowOptions, InvokeAndWaitOptions, InvokeResult, ListSnapshotsOptions, TemplateRow, ListTemplatesOptions, CreateFactoryInput, UpdateFactoryInput, SecretOptions, SetSecretResult, SecretListEntry, CreateApiKeyInput, StreamRunLogsOptions, EventSubjectType, EventRow, ReportEventInput, ListEventsOptions, ListEventsResult, RunLogLine, ListRunLogsOptions, RegisteredRuntime, RunState, RunStatus, FactoryRow, SnapshotListEntry, SnapshotListResponse, ApiKey, ApiKeyCreated, UsageRollupRow, UsageResponse, CancelRunResponse, } from "./client.js";
30
+ export type { RegisterResult, RegisterWorkflowInput, RuntimeSourceInput, InvokeWorkflowOptions, InvokeAndWaitOptions, InvokeResult, ListSnapshotsOptions, TemplateRow, ListTemplatesOptions, CreateFactoryInput, UpdateFactoryInput, SecretOptions, SetSecretResult, SecretListEntry, CreateApiKeyInput, StreamRunLogsOptions, EventSubjectType, EventRow, ReportEventInput, ListEventsOptions, ListEventsResult, RunLogLine, ListRunLogsOptions, RegisteredRuntime, RunState, RunStatus, FactoryRow, SnapshotListEntry, SnapshotListResponse, ApiKey, ApiKeyCreated, UsageRollupRow, UsageResponse, CancelRunResponse, RequestAgentPauseOptions, RequestAgentPauseResponse, SendAgentMessageOptions, SendAgentMessageResponse, AnswerSteerOptions, } from "./client.js";
31
31
  export { parseSseStream } from "./sse.js";
32
32
  export { AgentComposeError } from "./errors.js";
33
33
  export { formatError } from "./utils/errors.js";
34
- export { discoverRuntimeName } from "./utils/discovery.js";
35
34
  export { bundleWorkflow, BUNDLER_VERSION, WorkflowSourceValidationError, assertDefaultExportIsDefineWorkflow, } from "./utils/bundler.js";
36
35
  export type { BundledWorkflow, WorkflowManifest } from "./utils/bundler.js";
37
36
  export { AgentStatusSchema } from "./utils/schemas.js";
@@ -50,8 +49,12 @@ export type { WorkflowResult, RunWorkflowOptions, EngineSubsystem } from "./work
50
49
  export { buildInvokeChild } from "./workflows/invoke-child.js";
51
50
  export { defineStep, isWorkflow, runWorkflowSteps, runWorkflowSingleStep, StepValidationError, WorkflowInputValidationError, WorkflowOutputValidationError, } from "./workflow-steps/index.js";
52
51
  export type { Step, StepContext, StepRunResult, Workflow, DefineStepOpts, StepWorkflowDefinition, WorkflowBuilder, RunWorkflowStepsOpts, RunWorkflowStepsResult, RunWorkflowSingleStepOpts, RunWorkflowSingleStepResult, StepObservability, SubStepEvent, } from "./workflow-steps/index.js";
53
- export { invokeStep, serveStep, parseStepResult, buildStepEnvs, StepExecutionError, STEP_RESULT_PREFIX, STEP_ENV, RUNNER_BUNDLE_PATH, RUNNER_COMMAND, stepInputPath, requestContextPath, } from "./step-invocation/index.js";
54
- export type { StepRequest, StepResult, StepInvocationError, StepHandler, StepHandlerResult, ServeStepRequest, } from "./step-invocation/index.js";
52
+ export { invokeStep, serveStep, parseStepResult, buildStepEnvs, StepExecutionError, STEP_RESULT_PREFIX, STEP_PAUSE_PREFIX, STEP_ENV, RUNNER_BUNDLE_PATH, RUNNER_COMMAND, stepInputPath, requestContextPath, } from "./step-invocation/index.js";
53
+ export { PauseError, PauseExpiredError, PauseSchemaError, PauseRequestError, } from "./pause/errors.js";
54
+ export type { PauseErrorCode } from "./pause/errors.js";
55
+ export type { PauseRequest } from "./pause/pause-core.js";
56
+ export type { RequestDecisionRequest, WaitForEventRequest } from "./pause/wrappers.js";
57
+ export type { StepRequest, StepResult, StepInvocationError, StepPauseRequest, StepHandler, StepHandlerResult, ServeStepRequest, } from "./step-invocation/index.js";
55
58
  export { agentLoop, parseAgentStatus, DEFAULT_CLAUDE_MODEL } from "./agent/agent-loop.js";
56
59
  export type { AgentLifecycleEvent, AgentLoopOpts, AgentLoopResult } from "./agent/agent-loop.js";
57
60
  export { agent } from "./agent/run-agent.js";