@agent-compose/sdk 0.8.3 → 0.8.5
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/dist/agent/agent-context.d.ts +9 -1
- package/dist/agent/agent-loop.d.ts +14 -1
- package/dist/client.d.ts +171 -33
- package/dist/directives.d.ts +14 -0
- package/dist/generated/verb-synopsis.d.ts +34 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.js +1043 -41
- package/dist/runtimes/_cli-agent.d.ts +118 -0
- package/dist/runtimes/claude-code.d.ts +31 -1
- package/dist/runtimes/openai-desktop.d.ts +50 -0
- package/dist/runtimes/openai-desktop.js +1065 -59
- package/dist/runtimes/openai-desktop.test.d.ts +20 -0
- package/dist/runtimes/tool-pulse.test.d.ts +17 -0
- package/dist/sandbox/devbox.d.ts +5 -5
- package/dist/sandbox/registry.d.ts +12 -0
- package/dist/sandbox/sizes.d.ts +11 -5
- package/dist/sandbox.d.ts +2 -2
- package/dist/step-invocation/types.d.ts +1 -1
- package/dist/types/api-conversations.d.ts +85 -12
- package/dist/types/api-factory.d.ts +111 -1
- package/dist/types/conversation-stream.d.ts +22 -1
- package/dist/types/protocol.d.ts +130 -1
- package/dist/types/runtime.d.ts +71 -0
- package/package.json +1 -1
- package/src/agent/agent-context.ts +43 -9
- package/src/agent/agent-loop.ts +14 -3
- package/src/agent/desktop-open.ts +13 -1
- package/src/client.ts +256 -38
- package/src/directives.ts +21 -1
- package/src/generated/verb-synopsis.ts +544 -0
- package/src/index.ts +20 -5
- package/src/runtimes/_cli-agent.ts +333 -22
- package/src/runtimes/claude-code.ts +260 -14
- package/src/runtimes/openai-desktop.ts +82 -19
- package/src/sandbox/devbox.ts +5 -5
- package/src/sandbox/providers/e2b.ts +89 -17
- package/src/sandbox/registry.ts +19 -1
- package/src/sandbox/sizes.ts +11 -5
- package/src/sandbox.ts +2 -1
- package/src/types/api-conversations.ts +65 -13
- package/src/types/api-factory.ts +121 -1
- package/src/types/conversation-stream.ts +24 -1
- package/src/types/protocol.ts +127 -1
- package/src/types/runtime.ts +63 -0
package/src/types/protocol.ts
CHANGED
|
@@ -147,6 +147,128 @@ export interface AgentMessageTaskNotification extends AgentMessageBase {
|
|
|
147
147
|
usage?: { tokens?: number; toolUses?: number; durationMs?: number };
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/** One entry of a harness workflow's live progress feed — the
|
|
151
|
+
* `workflow_progress` array claude-code's `system`/`task_progress` events
|
|
152
|
+
* carry for its in-harness Workflow tool (the dynamic-workflow
|
|
153
|
+
* orchestrator). `phase` entries are the script's declared phases (seeded
|
|
154
|
+
* up front, 1-based `index`); `agent` entries are the spawned workflow
|
|
155
|
+
* agents, updated in place as they queue → run → settle. Preview text the
|
|
156
|
+
* harness includes (prompt/result previews) is internal plumbing and is
|
|
157
|
+
* deliberately NOT forwarded — same rule as task notifications. */
|
|
158
|
+
export type WorkflowProgressEntry =
|
|
159
|
+
| { kind: "phase"; index: number; title: string }
|
|
160
|
+
| {
|
|
161
|
+
kind: "agent"; index: number; label: string;
|
|
162
|
+
/** Lifecycle: `start` (spawned) / `progress` (heartbeat) are live;
|
|
163
|
+
* `done` / `error` are settled. Verbatim from the harness. */
|
|
164
|
+
state: "start" | "progress" | "done" | "error";
|
|
165
|
+
phaseIndex?: number; phaseTitle?: string;
|
|
166
|
+
model?: string; agentId?: string;
|
|
167
|
+
/** Self-reported usage so far (cumulative for this agent). */
|
|
168
|
+
tokens?: number; toolCalls?: number; durationMs?: number;
|
|
169
|
+
/** Epoch ms the agent actually started (for live elapsed). */
|
|
170
|
+
startedAt?: number;
|
|
171
|
+
/** The failure message when `state: "error"`, clamped. */
|
|
172
|
+
error?: string;
|
|
173
|
+
/** Replayed from a resume cache — settled instantly, no fresh spend. */
|
|
174
|
+
cached?: true;
|
|
175
|
+
/** Skipped by the user (workflow dialog) — an error state that is
|
|
176
|
+
* not a failure. */
|
|
177
|
+
skipped?: true;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/** LIVE progress of a harness BACKGROUND task (claude-code
|
|
181
|
+
* `system`/`task_progress`). For the in-harness Workflow tool the message
|
|
182
|
+
* carries the CUMULATIVE `workflow_progress` entry array (the harness
|
|
183
|
+
* re-sends the whole picture: state changes immediately, heartbeats
|
|
184
|
+
* throttled ~10s), so a consumer treats the latest message as
|
|
185
|
+
* authoritative per entry `(kind, index)`. A plain background AGENT task
|
|
186
|
+
* (Task tool, run_in_background) heartbeats on the same event with NO
|
|
187
|
+
* workflow entries — forwarded with `workflow: []` as liveness evidence
|
|
188
|
+
* so the platform can declare the running task as session background
|
|
189
|
+
* work; its completion evidence rides `task_notification`. `toolUseId`
|
|
190
|
+
* names the spawning call — the correlation key to its card. Additive
|
|
191
|
+
* kind: existing producers never emit it. */
|
|
192
|
+
export interface AgentMessageTaskProgress extends AgentMessageBase {
|
|
193
|
+
type: "task_progress";
|
|
194
|
+
/** The harness's background task id. */
|
|
195
|
+
taskId: string;
|
|
196
|
+
/** The SPAWNING Workflow/Task call's tool_use id, when carried. */
|
|
197
|
+
toolUseId?: string;
|
|
198
|
+
/** The task's cumulative usage totals so far. */
|
|
199
|
+
usage?: { tokens?: number; toolUses?: number; durationMs?: number };
|
|
200
|
+
/** The cumulative workflow progress entries — EMPTY for a plain
|
|
201
|
+
* background Agent-task heartbeat (only Workflow tasks carry entries). */
|
|
202
|
+
workflow: WorkflowProgressEntry[];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** HARNESS-authored notice text — content the CLI composed itself rather
|
|
206
|
+
* than the model speaking: slash-command stdout, model/skills advisories,
|
|
207
|
+
* queued-input notes. claude-code marks these structurally (assistant
|
|
208
|
+
* events whose `message.model` is `"<synthetic>"`), and the normaliser
|
|
209
|
+
* forwards them under this kind so downstream persists them as collapsed
|
|
210
|
+
* system notices instead of agent prose (the 2026-08-22 "(session model)"
|
|
211
|
+
* / skills-reminder leak: harness plumbing rendered as message content).
|
|
212
|
+
* Additive kind: existing producers never emit it. */
|
|
213
|
+
export interface AgentMessageHarnessNotice extends AgentMessageBase {
|
|
214
|
+
type: "harness_notice";
|
|
215
|
+
text: string;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Context-compaction lifecycle — the harness summarizing its own
|
|
219
|
+
* conversation to reclaim context. Mapped 1:1 from claude-code's wire
|
|
220
|
+
* (verified live on 2.1.212, the baked sandbox pin, and 2.1.241 — both
|
|
221
|
+
* emit the identical shapes, `/compact` and auto alike):
|
|
222
|
+
*
|
|
223
|
+
* `system`/`status` `{status:"compacting"}` → phase "start"
|
|
224
|
+
* `system`/`status` `{status:null, compact_result, → phase "settled"
|
|
225
|
+
* compact_error?}`
|
|
226
|
+
* `system`/`compact_boundary` `{compact_metadata: → phase "boundary"
|
|
227
|
+
* {trigger, pre_tokens, post_tokens,
|
|
228
|
+
* cumulative_dropped_tokens, duration_ms, …}}`
|
|
229
|
+
*
|
|
230
|
+
* Order on the wire: start → settled → (fresh init) → boundary → the
|
|
231
|
+
* continuation summary as a SYNTHETIC user message (never forwarded — it
|
|
232
|
+
* quotes conversation content verbatim). "boundary" only follows a
|
|
233
|
+
* successful settle and only on the turn the compaction ran (verified: it
|
|
234
|
+
* does NOT replay on later resumes). A compaction can span MINUTES of
|
|
235
|
+
* otherwise-silent stream — the whole point of forwarding it is that
|
|
236
|
+
* downstream can show the silence as work (the 2026-08-23 dead-air
|
|
237
|
+
* incident: 94% auto-compact read as a dead session). Additive kind:
|
|
238
|
+
* existing producers never emit it. */
|
|
239
|
+
export interface AgentMessageCompaction extends AgentMessageBase {
|
|
240
|
+
type: "compaction";
|
|
241
|
+
phase: "start" | "settled" | "boundary";
|
|
242
|
+
/** settled: how it ended. Absent on start/boundary (a boundary IS a
|
|
243
|
+
* success by construction — the harness only emits it after one). */
|
|
244
|
+
result?: "success" | "failed";
|
|
245
|
+
/** settled+failed: the harness's own reason, clamped. */
|
|
246
|
+
error?: string;
|
|
247
|
+
/** boundary: what initiated the compaction. */
|
|
248
|
+
trigger?: "auto" | "manual";
|
|
249
|
+
/** boundary: context tokens before / after, dropped total, wall time. */
|
|
250
|
+
preTokens?: number;
|
|
251
|
+
postTokens?: number;
|
|
252
|
+
droppedTokens?: number;
|
|
253
|
+
durationMs?: number;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** A user-role message landing INSIDE a subagent's thread — the delivered
|
|
257
|
+
* form of a steer (the parent's `SendMessage` to a RUNNING child, queued
|
|
258
|
+
* "for delivery at its next tool round") or any other message the harness
|
|
259
|
+
* folds into a child's conversation mid-flight. Emitted ONLY with sidechain
|
|
260
|
+
* attribution: `parentToolUseId` (the spawning Agent/Task call's tool_use
|
|
261
|
+
* id) is REQUIRED — an unattributed user event is the parent's own prompt
|
|
262
|
+
* echo, which stays unmapped as before. Lets renderers show the steer as a
|
|
263
|
+
* user-role message inside the child's mini-session instead of leaving it
|
|
264
|
+
* an opaque SendMessage tool call on the parent only (task #97, owner
|
|
265
|
+
* directive 2026-08-27). Additive kind: existing producers never emit it. */
|
|
266
|
+
export interface AgentMessageSubagentUserMessage extends AgentMessageBase {
|
|
267
|
+
type: "subagent_user_message";
|
|
268
|
+
text: string;
|
|
269
|
+
parentToolUseId: string;
|
|
270
|
+
}
|
|
271
|
+
|
|
150
272
|
export type AgentMessage =
|
|
151
273
|
| AgentMessageInit
|
|
152
274
|
| AgentMessageText
|
|
@@ -159,7 +281,11 @@ export type AgentMessage =
|
|
|
159
281
|
| AgentMessageUsage
|
|
160
282
|
| AgentMessageUsageDelta
|
|
161
283
|
| AgentMessagePlan
|
|
162
|
-
| AgentMessageTaskNotification
|
|
284
|
+
| AgentMessageTaskNotification
|
|
285
|
+
| AgentMessageTaskProgress
|
|
286
|
+
| AgentMessageHarnessNotice
|
|
287
|
+
| AgentMessageCompaction
|
|
288
|
+
| AgentMessageSubagentUserMessage;
|
|
163
289
|
|
|
164
290
|
/** Status block the agent emits to signal iteration completion or blockers. */
|
|
165
291
|
export interface AgentStatus {
|
package/src/types/runtime.ts
CHANGED
|
@@ -94,6 +94,16 @@ export interface RuntimeOptions {
|
|
|
94
94
|
* Absent ⇒ nothing extra is sourced. Must be a plain absolute path — no
|
|
95
95
|
* quotes, no `..`; the runtime validates and drops anything else. */
|
|
96
96
|
credEnvFile?: string;
|
|
97
|
+
/** Durable launch report (boot-time turn adoption): called by the durable
|
|
98
|
+
* detached transport the moment its in-guest runner exists — with the
|
|
99
|
+
* guest prompt path (every durable file derives from it), the exit
|
|
100
|
+
* sentinel string, and the detached wrapper's pid. The caller stamps
|
|
101
|
+
* these on the turn row so a SUCCESSOR process (a deploy roll's new
|
|
102
|
+
* server) can re-attach to the runner's durable `.out` without this
|
|
103
|
+
* process's memory. Fired once per detached launch (a retry with a fresh
|
|
104
|
+
* runner fires again with the new paths); never on transports without
|
|
105
|
+
* durable files. Must not throw — the transport calls it inline. */
|
|
106
|
+
onDetachedLaunch?: (info: { promptPath: string; sentinel: string; pid: number }) => void;
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
/** Three-valued liveness verdict for a runtime's CURRENT turn, read from
|
|
@@ -182,6 +192,21 @@ export interface ModelExecutionContract {
|
|
|
182
192
|
* fallback probe it already had; null is never a verdict.
|
|
183
193
|
*/
|
|
184
194
|
probeTurnLiveness?(): Promise<RunnerLivenessVerdict | null>;
|
|
195
|
+
/**
|
|
196
|
+
* TELEMETRY, NEVER A VERDICT (tool-run pulse, 2026-08-29): the newest
|
|
197
|
+
* tool-run pulse the durable liveness probe carried — the guest
|
|
198
|
+
* heartbeat's sample of the runner's own session (aggregate CPU jiffies,
|
|
199
|
+
* written bytes, live process count) plus the guest clock it was read
|
|
200
|
+
* against. The executor's evidence ticker peeks it AFTER its liveness
|
|
201
|
+
* check and compares successive samples: counters ADVANCING is proof a
|
|
202
|
+
* long silent foreground tool is working, fanned to clients as a live
|
|
203
|
+
* `tool_pulse` frame. Never probes on its own; null before any probe or
|
|
204
|
+
* on a transport without the pulse file. No liveness decision may ever
|
|
205
|
+
* read it.
|
|
206
|
+
*/
|
|
207
|
+
peekTurnPulse?(): {
|
|
208
|
+
atMs: number; cpuJiffies: number; ioBytes: number; procs: number; guestNowMs: number;
|
|
209
|
+
} | null;
|
|
185
210
|
/**
|
|
186
211
|
* DOORBELL, NEVER A VERDICT (exit-event push, v0.10.43): wake the current
|
|
187
212
|
* turn's durable watchdog NOW so it runs its normal verification pass —
|
|
@@ -232,6 +257,44 @@ export interface ModelExecutionContract {
|
|
|
232
257
|
* Calls are serialized per turn; never throws.
|
|
233
258
|
*/
|
|
234
259
|
injectUserMessage?(text: string): Promise<"delivered" | "pending" | "closed" | "unsupported">;
|
|
260
|
+
/**
|
|
261
|
+
* Request an in-band STEP INTERRUPT of the currently running turn — the
|
|
262
|
+
* ESC equivalent. Where `injectUserMessage` queues content for the turn
|
|
263
|
+
* loop's next boundary, this rides the same durable inbox but carries a
|
|
264
|
+
* control line the CLI handles immediately, mid-step included: the
|
|
265
|
+
* running tool call aborts, the run ends within ~100ms, and the guest
|
|
266
|
+
* session stays resumable with the whole turn context (verified live
|
|
267
|
+
* against claude 2.1.236). Verdicts mirror `injectUserMessage`; only
|
|
268
|
+
* "delivered" means the CLI got the control line — callers escalate
|
|
269
|
+
* anything else (and "unsupported": no stream-input turn, or a runtime
|
|
270
|
+
* with no in-band interrupt, e.g. codex) to kill semantics, which stay
|
|
271
|
+
* honest because thread stores are durable and the successor turn
|
|
272
|
+
* resumes them. Never throws.
|
|
273
|
+
*/
|
|
274
|
+
interruptTurn?(): Promise<"delivered" | "pending" | "closed" | "unsupported">;
|
|
275
|
+
/**
|
|
276
|
+
* Guest pid of the CURRENT turn's detached runner wrapper (the setsid
|
|
277
|
+
* process-group leader recorded at launch), or null when no detached
|
|
278
|
+
* durable-transport runner is live (boot phase, ACP path, single-exec
|
|
279
|
+
* transports). Advisory identity, NEVER a liveness verdict: the platform
|
|
280
|
+
* reads it to DECLARE harness-reported background work (an in-harness
|
|
281
|
+
* Workflow task) against the process tree that hosts it, so the park
|
|
282
|
+
* machinery can verify the tree from `/proc/<pid>` later. Runtimes
|
|
283
|
+
* without a detached guest simply omit the method.
|
|
284
|
+
*/
|
|
285
|
+
currentRunnerPid?(): number | null;
|
|
286
|
+
/**
|
|
287
|
+
* Durable byte offset of the CURRENT turn's `.out` file just past the
|
|
288
|
+
* last line whose messages have ALL been yielded to the consumer — the
|
|
289
|
+
* safe harvest watermark for boot-time turn adoption. Null when no
|
|
290
|
+
* durable-transport turn is live, or before the first line completes.
|
|
291
|
+
* The contract is deliberately one line BEHIND the parse cursor: a
|
|
292
|
+
* caller that persists parts after each yielded message may stamp this
|
|
293
|
+
* offset at any time and a successor re-parses AT MOST the line whose
|
|
294
|
+
* parts were mid-persist (the same crash window the workflow tailer's
|
|
295
|
+
* flush-before-advance ordering accepts). Advisory, never a verdict.
|
|
296
|
+
*/
|
|
297
|
+
currentTurnDurableOffset?(): number | null;
|
|
235
298
|
sendMessage(opts: {
|
|
236
299
|
prompt: string;
|
|
237
300
|
sessionId?: string;
|