@agent-compose/sdk 0.2.5 → 0.3.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.
@@ -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
- /** Run UUID, workflow name, or `name@version` referencing the snapshot
69
- * this workflow's runner boots from, if declared via the `snapshot`
70
- * field on `defineWorkflow`. */
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> {
@@ -270,14 +275,76 @@ export async function bundleWorkflow(
270
275
  bundlerVersion: BUNDLER_VERSION,
271
276
  };
272
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
+
273
289
  return {
274
290
  source,
275
291
  manifest,
276
292
  workflowPlan: plan,
277
293
  networkPolicy: overrides?.networkPolicy ?? metadata.networkPolicy,
278
294
  placeholders: overrides?.placeholders ?? metadata.placeholders,
279
- ...(metadata.snapshot !== undefined ? { snapshot: metadata.snapshot } : {}),
280
- ...(metadata.saveSnapshot !== undefined ? { saveSnapshot: metadata.saveSnapshot } : {}),
281
- ...(metadata.memory !== undefined ? { memory: metadata.memory } : {}),
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 } : {}),
282
300
  };
283
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
 
@@ -42,12 +43,16 @@ export interface WorkflowBuilder<TInput, TCurrent> {
42
43
 
43
44
  export interface StepWorkflowDefinition<TInput, TOutput> {
44
45
  id: string;
46
+ /** One-line, human-readable description of what this workflow does.
47
+ * Surfaced on the dashboard template tile + run page header. */
48
+ description?: string;
45
49
  input: z.ZodType<TInput>;
46
50
  output: z.ZodType<TOutput>;
47
51
  networkPolicy?: SandboxNetworkPolicy;
48
52
  placeholders?: Record<string, string>;
49
- snapshot?: string;
50
- saveSnapshot?: boolean;
53
+ snapshots?: SnapshotConfig;
54
+ memory?: WorkflowMemoryConfig;
55
+ postRunHooks?: readonly string[];
51
56
  processors?: readonly Processor[];
52
57
  }
53
58
 
@@ -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(baseUrl, apiKey);
21
+ childClient = new AgentComposeClient({ apiKey, baseUrl });
22
22
  return childClient;
23
23
  };
24
24
  return (name, input, childOpts) => getChildClient().invokeAndWait(name, input, {