@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
package/dist/client.d.ts CHANGED
@@ -10,524 +10,20 @@
10
10
  * `register()` accepts pre-built sources — use the CLI (`agent-compose
11
11
  * register`) or build sources yourself and pass them directly.
12
12
  */
13
- import type { SandboxNetworkPolicy, SandboxSize } from "./sandbox.js";
14
13
  import type { RunEvent } from "./types/events.js";
15
- import type { WorkflowPlan } from "./types/workflow-plan.js";
16
- import type { SnapshotConfig, IOSchema, ConnectorRequirements, ConnectorOperationTag, InvokePolicy, SandboxResources } from "./types/workflow-metadata.js";
17
- import type { WorkflowManifest } from "./utils/bundler.js";
18
- export interface RegisterResult {
19
- id: string;
20
- name: string;
21
- version: string;
22
- runtimes?: RegisteredRuntime[];
23
- }
24
- export interface RegisteredRuntime {
25
- id: string;
26
- name: string;
27
- version: string;
28
- }
29
- export interface RuntimeSourceInput {
30
- name: string;
31
- source: string;
32
- }
33
- /** GitHub provenance for a registered template's source file — stored as
34
- * `metadata.source` on the registration. `cloud-build` stamps the built
35
- * commit's sha; the dashboard's manual link path writes `sha: "manual"`. */
36
- export interface TemplateSourceRef {
37
- owner: string;
38
- repo: string;
39
- branch: string;
40
- /** Repo-relative file path, e.g. `.agentc/workflows/workflow-deploy.ts`. */
41
- path: string;
42
- /** Commit sha the version was built from, or `"manual"` for hand-links. */
43
- sha: string;
44
- }
45
- export interface RegisterWorkflowInput {
46
- name: string;
47
- source: string;
48
- /** Structured attestation produced by `bundleWorkflow`. The server
49
- * requires this on every registration; it proves the source was
50
- * bundled by a `defineWorkflow`-aware toolchain. The server validates
51
- * the manifest's shape and verifies `manifest.sourceHash` matches
52
- * sha256(source) — the source bytes themselves are never parsed or
53
- * executed on the server. */
54
- manifest: WorkflowManifest;
55
- version?: string;
56
- /** Where the source file lives on GitHub — stored as `metadata.source`.
57
- * Named `sourceRef` because `source` is the bundled code itself. */
58
- sourceRef?: TemplateSourceRef;
59
- schedule?: string;
60
- runtimes?: RuntimeSourceInput[];
61
- /** Human-readable description declared via
62
- * `defineWorkflow({ description })`. Stored in template metadata and
63
- * surfaced on the dashboard template card. */
64
- description?: string;
65
- networkPolicy?: unknown;
66
- placeholders?: Record<string, string>;
67
- /** All snapshot config — `bootFrom` (where to restore at run start),
68
- * `save`, `retain`. See `WorkflowMetadata.snapshots`. */
69
- snapshots?: SnapshotConfig;
70
- /** Sandbox machine resources — size + provider (template defaults).
71
- * See `WorkflowMetadata.resources`. */
72
- resources?: SandboxResources;
73
- /** Provider-neutral execution plan detected by the CLI bundler. */
74
- workflowPlan?: WorkflowPlan;
75
- /** Connector requirements declared via `defineWorkflow({ connectors })`
76
- * (ADR-0007). Validated against the server's provider registry at
77
- * registration; tokens are injected at the network layer at dispatch. */
78
- connectors?: ConnectorRequirements;
79
- /** Connector-catalogue operation tag — see `ConnectorOperationTag`. */
80
- connectorOperation?: ConnectorOperationTag;
81
- /** Tier-1 invoke ACL declared via `defineWorkflow({ invokePolicy })`.
82
- * Only meaningful when the workflow also declares `connectors` — the
83
- * server gates dispatch on it before binding any grant. */
84
- invokePolicy?: InvokePolicy;
85
- /** Input schema extracted from the workflow's `input` zod schema. */
86
- inputSchema?: IOSchema;
87
- /** Output schema extracted from the workflow's `output` zod schema. */
88
- outputSchema?: IOSchema;
89
- /** Set by `defineSandboxEnvironment` — marks an environment build so the
90
- * server skips the /factory mount for its runs (#13). See
91
- * `WorkflowMetadata.environmentBuild`. */
92
- environmentBuild?: boolean;
93
- /** Factory slug. Defaults to `"default"`. */
94
- factorySlug?: string;
95
- }
96
- export type RunState = "running" | "success" | "failed" | "abandoned" | "canceled";
97
- export interface InvokeWorkflowOptions {
98
- /** Per-invocation snapshot config override. `snapshots.bootFrom`
99
- * replaces the template's boot source; `snapshots.saveLatest` and
100
- * `snapshots.retainSteps` override capture mode. Anything omitted
101
- * falls back to the template's registered default. */
102
- snapshots?: SnapshotConfig;
103
- /** Per-invocation network policy override. Replaces the template-level
104
- * policy for this run only — registered metadata is not mutated. */
105
- networkPolicy?: SandboxNetworkPolicy;
106
- /** Per-invocation placeholder override. Maps secret names referenced in
107
- * `networkPolicy` ($VAR) to the values the runner should see for env
108
- * vars after brokering. Replaces the template-level placeholders for
109
- * this run only — registered metadata is not mutated. */
110
- placeholders?: Record<string, string>;
111
- /** Per-invocation machine-size override of the template's `resources.size`.
112
- * `small` (default) | `medium` | `large`; omit → the template default,
113
- * else `small`. Honoured on Vercel (→ vCPUs); E2B ignores it. */
114
- size?: SandboxSize;
115
- /** Explicit parent run id. Pass `null` to suppress ambient RUN_ID auto-detection. */
116
- parentRunId?: string | null;
117
- /** Agent loop inside the parent run that caused this invoke, when applicable. */
118
- agentId?: string | null;
119
- /** Factory slug. Defaults to `"default"`. */
120
- factorySlug?: string;
121
- /** Idempotency key — sent as the `Idempotency-Key` header. A repeat invoke
122
- * with the same key inside the server's dedup window returns the original
123
- * run instead of starting a new one (matches `resumePause`'s pattern). */
124
- idempotencyKey?: string;
125
- }
126
- export interface InvokeAndWaitOptions extends InvokeWorkflowOptions {
127
- timeoutMs?: number;
128
- pollIntervalMs?: number;
129
- }
130
- export interface InvokeResult {
131
- id: string;
132
- }
133
- export interface ListSnapshotsOptions {
134
- /** Factory slug. Defaults to `"default"`. */
135
- factorySlug?: string;
136
- workflow?: string;
137
- limit?: number;
138
- /** Cursor returned as `next_cursor` from `listSnapshotsPage`. */
139
- before?: string;
140
- }
141
- export interface TemplateRow {
142
- name: string;
143
- version: string;
144
- factorySlug: string;
145
- }
146
- export interface ListTemplatesOptions {
147
- factorySlug?: string;
148
- }
149
- /** A human member of your team — the people an agent (or you) can @-flag. */
150
- export interface TeamMember {
151
- /** Membership row id. */
152
- id: string;
153
- /** The user id — what you pass to `createMentions({ mentionedUserIds })`. */
154
- userId: string;
155
- role: string;
156
- email: string;
157
- name: string;
158
- joinedAt: string;
159
- }
160
- /** A "you were flagged" ping, persisted server-side so it reaches the
161
- * mentioned teammate in their Workbench. */
162
- export interface Mention {
163
- id: string;
164
- factoryId: string;
165
- mentionedUserId: string;
166
- /** Who flagged: 'user' | 'api_key' | 'run' | 'system'. */
167
- actorKind: string;
168
- actorId: string | null;
169
- actorLabel: string | null;
170
- /** Where it lives: 'doc' | 'comment' | 'plan' | 'run'. */
171
- contextKind: string;
172
- contextPath: string | null;
173
- /** Ready-made relative dashboard URL the Workbench card links to. */
174
- contextUrl: string | null;
175
- text: string;
176
- runId: string | null;
177
- seenAt: string | null;
178
- resolvedAt: string | null;
179
- createdAt: string;
180
- }
181
- export interface CreateMentionsInput {
182
- /** Team-member user ids to flag (1–20). Discover them via `listMembers()`.
183
- * Non-members are dropped server-side. */
184
- mentionedUserIds: string[];
185
- /** The flag message shown in the teammate's Workbench. */
186
- text: string;
187
- contextKind: "doc" | "comment" | "plan" | "run";
188
- /** Factory-relative file path or comment thread id, when applicable. */
189
- contextPath?: string;
190
- /** Ready-made relative dashboard URL the Workbench card links to (e.g.
191
- * `/factories/<slug>/files/view?path=<plan>`). */
192
- contextUrl?: string;
193
- runId?: string;
194
- factorySlug?: string;
195
- }
196
- export interface CreateFactoryInput {
197
- slug: string;
198
- name: string;
199
- description?: string;
200
- }
201
- export interface UpdateFactoryInput {
202
- name?: string;
203
- description?: string;
204
- }
205
- export interface ScheduleRow {
206
- id: string;
207
- name: string;
208
- workflowName: string;
209
- cron: string;
210
- createdAt: string;
211
- updatedAt: string;
212
- nextFireAt: string | null;
213
- lastFireAt: string | null;
214
- }
215
- export interface CreateScheduleInput {
216
- /** Human-friendly schedule name. Unique within the factory. */
217
- name: string;
218
- /** The workflow this schedule should fire. Must already be registered
219
- * in the same factory. */
220
- workflow: string;
221
- /** Cron expression (UTC). */
222
- cron: string;
223
- /** Factory to attach the schedule to. Defaults to `"default"`. */
224
- factorySlug?: string;
225
- }
226
- export interface SecretOptions {
227
- factorySlug?: string;
228
- }
229
- export interface SetSecretResult {
230
- key: string;
231
- }
232
- export interface SecretListEntry {
233
- key: string;
234
- createdAt: string;
235
- updatedAt: string;
236
- }
237
- export interface CreateApiKeyInput {
238
- name?: string;
239
- scopes?: string[];
240
- expiresAt?: string;
241
- factorySlug?: string;
242
- }
243
- export interface StreamRunLogsOptions {
244
- lastEventId?: number;
245
- signal?: AbortSignal;
246
- }
247
- export interface RunStatus<TOutput = unknown> {
248
- id: string;
249
- status: RunState;
250
- output?: TOutput;
251
- /** The run's latest (`saveLatest`) snapshot id, populated once the run has
252
- * succeeded — the boot source to fork this run's evolved filesystem from
253
- * (pass as `snapshots.bootFrom` on a follow-up invoke). `null` while the run
254
- * is still in flight or when it captured no snapshot. Lets an orchestrator
255
- * fork a child straight off the `invokeChild` result without a separate
256
- * `listRunSnapshots` call. */
257
- latestSnapshotId?: string | null;
258
- }
259
- /** ADR-0006 step 10 — actor record returned on a successful resume.
260
- * Shape mirrors the server's `PauseResumeActor` type after the row
261
- * has been stamped. Audit FKs (`userId` / `keyId` / `runId`) may be
262
- * null when the referenced row was deleted between resume and the
263
- * response render — the immutable `label` survives. */
264
- export interface ResumePauseActor {
265
- kind: "session_user" | "api_key" | "agent";
266
- /** Better Auth user id when kind='session_user'. */
267
- userId?: string | null;
268
- /** api_keys.id when kind='api_key'. */
269
- keyId?: string | null;
270
- /** Caller-run id when kind='agent' (NOT the run being resumed). */
271
- runId?: string | null;
272
- /** Agent-instance within `runId` when kind='agent'. */
273
- agentId?: string | null;
274
- label: string;
275
- }
276
- /** Success branch of the resume HTTP response. The pause has reached
277
- * a terminal state — `resolved` (workflow signal arrived), `expired`
278
- * (TTL fired first), or `cancelled` (workflow terminated mid-pause).
279
- * Only `resolved` carries the resume payload the user supplied. */
280
- export interface ResumePauseSuccess {
281
- status: "resolved" | "expired" | "cancelled";
282
- pauseId: string;
283
- resolvedAt: string | null;
284
- resumePayload: unknown;
285
- actor: ResumePauseActor | null;
286
- }
287
- /** Pending branch — the workflow accepted the signal but the row
288
- * flip didn't observe within the route's 5s wait window. The
289
- * operation is in-flight; retry with the same `Idempotency-Key`
290
- * and the cache collapses the duplicate to a single canonical
291
- * response. */
292
- export interface ResumePausePending {
293
- status: "pending";
294
- pauseId: string;
295
- timedOut: true;
296
- }
297
- export type ResumePauseResponse = ResumePauseSuccess | ResumePausePending;
298
- export interface ResumePauseOptions {
299
- /** Stripe-style retry-dedup key — same syntax as the workflow-invoke
300
- * route: 1..255 chars of `[A-Za-z0-9_\-:.]`, no embedded CR/LF.
301
- * Sent as the `Idempotency-Key` request header. (The server reads the
302
- * header first, falling back to a body field for callers behind a
303
- * header-stripping proxy; this client only sends the header.) */
304
- idempotencyKey?: string;
305
- /** Abort the HTTP request mid-wait (e.g. from a UI cancel button).
306
- * The server's LISTEN tears down via the request's AbortSignal. */
307
- signal?: AbortSignal;
308
- }
309
- export interface RequestAgentPauseOptions {
310
- /** Human-readable note surfaced to the agent as the pause reason. */
311
- reason?: string;
312
- /** Your handle for answering this pause without the minted pauseId:
313
- * pass the same value to `resumePauseByKey`. */
314
- correlationKey?: string;
315
- /** Abort the HTTP request. */
316
- signal?: AbortSignal;
317
- }
318
- export interface AnswerSteerOptions extends ResumePauseOptions {
319
- /** Who answered — surfaced to the agent as `[human steer from <actor>]`. */
320
- actor?: string;
321
- }
322
- /** 202 envelope from a steer-pause request. The request is best-effort and
323
- * fire-and-forget: it publishes a transient control message and returns
324
- * immediately — the agent parks at its next iteration boundary (if it is
325
- * `mode: "hitl"` and still running). Answer it via `answerSteerByKey`
326
- * (pass the `correlationKey` you set here) or `answerSteer` (by pauseId). */
327
- export interface RequestAgentPauseResponse {
328
- status: "steer_requested";
329
- runId: string;
330
- agentId: string;
331
- }
332
- export interface SendAgentMessageOptions {
333
- /** Transcript attribution. For non-session callers (API key, orchestrator)
334
- * this names the sender; defaults to the caller's identity server-side. */
335
- senderName?: string;
336
- /** Abort the HTTP request. */
337
- signal?: AbortSignal;
338
- }
339
- /** 202 envelope from a message-to-running-agent request. The message is queued
340
- * durably and delivered mid-stream as the agent's next user turn — the workflow
341
- * is NOT paused. `seq` is the message's per-run ordinal. */
342
- export interface SendAgentMessageResponse {
343
- status: "message_enqueued";
344
- runId: string;
345
- agentId: string;
346
- seq: number;
347
- }
348
- export interface RunDetail<TOutput = unknown> {
349
- runId: string;
350
- title: string;
351
- metadata: Record<string, unknown>;
352
- outcome: string;
353
- startedAt: string;
354
- endedAt: string | null;
355
- durationMs: number | null;
356
- failureReason: string | null;
357
- input: unknown;
358
- output: TOutput | null;
359
- lifecycleEvents: Array<{
360
- at: string;
361
- type: string;
362
- payload: unknown;
363
- }>;
364
- children?: RunDetail[];
365
- }
366
- export interface TimelineEvent {
367
- kind: string;
368
- at: string;
369
- seq: number;
370
- type: string;
371
- payload: Record<string, unknown>;
372
- }
373
- export type EventSubjectType = "run" | "agent" | "workflow" | "factory";
374
- export interface EventRow {
375
- id: string;
376
- teamId: string;
377
- subjectType: EventSubjectType | string;
378
- subjectId: string;
379
- runId: string | null;
380
- agentId: string | null;
381
- workflowId: string | null;
382
- factoryId: string | null;
383
- name: string;
384
- body: unknown;
385
- summary: string | null;
386
- confidence: string | null;
387
- timestamp: string;
388
- attributes: Record<string, unknown>;
389
- propagate: boolean;
390
- idempotencyKey: string | null;
391
- createdAt: string;
392
- }
393
- export interface RunArtifactRow {
394
- path: string;
395
- factorySlug: string | null;
396
- sizeBytes: number | null;
397
- lastWriteAt: string;
398
- /** Opening text of the file (≤320 chars) — null for binary/empty. */
399
- preview: string | null;
400
- }
401
- export interface FactoryFileWriteResult {
402
- path: string;
403
- contentHash: string;
404
- sizeBytes: number;
405
- created: boolean;
406
- }
407
- export interface ReportEventInput {
408
- name: string;
409
- body: unknown;
410
- summary?: string;
411
- confidence?: number;
412
- timestamp?: string | Date;
413
- attributes?: Record<string, unknown>;
414
- propagate?: boolean;
415
- idempotencyKey?: string;
416
- }
417
- export interface ListEventsOptions {
418
- factorySlug?: string;
419
- limit?: number;
420
- /** Case-insensitive substring match. Server uses `ILIKE %name%`, so
421
- * `"site"` matches `site.created`, `site.failed`, etc. Pass the
422
- * full event name for an effectively-exact filter (any string is a
423
- * substring of itself). */
424
- name?: string;
425
- /** Date-range lower bound: only include events at or after this
426
- * timestamp. Used by the dashboard's range toggle (1h / 24h / 7d
427
- * / 30d). Same semantics as `from` on the runs list endpoint. */
428
- from?: string;
429
- /** Timestamp cursor for "load older" pagination. Pass the
430
- * `timestamp` of the last row from the previous page; the server
431
- * returns rows strictly older than that. Distinct from `from`:
432
- * `from` filters a date range, `before` walks the page boundary.
433
- * Both can be supplied together for a paginated range-query. */
434
- before?: string;
435
- }
436
- export interface ListEventsResult {
437
- events: EventRow[];
438
- has_more: boolean;
439
- }
440
- /** One captured stdout or stderr line from a run's sandbox subprocess.
441
- * `id` is per-run monotonically increasing — pass the highest `id`
442
- * you've seen as `afterId` to paginate forward. */
443
- export interface RunLogLine {
444
- id: number;
445
- at: string;
446
- stream: "stdout" | "stderr";
447
- line: string;
448
- }
449
- export interface ListRunLogsOptions {
450
- /** Return only lines with `id > afterId` (forward pagination). */
451
- afterId?: number;
452
- /** Max lines (server clamps to [1, 1000], defaults to 200). */
453
- limit?: number;
454
- /** Stream direction. `"asc"` (default) returns the oldest lines first
455
- * — use with `afterId` to paginate forward. `"desc"` returns the newest
456
- * lines first — use to fetch the last N lines of a finished run. */
457
- direction?: "asc" | "desc";
458
- }
459
- /** Row shape returned by `GET /api-keys`. */
460
- export interface ApiKey {
461
- object: "api_key";
462
- id: string;
463
- name: string | null;
464
- last4: string | null;
465
- scopes: string[];
466
- teamId: string;
467
- createdByUserId: string | null;
468
- /** Non-null when the key is restricted to a single factory. */
469
- factoryId: string | null;
470
- createdAt: string;
471
- expiresAt: string | null;
472
- lastUsedAt: string | null;
473
- revokedAt: string | null;
474
- }
475
- /** Response from `POST /api-keys`. The `key` field is the plaintext token —
476
- * shown once at creation, never retrievable again. */
477
- export interface ApiKeyCreated extends ApiKey {
478
- key: string;
479
- }
480
- /** Single rollup row from `GET /api/v1/usage`. */
481
- export interface UsageRollupRow {
482
- eventType: string;
483
- unit: string;
484
- total: number;
485
- tags: Record<string, unknown>;
486
- }
487
- /** Response from `GET /api/v1/usage`. */
488
- export interface UsageResponse {
489
- object: "list";
490
- data: UsageRollupRow[];
491
- has_more: boolean;
492
- from: string | null;
493
- to: string | null;
494
- }
495
- /** Response from `POST /api/v1/workflows/:id/cancel`. The endpoint is
496
- * idempotent: cancelling a run that's already terminal returns its current
497
- * outcome verbatim (rather than throwing or pretending it just canceled),
498
- * so `status` widens to every terminal value the server might surface. */
499
- export interface CancelRunResponse {
500
- runId: string;
501
- status: "canceled" | "success" | "failed" | "abandoned";
502
- canceledAt: string;
503
- }
504
- export interface SnapshotListEntry {
505
- snapshotId: string;
506
- kind: "latest" | "step";
507
- stepIndex: number | null;
508
- runId: string;
509
- workflow: string | null;
510
- version: string | null;
511
- createdAt: string | null;
512
- /** Provider-reported on-disk size, or null when unavailable. */
513
- sizeBytes: number | null;
514
- }
515
- export interface SnapshotListResponse {
516
- object: "list";
517
- data: SnapshotListEntry[];
518
- has_more: boolean;
519
- next_cursor: string | null;
520
- }
521
- export interface RunSnapshotEntry {
522
- snapshotId: string;
523
- /** `"latest"` = current/last pointer on the run.
524
- * `"step"` = retained per-step snapshot. */
525
- kind: "latest" | "step";
526
- stepIndex: number | null;
527
- createdAt: string | null;
528
- /** Provider-reported on-disk size, or null when unavailable. */
529
- sizeBytes: number | null;
530
- }
14
+ import type { ConversationStreamEvent } from "./types/conversation-stream.js";
15
+ import type { InvokeWorkflowOptions, InvokeAndWaitOptions, InvokeResult, StreamRunLogsOptions, InlineWorkflowPayload, InvokeInlineOptions, InvokeInlineAndWaitOptions, RunStatus, ResumePauseOptions, ResumePauseResponse, AnswerSteerOptions, RequestAgentPauseOptions, RequestAgentPauseResponse, SendAgentMessageOptions, SendAgentMessageResponse, RunDetail, RunListEntry, ListRunsOptions, TimelineEvent, RunFundingResponse, EventRow, ReportEventInput, ListEventsOptions, ListEventsResult, RunArtifactRow, RunLogLine, ListRunLogsOptions, CancelRunResponse, ListSnapshotsOptions, SnapshotListResponse, SnapshotListEntry, RunSnapshotEntry } from "./types/api-runs.js";
16
+ import type { TeamMember, Mention, CreateMentionsInput, ConversationsPage, SessionsPage, ConversationDetail, ConversationThread, CreateCloudSessionInput, CloudSessionCreated, SessionPreview, PreviewOpened, OpenPreviewInput, SessionForked, SessionChangeSet, SessionMergeReport, SessionDiscardReport, SendConversationMessageInput, SendConversationMessageResult, ChannelSessionRow, SessionChannelMessagePosted, ConversationPresenceSnapshot, StreamConversationOptions, AgentListRow } from "./types/api-conversations.js";
17
+ import type { ConversationMemberRole, ConversationMember, ArtifactScope, SetScopeGrantsInput, SetTemplateScopeInput } from "./types/api-scopes.js";
18
+ import type { Project, ProjectsPage, ProjectRole, ProjectMember, ProjectObjectsPage, ProjectAddPreview, AddProjectObjectInput, AddProjectObjectResult, RefreshProjectObjectResult } from "./types/api-projects.js";
19
+ import type { RegisterResult, RegisterWorkflowInput, TemplateRow, TemplateDetail, ListTemplatesOptions, SearchFactoryFilesOptions, FactoryFileSearchResult, FactoryFileWriteResult, FactoryRow, CreateFactoryInput, UpdateFactoryInput, ScheduleRow, CreateScheduleInput, SecretOptions, SetSecretResult, SecretListEntry, CreateApiKeyInput, ApiKey, ApiKeyCreated, UsageResponse, DriveRepoLink, CreateDriveRepoLinkInput, DriveMountSession, CreateDriveMountSessionInput } from "./types/api-factory.js";
20
+ import type { ComplianceSession, RequestComplianceSessionInput, ListComplianceSessionsOptions, ComplianceSessionsPage, ListComplianceAccessesOptions, ComplianceAccessesPage } from "./types/api-compliance.js";
21
+ export type { RunState, InvokeWorkflowOptions, InvokeAndWaitOptions, InvokeResult, FundingChoice, StreamRunLogsOptions, InlineWorkflowPayload, InvokeInlineOptions, InvokeInlineAndWaitOptions, RunStatus, ResumePauseActor, ResumePauseSuccess, ResumePausePending, ResumePauseResponse, ResumePauseOptions, RequestAgentPauseOptions, AnswerSteerOptions, RequestAgentPauseResponse, SendAgentMessageOptions, SendAgentMessageResponse, RunDetail, RunListEntry, ListRunsOptions, TimelineEvent, FundingLane, RunFundingStamp, RunFundingUsageRow, RunFundingResponse, EventSubjectType, EventRow, RunArtifactRow, ReportEventInput, ListEventsOptions, ListEventsResult, RunLogLine, ListRunLogsOptions, CancelRunResponse, ListSnapshotsOptions, SnapshotListEntry, SnapshotListResponse, RunSnapshotEntry, } from "./types/api-runs.js";
22
+ export type { TeamMember, Mention, CreateMentionsInput, ConversationMessagePart, ConversationRow, ConversationMessageRow, ConversationsPage, SessionsPage, ConversationDetail, CreateCloudSessionInput, CloudSessionCreated, ConversationThread, SessionPreview, PreviewOpened, OpenPreviewInput, SessionForked, SessionFileChange, SessionChangeSet, SessionMergeReportDetail, SessionMergeReport, SessionDiscardReport, ConversationPageContext, SendConversationMessageInput, ConversationTurnState, SendConversationMessageResult, ConversationPresenceSnapshot, AgentListRow, StreamConversationOptions, ChannelSessionStatus, ChannelSessionRow, ChannelSessionsResponse, SessionChannelMessagePosted, } from "./types/api-conversations.js";
23
+ export type { ConversationMemberRole, ConversationMember, DocumentCapability, TemplateCapability, ScopeGrant, ArtifactScope, RunContext, SetScopeGrantsInput, SetTemplateScopeInput, } from "./types/api-scopes.js";
24
+ export type { Project, ProjectsPage, ProjectRole, ProjectMember, ProjectObject, ProjectObjectsPage, ProjectSkippedFile, ProjectPreviewFile, ProjectAddPreview, AddProjectObjectInput, AddProjectObjectResult, RefreshProjectObjectResult, } from "./types/api-projects.js";
25
+ export type { RegisterResult, RegisteredRuntime, RuntimeSourceInput, TemplateSourceRef, RegisterWorkflowInput, TemplateRow, TemplateDetail, ListTemplatesOptions, FactoryFileSearchRow, FactoryFolderSearchRow, SearchFactoryFilesOptions, FactoryFileSearchResult, FactoryFileWriteResult, PublicFileLinkState, FactoryRow, CreateFactoryInput, UpdateFactoryInput, ScheduleRow, CreateScheduleInput, SecretOptions, SetSecretResult, SecretListEntry, CreateApiKeyInput, ApiKey, ApiKeyCreated, UsageRollupRow, UsageResponse, DriveRepoLink, CreateDriveRepoLinkInput, DriveMountSession, CreateDriveMountSessionInput, } from "./types/api-factory.js";
26
+ export type { ComplianceScopeKind, ComplianceStatus, ComplianceSession, ComplianceAccess, RequestComplianceSessionInput, ListComplianceSessionsOptions, ComplianceSessionsPage, ListComplianceAccessesOptions, ComplianceAccessesPage, } from "./types/api-compliance.js";
531
27
  export interface AgentComposeClientOptions {
532
28
  /** Your team's API key — minted from the dashboard or `agentc keys create`.
533
29
  * Required. Resolved from `process.env.AGENT_COMPOSE_API_KEY` when omitted. */
@@ -543,6 +39,13 @@ export declare class AgentComposeClient {
543
39
  private readonly baseUrl;
544
40
  private readonly apiKey;
545
41
  constructor(options?: AgentComposeClientOptions);
42
+ /** Open an authenticated SSE stream and yield its parsed frames. Uses raw
43
+ * `fetch` (not ofetch) because SSE requires access to the response's
44
+ * `ReadableStream`, which ofetch consumes when parsing. Auth + base URL
45
+ * come from the same constructor inputs, and non-2xx responses throw the
46
+ * same `AgentComposeError`. Shared by `streamRunLogs` / `streamConversation`
47
+ * — per-event mapping stays at each call site. */
48
+ private openSseStream;
546
49
  /** Register (or update) a workflow template inside a factory. Defaults to
547
50
  * the team's `default` factory when `factorySlug` is omitted. */
548
51
  register(payload: RegisterWorkflowInput): Promise<RegisterResult>;
@@ -562,6 +65,14 @@ export declare class AgentComposeClient {
562
65
  *
563
66
  * `factorySlug`: defaults to `"default"`. */
564
67
  invoke(name: string, input?: Record<string, unknown>, opts?: InvokeWorkflowOptions): Promise<InvokeResult>;
68
+ /** Invoke an INLINE workflow — the exact payload `bundleWorkflow` produced
69
+ * plus a `name` — WITHOUT registering it. The server validates it through
70
+ * the same core as registration (manifest required + bound to the source
71
+ * bytes) but writes no registry row: the run snapshots the source it
72
+ * executes, and registration stays the door for named/versioned/scheduled
73
+ * workflows. Same parent-child auto-detection and `Idempotency-Key`
74
+ * semantics as `invoke()`. Requires the `invoke` scope. */
75
+ invokeInline(workflow: InlineWorkflowPayload, input?: Record<string, unknown>, opts?: InvokeInlineOptions): Promise<InvokeResult>;
565
76
  /** Invoke a workflow and wait for it to settle (success / failed / abandoned).
566
77
  * Polls `getStatus` on a fixed interval. Rejects with `AgentComposeError`
567
78
  * if the run settles non-success, or a plain `Error` on timeout.
@@ -570,6 +81,16 @@ export declare class AgentComposeClient {
570
81
  * tests, tune up for long-running workflows. The parent-child auto-
571
82
  * detection from `invoke()` applies here too. */
572
83
  invokeAndWait<TOutput = unknown>(name: string, input?: Record<string, unknown>, opts?: InvokeAndWaitOptions): Promise<RunStatus<TOutput>>;
84
+ /** `invokeInline` + block until the run settles — the "call blocks →
85
+ * result returns on the same turn" contract for inline sub-workflows. */
86
+ invokeInlineAndWait<TOutput = unknown>(workflow: InlineWorkflowPayload, input?: Record<string, unknown>, opts?: InvokeInlineAndWaitOptions): Promise<RunStatus<TOutput>>;
87
+ /** Poll one run until it settles (success / failed / abandoned) and return
88
+ * its final status. Shared tail of `invokeAndWait` / `invokeInlineAndWait`;
89
+ * also useful to re-attach to a run you dispatched fire-and-forget. */
90
+ waitForRun<TOutput = unknown>(runId: string, opts?: {
91
+ timeoutMs?: number;
92
+ pollIntervalMs?: number;
93
+ }): Promise<RunStatus<TOutput>>;
573
94
  /** List captured snapshots in a factory. */
574
95
  listSnapshots(opts?: ListSnapshotsOptions): Promise<SnapshotListEntry[]>;
575
96
  /** List one page of captured snapshots in a factory. */
@@ -658,11 +179,21 @@ export declare class AgentComposeClient {
658
179
  sendAgentMessage(runId: string, agentId: string, message: string, opts?: SendAgentMessageOptions): Promise<SendAgentMessageResponse>;
659
180
  /** Full run detail, including input/output and lifecycle events. */
660
181
  getRun<TOutput = unknown>(runId: string): Promise<RunDetail<TOutput>>;
182
+ /** Recent runs in one factory, newest first by default. Bounded at the
183
+ * server (limit ≤ 200). `workflow` filters by the registered workflow
184
+ * name (substring) — `listRuns({ workflow: "report", limit: 1 })` is
185
+ * "the latest report run". */
186
+ listRuns(opts?: ListRunsOptions): Promise<RunListEntry[]>;
661
187
  /** Ordered lifecycle timeline for one run. */
662
188
  getRunTimeline(runId: string, opts?: {
663
189
  limit?: number;
664
190
  offset?: number;
665
191
  }): Promise<TimelineEvent[]>;
192
+ /** One run's funding-lane surface (ADR-0048): per-step credential stamps
193
+ * recorded at resolution, plus the gateway-attested platform dollars —
194
+ * the only usage the ledger records (non-platform lanes are attribution,
195
+ * never metered). */
196
+ getRunFunding(runId: string): Promise<RunFundingResponse>;
666
197
  /** Report a durable event against a run. Events are late-binding facts
667
198
  * like quality.accepted, defect.regression, or intervention.override. */
668
199
  reportEvent(runId: string, input: ReportEventInput): Promise<EventRow>;
@@ -670,16 +201,222 @@ export declare class AgentComposeClient {
670
201
  /** Files the run wrote on the factory drive — run-attributed revisions,
671
202
  * latest write per path, paths the run later deleted excluded. */
672
203
  listRunArtifacts(runId: string): Promise<RunArtifactRow[]>;
204
+ /** One run artifact's bytes, resolved server-side through the DRIVE INDEX
205
+ * (never the run's gone sandbox or branch) — a listed artifact with an
206
+ * indexed path is always readable here, including after the run's branch
207
+ * is merged/retired. The path is the listing's `path`, sent as a single
208
+ * query parameter so slashes / spaces / unicode in agent-derived
209
+ * filenames survive verbatim. */
210
+ getRunArtifactBytes(runId: string, path: string): Promise<Uint8Array>;
673
211
  /** Write (create or overwrite) one file on a factory's drive. */
674
212
  putFactoryFile(path: string, content: string | Uint8Array, opts?: {
675
213
  factorySlug?: string;
676
214
  contentType?: string;
677
215
  }): Promise<FactoryFileWriteResult>;
678
- /** Read one file's current content (or a specific revision) as text. */
216
+ /** Read one file's current content (or a specific revision) as RAW BYTES —
217
+ * byte-exact for any content type. This is the wire truth; `getFactoryFile`
218
+ * is a UTF-8 decode over it. Binaries (images, archives) MUST come through
219
+ * here: a text decode is lossy (every non-UTF-8 sequence collapses to
220
+ * U+FFFD and the original bytes are unrecoverable). */
221
+ getFactoryFileBytes(path: string, opts?: {
222
+ factorySlug?: string;
223
+ revision?: number;
224
+ branch?: string;
225
+ }): Promise<Uint8Array>;
226
+ /** Read one file's current content (or a specific revision) as text
227
+ * (UTF-8). For binary files use `getFactoryFileBytes` — decoding them to
228
+ * text corrupts the bytes irreversibly. */
679
229
  getFactoryFile(path: string, opts?: {
680
230
  factorySlug?: string;
681
231
  revision?: number;
232
+ branch?: string;
682
233
  }): Promise<string>;
234
+ /** Create a local drive mount (or re-mint an existing one's token by
235
+ * passing its `conversationId`). */
236
+ createDriveMountSession(opts?: CreateDriveMountSessionInput & {
237
+ factorySlug?: string;
238
+ }): Promise<DriveMountSession>;
239
+ /** Release a local mount's gateway branch mount (clean unmount). The
240
+ * branch and its review card survive — this only drops the gateway's
241
+ * in-memory mount so the exclusive branch is not pinned. */
242
+ releaseDriveMountSession(conversationId: string, opts?: {
243
+ factorySlug?: string;
244
+ }): Promise<{
245
+ released: boolean;
246
+ }>;
247
+ /** List conversations the caller can access, newest-activity first.
248
+ * Cursor-paginated: pass the previous page's `next_cursor`. */
249
+ listConversations(opts?: {
250
+ cursor?: string;
251
+ }): Promise<ConversationsPage>;
252
+ /** List the sessions the caller can ACCESS in one factory (their own +
253
+ * shared/project-reachable ones), newest first (kind='session' rows are
254
+ * excluded from listConversations by design). Session or user-bound driver credential only. */
255
+ listSessions(factoryId: string, opts?: {
256
+ cursor?: string;
257
+ }): Promise<SessionsPage>;
258
+ /** One conversation with its latest page of messages. `limit` bounds the
259
+ * page (newest N) — metadata-only consumers (e.g. resolving the
260
+ * session's drive branch) pass 1 instead of pulling the full hydrate. */
261
+ getConversation(id: string, opts?: {
262
+ limit?: number;
263
+ }): Promise<ConversationDetail>;
264
+ /** Provision a CLOUD-native session (ADR-0037 Phase 3b / ADR-0055 §9): a
265
+ * persistent server-side sandbox on the factory drive that keeps working
266
+ * after the caller's terminal (and laptop) closes. The session's TYPE is
267
+ * fixed at creation: `chat` hosts a coding runtime driven via ACP (open →
268
+ * the transcript, drive it like any conversation); `terminal`/`custom`
269
+ * are raw machine surfaces with no chat pane (open → the PTY). Omitting
270
+ * `type` lets the server derive it from `runtime` (the older-caller
271
+ * grandfather); send it explicitly. Requires the `invoke` scope and a
272
+ * user-bound credential. */
273
+ createCloudSession(input: CreateCloudSessionInput): Promise<CloudSessionCreated>;
274
+ /** One thread (root + replies, oldest→newest) inside a channel. */
275
+ getConversationThread(conversationId: string, rootId: string): Promise<ConversationThread>;
276
+ /** The sessions attached to a channel, newest attach first, each with its
277
+ * durable rail status (channel read gate). 404 on non-channels. */
278
+ listChannelSessions(channelId: string): Promise<ChannelSessionRow[]>;
279
+ /** Attach an existing session to a channel — an explicit share act
280
+ * (ADR-0052 consent): only the session's CREATOR may attach it, with
281
+ * channel role ≥ write and a human credential. Idempotent (re-attach is
282
+ * a no-op). Failures: 403 `human_credential_required` | `role_read_only`
283
+ * | `owner_required`; 400 `not_a_session`; 409 `attach_limit_reached`. */
284
+ attachChannelSession(channelId: string, sessionConversationId: string): Promise<void>;
285
+ /** Detach a session from a channel — either side ends the visit (channel
286
+ * role ≥ write, OR the session's creator). Forward-only: the channel's
287
+ * members lose the derived access; relay rows already in the session
288
+ * transcript stay; explicit shares survive. 404 when not attached. */
289
+ detachChannelSession(channelId: string, sessionConversationId: string): Promise<void>;
290
+ /** Post one message into a channel AS the calling session (ADR-0057 Seam
291
+ * 4) — progress, results, questions, attributed to the session (title +
292
+ * runtime mark). Session toolbelt credential ONLY (the calling session
293
+ * resolves from the key server-side — 403 `session_credential_required`
294
+ * otherwise); the session must be attached (409 `not_attached`). By
295
+ * default the post lands in the thread of the message that last
296
+ * addressed the session from that channel (the room when none);
297
+ * `threadRootId` overrides it — must be a root message in the channel
298
+ * (400 `invalid_thread_root`). The post never triggers any turn. */
299
+ postSessionChannelMessage(channelId: string, input: {
300
+ text: string;
301
+ threadRootId?: string;
302
+ }): Promise<SessionChannelMessagePosted>;
303
+ /** Open a dev preview on a cloud session: expose a port a dev server is
304
+ * LISTENING on inside the session sandbox at a member-gated proxy URL, and
305
+ * post an "Open preview" card to the transcript. Resumes a suspended VM
306
+ * (write-tier act — read members get 403). Returns the row + the proxy URL
307
+ * (never the raw sandbox host). */
308
+ openPreview(conversationId: string, input: OpenPreviewInput): Promise<PreviewOpened>;
309
+ /** The live dev previews on a cloud session (read-tier allowed). Rows carry
310
+ * `url: null` — a URL is minted on OPEN (short-lived, member-bound). */
311
+ listPreviews(conversationId: string): Promise<SessionPreview[]>;
312
+ /** Take a dev preview down (write-tier). Idempotent — `closed` is false when
313
+ * no active row matched. */
314
+ closePreview(conversationId: string, port: number): Promise<boolean>;
315
+ /** Fork a cloud session from HEAD: snapshot the VM + branch the drive + seed
316
+ * a new conversation from the transcript so far, booting from both. Returns
317
+ * the child conversation id to switch to. Write-tier; "Branch from here." */
318
+ forkSession(conversationId: string, input?: {
319
+ title?: string;
320
+ }): Promise<SessionForked>;
321
+ /** The session's proposed change set: files changed on its drive branch
322
+ * since it forked from `main` (read-tier — any conversation member).
323
+ * `state: "unbranched"` means the session predates branching and still
324
+ * writes `main` directly. The list reflects the branch's last flush and
325
+ * is advisory; a merge re-verifies against fresh state. 404 = not found
326
+ * or not a member (uniform). */
327
+ getSessionChanges(conversationId: string): Promise<SessionChangeSet>;
328
+ /** Approve the session's proposed changes: 3-way merge its branch into
329
+ * `main`, then continue the session on a fresh branch off post-merge
330
+ * `main`. Write-tier + human caller. Pass `opts.branch` (the branch you
331
+ * reviewed) to fail 409 `branch_changed` if it moved since.
332
+ *
333
+ * Failures: 403 `role_read_only` (read-only member) or a plain 403 for
334
+ * session toolbelt keys (agents cannot self-approve); 409 `turn_active`
335
+ * (a turn is running — retry when idle) | `branch_changed`; 400
336
+ * `no_branch` (session predates branching); 502 `quiesce_failed`
337
+ * (nothing changed — safe to retry) | `merge_failed` (branch retained,
338
+ * named in the body) | `rebranch_failed` (merge landed; retry safe). */
339
+ mergeSessionChanges(conversationId: string, opts?: {
340
+ branch?: string;
341
+ }): Promise<SessionMergeReport>;
342
+ /** Reject the session's proposed changes: abandon its branch (retained
343
+ * dormant, never deleted — an admin re-merge can recover a mistaken
344
+ * discard) and continue the session on a fresh branch off `main`.
345
+ * Write-tier + human caller; same 4xx/5xx contract as
346
+ * `mergeSessionChanges` minus the merge-step failures. */
347
+ discardSessionChanges(conversationId: string, opts?: {
348
+ branch?: string;
349
+ }): Promise<SessionDiscardReport>;
350
+ /** The conversation's member roster with roles. Solo conversations
351
+ * return an empty roster; a dm returns the pair. */
352
+ getConversationMembers(conversationId: string): Promise<ConversationMember[]>;
353
+ /** Invite members to a channel (requires `write` role). Per-invitee
354
+ * `role` is `'write'` (default) or `'read'` — `'owner'` is rejected
355
+ * with 400. Non-team userIds are dropped server-side. */
356
+ addConversationMembers(conversationId: string, members: Array<{
357
+ userId: string;
358
+ role?: "write" | "read";
359
+ }>): Promise<ConversationMember[]>;
360
+ /** Remove a member (conversation `owner` or team admin only).
361
+ * Throws 400 `last_owner` when the target is the roster's last owner. */
362
+ removeConversationMember(conversationId: string, userId: string): Promise<ConversationMember[]>;
363
+ /** Change a member's role (conversation `owner` or team admin only).
364
+ * Throws 400 `last_owner` when demoting the roster's last owner. */
365
+ setConversationMemberRole(conversationId: string, userId: string, role: ConversationMemberRole): Promise<ConversationMember[]>;
366
+ /** Send one message into a conversation. The message persists and fans
367
+ * out before this resolves; the response carries the server's
368
+ * authoritative turn verdict (`turnState`, ADR-0037 §4) — `queued` means
369
+ * a turn is already in flight and a coalesced follow-up will answer, not
370
+ * an error. Requires the `invoke` scope. */
371
+ sendConversationMessage(conversationId: string, input: SendConversationMessageInput): Promise<SendConversationMessageResult>;
372
+ /** Pre-warm a CLOUD session's sandbox (ADR-0040 §6): resumes the
373
+ * suspended VM without running a turn, so the resume latency rides the
374
+ * attach/focus gap instead of the first reply. Plain no-op
375
+ * (`warming: false`) for local/platform sessions; rate-limited
376
+ * server-side per session. Fire-and-forget by design — never block a
377
+ * surface on it. Requires the `invoke` scope. */
378
+ prewarmConversation(conversationId: string): Promise<{
379
+ warming: boolean;
380
+ rateLimited?: boolean;
381
+ }>;
382
+ /** Stop the conversation's LIVE agent turn (ADR-0037 §5). Conversation-
383
+ * scoped, not surface-scoped: any member can cancel, whichever surface
384
+ * started the turn. The canceled turn closes with a terminal error part
385
+ * (it is never re-run); a message sent after it stays queued and is
386
+ * answered next. `canceled: false` = nothing was in flight. Requires
387
+ * the `invoke` scope. */
388
+ cancelConversationTurn(conversationId: string): Promise<{
389
+ canceled: boolean;
390
+ }>;
391
+ /** Announce this client as ATTACHED to a conversation (ADR-0037 §6) —
392
+ * beat every ~30s while a surface shows the transcript. Each beat fans
393
+ * out one live-only `presence` event to every stream subscriber (the
394
+ * roster assembles client-side, keyed by `clientId`) and returns a
395
+ * fresh agent-liveness snapshot. Member-gated like the stream; no
396
+ * scope beyond conversation access — presence is a read-side beacon. */
397
+ heartbeatConversationPresence(conversationId: string, input: {
398
+ clientId: string;
399
+ surface: "dashboard" | "terminal";
400
+ }): Promise<ConversationPresenceSnapshot>;
401
+ /** Subscribe to a conversation's SSE stream as an async iterable of
402
+ * typed events, with two conversation-specific rules the consumer must
403
+ * uphold:
404
+ *
405
+ * - advance `lastEventId` ONLY from events that carry `id` (durable
406
+ * rows) — never from `part_partial` / `turn_state` / `presence`,
407
+ * which are live-only and would corrupt reconnect replay;
408
+ * - a conversation never "completes": the generator ends on the
409
+ * server's bounded-replay batch boundary (`replay.continue` — pass
410
+ * its `nextAfterSeq` back as `lastEventId` and reconnect at once) or
411
+ * its 2h stream lifetime. Callers loop with their tracked id. */
412
+ streamConversation(conversationId: string, opts?: StreamConversationOptions): AsyncGenerator<ConversationStreamEvent>;
413
+ /** List the team's agents (platform operators + local bridge agents).
414
+ * Bridge rows carry live presence (`online`) and the hosting machine's
415
+ * label — what the terminal/dashboard presence dots render from. */
416
+ listAgents(): Promise<AgentListRow[]>;
417
+ /** Search a factory drive's live files — path substring OR full-text match
418
+ * on extracted content. Cursor-paginated by path. */
419
+ searchFactoryFiles(query: string, opts?: SearchFactoryFilesOptions): Promise<FactoryFileSearchResult>;
683
420
  /** List the human members of your team — the people you (or an agent) can
684
421
  * @-flag with `createMentions`. Each row's `userId` is what
685
422
  * `mentionedUserIds` expects. */
@@ -708,6 +445,96 @@ export declare class AgentComposeClient {
708
445
  * `factorySlug` so callers can route per-template actions to the right
709
446
  * factory. */
710
447
  listTemplates(opts?: ListTemplatesOptions): Promise<TemplateRow[]>;
448
+ /** One template's detail (registration metadata + share scope). Falls
449
+ * back to the published registry for platform templates. */
450
+ getTemplate(name: string, opts?: {
451
+ factorySlug?: string;
452
+ }): Promise<TemplateDetail>;
453
+ /** Full-replace a template's share grants; optionally bind/unbind its
454
+ * owning conversation. Capabilities: `read|write|invoke|see_runs`. */
455
+ setTemplateScope(name: string, input: SetTemplateScopeInput, opts?: {
456
+ factorySlug?: string;
457
+ }): Promise<{
458
+ scope: ArtifactScope;
459
+ }>;
460
+ /** Full-replace a drive file's share grants. Capabilities: `read|write`. */
461
+ setFileScope(path: string, input: SetScopeGrantsInput, opts?: {
462
+ factorySlug?: string;
463
+ }): Promise<{
464
+ scope: ArtifactScope;
465
+ }>;
466
+ /** Share a drive file WITH a cloud session — the session becomes a grantee
467
+ * and the file appears in its fsgw mount. Fixed capabilities: the mount is
468
+ * concealment-only, so the session can read AND edit the file. Requires the
469
+ * `share` capability on the file (its owner or a team admin). The target
470
+ * must be a CLOUD session (local sessions never mount fsgw → 400
471
+ * `cloud_session_required`). No capabilities argument — semantics are fixed
472
+ * "open and edit". */
473
+ shareFileWithSession(factorySlug: string, input: {
474
+ path: string;
475
+ conversationId: string;
476
+ }): Promise<void>;
477
+ /** Revoke a file's share to a session (revocation-critical — re-conceals on
478
+ * the session's live mount within push latency). Idempotent. */
479
+ unshareFileWithSession(factorySlug: string, input: {
480
+ path: string;
481
+ conversationId: string;
482
+ }): Promise<void>;
483
+ /** List the projects the caller is a member of, newest-activity first.
484
+ * Cursor-paginated. A creator who has left sees nothing (no implicit
485
+ * creator authority) — membership is the sole gate. */
486
+ listProjects(opts?: {
487
+ cursor?: string;
488
+ }): Promise<ProjectsPage>;
489
+ /** Create a project. The caller is seeded as its first `owner` member. 409
490
+ * on a duplicate name within the team. */
491
+ createProject(name: string): Promise<Project>;
492
+ /** One project (with the caller's role + member/object counts). 404 when
493
+ * the caller is not a member. */
494
+ getProject(id: string): Promise<Project>;
495
+ /** Rename a project (requires `write` role). */
496
+ renameProject(id: string, name: string): Promise<Project>;
497
+ /** Delete a project (owner or team admin). Revokes every derived grant. */
498
+ deleteProject(id: string): Promise<void>;
499
+ /** The project's member roster with roles (member only). */
500
+ getProjectMembers(id: string): Promise<ProjectMember[]>;
501
+ /** Invite members (requires `write` role). Per-invitee `role` is `'write'`
502
+ * (default) or `'read'` — `'owner'` is never grantable at invite. Non-team
503
+ * userIds are dropped server-side; the full refreshed roster is returned. */
504
+ addProjectMembers(id: string, members: Array<{
505
+ userId: string;
506
+ role?: "write" | "read";
507
+ }>): Promise<ProjectMember[]>;
508
+ /** Remove a member — project owner/team admin, or self-leave. Throws 400
509
+ * `last_owner` when the target is the roster's last owner. */
510
+ removeProjectMember(id: string, userId: string): Promise<ProjectMember[]>;
511
+ /** Change a member's role (project owner or team admin). Throws 400
512
+ * `last_owner` when demoting the roster's last owner. */
513
+ setProjectMemberRole(id: string, userId: string, role: ProjectRole): Promise<ProjectMember[]>;
514
+ /** List a project's objects (member only), newest first. Cursor-paginated. */
515
+ listProjectObjects(id: string, opts?: {
516
+ cursor?: string;
517
+ }): Promise<ProjectObjectsPage>;
518
+ /** DRY-RUN preview of a session add: the files that WOULD be shared (from
519
+ * the caller's owned scopes) + any owned-but-skipped entries (paths
520
+ * concealed from the caller are omitted). Powers the consent dialog. Same
521
+ * gates as the add, but mutates nothing. */
522
+ previewProjectObject(id: string, input: {
523
+ conversationId: string;
524
+ }): Promise<ProjectAddPreview>;
525
+ /** Add an object to a project (requires `write` role AND authority on the
526
+ * object itself). A session add also materializes the caller-owned files in
527
+ * the session's context, returning them alongside the session object. */
528
+ addProjectObject(id: string, input: AddProjectObjectInput): Promise<AddProjectObjectResult>;
529
+ /** Re-materialize a session object's file context (add-only — never removes;
530
+ * picks up files scoped/created after the original add). Session objects
531
+ * only; caller must be the session owner and a project writer. */
532
+ refreshProjectObject(id: string, objectId: string): Promise<RefreshProjectObjectResult>;
533
+ /** Remove an object from a project (revocation-critical). Authorized for a
534
+ * project writer, the member who added it, OR — for a file object — the
535
+ * file's owner even without project membership (share implies unshare).
536
+ * Unauthorized → 404. */
537
+ removeProjectObject(id: string, objectId: string): Promise<void>;
711
538
  /** List factories for the caller's team. */
712
539
  listFactories(): Promise<FactoryRow[]>;
713
540
  /** Create a factory. `slug` must be lowercase kebab-case and unique
@@ -737,10 +564,27 @@ export declare class AgentComposeClient {
737
564
  deleteSchedule(id: string, factorySlug?: string): Promise<void>;
738
565
  /** Create or update a workflow secret. Value is stored in GCP Secret Manager. */
739
566
  setSecret(workflowName: string, key: string, value: string, opts?: SecretOptions): Promise<SetSecretResult>;
567
+ /** Both secret tiers list the same `{ secrets }` envelope — fetch + map the
568
+ * wire's `secretKey` to `SecretListEntry.key`. */
569
+ private listSecretEntries;
740
570
  /** List secret keys registered for a workflow (metadata only — values are never returned). */
741
571
  listSecrets(workflowName: string, opts?: SecretOptions): Promise<SecretListEntry[]>;
742
572
  /** Delete a workflow secret. */
743
573
  deleteSecret(workflowName: string, key: string, opts?: SecretOptions): Promise<void>;
574
+ /** List a factory's drive⇄repo links. */
575
+ listRepoLinks(opts?: {
576
+ factorySlug?: string;
577
+ }): Promise<DriveRepoLink[]>;
578
+ /** Link a drive directory to a GitHub repo + tracked branch (`manage`
579
+ * scope). Requires the drive to be graph-authoritative — 409 names the
580
+ * promotion prerequisite otherwise. */
581
+ createRepoLink(input: CreateDriveRepoLinkInput, opts?: {
582
+ factorySlug?: string;
583
+ }): Promise<DriveRepoLink>;
584
+ /** Unlink (§6.3: the prefix's files and history stay on the drive). */
585
+ deleteRepoLink(linkId: string, opts?: {
586
+ factorySlug?: string;
587
+ }): Promise<void>;
744
588
  /** Create or update a factory-level secret. */
745
589
  setFactorySecret(key: string, value: string, opts?: SecretOptions): Promise<SetSecretResult>;
746
590
  /** List factory-level secret keys (metadata only — values are never returned). */
@@ -762,6 +606,25 @@ export declare class AgentComposeClient {
762
606
  * run returns the current state without throwing. The server stamps the
763
607
  * run as `canceled` and kills any live sandboxes. */
764
608
  cancelRun(runId: string): Promise<CancelRunResponse>;
609
+ /** Request a break-glass compliance session — returns it `pending` until a
610
+ * team owner (≠ requester) approves. `scopeRef` is the factory id for
611
+ * factory scope; omit it for team scope. `ttlSeconds` is the session's
612
+ * lifetime once approved (15 min floor, 7 day ceiling). */
613
+ requestComplianceSession(input: RequestComplianceSessionInput): Promise<ComplianceSession>;
614
+ /** Approve a pending compliance session → active with its TTL. The caller
615
+ * must be a team owner ≠ the requester (or, when the requester is the sole
616
+ * owner, any admin ≠ requester). Throws 403 on self-approval or wrong role,
617
+ * 409 when the session is no longer pending. */
618
+ approveComplianceSession(sessionId: string): Promise<ComplianceSession>;
619
+ /** Revoke a pending or active compliance session — revocation always
620
+ * tightens, so any team owner/admin may do it. */
621
+ revokeComplianceSession(sessionId: string): Promise<ComplianceSession>;
622
+ /** List the team's compliance sessions, newest first. Optional `status`
623
+ * filter; opaque `cursor` pagination. */
624
+ listComplianceSessions(opts?: ListComplianceSessionsOptions): Promise<ComplianceSessionsPage>;
625
+ /** The documents touched under one compliance session — the individual
626
+ * per-document audit trail its reasoned entry authorized. */
627
+ listComplianceAccesses(sessionId: string, opts?: ListComplianceAccessesOptions): Promise<ComplianceAccessesPage>;
765
628
  /** Stream lifecycle events for a run as an async iterable. Yields parsed
766
629
  * `RunEvent` payloads in order; caller breaks on terminal events
767
630
  * (`run_complete`, `run_failed`, `run_canceled`).
@@ -769,21 +632,6 @@ export declare class AgentComposeClient {
769
632
  * `lastEventId` enables resume — pass the highest `seq` you've already
770
633
  * processed to receive only events you missed.
771
634
  *
772
- * `event` can be used to abort the stream from the caller side.
773
- *
774
- * Uses raw `fetch` (not ofetch) because SSE requires access to the
775
- * response's `ReadableStream`, which ofetch consumes when parsing. Auth
776
- * + base URL are still sourced from the same constructor inputs, and
777
- * non-2xx responses throw the same `AgentComposeError`. */
635
+ * `event` can be used to abort the stream from the caller side. */
778
636
  streamRunLogs(runId: string, opts?: StreamRunLogsOptions): AsyncGenerator<RunEvent>;
779
637
  }
780
- /** A factory: a project-level grouping of workflows inside a team. */
781
- export interface FactoryRow {
782
- id: string;
783
- teamId: string;
784
- slug: string;
785
- name: string;
786
- description: string | null;
787
- createdAt: string;
788
- updatedAt: string;
789
- }