@barnum/barnum 0.0.0-main-45fcbab9 → 0.0.0-main-94079f39

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.
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -89,6 +89,10 @@
89
89
  "stepConfig": {
90
90
  "description": "Step configuration passed through to the handler. Rust stores this as-is and includes it in the envelope.",
91
91
  "default": null
92
+ },
93
+ "valueSchema": {
94
+ "description": "JSON Schema for this step's input value. Produced by JS from Zod. Used to validate transition values targeting this step.",
95
+ "default": null
92
96
  }
93
97
  }
94
98
  }
@@ -10,6 +10,7 @@ const ActionKind = z.discriminatedUnion("kind", [
10
10
  kind: z.literal("TypeScript"),
11
11
  path: z.string().describe("Path to the handler file (absolute — JS layer resolves before passing to Rust)."),
12
12
  stepConfig: z.any().optional().default(null).describe("Step configuration passed through to the handler. Rust stores this as-is and includes it in the envelope."),
13
+ valueSchema: z.any().optional().default(null).describe("JSON Schema for this step's input value. Produced by JS from Zod. Used to validate transition values targeting this step."),
13
14
  }).describe("Run a TypeScript handler."),
14
15
  ]).describe("How a step processes tasks.");
15
16
 
package/index.ts CHANGED
@@ -1,3 +1,8 @@
1
1
  export * from "./barnum-config-schema.zod.js";
2
2
  export * from "./barnum-cli-schema.zod.js";
3
3
  export { BarnumConfig, type RunOptions } from "./run.js";
4
+ export type {
5
+ HandlerDefinition,
6
+ HandlerContext,
7
+ FollowUpTask,
8
+ } from "./types.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barnum/barnum",
3
- "version": "0.0.0-main-45fcbab9",
3
+ "version": "0.0.0-main-94079f39",
4
4
  "type": "module",
5
5
  "description": "Barnum CLI - workflow engine for agents.",
6
6
  "main": "index.ts",
@@ -40,13 +40,15 @@
40
40
  "barnum-config-schema.zod.ts",
41
41
  "barnum-cli-schema.zod.ts",
42
42
  "run.ts",
43
+ "types.ts",
43
44
  "actions/**/*.ts"
44
45
  ],
45
46
  "scripts": {
46
47
  "typecheck": "tsc --noEmit"
47
48
  },
48
49
  "dependencies": {
49
- "zod": "^3.0.0"
50
+ "zod": "^3.0.0",
51
+ "zod-to-json-schema": "^3.25.1"
50
52
  },
