@clemrig/factory 0.0.0-stage → 0.2.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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +187 -2
  3. package/dist/app/doctor.d.ts +18 -0
  4. package/dist/app/doctor.js +40 -0
  5. package/dist/app/doctor.js.map +1 -0
  6. package/dist/app/factory.d.ts +14 -0
  7. package/dist/app/factory.js +33 -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/options.d.ts +17 -0
  13. package/dist/app/options.js +78 -0
  14. package/dist/app/options.js.map +1 -0
  15. package/dist/app/run.d.ts +8 -0
  16. package/dist/app/run.js +29 -0
  17. package/dist/app/run.js.map +1 -0
  18. package/dist/app/runs.d.ts +4 -0
  19. package/dist/app/runs.js +6 -0
  20. package/dist/app/runs.js.map +1 -0
  21. package/dist/cli/application.d.ts +6 -0
  22. package/dist/cli/application.js +63 -0
  23. package/dist/cli/application.js.map +1 -0
  24. package/dist/cli/args.d.ts +12 -0
  25. package/dist/cli/args.js +45 -0
  26. package/dist/cli/args.js.map +1 -0
  27. package/dist/cli/doctor.d.ts +5 -0
  28. package/dist/cli/doctor.js +33 -0
  29. package/dist/cli/doctor.js.map +1 -0
  30. package/dist/cli/help.d.ts +1 -0
  31. package/dist/cli/help.js +17 -0
  32. package/dist/cli/help.js.map +1 -0
  33. package/dist/cli/init.d.ts +6 -0
  34. package/dist/cli/init.js +18 -0
  35. package/dist/cli/init.js.map +1 -0
  36. package/dist/cli/launcher.d.ts +5 -0
  37. package/dist/cli/launcher.js +55 -0
  38. package/dist/cli/launcher.js.map +1 -0
  39. package/dist/cli/reporter.d.ts +17 -0
  40. package/dist/cli/reporter.js +122 -0
  41. package/dist/cli/reporter.js.map +1 -0
  42. package/dist/cli/run.d.ts +5 -0
  43. package/dist/cli/run.js +52 -0
  44. package/dist/cli/run.js.map +1 -0
  45. package/dist/cli/status.d.ts +4 -0
  46. package/dist/cli/status.js +15 -0
  47. package/dist/cli/status.js.map +1 -0
  48. package/dist/cli/ui.d.ts +3 -0
  49. package/dist/cli/ui.js +25 -0
  50. package/dist/cli/ui.js.map +1 -0
  51. package/dist/index.d.ts +6 -0
  52. package/dist/index.js +7 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/main.d.ts +2 -0
  55. package/dist/main.js +4 -0
  56. package/dist/main.js.map +1 -0
  57. package/dist/system/environment.d.ts +2 -0
  58. package/dist/system/environment.js +13 -0
  59. package/dist/system/environment.js.map +1 -0
  60. package/dist/system/factory.d.ts +16 -0
  61. package/dist/system/factory.js +62 -0
  62. package/dist/system/factory.js.map +1 -0
  63. package/dist/system/templates.d.ts +8 -0
  64. package/dist/system/templates.js +30 -0
  65. package/dist/system/templates.js.map +1 -0
  66. package/package.json +42 -4
  67. package/templates/init/factory.ts +4 -0
  68. package/templates/init/gitignore +3 -0
  69. package/templates/init/tsconfig.json +13 -0
  70. package/templates/init/workflows/ask/index.ts +57 -0
  71. package/templates/init/workflows/ask/prompts/answer.md +7 -0
