@agent-compose/sdk 0.1.0 → 0.2.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.
- package/README.md +276 -94
- package/dist/client.d.ts +178 -21
- package/dist/index.d.ts +2 -1
- package/dist/index.js +146 -21
- package/dist/runtimes/openai-desktop.js +145 -21
- package/dist/sse.d.ts +25 -0
- package/dist/types/events.d.ts +5 -0
- package/dist/types/sandbox-environment.d.ts +13 -12
- package/dist/types/workflow.d.ts +13 -11
- package/dist/utils/bundler.d.ts +6 -5
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AgentComposeClient — HTTP client for the agent-compose server API.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Templates always live inside a factory (project). Methods that touch a
|
|
5
|
+
* specific template (`register`, `invoke`, `setSecret`, `listSecrets`,
|
|
6
|
+
* `deleteSecret`) take an optional `factorySlug`; when omitted, they target
|
|
7
|
+
* the team's auto-created `default` factory. There is no second URL space
|
|
8
|
+
* for "templates without a factory" — every workflow belongs to exactly one.
|
|
9
|
+
*
|
|
10
|
+
* `register()` accepts pre-built sources — use the CLI (`agent-compose
|
|
11
|
+
* register`) or build sources yourself and pass them directly.
|
|
6
12
|
*/
|
|
13
|
+
import type { RunEvent } from "./types/events.js";
|
|
14
|
+
import type { SandboxNetworkPolicy } from "./sandbox.js";
|
|
7
15
|
export interface RegisterResult {
|
|
8
16
|
id: string;
|
|
9
17
|
name: string;
|
|
@@ -16,9 +24,54 @@ export interface RegisterResult {
|
|
|
16
24
|
}
|
|
17
25
|
export interface RunStatus {
|
|
18
26
|
id: string;
|
|
19
|
-
status: "running" | "success" | "failed" | "abandoned";
|
|
27
|
+
status: "running" | "success" | "failed" | "abandoned" | "canceled";
|
|
20
28
|
output?: Record<string, unknown>;
|
|
21
29
|
}
|
|
30
|
+
/** Row shape returned by `GET /api-keys`. */
|
|
31
|
+
export interface ApiKey {
|
|
32
|
+
object: "api_key";
|
|
33
|
+
id: string;
|
|
34
|
+
name: string | null;
|
|
35
|
+
last4: string | null;
|
|
36
|
+
scopes: string[];
|
|
37
|
+
teamId: string;
|
|
38
|
+
createdByUserId: string | null;
|
|
39
|
+
/** Non-null when the key is restricted to a single factory. */
|
|
40
|
+
factoryId: string | null;
|
|
41
|
+
createdAt: string;
|
|
42
|
+
expiresAt: string | null;
|
|
43
|
+
lastUsedAt: string | null;
|
|
44
|
+
revokedAt: string | null;
|
|
45
|
+
}
|
|
46
|
+
/** Response from `POST /api-keys`. The `key` field is the plaintext token —
|
|
47
|
+
* shown once at creation, never retrievable again. */
|
|
48
|
+
export interface ApiKeyCreated extends ApiKey {
|
|
49
|
+
key: string;
|
|
50
|
+
}
|
|
51
|
+
/** Single rollup row from `GET /api/v1/usage`. */
|
|
52
|
+
export interface UsageRollupRow {
|
|
53
|
+
eventType: string;
|
|
54
|
+
unit: string;
|
|
55
|
+
total: number;
|
|
56
|
+
tags: Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
/** Response from `GET /api/v1/usage`. */
|
|
59
|
+
export interface UsageResponse {
|
|
60
|
+
object: "list";
|
|
61
|
+
data: UsageRollupRow[];
|
|
62
|
+
has_more: boolean;
|
|
63
|
+
from: string | null;
|
|
64
|
+
to: string | null;
|
|
65
|
+
}
|
|
66
|
+
/** Response from `POST /api/v1/workflows/:id/cancel`. The endpoint is
|
|
67
|
+
* idempotent: cancelling a run that's already terminal returns its current
|
|
68
|
+
* outcome verbatim (rather than throwing or pretending it just canceled),
|
|
69
|
+
* so `status` widens to every terminal value the server might surface. */
|
|
70
|
+
export interface CancelRunResponse {
|
|
71
|
+
runId: string;
|
|
72
|
+
status: "canceled" | "success" | "failed" | "abandoned";
|
|
73
|
+
canceledAt: string;
|
|
74
|
+
}
|
|
22
75
|
export interface SnapshotListEntry {
|
|
23
76
|
runId: string;
|
|
24
77
|
workflow: string | null;
|
|
@@ -28,8 +81,11 @@ export interface SnapshotListEntry {
|
|
|
28
81
|
}
|
|
29
82
|
export declare class AgentComposeClient {
|
|
30
83
|
private readonly fetch;
|
|
84
|
+
private readonly baseUrl;
|
|
85
|
+
private readonly apiKey;
|
|
31
86
|
constructor(baseUrl: string, apiKey: string);
|
|
32
|
-
/** Register a workflow
|
|
87
|
+
/** Register (or update) a workflow template inside a factory. Defaults to
|
|
88
|
+
* the team's `default` factory when `factorySlug` is omitted. */
|
|
33
89
|
register(payload: {
|
|
34
90
|
name: string;
|
|
35
91
|
source: string;
|
|
@@ -41,19 +97,31 @@ export declare class AgentComposeClient {
|
|
|
41
97
|
}>;
|
|
42
98
|
networkPolicy?: unknown;
|
|
43
99
|
placeholders?: Record<string, string>;
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
* registered with `--build
|
|
47
|
-
|
|
100
|
+
/** Reference to a snapshot the runner should boot from at run start.
|
|
101
|
+
* A run UUID, workflow name, or `name@version`. The referenced
|
|
102
|
+
* workflow must have been registered with `--build` (or any prior
|
|
103
|
+
* successful run with `saveSnapshot: true`). Per-invocation
|
|
104
|
+
* `invoke({ snapshot })` overrides this default. */
|
|
105
|
+
snapshot?: string;
|
|
48
106
|
/** If true, runs default to capturing a long-lived sandbox snapshot on
|
|
49
|
-
* success. Individual invocations can override via
|
|
50
|
-
|
|
107
|
+
* success. Individual invocations can override via
|
|
108
|
+
* `invoke(..., { saveSnapshot })`. */
|
|
109
|
+
saveSnapshot?: boolean;
|
|
110
|
+
/** Factory slug. Defaults to `"default"`. */
|
|
111
|
+
factorySlug?: string;
|
|
51
112
|
}): Promise<RegisterResult>;
|
|
52
113
|
/** Invoke a workflow. Returns run ID immediately — workflow runs asynchronously.
|
|
53
114
|
*
|
|
54
|
-
* `snapshot`:
|
|
55
|
-
*
|
|
56
|
-
*
|
|
115
|
+
* `snapshot`: per-invocation override of the template-level `snapshot`
|
|
116
|
+
* field. Same forms — a run UUID, a workflow name, or `name@version`.
|
|
117
|
+
* Use this when one template needs to boot from many different
|
|
118
|
+
* snapshots (e.g. a benchmark workflow running against a different
|
|
119
|
+
* starting state per invocation). Does not change the template's
|
|
120
|
+
* registered default; only affects this run.
|
|
121
|
+
*
|
|
122
|
+
* `saveSnapshot`: `true` overrides the workflow default; `false` opts
|
|
123
|
+
* out. When the run captures a snapshot, its id is stamped on the row
|
|
124
|
+
* and can be referenced as the `snapshot` field on other workflows.
|
|
57
125
|
*
|
|
58
126
|
* `parentRunId`: links the new run to another of the same account's
|
|
59
127
|
* currently-running runs. When omitted, the client auto-detects from
|
|
@@ -61,10 +129,16 @@ export declare class AgentComposeClient {
|
|
|
61
129
|
* so workflows invoking other workflows get the parent/child tree for
|
|
62
130
|
* free. Pass `null` to suppress auto-detection (e.g. invoking a top-level
|
|
63
131
|
* sibling workflow from inside a runner for a reason unrelated to the
|
|
64
|
-
* current run). Explicit non-null wins over auto-detection.
|
|
132
|
+
* current run). Explicit non-null wins over auto-detection.
|
|
133
|
+
*
|
|
134
|
+
* `factorySlug`: defaults to `"default"`. */
|
|
65
135
|
invoke(name: string, input?: Record<string, unknown>, opts?: {
|
|
66
|
-
snapshot?:
|
|
136
|
+
snapshot?: string;
|
|
137
|
+
saveSnapshot?: boolean;
|
|
67
138
|
parentRunId?: string | null;
|
|
139
|
+
factorySlug?: string;
|
|
140
|
+
networkPolicy?: SandboxNetworkPolicy;
|
|
141
|
+
placeholders?: Record<string, string>;
|
|
68
142
|
}): Promise<{
|
|
69
143
|
id: string;
|
|
70
144
|
}>;
|
|
@@ -76,8 +150,12 @@ export declare class AgentComposeClient {
|
|
|
76
150
|
* tests, tune up for long-running workflows. The parent-child auto-
|
|
77
151
|
* detection from `invoke()` applies here too. */
|
|
78
152
|
invokeAndWait(name: string, input?: Record<string, unknown>, opts?: {
|
|
79
|
-
snapshot?:
|
|
153
|
+
snapshot?: string;
|
|
154
|
+
saveSnapshot?: boolean;
|
|
80
155
|
parentRunId?: string | null;
|
|
156
|
+
factorySlug?: string;
|
|
157
|
+
networkPolicy?: SandboxNetworkPolicy;
|
|
158
|
+
placeholders?: Record<string, string>;
|
|
81
159
|
timeoutMs?: number;
|
|
82
160
|
pollIntervalMs?: number;
|
|
83
161
|
}): Promise<RunStatus>;
|
|
@@ -90,21 +168,100 @@ export declare class AgentComposeClient {
|
|
|
90
168
|
deleteSnapshot(runId: string): Promise<void>;
|
|
91
169
|
/** Poll run status. */
|
|
92
170
|
getStatus(runId: string): Promise<RunStatus>;
|
|
93
|
-
/** List registered workflow templates.
|
|
94
|
-
|
|
171
|
+
/** List registered workflow templates. When `factorySlug` is supplied,
|
|
172
|
+
* scopes to that factory; otherwise returns every template the team can
|
|
173
|
+
* see across every factory in one round trip — each row carries its
|
|
174
|
+
* `factorySlug` so callers can route per-template actions to the right
|
|
175
|
+
* factory. */
|
|
176
|
+
listTemplates(opts?: {
|
|
177
|
+
factorySlug?: string;
|
|
178
|
+
}): Promise<Array<{
|
|
95
179
|
name: string;
|
|
96
180
|
version: string;
|
|
181
|
+
factorySlug: string;
|
|
97
182
|
}>>;
|
|
183
|
+
/** List factories for the caller's team. */
|
|
184
|
+
listFactories(): Promise<FactoryRow[]>;
|
|
185
|
+
/** Create a factory. `slug` must be lowercase kebab-case and unique
|
|
186
|
+
* within the team. */
|
|
187
|
+
createFactory(payload: {
|
|
188
|
+
slug: string;
|
|
189
|
+
name: string;
|
|
190
|
+
description?: string;
|
|
191
|
+
}): Promise<FactoryRow>;
|
|
192
|
+
/** Get a factory by slug. */
|
|
193
|
+
getFactory(slug: string): Promise<FactoryRow>;
|
|
194
|
+
/** Rename or describe a factory. */
|
|
195
|
+
updateFactory(slug: string, updates: {
|
|
196
|
+
name?: string;
|
|
197
|
+
description?: string;
|
|
198
|
+
}): Promise<FactoryRow>;
|
|
199
|
+
/** Delete a factory. Refuses `default` and any factory still
|
|
200
|
+
* containing workflows. */
|
|
201
|
+
deleteFactory(slug: string): Promise<void>;
|
|
98
202
|
/** Create or update a workflow secret. Value is stored in GCP Secret Manager. */
|
|
99
|
-
setSecret(workflowName: string, key: string, value: string
|
|
203
|
+
setSecret(workflowName: string, key: string, value: string, opts?: {
|
|
204
|
+
factorySlug?: string;
|
|
205
|
+
}): Promise<{
|
|
100
206
|
key: string;
|
|
101
207
|
}>;
|
|
102
208
|
/** List secret keys registered for a workflow (metadata only — values are never returned). */
|
|
103
|
-
listSecrets(workflowName: string
|
|
209
|
+
listSecrets(workflowName: string, opts?: {
|
|
210
|
+
factorySlug?: string;
|
|
211
|
+
}): Promise<Array<{
|
|
104
212
|
key: string;
|
|
105
213
|
createdAt: string;
|
|
106
214
|
updatedAt: string;
|
|
107
215
|
}>>;
|
|
108
216
|
/** Delete a workflow secret. */
|
|
109
|
-
deleteSecret(workflowName: string, key: string
|
|
217
|
+
deleteSecret(workflowName: string, key: string, opts?: {
|
|
218
|
+
factorySlug?: string;
|
|
219
|
+
}): Promise<void>;
|
|
220
|
+
/** Create a new API key on the caller's team. The plaintext `key` is
|
|
221
|
+
* returned once — it cannot be retrieved later.
|
|
222
|
+
*
|
|
223
|
+
* When `factorySlug` is set, the new key is restricted to that factory.
|
|
224
|
+
* Factory-scoped keys can only mint other keys bound to the same factory. */
|
|
225
|
+
createApiKey(input: {
|
|
226
|
+
name?: string;
|
|
227
|
+
scopes?: string[];
|
|
228
|
+
expiresAt?: string;
|
|
229
|
+
factorySlug?: string;
|
|
230
|
+
}): Promise<ApiKeyCreated>;
|
|
231
|
+
/** List API keys on the caller's team (metadata only — plaintext keys are
|
|
232
|
+
* never returned). */
|
|
233
|
+
listApiKeys(): Promise<ApiKey[]>;
|
|
234
|
+
/** Billable usage rollup for the caller's team over the [from, to) window. */
|
|
235
|
+
getUsage(from: Date, to: Date): Promise<UsageResponse>;
|
|
236
|
+
/** Cancel an in-progress run. Idempotent: cancelling an already-terminal
|
|
237
|
+
* run returns the current state without throwing. The server stamps the
|
|
238
|
+
* run as `canceled` and kills any live sandboxes. */
|
|
239
|
+
cancelRun(runId: string): Promise<CancelRunResponse>;
|
|
240
|
+
/** Stream lifecycle events for a run as an async iterable. Yields parsed
|
|
241
|
+
* `RunEvent` payloads in order; caller breaks on terminal events
|
|
242
|
+
* (`run_complete`, `run_failed`, `run_canceled`).
|
|
243
|
+
*
|
|
244
|
+
* `lastEventId` enables resume — pass the highest `seq` you've already
|
|
245
|
+
* processed to receive only events you missed.
|
|
246
|
+
*
|
|
247
|
+
* `signal` can be used to abort the stream from the caller side.
|
|
248
|
+
*
|
|
249
|
+
* Uses raw `fetch` (not ofetch) because SSE requires access to the
|
|
250
|
+
* response's `ReadableStream`, which ofetch consumes when parsing. Auth
|
|
251
|
+
* + base URL are still sourced from the same constructor inputs, and
|
|
252
|
+
* non-2xx responses throw the same `AgentComposeError`. */
|
|
253
|
+
streamRunLogs(runId: string, opts?: {
|
|
254
|
+
lastEventId?: number;
|
|
255
|
+
signal?: AbortSignal;
|
|
256
|
+
}): AsyncGenerator<RunEvent>;
|
|
257
|
+
}
|
|
258
|
+
/** A factory: a project-level grouping of workflows inside a team. */
|
|
259
|
+
export interface FactoryRow {
|
|
260
|
+
id: string;
|
|
261
|
+
teamId: string;
|
|
262
|
+
slug: string;
|
|
263
|
+
name: string;
|
|
264
|
+
description: string | null;
|
|
265
|
+
createdAt: string;
|
|
266
|
+
updatedAt: string;
|
|
110
267
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,8 @@ export type { WorkflowFn, WorkflowCtx, WorkflowRun, AgentBudget, WorkflowHooks,
|
|
|
20
20
|
export type { AgentMessage, AgentMessageInit, AgentMessageText, AgentMessageThinking, AgentMessageToolUse, AgentMessageToolResult, AgentMessageDone, AgentMessageError, AgentMessageUsage, AgentStatus, } from "./types/protocol.js";
|
|
21
21
|
export type { SandboxProvider, DesktopSandboxProvider, } from "./types/sandbox.js";
|
|
22
22
|
export { AgentComposeClient } from "./client.js";
|
|
23
|
-
export type { RegisterResult, RunStatus } from "./client.js";
|
|
23
|
+
export type { RegisterResult, RunStatus, FactoryRow, SnapshotListEntry, ApiKey, ApiKeyCreated, UsageRollupRow, UsageResponse, CancelRunResponse, } from "./client.js";
|
|
24
|
+
export { parseSseStream } from "./sse.js";
|
|
24
25
|
export { AgentComposeError } from "./errors.js";
|
|
25
26
|
export { formatError } from "./utils/errors.js";
|
|
26
27
|
export { discoverRuntimeName } from "./utils/discovery.js";
|
package/dist/index.js
CHANGED
|
@@ -28,8 +28,8 @@ function defineWorkflow(def) {
|
|
|
28
28
|
return Object.assign(def.run, {
|
|
29
29
|
networkPolicy: def.networkPolicy,
|
|
30
30
|
placeholders: def.placeholders,
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
snapshot: def.snapshot,
|
|
32
|
+
saveSnapshot: def.saveSnapshot
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
// src/sandbox.ts
|
|
@@ -350,7 +350,7 @@ function defineSandboxEnvironment(env) {
|
|
|
350
350
|
throw new Error(`defineSandboxEnvironment(${env.name}): 'setup' must be a function`);
|
|
351
351
|
}
|
|
352
352
|
return defineWorkflow({
|
|
353
|
-
|
|
353
|
+
saveSnapshot: env.saveSnapshot ?? true,
|
|
354
354
|
run: () => env.setup(makeLocalSandboxProvider())
|
|
355
355
|
});
|
|
356
356
|
}
|
|
@@ -367,18 +367,74 @@ class AgentComposeError extends Error {
|
|
|
367
367
|
}
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
+
// src/sse.ts
|
|
371
|
+
async function* parseSseStream(body) {
|
|
372
|
+
const reader = body.getReader();
|
|
373
|
+
const decoder = new TextDecoder;
|
|
374
|
+
let buffer = "";
|
|
375
|
+
let event = "";
|
|
376
|
+
let seq = 0;
|
|
377
|
+
let dataLines = [];
|
|
378
|
+
try {
|
|
379
|
+
while (true) {
|
|
380
|
+
const { done, value } = await reader.read();
|
|
381
|
+
if (done)
|
|
382
|
+
break;
|
|
383
|
+
buffer += decoder.decode(value, { stream: true });
|
|
384
|
+
const lines = buffer.split(`
|
|
385
|
+
`);
|
|
386
|
+
buffer = lines.pop() ?? "";
|
|
387
|
+
for (const line of lines) {
|
|
388
|
+
if (line.startsWith("id:")) {
|
|
389
|
+
seq = Number(line.slice(3).trim());
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
if (line.startsWith("event:")) {
|
|
393
|
+
event = line.slice(6).trim();
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (line.startsWith("data:")) {
|
|
397
|
+
dataLines.push(line.slice(5).trim());
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
if (line === "" && dataLines.length > 0) {
|
|
401
|
+
try {
|
|
402
|
+
const data = JSON.parse(dataLines.join(`
|
|
403
|
+
`));
|
|
404
|
+
yield { id: seq, event, data };
|
|
405
|
+
} catch {}
|
|
406
|
+
event = "";
|
|
407
|
+
seq = 0;
|
|
408
|
+
dataLines = [];
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
} finally {
|
|
413
|
+
reader.releaseLock();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
370
417
|
// src/client.ts
|
|
371
418
|
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
419
|
+
var DEFAULT_FACTORY = "default";
|
|
372
420
|
function detectAmbientParentRunId() {
|
|
373
421
|
const envRunId = typeof process !== "undefined" ? process.env?.RUN_ID : undefined;
|
|
374
422
|
return envRunId && UUID_REGEX.test(envRunId) ? envRunId : null;
|
|
375
423
|
}
|
|
424
|
+
function templatePath(factorySlug, ...rest) {
|
|
425
|
+
const tail = rest.length > 0 ? "/" + rest.map(encodeURIComponent).join("/") : "";
|
|
426
|
+
return `/api/v1/factories/${encodeURIComponent(factorySlug)}/templates${tail}`;
|
|
427
|
+
}
|
|
376
428
|
|
|
377
429
|
class AgentComposeClient {
|
|
378
430
|
fetch;
|
|
431
|
+
baseUrl;
|
|
432
|
+
apiKey;
|
|
379
433
|
constructor(baseUrl, apiKey) {
|
|
434
|
+
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
435
|
+
this.apiKey = apiKey;
|
|
380
436
|
this.fetch = ofetch.create({
|
|
381
|
-
baseURL: baseUrl
|
|
437
|
+
baseURL: this.baseUrl,
|
|
382
438
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
383
439
|
async onResponseError({ response }) {
|
|
384
440
|
const body = response._data;
|
|
@@ -387,16 +443,21 @@ class AgentComposeClient {
|
|
|
387
443
|
});
|
|
388
444
|
}
|
|
389
445
|
register(payload) {
|
|
390
|
-
|
|
446
|
+
const { factorySlug = DEFAULT_FACTORY, ...body } = payload;
|
|
447
|
+
return this.fetch(templatePath(factorySlug), { method: "POST", body });
|
|
391
448
|
}
|
|
392
449
|
invoke(name, input, opts) {
|
|
393
450
|
const parentRunId = opts?.parentRunId === undefined ? detectAmbientParentRunId() : opts.parentRunId;
|
|
394
|
-
|
|
451
|
+
const factorySlug = opts?.factorySlug ?? DEFAULT_FACTORY;
|
|
452
|
+
return this.fetch(templatePath(factorySlug, name, "invoke"), {
|
|
395
453
|
method: "POST",
|
|
396
454
|
body: {
|
|
397
455
|
input,
|
|
398
456
|
...opts?.snapshot !== undefined ? { snapshot: opts.snapshot } : {},
|
|
399
|
-
...
|
|
457
|
+
...opts?.saveSnapshot !== undefined ? { saveSnapshot: opts.saveSnapshot } : {},
|
|
458
|
+
...parentRunId ? { parentRunId } : {},
|
|
459
|
+
...opts?.networkPolicy !== undefined ? { networkPolicy: opts.networkPolicy } : {},
|
|
460
|
+
...opts?.placeholders !== undefined ? { placeholders: opts.placeholders } : {}
|
|
400
461
|
}
|
|
401
462
|
});
|
|
402
463
|
}
|
|
@@ -405,7 +466,11 @@ class AgentComposeClient {
|
|
|
405
466
|
const pollMs = opts?.pollIntervalMs ?? 1000;
|
|
406
467
|
const { id: runId } = await this.invoke(name, input, {
|
|
407
468
|
...opts?.snapshot !== undefined ? { snapshot: opts.snapshot } : {},
|
|
408
|
-
...opts?.
|
|
469
|
+
...opts?.saveSnapshot !== undefined ? { saveSnapshot: opts.saveSnapshot } : {},
|
|
470
|
+
...opts?.parentRunId !== undefined ? { parentRunId: opts.parentRunId } : {},
|
|
471
|
+
...opts?.factorySlug !== undefined ? { factorySlug: opts.factorySlug } : {},
|
|
472
|
+
...opts?.networkPolicy !== undefined ? { networkPolicy: opts.networkPolicy } : {},
|
|
473
|
+
...opts?.placeholders !== undefined ? { placeholders: opts.placeholders } : {}
|
|
409
474
|
});
|
|
410
475
|
const deadline = Date.now() + timeoutMs;
|
|
411
476
|
while (Date.now() < deadline) {
|
|
@@ -432,19 +497,78 @@ class AgentComposeClient {
|
|
|
432
497
|
getStatus(runId) {
|
|
433
498
|
return this.fetch(`/api/v1/workflows/${runId}/status`);
|
|
434
499
|
}
|
|
435
|
-
async listTemplates() {
|
|
436
|
-
const
|
|
500
|
+
async listTemplates(opts) {
|
|
501
|
+
const path = opts?.factorySlug ? templatePath(opts.factorySlug) : "/api/v1/templates";
|
|
502
|
+
const body = await this.fetch(path);
|
|
437
503
|
return body.templates;
|
|
438
504
|
}
|
|
439
|
-
|
|
440
|
-
|
|
505
|
+
async listFactories() {
|
|
506
|
+
const body = await this.fetch("/api/v1/factories");
|
|
507
|
+
return body.factories;
|
|
508
|
+
}
|
|
509
|
+
createFactory(payload) {
|
|
510
|
+
return this.fetch("/api/v1/factories", { method: "POST", body: payload });
|
|
441
511
|
}
|
|
442
|
-
|
|
443
|
-
|
|
512
|
+
getFactory(slug) {
|
|
513
|
+
return this.fetch(`/api/v1/factories/${encodeURIComponent(slug)}`);
|
|
514
|
+
}
|
|
515
|
+
updateFactory(slug, updates) {
|
|
516
|
+
return this.fetch(`/api/v1/factories/${encodeURIComponent(slug)}`, { method: "PATCH", body: updates });
|
|
517
|
+
}
|
|
518
|
+
deleteFactory(slug) {
|
|
519
|
+
return this.fetch(`/api/v1/factories/${encodeURIComponent(slug)}`, { method: "DELETE" });
|
|
520
|
+
}
|
|
521
|
+
setSecret(workflowName, key, value, opts) {
|
|
522
|
+
const factorySlug = opts?.factorySlug ?? DEFAULT_FACTORY;
|
|
523
|
+
return this.fetch(templatePath(factorySlug, workflowName, "secrets"), {
|
|
524
|
+
method: "POST",
|
|
525
|
+
body: { key, value }
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
async listSecrets(workflowName, opts) {
|
|
529
|
+
const factorySlug = opts?.factorySlug ?? DEFAULT_FACTORY;
|
|
530
|
+
const body = await this.fetch(templatePath(factorySlug, workflowName, "secrets"));
|
|
444
531
|
return body.secrets.map((s) => ({ key: s.secretKey, createdAt: s.createdAt, updatedAt: s.updatedAt }));
|
|
445
532
|
}
|
|
446
|
-
deleteSecret(workflowName, key) {
|
|
447
|
-
|
|
533
|
+
deleteSecret(workflowName, key, opts) {
|
|
534
|
+
const factorySlug = opts?.factorySlug ?? DEFAULT_FACTORY;
|
|
535
|
+
return this.fetch(templatePath(factorySlug, workflowName, "secrets", key), { method: "DELETE" });
|
|
536
|
+
}
|
|
537
|
+
createApiKey(input) {
|
|
538
|
+
return this.fetch("/api-keys", { method: "POST", body: input });
|
|
539
|
+
}
|
|
540
|
+
async listApiKeys() {
|
|
541
|
+
const body = await this.fetch("/api-keys");
|
|
542
|
+
return body.data;
|
|
543
|
+
}
|
|
544
|
+
getUsage(from, to) {
|
|
545
|
+
const qs = `?from=${encodeURIComponent(from.toISOString())}&to=${encodeURIComponent(to.toISOString())}`;
|
|
546
|
+
return this.fetch(`/api/v1/usage${qs}`);
|
|
547
|
+
}
|
|
548
|
+
cancelRun(runId) {
|
|
549
|
+
return this.fetch(`/api/v1/workflows/${encodeURIComponent(runId)}/cancel`, { method: "POST" });
|
|
550
|
+
}
|
|
551
|
+
async* streamRunLogs(runId, opts) {
|
|
552
|
+
const headers = { Authorization: `Bearer ${this.apiKey}` };
|
|
553
|
+
if (opts?.lastEventId && opts.lastEventId > 0) {
|
|
554
|
+
headers["Last-Event-ID"] = String(opts.lastEventId);
|
|
555
|
+
}
|
|
556
|
+
const res = await fetch(`${this.baseUrl}/api/v1/workflows/${encodeURIComponent(runId)}/stream`, {
|
|
557
|
+
headers,
|
|
558
|
+
...opts?.signal ? { signal: opts.signal } : {}
|
|
559
|
+
});
|
|
560
|
+
if (!res.ok || !res.body) {
|
|
561
|
+
let message = res.statusText;
|
|
562
|
+
try {
|
|
563
|
+
const body = await res.json();
|
|
564
|
+
if (body.error)
|
|
565
|
+
message = body.error;
|
|
566
|
+
} catch {}
|
|
567
|
+
throw new AgentComposeError(res.status, message);
|
|
568
|
+
}
|
|
569
|
+
for await (const ev of parseSseStream(res.body)) {
|
|
570
|
+
yield ev.data;
|
|
571
|
+
}
|
|
448
572
|
}
|
|
449
573
|
}
|
|
450
574
|
// src/utils/errors.ts
|
|
@@ -499,16 +623,16 @@ async function bundleWorkflow(workflowPath, overrides) {
|
|
|
499
623
|
const wfBits = await extractFromBundle(source, "workflow", (wf) => wf ? {
|
|
500
624
|
networkPolicy: wf.networkPolicy,
|
|
501
625
|
placeholders: wf.placeholders,
|
|
502
|
-
|
|
503
|
-
|
|
626
|
+
snapshot: wf.snapshot,
|
|
627
|
+
saveSnapshot: wf.saveSnapshot
|
|
504
628
|
} : undefined);
|
|
505
|
-
const { networkPolicy, placeholders,
|
|
629
|
+
const { networkPolicy, placeholders, snapshot, saveSnapshot } = wfBits ?? {};
|
|
506
630
|
return {
|
|
507
631
|
source,
|
|
508
632
|
networkPolicy: overrides?.networkPolicy ?? networkPolicy,
|
|
509
633
|
placeholders: overrides?.placeholders ?? placeholders,
|
|
510
|
-
...
|
|
511
|
-
...
|
|
634
|
+
...snapshot !== undefined ? { snapshot } : {},
|
|
635
|
+
...saveSnapshot !== undefined ? { saveSnapshot } : {}
|
|
512
636
|
};
|
|
513
637
|
}
|
|
514
638
|
// src/utils/schemas.ts
|
|
@@ -1077,6 +1201,7 @@ export {
|
|
|
1077
1201
|
runWorkflow,
|
|
1078
1202
|
runAgent,
|
|
1079
1203
|
reconnectSandbox,
|
|
1204
|
+
parseSseStream,
|
|
1080
1205
|
parseSseExecStream,
|
|
1081
1206
|
parseNameVersion,
|
|
1082
1207
|
parseAgentStatus,
|