@clemrig/factory 0.0.0-stage → 0.1.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.
Files changed (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +198 -2
  3. package/dist/app/doctor.d.ts +20 -0
  4. package/dist/app/doctor.js +38 -0
  5. package/dist/app/doctor.js.map +1 -0
  6. package/dist/app/factory.d.ts +12 -0
  7. package/dist/app/factory.js +22 -0
  8. package/dist/app/factory.js.map +1 -0
  9. package/dist/app/init.d.ts +6 -0
  10. package/dist/app/init.js +15 -0
  11. package/dist/app/init.js.map +1 -0
  12. package/dist/app/run.d.ts +24 -0
  13. package/dist/app/run.js +100 -0
  14. package/dist/app/run.js.map +1 -0
  15. package/dist/app/runs.d.ts +36 -0
  16. package/dist/app/runs.js +66 -0
  17. package/dist/app/runs.js.map +1 -0
  18. package/dist/cli/application.d.ts +6 -0
  19. package/dist/cli/application.js +63 -0
  20. package/dist/cli/application.js.map +1 -0
  21. package/dist/cli/args.d.ts +12 -0
  22. package/dist/cli/args.js +45 -0
  23. package/dist/cli/args.js.map +1 -0
  24. package/dist/cli/doctor.d.ts +5 -0
  25. package/dist/cli/doctor.js +33 -0
  26. package/dist/cli/doctor.js.map +1 -0
  27. package/dist/cli/help.d.ts +1 -0
  28. package/dist/cli/help.js +17 -0
  29. package/dist/cli/help.js.map +1 -0
  30. package/dist/cli/init.d.ts +6 -0
  31. package/dist/cli/init.js +18 -0
  32. package/dist/cli/init.js.map +1 -0
  33. package/dist/cli/launcher.d.ts +5 -0
  34. package/dist/cli/launcher.js +55 -0
  35. package/dist/cli/launcher.js.map +1 -0
  36. package/dist/cli/reporter.d.ts +17 -0
  37. package/dist/cli/reporter.js +123 -0
  38. package/dist/cli/reporter.js.map +1 -0
  39. package/dist/cli/run.d.ts +9 -0
  40. package/dist/cli/run.js +39 -0
  41. package/dist/cli/run.js.map +1 -0
  42. package/dist/cli/status.d.ts +4 -0
  43. package/dist/cli/status.js +15 -0
  44. package/dist/cli/status.js.map +1 -0
  45. package/dist/cli/ui.d.ts +3 -0
  46. package/dist/cli/ui.js +18 -0
  47. package/dist/cli/ui.js.map +1 -0
  48. package/dist/engine/metrics.d.ts +45 -0
  49. package/dist/engine/metrics.js +60 -0
  50. package/dist/engine/metrics.js.map +1 -0
  51. package/dist/engine/primitives.d.ts +34 -0
  52. package/dist/engine/primitives.js +81 -0
  53. package/dist/engine/primitives.js.map +1 -0
  54. package/dist/engine/profiles.d.ts +53 -0
  55. package/dist/engine/profiles.js +117 -0
  56. package/dist/engine/profiles.js.map +1 -0
  57. package/dist/engine/runner.d.ts +13 -0
  58. package/dist/engine/runner.js +157 -0
  59. package/dist/engine/runner.js.map +1 -0
  60. package/dist/engine/types.d.ts +194 -0
  61. package/dist/engine/types.js +2 -0
  62. package/dist/engine/types.js.map +1 -0
  63. package/dist/engine/workflow.d.ts +18 -0
  64. package/dist/engine/workflow.js +196 -0
  65. package/dist/engine/workflow.js.map +1 -0
  66. package/dist/index.d.ts +10 -0
  67. package/dist/index.js +9 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/main.d.ts +2 -0
  70. package/dist/main.js +4 -0
  71. package/dist/main.js.map +1 -0
  72. package/dist/system/environment.d.ts +2 -0
  73. package/dist/system/environment.js +13 -0
  74. package/dist/system/environment.js.map +1 -0
  75. package/dist/system/factory.d.ts +16 -0
  76. package/dist/system/factory.js +62 -0
  77. package/dist/system/factory.js.map +1 -0
  78. package/dist/system/process.d.ts +21 -0
  79. package/dist/system/process.js +238 -0
  80. package/dist/system/process.js.map +1 -0
  81. package/dist/system/runtimes/adapter.d.ts +90 -0
  82. package/dist/system/runtimes/adapter.js +20 -0
  83. package/dist/system/runtimes/adapter.js.map +1 -0
  84. package/dist/system/runtimes/agent-runtime.d.ts +45 -0
  85. package/dist/system/runtimes/agent-runtime.js +184 -0
  86. package/dist/system/runtimes/agent-runtime.js.map +1 -0
  87. package/dist/system/runtimes/claude-code.d.ts +10 -0
  88. package/dist/system/runtimes/claude-code.js +383 -0
  89. package/dist/system/runtimes/claude-code.js.map +1 -0
  90. package/dist/system/runtimes/inspect.d.ts +25 -0
  91. package/dist/system/runtimes/inspect.js +129 -0
  92. package/dist/system/runtimes/inspect.js.map +1 -0
  93. package/dist/system/runtimes/pi.d.ts +7 -0
  94. package/dist/system/runtimes/pi.js +235 -0
  95. package/dist/system/runtimes/pi.js.map +1 -0
  96. package/dist/system/runtimes/protocol.d.ts +9 -0
  97. package/dist/system/runtimes/protocol.js +38 -0
  98. package/dist/system/runtimes/protocol.js.map +1 -0
  99. package/dist/system/runtimes/registry.d.ts +5 -0
  100. package/dist/system/runtimes/registry.js +5 -0
  101. package/dist/system/runtimes/registry.js.map +1 -0
  102. package/dist/system/store.d.ts +20 -0
  103. package/dist/system/store.js +126 -0
  104. package/dist/system/store.js.map +1 -0
  105. package/dist/system/templates.d.ts +8 -0
  106. package/dist/system/templates.js +30 -0
  107. package/dist/system/templates.js.map +1 -0
  108. package/dist/ui/server.d.ts +8 -0
  109. package/dist/ui/server.js +111 -0
  110. package/dist/ui/server.js.map +1 -0
  111. package/dist/ui/static/dashboard.js +266 -0
  112. package/dist/ui/static/follow.js +67 -0
  113. package/dist/ui/static/index.html +20 -0
  114. package/dist/ui/static/style.css +166 -0
  115. package/dist/ui/static/timeline.js +180 -0
  116. package/package.json +52 -4
  117. package/templates/init/factory.ts +4 -0
  118. package/templates/init/gitignore +3 -0
  119. package/templates/init/tsconfig.json +13 -0
  120. package/templates/init/workflows/ask/index.ts +57 -0
  121. package/templates/init/workflows/ask/prompts/answer.md +7 -0
@@ -0,0 +1,194 @@
1
+ import type { z } from "zod";
2
+ import type { AgentUsage, RunMetrics, TokenCounts } from "./metrics.js";
3
+ import type { AgentProfile, ResolvedProfile, Runtime } from "./profiles.js";
4
+ export type StageKind = "AGENT" | "CODE" | "GATE";
5
+ /** What an agent stage asks of the agent runtime. */
6
+ export interface AgentRequest {
7
+ /** The stage's profile as declared; the runtime validates it and applies its defaults. */
8
+ profile: AgentProfile;
9
+ /** Name of the prompt file the runtime appends to its system prompt. */
10
+ prompt: string;
11
+ /** The run-local conversation the request continues. */
12
+ session: string;
13
+ context: unknown;
14
+ schema: Record<string, unknown>;
15
+ }
16
+ /** Adds a message to the run journal: events.jsonl, terminal and --json. */
17
+ export type Log = (message: string, data?: Record<string, unknown>) => void;
18
+ /** What an agent call does, as its runtime reports it; never the messages themselves. */
19
+ export type AgentActivity = {
20
+ kind: "call";
21
+ status: "started";
22
+ runtime: Runtime;
23
+ model: string;
24
+ session: string;
25
+ } | {
26
+ kind: "call";
27
+ status: "completed" | "failed";
28
+ runtime: Runtime;
29
+ /** As the runtime announced it at the end of the call: the call's own, or its session's total. */
30
+ usage?: AgentUsage;
31
+ scope?: "call" | "session";
32
+ } | {
33
+ kind: "tool";
34
+ id: string;
35
+ name: string;
36
+ status: "started";
37
+ } | {
38
+ kind: "tool";
39
+ id: string;
40
+ name: string;
41
+ status: "completed" | "failed";
42
+ durationMs: number;
43
+ } | {
44
+ kind: "response";
45
+ tokens: TokenCounts;
46
+ costUsd?: number;
47
+ /** Reported while the call runs and replaced by the figures announced at its end. */
48
+ provisional: boolean;
49
+ } | {
50
+ kind: "warning";
51
+ message: string;
52
+ };
53
+ /** Records an agent call's activity under the calling stage. */
54
+ export type RecordActivity = (activity: AgentActivity) => void;
55
+ /** Agent execution managed by the core runtime; `record` journals its activity under the calling stage. */
56
+ export interface AgentPort {
57
+ execute(request: AgentRequest, record?: RecordActivity): Promise<unknown>;
58
+ }
59
+ export interface RunState {
60
+ /** 4 since workflows declare their inputs, agent profiles and retry maximums. */
61
+ version: 4;
62
+ id: string;
63
+ workflow: string;
64
+ /** Options validated by the workflow's input object. */
65
+ input: Record<string, unknown>;
66
+ stage: string;
67
+ status: "running" | "completed" | "failed";
68
+ /** Validated values written by the workflow's stages. */
69
+ data: Record<string, unknown>;
70
+ /** Owned by the engine: untrusted output of the last agent, cleared when a gate accepts. */
71
+ output?: unknown;
72
+ /** Owned by the engine: correction routed by the last retry edge, cleared when a gate accepts. */
73
+ feedback?: unknown;
74
+ /** Corrections taken per retry edge, keyed `<stage>.<outcome>`. */
75
+ retries?: Record<string, number>;
76
+ error?: string;
77
+ createdAt: string;
78
+ updatedAt: string;
79
+ metrics?: RunMetrics;
80
+ /** Each runtime the run used, with its version and connection, as checked before it started. */
81
+ runtimes?: Partial<Record<Runtime, string>>;
82
+ }
83
+ export interface WorkflowDecision {
84
+ verdict: "accepted" | "correction";
85
+ reason: string;
86
+ destination: string | null;
87
+ }
88
+ /** What a stage receives: its run, the agent runtime, the run journal and the repository. */
89
+ export interface StageContext {
90
+ state: Readonly<RunState>;
91
+ agent: AgentPort;
92
+ log: Log;
93
+ /** The repository the workflow works in: the directory that contains `.factory/`. */
94
+ dir: string;
95
+ }
96
+ /** A stage reports a named outcome; the workflow graph decides where it leads. */
97
+ export interface StageResult<O extends string = string> {
98
+ outcome: O;
99
+ /** Why this outcome was chosen; becomes the decision reason. */
100
+ reason?: string;
101
+ /** Correction carried by a retry edge to the next stage; defaults to the reason. */
102
+ feedback?: unknown;
103
+ /** Validated values merged into the run's data. */
104
+ data?: Record<string, unknown>;
105
+ /** Untrusted agent output, kept for the next gate. */
106
+ output?: unknown;
107
+ detail?: string;
108
+ }
109
+ /** What an agent stage declares, checked by `defineWorkflow`. */
110
+ export interface AgentDeclaration {
111
+ profile: AgentProfile;
112
+ /** Prompt file `prompts/<prompt>.md`; defaults to the stage name. */
113
+ prompt?: string;
114
+ /** Conversation name; defaults to the stage name. */
115
+ session?: string | ((state: Readonly<RunState>) => string);
116
+ }
117
+ export interface Stage<O extends string = string> {
118
+ kind: StageKind;
119
+ outcomes: readonly O[];
120
+ agent?: AgentDeclaration;
121
+ run: (context: StageContext) => Promise<StageResult<O>>;
122
+ }
123
+ /** A correction route, taken at most `max` times per run. */
124
+ export interface RetryEdge {
125
+ to: string;
126
+ max: number;
127
+ }
128
+ /** Next stage name, END (null) or a bounded correction route. */
129
+ export type Edge = string | null | RetryEdge;
130
+ export interface WorkflowNode<O extends string = string> {
131
+ stage: Stage<O>;
132
+ on: Record<O, Edge>;
133
+ }
134
+ /** What a workflow author writes: inputs, graph and an optional rendering. */
135
+ export interface WorkflowDefinition {
136
+ /** Also names the workflow's folder, which holds its `prompts/`. */
137
+ name: string;
138
+ /** Each field becomes a `--<name>` option of `factory run`. */
139
+ input?: z.ZodObject;
140
+ initial: string;
141
+ nodes: Record<string, WorkflowNode>;
142
+ /** Fails a run once its agents' announced cost exceeds it; `--max-cost-usd` replaces it for a run. */
143
+ maxCostUsd?: number;
144
+ /** Result lines; by default the run's validated data as JSON. */
145
+ presentResult?(state: Readonly<RunState>): string[];
146
+ }
147
+ /** An agent stage as `defineWorkflow` resolves it. */
148
+ export interface AgentStage {
149
+ profile: ResolvedProfile;
150
+ prompt: string;
151
+ }
152
+ /** A workflow validated by `defineWorkflow`. */
153
+ export interface Workflow extends WorkflowDefinition {
154
+ /** Agent stages by stage name. */
155
+ agents: Record<string, AgentStage>;
156
+ presentResult(state: Readonly<RunState>): string[];
157
+ }
158
+ export interface RetryContext {
159
+ /** The retry edge, `<stage>.<outcome>`. */
160
+ key: string;
161
+ count: number;
162
+ max: number;
163
+ }
164
+ interface EventBase {
165
+ runId: string;
166
+ stage: string;
167
+ kind: StageKind;
168
+ at: string;
169
+ }
170
+ /** Recorded by the engine when a stage starts and when it ends. */
171
+ export interface StageEvent extends EventBase {
172
+ type: "stage";
173
+ status: "started" | "passed" | "failed" | "completed";
174
+ retry?: RetryContext;
175
+ decision?: WorkflowDecision;
176
+ detail?: string;
177
+ }
178
+ /** Recorded by a stage, or by the agent runtime on its behalf, while it runs. */
179
+ export interface LogEvent extends EventBase {
180
+ type: "log";
181
+ message: string;
182
+ data?: Record<string, unknown>;
183
+ }
184
+ /** Recorded by the agent runtime for the calling stage while it runs. */
185
+ export interface AgentEvent extends EventBase {
186
+ type: "agent";
187
+ activity: AgentActivity;
188
+ }
189
+ export type RunEvent = StageEvent | LogEvent | AgentEvent;
190
+ export interface RunStore {
191
+ save(state: RunState): Promise<void>;
192
+ event(event: RunEvent): Promise<void>;
193
+ }
194
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+ import type { RunState, Workflow, WorkflowDefinition } from "./types.js";
3
+ /** True for a workflow returned by `defineWorkflow`. */
4
+ export declare function isWorkflow(value: unknown): value is Workflow;
5
+ /** By default a run shows its validated data, never raw agent output. */
6
+ export declare function presentData(state: Readonly<RunState>): string[];
7
+ /**
8
+ * Validates a workflow when it is declared: graph, retry maximums, loops, agent
9
+ * stages and inputs. Agent profiles are returned with their defaults applied.
10
+ */
11
+ export declare function defineWorkflow(definition: WorkflowDefinition): Workflow;
12
+ /** Whether a field takes an option given alone: a boolean, possibly optional or defaulted. */
13
+ export declare function isFlag(schema: z.ZodType): boolean;
14
+ /**
15
+ * Validates `factory run` options against the workflow's input object. An option
16
+ * given without a value is `true`, accepted only by a boolean field.
17
+ */
18
+ export declare function parseInput(workflow: Pick<Workflow, "name" | "input">, options: Record<string, string | boolean>): Record<string, unknown>;
@@ -0,0 +1,196 @@
1
+ import { z } from "zod";
2
+ import { profileSchema } from "./profiles.js";
3
+ /** Workflow and prompt names name files and directories. */
4
+ const FILE_NAME = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
5
+ /** A session name is a segment of session file names: it starts and ends alphanumeric. */
6
+ const SESSION = /^[a-zA-Z0-9](?:[a-zA-Z0-9_-]*[a-zA-Z0-9])?$/;
7
+ const OPTION = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
8
+ const GLOBAL_OPTIONS = ["json", "help", "max-cost-usd"];
9
+ const defined = new WeakSet();
10
+ /** True for a workflow returned by `defineWorkflow`. */
11
+ export function isWorkflow(value) {
12
+ return typeof value === "object" && value !== null && defined.has(value);
13
+ }
14
+ function graphProblems(definition) {
15
+ const { nodes, initial } = definition;
16
+ const problems = [];
17
+ const exists = (name) => Object.hasOwn(nodes, name);
18
+ if (!exists(initial))
19
+ problems.push(`initial stage ${initial} is not defined`);
20
+ for (const [name, node] of Object.entries(nodes)) {
21
+ // A correction counter is named `<stage>.<outcome>`.
22
+ if (name.includes("."))
23
+ problems.push(`stage ${name} must not contain "."`);
24
+ for (const outcome of node.stage.outcomes)
25
+ if (outcome.includes("."))
26
+ problems.push(`${name}: outcome ${outcome} must not contain "."`);
27
+ const routed = Object.keys(node.on);
28
+ for (const outcome of node.stage.outcomes)
29
+ if (!routed.includes(outcome))
30
+ problems.push(`${name}: outcome ${outcome} has no route`);
31
+ for (const outcome of routed) {
32
+ if (!node.stage.outcomes.includes(outcome))
33
+ problems.push(`${name}: route for unknown outcome ${outcome}`);
34
+ const edge = node.on[outcome];
35
+ if (edge === null || edge === undefined)
36
+ continue;
37
+ const target = typeof edge === "string" ? edge : edge.to;
38
+ if (!exists(target))
39
+ problems.push(`${name}.${outcome}: unknown target ${target}`);
40
+ if (typeof edge === "object" &&
41
+ !(Number.isInteger(edge.max) && edge.max >= 1 && edge.max <= 100))
42
+ problems.push(`${name}.${outcome}: retry maximum must be an integer from 1 to 100, got ${edge.max}`);
43
+ }
44
+ }
45
+ const loop = loopWithoutRetry(nodes);
46
+ if (loop)
47
+ problems.push(`loop without retry: ${loop.join(" → ")}`);
48
+ return problems;
49
+ }
50
+ /** A cycle of plain routes: nothing would bound how often it runs. */
51
+ function loopWithoutRetry(nodes) {
52
+ const done = new Set();
53
+ const path = [];
54
+ const visit = (name) => {
55
+ if (done.has(name))
56
+ return undefined;
57
+ const start = path.indexOf(name);
58
+ if (start >= 0)
59
+ return [...path.slice(start), name];
60
+ path.push(name);
61
+ for (const edge of Object.values(nodes[name]?.on ?? {}))
62
+ if (typeof edge === "string" && Object.hasOwn(nodes, edge)) {
63
+ const loop = visit(edge);
64
+ if (loop)
65
+ return loop;
66
+ }
67
+ path.pop();
68
+ done.add(name);
69
+ return undefined;
70
+ };
71
+ for (const name of Object.keys(nodes)) {
72
+ const loop = visit(name);
73
+ if (loop)
74
+ return loop;
75
+ }
76
+ return undefined;
77
+ }
78
+ /** Each agent stage: profile, prompt name and session name. */
79
+ function agentProblems(definition, agents) {
80
+ const problems = [];
81
+ /** Stages by fixed session name, to keep each conversation on one runtime. */
82
+ const sessions = new Map();
83
+ for (const [name, node] of Object.entries(definition.nodes)) {
84
+ const declared = node.stage.agent;
85
+ if (!declared)
86
+ continue;
87
+ const prompt = declared.prompt ?? name;
88
+ if (!FILE_NAME.test(prompt))
89
+ problems.push(`${name}: prompt name ${prompt} must be letters, digits, - or _`);
90
+ const { session } = declared;
91
+ if (typeof session !== "function" && !SESSION.test(session ?? name))
92
+ problems.push(`${name}: session ${session ?? `${name} (the stage name by default)`} must start and end with a letter or digit and contain only letters, digits, - or _`);
93
+ const parsed = profileSchema.safeParse(declared.profile);
94
+ if (!parsed.success) {
95
+ for (const issue of parsed.error.issues)
96
+ problems.push(`${name}.profile${issue.path.map((key) => `.${String(key)}`).join("")}: ${issue.message}`);
97
+ continue;
98
+ }
99
+ agents[name] = { profile: parsed.data, prompt };
100
+ if (typeof session !== "function") {
101
+ const fixed = session ?? name;
102
+ sessions.set(fixed, [...(sessions.get(fixed) ?? []), name]);
103
+ }
104
+ }
105
+ for (const [session, stages] of sessions) {
106
+ const runtimes = new Set(stages.map((stage) => agents[stage]?.profile.runtime));
107
+ if (runtimes.size > 1)
108
+ problems.push(`session ${session} is used by stages on different runtimes: ${stages.map((stage) => `${stage} (${agents[stage]?.profile.runtime})`).join(", ")}`);
109
+ }
110
+ return problems;
111
+ }
112
+ function inputProblems(input) {
113
+ if (input === undefined)
114
+ return [];
115
+ if (!(input instanceof z.ZodObject))
116
+ return ["input must be a z.object"];
117
+ return Object.keys(input.shape).flatMap((name) => GLOBAL_OPTIONS.includes(name)
118
+ ? [`input ${name} conflicts with the global --${name} option`]
119
+ : OPTION.test(name)
120
+ ? []
121
+ : [`input ${name} is not a valid option name`]);
122
+ }
123
+ /** By default a run shows its validated data, never raw agent output. */
124
+ export function presentData(state) {
125
+ return [JSON.stringify(state.data, null, 2)];
126
+ }
127
+ /**
128
+ * Validates a workflow when it is declared: graph, retry maximums, loops, agent
129
+ * stages and inputs. Agent profiles are returned with their defaults applied.
130
+ */
131
+ export function defineWorkflow(definition) {
132
+ if (!FILE_NAME.test(definition.name))
133
+ throw new Error(`Invalid workflow ${definition.name}: name must be letters, digits, - or _`);
134
+ const agents = {};
135
+ const { maxCostUsd } = definition;
136
+ const problems = [
137
+ ...(maxCostUsd === undefined ||
138
+ (typeof maxCostUsd === "number" &&
139
+ Number.isFinite(maxCostUsd) &&
140
+ maxCostUsd > 0)
141
+ ? []
142
+ : [
143
+ `maxCostUsd must be a positive number of USD, got ${String(maxCostUsd)}`,
144
+ ]),
145
+ ...graphProblems(definition),
146
+ ...agentProblems(definition, agents),
147
+ ...inputProblems(definition.input),
148
+ ];
149
+ if (problems.length)
150
+ throw new Error(`Invalid workflow ${definition.name}: ${problems.join("; ")}`);
151
+ const workflow = {
152
+ ...definition,
153
+ agents,
154
+ presentResult: definition.presentResult ?? presentData,
155
+ };
156
+ defined.add(workflow);
157
+ return workflow;
158
+ }
159
+ /** Whether a field takes an option given alone: a boolean, possibly optional or defaulted. */
160
+ export function isFlag(schema) {
161
+ let def = schema.def;
162
+ while (def.innerType &&
163
+ ["optional", "nullable", "default"].includes(def.type))
164
+ def = def.innerType.def;
165
+ return def.type === "boolean";
166
+ }
167
+ /**
168
+ * Validates `factory run` options against the workflow's input object. An option
169
+ * given without a value is `true`, accepted only by a boolean field.
170
+ */
171
+ export function parseInput(workflow, options) {
172
+ const input = workflow.input ?? z.object({});
173
+ const shape = input.shape;
174
+ const valueless = Object.keys(options).filter((name) => {
175
+ const field = Object.hasOwn(shape, name) ? shape[name] : undefined;
176
+ return options[name] === true && field !== undefined && !isFlag(field);
177
+ });
178
+ const given = Object.fromEntries(Object.entries(options).filter(([name]) => !valueless.includes(name)));
179
+ const parsed = input.strict().safeParse(given);
180
+ if (parsed.success && !valueless.length)
181
+ return parsed.data;
182
+ const issues = parsed.success ? [] : parsed.error.issues;
183
+ const problems = valueless.map((name) => `--${name}: missing value`);
184
+ problems.push(...issues.flatMap((issue) => {
185
+ if (issue.code === "unrecognized_keys")
186
+ return issue.keys.map((key) => `unknown option --${key}`);
187
+ const name = String(issue.path[0] ?? "");
188
+ if (valueless.includes(name))
189
+ return [];
190
+ return Object.hasOwn(options, name)
191
+ ? [`--${name}: ${issue.message}`]
192
+ : [`missing option --${name}`];
193
+ }));
194
+ throw new Error(`Invalid input for ${workflow.name}: ${problems.join("; ")}`);
195
+ }
196
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/engine/workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Public API for writing workflows. A repository's `.factory/` imports only this
3
+ * module; `z` is re-exported so workflows and the core share one Zod instance.
4
+ */
5
+ export { z } from "zod";
6
+ export type { AgentProfile } from "./engine/profiles.js";
7
+ export { agent, type Check, code, END, gate, node, pick, retry, schemaGate, step, } from "./engine/primitives.js";
8
+ export type { Log, RunState, Stage, StageContext, StageResult, WorkflowDefinition, } from "./engine/types.js";
9
+ export { defineWorkflow } from "./engine/workflow.js";
10
+ export { ProcessInterruptedError, runProcess } from "./system/process.js";
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Public API for writing workflows. A repository's `.factory/` imports only this
3
+ * module; `z` is re-exported so workflows and the core share one Zod instance.
4
+ */
5
+ export { z } from "zod";
6
+ export { agent, code, END, gate, node, pick, retry, schemaGate, step, } from "./engine/primitives.js";
7
+ export { defineWorkflow } from "./engine/workflow.js";
8
+ export { ProcessInterruptedError, runProcess } from "./system/process.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,KAAK,EAEL,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,UAAU,EACV,IAAI,GACL,MAAM,wBAAwB,CAAC;AAShC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { launch } from "./cli/launcher.js";
3
+ process.exitCode = await launch(process.argv.slice(2), process.cwd());
4
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ /** Optional `.factory/.env` secrets; existing shell variables retain precedence. */
2
+ export declare function loadLocalEnvironment(factoryDir: string): void;
@@ -0,0 +1,13 @@
1
+ import { join } from "node:path";
2
+ import { loadEnvFile } from "node:process";
3
+ /** Optional `.factory/.env` secrets; existing shell variables retain precedence. */
4
+ export function loadLocalEnvironment(factoryDir) {
5
+ try {
6
+ loadEnvFile(join(factoryDir, ".env"));
7
+ }
8
+ catch (error) {
9
+ if (error.code !== "ENOENT")
10
+ throw new Error(`Cannot load .env from ${factoryDir}`);
11
+ }
12
+ }
13
+ //# sourceMappingURL=environment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/system/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,oFAAoF;AACpF,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,IAAI,CAAC;QACH,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YACpD,MAAM,IAAI,KAAK,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { Workflow } from "../engine/types.js";
2
+ /** A repository's `.factory/`: its workflows, where they work and where runs are kept. */
3
+ export interface Factory {
4
+ /** The repository: the directory that contains `.factory/`. */
5
+ dir: string;
6
+ factoryDir: string;
7
+ runsDir: string;
8
+ workflows: Map<string, Workflow>;
9
+ }
10
+ /** A factory without workflows, to read runs when `factory.ts` cannot load. */
11
+ export declare function emptyFactory(factoryDir: string): Factory;
12
+ /** Imports `.factory/factory.ts`, whose default export lists the repository's workflows. */
13
+ export declare function loadFactory(factoryDir: string): Promise<Factory>;
14
+ export declare function workflowOf(factory: Factory, name: string): Workflow;
15
+ /** Reads `workflows/<workflow>/prompts/<name>.md` for each agent stage of the workflow, at every run. */
16
+ export declare function loadPrompts(factoryDir: string, workflow: Workflow): Promise<Record<string, string>>;
@@ -0,0 +1,62 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ import { isWorkflow } from "../engine/workflow.js";
5
+ /** A factory without workflows, to read runs when `factory.ts` cannot load. */
6
+ export function emptyFactory(factoryDir) {
7
+ return {
8
+ dir: dirname(factoryDir),
9
+ factoryDir,
10
+ runsDir: join(factoryDir, "runs"),
11
+ workflows: new Map(),
12
+ };
13
+ }
14
+ /** Imports `.factory/factory.ts`, whose default export lists the repository's workflows. */
15
+ export async function loadFactory(factoryDir) {
16
+ const module = (await import(pathToFileURL(join(factoryDir, "factory.ts")).href));
17
+ const exported = module.default;
18
+ if (!Array.isArray(exported))
19
+ throw new Error("factory.ts must export default an array of defineWorkflow(…) results");
20
+ const workflows = new Map();
21
+ for (const workflow of exported) {
22
+ if (!isWorkflow(workflow))
23
+ throw new Error("factory.ts must export default an array of defineWorkflow(…) results");
24
+ if (workflows.has(workflow.name))
25
+ throw new Error(`Duplicate workflow ${workflow.name} in factory.ts`);
26
+ workflows.set(workflow.name, workflow);
27
+ }
28
+ return { ...emptyFactory(factoryDir), workflows };
29
+ }
30
+ export function workflowOf(factory, name) {
31
+ const workflow = factory.workflows.get(name);
32
+ if (!workflow)
33
+ throw new Error(`Unknown workflow ${name}; workflows: ${[...factory.workflows.keys()].join(", ") || "none"}`);
34
+ return workflow;
35
+ }
36
+ /** Reads `workflows/<workflow>/prompts/<name>.md` for each agent stage of the workflow, at every run. */
37
+ export async function loadPrompts(factoryDir, workflow) {
38
+ const prompts = {};
39
+ const problems = [];
40
+ for (const { prompt: name } of Object.values(workflow.agents)) {
41
+ if (Object.hasOwn(prompts, name))
42
+ continue;
43
+ const file = join(factoryDir, "workflows", workflow.name, "prompts", `${name}.md`);
44
+ let text;
45
+ try {
46
+ text = await readFile(file, "utf8");
47
+ }
48
+ catch (error) {
49
+ if (error.code !== "ENOENT")
50
+ throw error;
51
+ problems.push(`Missing prompt: ${file}`);
52
+ continue;
53
+ }
54
+ if (!text.trim())
55
+ problems.push(`Empty prompt: ${file}`);
56
+ prompts[name] = text.trimEnd();
57
+ }
58
+ if (problems.length)
59
+ throw new Error(problems.join("; "));
60
+ return prompts;
61
+ }
62
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/system/factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare class ProcessStartError extends Error {
2
+ constructor(executable: string, cause: Error);
3
+ }
4
+ export declare class ProcessInterruptedError extends Error {
5
+ constructor(signal: NodeJS.Signals, executable: string);
6
+ }
7
+ /** Kills every running child's process group at once, before a forced exit. */
8
+ export declare function killProcessGroups(): void;
9
+ /** Runs `work` with `dir` as the process's working directory, then restores the previous one. */
10
+ export declare function inDirectory<T>(dir: string, work: () => Promise<T>): Promise<T>;
11
+ /**
12
+ * Runs an executable without a shell. A failure terminates the entire child group
13
+ * and settles only after the child closes and the TERM→KILL grace period finishes.
14
+ */
15
+ export declare function runProcess(command: string[], cwd: string, timeoutMs: number, onLine?: (line: string) => void, stdin?: string): Promise<{
16
+ exitCode: number;
17
+ stdout: string;
18
+ stderr: string;
19
+ stdoutTruncated: boolean;
20
+ stderrTruncated: boolean;
21
+ }>;