@@ -0,0 +1,45 @@
1
+ import { OPTION_NAME } from "../app/options.js";
2
+ /** `--name value`, or `--name` alone for true; --json and --help never take a value. */
3
+ export function parseArgs(argv) {
4
+ const positional = [];
5
+ const options = {};
6
+ let json = false;
7
+ let help = false;
8
+ for (let i = 0; i < argv.length; i++) {
9
+ const arg = argv[i] ?? "";
10
+ if (!arg.startsWith("--")) {
11
+ positional.push(arg);
12
+ continue;
13
+ }
14
+ const name = arg.slice(2);
15
+ if (name === "json")
16
+ json = true;
17
+ else if (name === "help")
18
+ help = true;
19
+ else {
20
+ if (!OPTION_NAME.test(name))
21
+ throw new Error(`Invalid option ${arg}`);
22
+ if (Object.hasOwn(options, name))
23
+ throw new Error(`Duplicate option ${arg}`);
24
+ const value = argv[i + 1];
25
+ options[name] =
26
+ value === undefined || value.startsWith("--") ? true : value;
27
+ if (options[name] !== true)
28
+ i++;
29
+ }
30
+ }
31
+ return {
32
+ command: positional.shift() ?? "help",
33
+ positional,
34
+ options,
35
+ json,
36
+ help,
37
+ };
38
+ }
39
+ /** Commands other than `run` take no option of their own. */
40
+ export function noOptions(args) {
41
+ const [name] = Object.keys(args.options);
42
+ if (name)
43
+ throw new Error(`Unknown option --${name} for ${args.command}`);
44
+ }
45
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../../src/cli/args.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAWhD,wFAAwF;AACxF,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,OAAO,GAAyB,EAAE,CAAC;IACzC,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,IAAI,KAAK,MAAM;YAAE,IAAI,GAAG,IAAI,CAAC;aAC5B,IAAI,IAAI,KAAK,MAAM;YAAE,IAAI,GAAG,IAAI,CAAC;aACjC,CAAC;YACJ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC;YACtE,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC;gBACX,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;YAC/D,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI;gBAAE,CAAC,EAAE,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO;QACL,OAAO,EAAE,UAAU,CAAC,KAAK,EAAE,IAAI,MAAM;QACrC,UAAU;QACV,OAAO;QACP,IAAI;QACJ,IAAI;KACL,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,SAAS,CAAC,IAAe;IACvC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Workflow } from "@clemrig/flow";
2
+ /** `factory run <name>` followed by the workflow's input options. */
3
+ export declare function usage(workflow: Workflow): string;
4
+ /** Node, the factory and its workflows' prompts, then each runtime in use; no provider request. */
5
+ export declare function doctor(factoryDir: string, json: boolean): Promise<number>;
@@ -0,0 +1,33 @@
1
+ import { diagnose } from "../app/doctor.js";
2
+ import { isFlag } from "../app/options.js";
3
+ /** `factory run <name>` followed by the workflow's input options. */
4
+ export function usage(workflow) {
5
+ const options = Object.entries(workflow.input?.shape ?? {}).map(([name, schema]) => {
6
+ const option = isFlag(schema) ? `--${name}` : `--${name} <value>`;
7
+ return schema.safeParse(undefined).success ? `[${option}]` : option;
8
+ });
9
+ return ["factory run", workflow.name, ...options].join(" ");
10
+ }
11
+ /** Node, the factory and its workflows' prompts, then each runtime in use; no provider request. */
12
+ export async function doctor(factoryDir, json) {
13
+ const { ok, node, factory, runtimes, problems, ...found } = await diagnose(factoryDir);
14
+ const workflows = {};
15
+ for (const { workflow, error } of found.workflows)
16
+ workflows[workflow.name] =
17
+ error === undefined
18
+ ? { ok: true, detail: `Workflow ${workflow.name}: ${usage(workflow)}` }
19
+ : { ok: false, detail: `Workflow ${workflow.name}: ${error}` };
20
+ if (json) {
21
+ process.stdout.write(`${JSON.stringify({ ok, node, factory, workflows, runtimes, problems })}\n`);
22
+ return ok ? 0 : 1;
23
+ }
24
+ const line = (check, text = check.detail) => `${check.ok ? "✓" : "✗"} ${text}`;
25
+ const lines = [
26
+ ...[node, factory, ...Object.values(workflows)].map((check) => line(check)),
27
+ ...Object.values(runtimes).map((check) => line(check)),
28
+ ...problems.map(({ stage, runtime, reason }) => `✗ ${stage} (${runtime}): ${reason}`),
29
+ ];
30
+ process.stdout.write(`${lines.join("\n")}\n`);
31
+ return ok ? 0 : 1;
32
+ }
33
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const help = "factory \u2014 workflows written in this repository's .factory/\n\n factory init create .factory/ here and install it\n factory doctor [--json] check Node, workflows, prompts and runtimes\n factory run WORKFLOW [--INPUT VALUE\u2026] [--max-cost-usd USD] [--json]\n factory status [RUN_ID] [--json] list this repository's runs, or show one\n factory ui [--port N] serve a live read-only dashboard on 127.0.0.1\n\nCommands other than init and help use the nearest .factory/ in the current directory\nor a parent, with the factory version installed there. factory doctor lists each\nworkflow's input options. .factory/.env is loaded; shell variables take precedence.\n--max-cost-usd fails the run once its agents' announced cost exceeds it, instead\nof the workflow's maxCostUsd. --json writes events, then the result, as JSON lines.\nCtrl-C stops a run, which ends failed; press it again to quit at once.\nExit codes: 0 completed, 1 error or failed run, 130 second Ctrl-C.\n";
@@ -0,0 +1,17 @@
1
+ export const help = `factory — workflows written in this repository's .factory/
2
+
3
+ factory init create .factory/ here and install it
4
+ factory doctor [--json] check Node, workflows, prompts and runtimes
5
+ factory run WORKFLOW [--INPUT VALUE…] [--max-cost-usd USD] [--json]
6
+ factory status [RUN_ID] [--json] list this repository's runs, or show one
7
+ factory ui [--port N] serve a live read-only dashboard on 127.0.0.1
8
+
9
+ Commands other than init and help use the nearest .factory/ in the current directory
10
+ or a parent, with the factory version installed there. factory doctor lists each
11
+ workflow's input options. .factory/.env is loaded; shell variables take precedence.
12
+ --max-cost-usd fails the run once its agents' announced cost exceeds it, instead
13
+ of the workflow's maxCostUsd. --json writes events, then the result, as JSON lines.
14
+ Ctrl-C stops a run, which ends failed; press it again to quit at once.
15
+ Exit codes: 0 completed, 1 error or failed run, 130 second Ctrl-C.
16
+ `;
17
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;CAenB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `factory init`: creates `.factory/` in `cwd` from the templates, pinned to this
3
+ * factory version, then installs it. An existing `.factory/` is refused untouched;
4
+ * a failed installation keeps the files.
5
+ */
6
+ export declare function init(cwd: string): Promise<number>;
@@ -0,0 +1,18 @@
1
+ import { createFactory, installFactory } from "../app/init.js";
2
+ /**
3
+ * `factory init`: creates `.factory/` in `cwd` from the templates, pinned to this
4
+ * factory version, then installs it. An existing `.factory/` is refused untouched;
5
+ * a failed installation keeps the files.
6
+ */
7
+ export async function init(cwd) {
8
+ const { factoryDir, version } = await createFactory(cwd);
9
+ process.stdout.write(`Created ${factoryDir}; installing @clemrig/factory ${version}…\n`);
10
+ const install = await installFactory(factoryDir);
11
+ if (!install.ok) {
12
+ process.stderr.write(`${install.output}\n`);
13
+ throw new Error("Installation failed; .factory/ is kept: run npm install --prefix .factory");
14
+ }
15
+ process.stdout.write('Next: commit .factory/, run factory doctor, then factory run ask --question "What changed recently?"\n');
16
+ return 0;
17
+ }
18
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,GAAW;IACpC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,WAAW,UAAU,iCAAiC,OAAO,KAAK,CACnE,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wGAAwG,CACzG,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * The global `factory`: help and init run here; any other command runs with the
3
+ * factory version installed in the repository's `.factory/`.
4
+ */
5
+ export declare function launch(argv: string[], cwd: string): Promise<number>;
@@ -0,0 +1,55 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { dirname, join, relative } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { help } from "./help.js";
6
+ import { init } from "./init.js";
7
+ /** The nearest `.factory/` holding a package.json, in `cwd` or a parent. */
8
+ function findFactory(cwd) {
9
+ for (let dir = cwd;; dir = dirname(dir)) {
10
+ const factoryDir = join(dir, ".factory");
11
+ if (existsSync(join(factoryDir, "package.json")))
12
+ return factoryDir;
13
+ if (dirname(dir) === dir)
14
+ return undefined;
15
+ }
16
+ }
17
+ /**
18
+ * The `main` entry of the factory installed in `.factory/`. Node's resolution also
19
+ * searches parent `node_modules`: a factory found there is never used.
20
+ */
21
+ function installedCore(factoryDir, cwd) {
22
+ if (!existsSync(join(factoryDir, "node_modules", "@clemrig", "factory", "package.json"))) {
23
+ const lock = existsSync(join(factoryDir, "package-lock.json"));
24
+ throw new Error(`The factory is not installed in ${factoryDir}; run npm ${lock ? "ci" : "install"} --prefix ${relative(cwd, factoryDir)}`);
25
+ }
26
+ return createRequire(join(factoryDir, "package.json")).resolve("@clemrig/factory/cli");
27
+ }
28
+ /**
29
+ * The global `factory`: help and init run here; any other command runs with the
30
+ * factory version installed in the repository's `.factory/`.
31
+ */
32
+ export async function launch(argv, cwd) {
33
+ try {
34
+ const [command] = argv;
35
+ if (command === undefined || command === "help" || command === "--help") {
36
+ process.stdout.write(help);
37
+ return 0;
38
+ }
39
+ if (command === "init") {
40
+ if (argv.length > 1)
41
+ throw new Error("factory init takes no argument");
42
+ return await init(cwd);
43
+ }
44
+ const factoryDir = findFactory(cwd);
45
+ if (!factoryDir || !statSync(factoryDir).isDirectory())
46
+ throw new Error(`No .factory/ found in ${cwd} or its parents; run factory init at the root of your repository`);
47
+ const { main } = (await import(pathToFileURL(installedCore(factoryDir, cwd)).href));
48
+ return await main(argv, factoryDir);
49
+ }
50
+ catch (error) {
51
+ process.stderr.write(`factory: ${error instanceof Error ? error.message : String(error)}\n`);
52
+ return 1;
53
+ }
54
+ }
55
+ //# sourceMappingURL=launcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../src/cli/launcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type RunEvent, type RunState } from "@clemrig/flow";
2
+ /** The run's duration, then its agents' tokens and estimated cost. */
3
+ export declare function metricsSummary(state: RunState, now?: number): string[];
4
+ /** Stage events and journal on stderr; results on stdout; JSON lines on stdout with --json. */
5
+ export declare class TerminalReporter {
6
+ #private;
7
+ constructor(
8
+ /** The result lines of a run's workflow. */
9
+ present: (state: Readonly<RunState>) => string[], json?: boolean);
10
+ event: (event: RunEvent) => void;
11
+ /** A runtime the run uses, with its version and connection; --json output stays events only. */
12
+ runtime: (detail: string) => void;
13
+ /** A line under the current stage: journal messages, agent activity and runtimes. */
14
+ detail: (message: string) => void;
15
+ unreadable(runId: string, message: string): void;
16
+ result(state: RunState): void;
17
+ }
@@ -0,0 +1,122 @@
1
+ import { elapsedMs, runtimeLabels, } from "@clemrig/flow";
2
+ function duration(ms) {
3
+ const seconds = Math.max(0, Math.floor(ms / 1000));
4
+ const hours = Math.floor(seconds / 3600);
5
+ const minutes = Math.floor((seconds % 3600) / 60);
6
+ return `${hours ? `${hours} h ` : ""}${minutes} min ${seconds % 60} s`;
7
+ }
8
+ /** The run's duration, then its agents' tokens and estimated cost. */
9
+ export function metricsSummary(state, now = Date.now()) {
10
+ const elapsed = elapsedMs(state, now);
11
+ const usage = state.metrics?.usage;
12
+ const count = (n) => n.toLocaleString("en-US");
13
+ return [
14
+ `Duration: ${elapsed === null ? "unavailable" : duration(elapsed)}`,
15
+ !usage
16
+ ? "Agents: unavailable"
17
+ : usage.responses
18
+ ? `Agents: ${count(usage.input)} input · ${count(usage.output)} output · ${count(usage.cacheRead)} cache read · ${count(usage.cacheWrite)} cache write tokens · estimated cost ${usage.costUsd.toFixed(6)} USD${usage.missing ? " (partial)" : ""}`
19
+ : `Agents: ${usage.missing ? "unavailable (partial)" : "no measured call"}`,
20
+ ];
21
+ }
22
+ const icons = { started: "→", passed: "✓", failed: "✗", completed: "✓" };
23
+ const inSeconds = (ms) => `${(ms / 1000).toFixed(1)} s`;
24
+ /** An agent call's start and end, its finished tools and its warnings; not each response. */
25
+ function activityLine(activity) {
26
+ switch (activity.kind) {
27
+ case "call":
28
+ return activity.status === "started"
29
+ ? `${runtimeLabels[activity.runtime]} started with ${activity.model}`
30
+ : `${runtimeLabels[activity.runtime]} ${activity.status}`;
31
+ case "tool":
32
+ return activity.status === "started"
33
+ ? undefined
34
+ : activity.status === "failed"
35
+ ? `${activity.name} failed after ${inSeconds(activity.durationMs)}`
36
+ : `${activity.name} ${inSeconds(activity.durationMs)}`;
37
+ case "warning":
38
+ return activity.message;
39
+ default:
40
+ return undefined;
41
+ }
42
+ }
43
+ /** Stage events and journal on stderr; results on stdout; JSON lines on stdout with --json. */
44
+ export class TerminalReporter {
45
+ #present;
46
+ #json;
47
+ constructor(
48
+ /** The result lines of a run's workflow. */
49
+ present, json = false) {
50
+ this.#present = present;
51
+ this.#json = json;
52
+ }
53
+ event = (event) => {
54
+ if (this.#json) {
55
+ process.stdout.write(`${JSON.stringify(event)}\n`);
56
+ return;
57
+ }
58
+ if (event.type === "log") {
59
+ this.detail(event.message);
60
+ return;
61
+ }
62
+ if (event.type === "agent") {
63
+ const line = activityLine(event.activity);
64
+ if (line)
65
+ this.detail(line);
66
+ return;
67
+ }
68
+ const correction = event.decision?.verdict === "correction";
69
+ const icon = correction && event.status !== "failed" ? "↻" : icons[event.status];
70
+ const color = process.stderr.isTTY && !process.env.NO_COLOR
71
+ ? event.status === "failed"
72
+ ? "\x1b[31m"
73
+ : correction
74
+ ? "\x1b[33m"
75
+ : event.status === "started"
76
+ ? "\x1b[36m"
77
+ : "\x1b[32m"
78
+ : "";
79
+ const label = event.decision
80
+ ? `${event.decision.verdict}${event.status === "failed" ? " · failed" : ""}`
81
+ : event.status;
82
+ const reasonInDetail = event.decision && event.detail?.includes(event.decision.reason);
83
+ const decision = event.decision
84
+ ? `${reasonInDetail ? "" : ` — ${event.decision.reason}`} → ${event.decision.destination ?? "end"}`
85
+ : "";
86
+ const retry = event.retry
87
+ ? ` [${event.retry.key} ${event.retry.count}/${event.retry.max}]`
88
+ : "";
89
+ process.stderr.write(`${color}${icon} ${event.kind.padEnd(6)} ${event.stage.padEnd(24)} ${label}${color ? "\x1b[0m" : ""}${decision}${retry}${event.detail ? ` — ${event.detail}` : ""}\n`);
90
+ };
91
+ /** A runtime the run uses, with its version and connection; --json output stays events only. */
92
+ runtime = (detail) => {
93
+ if (!this.#json)
94
+ this.detail(detail);
95
+ };
96
+ /** A line under the current stage: journal messages, agent activity and runtimes. */
97
+ detail = (message) => {
98
+ process.stderr.write(` · ${message}\n`);
99
+ };
100
+ unreadable(runId, message) {
101
+ if (this.#json)
102
+ process.stdout.write(`${JSON.stringify({ type: "unreadable", runId, error: message })}\n`);
103
+ else
104
+ process.stdout.write(`\n${runId} · unreadable\n${message}\n`);
105
+ }
106
+ result(state) {
107
+ if (this.#json) {
108
+ process.stdout.write(`${JSON.stringify({ type: "result", state, elapsedMs: elapsedMs(state) })}\n`);
109
+ return;
110
+ }
111
+ const lines = [
112
+ "",
113
+ `${state.workflow} · ${state.id} · ${state.status}`,
114
+ ...(state.error ? [state.error] : []),
115
+ ...metricsSummary(state),
116
+ ...Object.values(state.runtimes ?? {}).map((runtime) => `Runtime: ${runtime}`),
117
+ ...this.#present(state),
118
+ ];
119
+ process.stdout.write(`${lines.join("\n")}\n`);
120
+ }
121
+ }
122
+ //# sourceMappingURL=reporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reporter.js","sourceRoot":"","sources":["../../src/cli/reporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Factory } from "../app/factory.js";
2
+ import type { Arguments } from "./args.js";
3
+ import type { TerminalReporter } from "./reporter.js";
4
+ /** `factory run`: the run executes in the foreground, with the repository as the current directory. */
5
+ export declare function run(factory: Factory, args: Arguments, reporter: TerminalReporter): Promise<number>;
@@ -0,0 +1,52 @@
1
+ import { killChildProcesses } from "@clemrig/flow";
2
+ import { startRun } from "../app/run.js";
3
+ /**
4
+ * Starts the run and waits for its end. The first SIGINT or SIGTERM stops it
5
+ * before its next stage (child processes are stopped at once); a second one
6
+ * kills the child process groups and exits with 130.
7
+ */
8
+ async function execute(factory, name, options, reporter) {
9
+ const started = await startRun(factory, name, options, {
10
+ onEvent: reporter.event,
11
+ });
12
+ for (const runtime of started.runtimes)
13
+ reporter.runtime(runtime.detail);
14
+ let interrupted = false;
15
+ const interrupt = (signal) => {
16
+ if (interrupted) {
17
+ killChildProcesses();
18
+ process.exit(130);
19
+ }
20
+ interrupted = true;
21
+ reporter.detail(`${signal} received: stopping the run; press Ctrl-C again to quit at once`);
22
+ started.stop(new Error(`Run interrupted by ${signal}`));
23
+ };
24
+ process.on("SIGINT", interrupt);
25
+ process.on("SIGTERM", interrupt);
26
+ try {
27
+ return await started.done;
28
+ }
29
+ finally {
30
+ process.off("SIGINT", interrupt);
31
+ process.off("SIGTERM", interrupt);
32
+ }
33
+ }
34
+ /** `factory run`: the run executes in the foreground, with the repository as the current directory. */
35
+ export async function run(factory, args, reporter) {
36
+ const name = args.positional[0];
37
+ if (!name)
38
+ throw new Error(`Usage: factory run WORKFLOW [--INPUT VALUE…]; workflows: ${[...factory.workflows.keys()].join(", ") || "none"}`);
39
+ // Relative paths in workflow code resolve in the repository, wherever the command was started.
40
+ const previous = process.cwd();
41
+ process.chdir(factory.dir);
42
+ let state;
43
+ try {
44
+ state = await execute(factory, name, args.options, reporter);
45
+ }
46
+ finally {
47
+ process.chdir(previous);
48
+ }
49
+ reporter.result(state);
50
+ return state.status === "completed" ? 0 : 1;
51
+ }
52
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAiB,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC;;;;GAIG;AACH,KAAK,UAAU,OAAO,CACpB,OAAgB,EAChB,IAAY,EACZ,OAA6B,EAC7B,QAA0B;IAE1B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE;QACrD,OAAO,EAAE,QAAQ,CAAC,KAAK;KACxB,CAAC,CAAC;IACH,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ;QAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACzE,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,MAAM,SAAS,GAAG,CAAC,MAAsB,EAAE,EAAE;QAC3C,IAAI,WAAW,EAAE,CAAC;YAChB,kBAAkB,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QACD,WAAW,GAAG,IAAI,CAAC;QACnB,QAAQ,CAAC,MAAM,CACb,GAAG,MAAM,iEAAiE,CAC3E,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC;IAC5B,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED,uGAAuG;AACvG,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,OAAgB,EAChB,IAAe,EACf,QAA0B;IAE1B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI;QACP,MAAM,IAAI,KAAK,CACb,4DAA4D,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CACjH,CAAC;IACJ,+FAA+F;IAC/F,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC/D,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IACD,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Factory } from "../app/factory.js";
2
+ import type { TerminalReporter } from "./reporter.js";
3
+ /** Every run of the repository, or one run. */
4
+ export declare function status(factory: Factory, reporter: TerminalReporter, runId: string | undefined): Promise<number>;
@@ -0,0 +1,15 @@
1
+ import { listRuns, loadRun } from "@clemrig/flow";
2
+ /** Every run of the repository, or one run. */
3
+ export async function status(factory, reporter, runId) {
4
+ if (runId) {
5
+ reporter.result(await loadRun(factory.runsDir, runId));
6
+ return 0;
7
+ }
8
+ for (const entry of await listRuns(factory.runsDir))
9
+ if ("state" in entry)
10
+ reporter.result(entry.state);
11
+ else
12
+ reporter.unreadable(entry.id, entry.error);
13
+ return 0;
14
+ }
15
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAIlD,+CAA+C;AAC/C,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAAgB,EAChB,QAA0B,EAC1B,KAAyB;IAEzB,IAAI,KAAK,EAAE,CAAC;QACV,QAAQ,CAAC,MAAM,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;QACjD,IAAI,OAAO,IAAI,KAAK;YAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;;YAC9C,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAClD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Factory } from "../app/factory.js";
2
+ /** `factory ui`: serves the dashboard of the repository's runs until Ctrl-C, on `port` or one the system chooses. */
3
+ export declare function ui(factory: Factory, port?: number): Promise<number>;
package/dist/cli/ui.js ADDED
@@ -0,0 +1,25 @@
1
+ import { basename } from "node:path";
2
+ import { startDashboard } from "@clemrig/flow-ui";
3
+ import { presentResult } from "../app/runs.js";
4
+ /** `factory ui`: serves the dashboard of the repository's runs until Ctrl-C, on `port` or one the system chooses. */
5
+ export async function ui(factory, port) {
6
+ const dashboard = await startDashboard({
7
+ runsDir: factory.runsDir,
8
+ title: "factory",
9
+ label: basename(factory.dir),
10
+ presentResult: (state) => presentResult(factory, state),
11
+ }, port);
12
+ process.stdout.write(`factory ui: ${dashboard.url} (read-only; Ctrl-C to stop)\n`);
13
+ await new Promise((resolve) => {
14
+ const stop = () => {
15
+ process.off("SIGINT", stop);
16
+ process.off("SIGTERM", stop);
17
+ resolve();
18
+ };
19
+ process.on("SIGINT", stop);
20
+ process.on("SIGTERM", stop);
21
+ });
22
+ await dashboard.close();
23
+ return 0;
24
+ }
25
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,qHAAqH;AACrH,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,OAAgB,EAAE,IAAa;IACtD,MAAM,SAAS,GAAG,MAAM,cAAc,CACpC;QACE,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC;QAC5B,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC;KACxD,EACD,IAAI,CACL,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,eAAe,SAAS,CAAC,GAAG,gCAAgC,CAC7D,CAAC;IACF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Public API for writing workflows. A repository's `.factory/` imports only this
3
+ * module; it re-exports the engine's, `z` included, so that workflows, the
4
+ * factory and the engine share one Zod instance.
5
+ */
6
+ export { type AgentProfile, agent, type Check, code, defineWorkflow, END, gate, type Log, node, ProcessInterruptedError, pick, type RunState, retry, runProcess, type Stage, type StageContext, type StageResult, schemaGate, step, type WorkflowDefinition, z, } from "@clemrig/flow";
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Public API for writing workflows. A repository's `.factory/` imports only this
3
+ * module; it re-exports the engine's, `z` included, so that workflows, the
4
+ * factory and the engine share one Zod instance.
5
+ */
6
+ export { agent, code, defineWorkflow, END, gate, node, ProcessInterruptedError, pick, retry, runProcess, schemaGate, step, z, } from "@clemrig/flow";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,KAAK,EAEL,IAAI,EACJ,cAAc,EACd,GAAG,EACH,IAAI,EAEJ,IAAI,EACJ,uBAAuB,EACvB,IAAI,EAEJ,KAAK,EACL,UAAU,EAIV,UAAU,EACV,IAAI,EAEJ,CAAC,GACF,MAAM,eAAe,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 "@clemrig/flow";
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>>;