51
53
  "devDependencies": {
52
54
  "@types/node": "^25.5.0",
package/run.ts CHANGED
@@ -4,7 +4,8 @@ import { createRequire } from "node:module";
4
4
  import { dirname, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { configSchema } from "./barnum-config-schema.zod.js";
7
- import type { z } from "zod";
7
+ import { z } from "zod";
8
+ import { zodToJsonSchema } from "zod-to-json-schema";
8
9
 
9
10
  const __dirname = dirname(fileURLToPath(import.meta.url));
10
11
  const require = createRequire(import.meta.url);
@@ -40,6 +41,67 @@ export interface RunOptions {
40
41
  cwd?: string;
41
42
  }
42
43
 
44
+ // ==================== Zod subset validation ====================
45
+
46
+ const UNSUPPORTED_ZOD_TYPES = new Set([
47
+ "ZodEffects", // .transform(), .refine(), .superRefine(), .preprocess()
48
+ "ZodPipeline", // .pipe()
49
+ "ZodBranded", // .brand()
50
+ ]);
51
+
52
+ function assertSerializableZod(schema: z.ZodType, stepName: string): void {
53
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
+ const def = (schema as any)._def;
55
+ if (!def) return;
56
+
57
+ const typeName: string | undefined = def.typeName;
58
+
59
+ if (typeName && UNSUPPORTED_ZOD_TYPES.has(typeName)) {
60
+ throw new Error(
61
+ `Step "${stepName}": Zod schema uses unsupported type "${typeName}". ` +
62
+ `Only JSON-Schema-representable types are allowed. ` +
63
+ `Remove .transform(), .refine(), .preprocess(), .pipe(), or .brand().`,
64
+ );
65
+ }
66
+
67
+ // Recurse into compound types
68
+ if (def.innerType) assertSerializableZod(def.innerType, stepName);
69
+ if (def.schema) assertSerializableZod(def.schema, stepName);
70
+ if (def.left) assertSerializableZod(def.left, stepName);
71
+ if (def.right) assertSerializableZod(def.right, stepName);
72
+
73
+ // z.object() — check each value
74
+ if (def.shape) {
75
+ const shape = typeof def.shape === "function" ? def.shape() : def.shape;
76
+ for (const value of Object.values(shape)) {
77
+ assertSerializableZod(value as z.ZodType, stepName);
78
+ }
79
+ }
80
+
81
+ // z.array(), z.set()
82
+ if (def.type) assertSerializableZod(def.type, stepName);
83
+
84
+ // z.union(), z.discriminatedUnion()
85
+ if (def.options) {
86
+ for (const option of def.options) {
87
+ assertSerializableZod(option as z.ZodType, stepName);
88
+ }
89
+ }
90
+
91
+ // z.tuple()
92
+ if (def.items) {
93
+ for (const item of def.items) {
94
+ assertSerializableZod(item as z.ZodType, stepName);
95
+ }
96
+ }
97
+
98
+ // z.record()
99
+ if (def.keyType) assertSerializableZod(def.keyType, stepName);
100
+ if (def.valueType) assertSerializableZod(def.valueType, stepName);
101
+ }
102
+
103
+ // ==================== BarnumConfig ====================
104
+
43
105
  export class BarnumConfig {
44
106
  private readonly config: z.output<typeof configSchema>;
45
107
 
@@ -51,11 +113,52 @@ export class BarnumConfig {
51
113
  return new BarnumConfig(configSchema.parse(config));
52
114
  }
53
115
 
54
- run(opts?: RunOptions): ChildProcess {
116
+ private async resolveConfig(): Promise<z.output<typeof configSchema>> {
117
+ const config = structuredClone(this.config);
118
+
119
+ for (const step of config.steps) {
120
+ if (step.action.kind !== "TypeScript") continue;
121
+ const action = step.action;
122
+
123
+ // Import the handler module
124
+ const mod = await import(action.path);
125
+ const handler = mod[action.exportedAs ?? "default"];
126
+
127
+ if (!handler?.stepConfigValidator || !handler?.getStepValueValidator) {
128
+ throw new Error(
129
+ `Step "${step.name}": handler at "${action.path}" is missing required ` +
130
+ `"stepConfigValidator" or "getStepValueValidator". ` +
131
+ `See HandlerDefinition interface.`,
132
+ );
133
+ }
134
+
135
+ // Validate step config
136
+ const parsedStepConfig = handler.stepConfigValidator.parse(
137
+ action.stepConfig ?? {},
138
+ );
139
+
140
+ // Get value validator
141
+ const valueValidator = handler.getStepValueValidator(parsedStepConfig);
142
+
143
+ // Reject non-serializable Zod features
144
+ assertSerializableZod(valueValidator, step.name);
145
+
146
+ // Convert Zod → JSON Schema and embed in config
147
+ action.valueSchema = zodToJsonSchema(valueValidator, {
148
+ target: "jsonSchema7",
149
+ });
150
+ }
151
+
152
+ return config;
153
+ }
154
+
155
+ async run(opts?: RunOptions): Promise<ChildProcess> {
156
+ const config = await this.resolveConfig();
55
157
  const args = opts?.resumeFrom
56
158
  ? ["run", "--resume-from", opts.resumeFrom]
57
- : ["run", "--config", JSON.stringify(this.config)];
58
- if (opts?.entrypointValue) args.push("--entrypoint-value", opts.entrypointValue);
159
+ : ["run", "--config", JSON.stringify(config)];
160
+ if (opts?.entrypointValue)
161
+ args.push("--entrypoint-value", opts.entrypointValue);
59
162
  if (opts?.logLevel) args.push("--log-level", opts.logLevel);
60
163
  if (opts?.logFile) args.push("--log-file", opts.logFile);
61
164
  if (opts?.stateLog) args.push("--state-log", opts.stateLog);
package/types.ts ADDED
@@ -0,0 +1,19 @@
1
+ import type { z } from "zod";
2
+
3
+ export interface HandlerDefinition<C = unknown, V = unknown> {
4
+ stepConfigValidator: z.ZodType<C>;
5
+ getStepValueValidator: (stepConfig: C) => z.ZodType<V>;
6
+ handle: (context: HandlerContext<C, V>) => Promise<FollowUpTask[]>;
7
+ }
8
+
9
+ export interface HandlerContext<C, V> {
10
+ stepConfig: C;
11
+ value: V;
12
+ config: unknown;
13
+ stepName: string;
14
+ }
15
+
16
+ export interface FollowUpTask {
17
+ kind: string;
18
+ value: unknown;
19
+ }