@agent-compose/sdk 0.2.4 → 0.3.0
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 +31 -19
- package/dist/client.d.ts +83 -26
- package/dist/index.d.ts +3 -2
- package/dist/index.js +89 -18
- package/dist/runtimes/openai-desktop.js +89 -18
- package/dist/types/sandbox-environment.d.ts +23 -14
- package/dist/types/sandbox.d.ts +6 -1
- package/dist/types/workflow-metadata.d.ts +72 -8
- package/dist/types/workflow.d.ts +23 -19
- package/dist/utils/bundler.d.ts +12 -7
- package/dist/workflow-steps/workflow.d.ts +4 -2
- package/package.json +1 -1
- package/src/client.ts +124 -30
- package/src/index.ts +9 -1
- package/src/sandbox.ts +5 -1
- package/src/types/sandbox-environment.ts +25 -15
- package/src/types/sandbox.ts +6 -2
- package/src/types/workflow-metadata.ts +77 -12
- package/src/types/workflow.ts +23 -19
- package/src/utils/bundler.ts +87 -12
- package/src/workflow-steps/workflow.ts +4 -2
- package/src/workflows/invoke-child.ts +1 -1
package/src/utils/bundler.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { createHash } from "node:crypto";
|
|
|
24
24
|
import { parse as babelParse } from "@babel/parser";
|
|
25
25
|
import type { File, ExportDefaultDeclaration, CallExpression, Expression, Statement } from "@babel/types";
|
|
26
26
|
import { importSourceModule } from "./source-loader.js";
|
|
27
|
-
import type { WorkflowMemoryConfig } from "../types/workflow.js";
|
|
27
|
+
import type { WorkflowMemoryConfig, SnapshotConfig } from "../types/workflow.js";
|
|
28
28
|
import type { SandboxNetworkPolicy } from "../sandbox.js";
|
|
29
29
|
import { isWorkflow } from "../workflow-steps/workflow.js";
|
|
30
30
|
import type { Workflow } from "../workflow-steps/types.js";
|
|
@@ -65,15 +65,20 @@ export interface BundledWorkflow {
|
|
|
65
65
|
manifest: WorkflowManifest;
|
|
66
66
|
networkPolicy?: SandboxNetworkPolicy;
|
|
67
67
|
placeholders?: Record<string, string>;
|
|
68
|
-
/**
|
|
69
|
-
*
|
|
70
|
-
|
|
71
|
-
snapshot?: string;
|
|
72
|
-
/** Default capture-on-success flag from the workflow definition. */
|
|
73
|
-
saveSnapshot?: boolean;
|
|
68
|
+
/** Snapshot config from the workflow definition — `bootFrom` (where to
|
|
69
|
+
* restore at run start), `save`, `retain`. */
|
|
70
|
+
snapshots?: SnapshotConfig;
|
|
74
71
|
workflowPlan: WorkflowPlan;
|
|
75
72
|
/** Workflow Memory extractor config. */
|
|
76
73
|
memory?: WorkflowMemoryConfig;
|
|
74
|
+
/** Ordered post-hook workflow names declared on the workflow. */
|
|
75
|
+
postRunHooks?: readonly string[];
|
|
76
|
+
/** Compact JSON-Schema-shaped description of the workflow's input
|
|
77
|
+
* type. Extracted from the workflow's declared `input` zod schema
|
|
78
|
+
* at bundle time; undefined when the schema is `z.unknown()`. */
|
|
79
|
+
inputSchema?: import("../types/workflow-metadata.js").IOSchema;
|
|
80
|
+
/** Same for the workflow's output zod schema. */
|
|
81
|
+
outputSchema?: import("../types/workflow-metadata.js").IOSchema;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
async function bundle(path: string, label: string): Promise<string> {
|
|
@@ -120,11 +125,19 @@ async function extractFromBundle<T>(
|
|
|
120
125
|
/**
|
|
121
126
|
* Bun bundles `import { defineWorkflow }` to a local identifier — usually
|
|
122
127
|
* the exact name, or a numeric suffix like `defineWorkflow2` to disambiguate
|
|
123
|
-
* scopes. Match exactly
|
|
128
|
+
* scopes. Match exactly those patterns, NOT `startsWith("defineWorkflow")` —
|
|
124
129
|
* the latter would also accept `defineWorkflowAttacker`. The runtime brand
|
|
125
130
|
* check is the second gate, but the syntactic check should be tight.
|
|
131
|
+
*
|
|
132
|
+
* `defineSandboxEnvironment` is sugar over `defineWorkflow` (see
|
|
133
|
+
* `src/types/sandbox-environment.ts`) and is explicitly registerable via
|
|
134
|
+
* `agentc register setup.ts --build` to capture a snapshot. The AST gate
|
|
135
|
+
* accepts it for the same reason it accepts `defineWorkflow`: the bundled
|
|
136
|
+
* default export is a CallExpression to a known SDK identifier, and the
|
|
137
|
+
* runtime brand check downstream catches anything that lies about being a
|
|
138
|
+
* workflow.
|
|
126
139
|
*/
|
|
127
|
-
const DEFINE_WORKFLOW_CALLEE = /^defineWorkflow\d*$/;
|
|
140
|
+
const DEFINE_WORKFLOW_CALLEE = /^(?:defineWorkflow|defineSandboxEnvironment)\d*$/;
|
|
128
141
|
|
|
129
142
|
function isDefineWorkflowCall(node: CallExpression): boolean {
|
|
130
143
|
if (node.callee.type === "Identifier") {
|
|
@@ -262,14 +275,76 @@ export async function bundleWorkflow(
|
|
|
262
275
|
bundlerVersion: BUNDLER_VERSION,
|
|
263
276
|
};
|
|
264
277
|
|
|
278
|
+
// Input + output schemas: the workflow's `input` / `output` zod
|
|
279
|
+
// schemas → compact JSON-Schema-shaped descriptions carried in
|
|
280
|
+
// template metadata. Used by the dashboard's "Registered" panel to
|
|
281
|
+
// render schema tables and (eventually) client-side validation in
|
|
282
|
+
// the playground. Run-form workflows stamp `z.unknown()` for both
|
|
283
|
+
// — `extractIOSchema` filters those down to undefined so the
|
|
284
|
+
// dashboard renders the "no declared schema" empty state instead
|
|
285
|
+
// of a meaningless empty table.
|
|
286
|
+
const inputSchema = extractIOSchema(workflow.input);
|
|
287
|
+
const outputSchema = extractIOSchema(workflow.output);
|
|
288
|
+
|
|
265
289
|
return {
|
|
266
290
|
source,
|
|
267
291
|
manifest,
|
|
268
292
|
workflowPlan: plan,
|
|
269
293
|
networkPolicy: overrides?.networkPolicy ?? metadata.networkPolicy,
|
|
270
294
|
placeholders: overrides?.placeholders ?? metadata.placeholders,
|
|
271
|
-
...(
|
|
272
|
-
...(
|
|
273
|
-
...(metadata.
|
|
295
|
+
...(inputSchema !== undefined ? { inputSchema } : {}),
|
|
296
|
+
...(outputSchema !== undefined ? { outputSchema } : {}),
|
|
297
|
+
...(metadata.snapshots !== undefined ? { snapshots: metadata.snapshots } : {}),
|
|
298
|
+
...(metadata.memory !== undefined ? { memory: metadata.memory } : {}),
|
|
299
|
+
...(metadata.postRunHooks !== undefined ? { postRunHooks: metadata.postRunHooks } : {}),
|
|
274
300
|
};
|
|
275
301
|
}
|
|
302
|
+
|
|
303
|
+
/** Convert a workflow's `input` or `output` zod schema into a compact,
|
|
304
|
+
* serialisable description for template metadata. Uses Zod 4's
|
|
305
|
+
* `toJSONSchema` and trims the result to fields the dashboard
|
|
306
|
+
* renders — full draft 2020-12 schemas have refs / unions / nested
|
|
307
|
+
* allOf chains that are noisier than the dashboard needs.
|
|
308
|
+
*
|
|
309
|
+
* Returns undefined when:
|
|
310
|
+
* - The schema can't be serialised (corrupt / unknown variant)
|
|
311
|
+
* - The schema is effectively `unknown` (the run-form sugar default —
|
|
312
|
+
* no meaningful contract to render). */
|
|
313
|
+
function extractIOSchema(
|
|
314
|
+
zodSchema: { _zod?: unknown } | unknown,
|
|
315
|
+
): import("../types/workflow-metadata.js").IOSchema | undefined {
|
|
316
|
+
// Late require to keep this module tree-shakeable for callers that
|
|
317
|
+
// don't bundle. `toJSONSchema` lives on the top-level Zod export in v4.
|
|
318
|
+
let json: Record<string, unknown> | undefined;
|
|
319
|
+
try {
|
|
320
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
|
321
|
+
const z = require("zod") as { toJSONSchema?: (s: unknown) => Record<string, unknown> };
|
|
322
|
+
if (!z.toJSONSchema) return undefined;
|
|
323
|
+
json = z.toJSONSchema(zodSchema);
|
|
324
|
+
} catch {
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
if (!json || typeof json !== "object") return undefined;
|
|
328
|
+
|
|
329
|
+
// `z.unknown()` serialises to `{}` (no type, no properties). Skip that
|
|
330
|
+
// — there's nothing useful to show.
|
|
331
|
+
if (Object.keys(json).filter((k) => k !== "$schema").length === 0) return undefined;
|
|
332
|
+
|
|
333
|
+
const out: import("../types/workflow-metadata.js").OutputSchema = {};
|
|
334
|
+
if (json.type !== undefined) out.type = json.type as string | string[];
|
|
335
|
+
if (json.description !== undefined) out.description = String(json.description);
|
|
336
|
+
if (json.properties && typeof json.properties === "object") {
|
|
337
|
+
const props: Record<string, { type?: string | string[]; description?: string }> = {};
|
|
338
|
+
for (const [key, raw] of Object.entries(json.properties as Record<string, unknown>)) {
|
|
339
|
+
if (raw && typeof raw === "object") {
|
|
340
|
+
const r = raw as Record<string, unknown>;
|
|
341
|
+
props[key] = {};
|
|
342
|
+
if (r.type !== undefined) props[key].type = r.type as string | string[];
|
|
343
|
+
if (r.description !== undefined) props[key].description = String(r.description);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (Object.keys(props).length > 0) out.properties = props;
|
|
347
|
+
}
|
|
348
|
+
if (Array.isArray(json.required)) out.required = json.required.map(String);
|
|
349
|
+
return out;
|
|
350
|
+
}
|
|
@@ -23,6 +23,7 @@ import type { z } from "zod";
|
|
|
23
23
|
import type { Step, Workflow } from "./types.js";
|
|
24
24
|
import { WORKFLOW_BRAND } from "./types.js";
|
|
25
25
|
import { extractMetadata } from "../types/workflow-metadata.js";
|
|
26
|
+
import type { SnapshotConfig, WorkflowMemoryConfig } from "../types/workflow-metadata.js";
|
|
26
27
|
import type { SandboxNetworkPolicy } from "../sandbox.js";
|
|
27
28
|
import type { Processor } from "../processors/processor.js";
|
|
28
29
|
|
|
@@ -46,8 +47,9 @@ export interface StepWorkflowDefinition<TInput, TOutput> {
|
|
|
46
47
|
output: z.ZodType<TOutput>;
|
|
47
48
|
networkPolicy?: SandboxNetworkPolicy;
|
|
48
49
|
placeholders?: Record<string, string>;
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
snapshots?: SnapshotConfig;
|
|
51
|
+
memory?: WorkflowMemoryConfig;
|
|
52
|
+
postRunHooks?: readonly string[];
|
|
51
53
|
processors?: readonly Processor[];
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -18,7 +18,7 @@ export function buildInvokeChild(
|
|
|
18
18
|
if (!baseUrl || !apiKey) {
|
|
19
19
|
throw new Error("ctx.invokeChild requires AGENT_COMPOSE_URL and AGENT_COMPOSE_API_KEY");
|
|
20
20
|
}
|
|
21
|
-
childClient = new AgentComposeClient(
|
|
21
|
+
childClient = new AgentComposeClient({ apiKey, baseUrl });
|
|
22
22
|
return childClient;
|
|
23
23
|
};
|
|
24
24
|
return (name, input, childOpts) => getChildClient().invokeAndWait(name, input, {
|