@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.
- package/LICENSE +21 -0
- package/README.md +187 -2
- package/dist/app/doctor.d.ts +18 -0
- package/dist/app/doctor.js +40 -0
- package/dist/app/doctor.js.map +1 -0
- package/dist/app/factory.d.ts +14 -0
- package/dist/app/factory.js +33 -0
- package/dist/app/factory.js.map +1 -0
- package/dist/app/init.d.ts +6 -0
- package/dist/app/init.js +15 -0
- package/dist/app/init.js.map +1 -0
- package/dist/app/options.d.ts +17 -0
- package/dist/app/options.js +78 -0
- package/dist/app/options.js.map +1 -0
- package/dist/app/run.d.ts +8 -0
- package/dist/app/run.js +29 -0
- package/dist/app/run.js.map +1 -0
- package/dist/app/runs.d.ts +4 -0
- package/dist/app/runs.js +6 -0
- package/dist/app/runs.js.map +1 -0
- package/dist/cli/application.d.ts +6 -0
- package/dist/cli/application.js +63 -0
- package/dist/cli/application.js.map +1 -0
- package/dist/cli/args.d.ts +12 -0
- package/dist/cli/args.js +45 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/doctor.d.ts +5 -0
- package/dist/cli/doctor.js +33 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/help.d.ts +1 -0
- package/dist/cli/help.js +17 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/init.d.ts +6 -0
- package/dist/cli/init.js +18 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/launcher.d.ts +5 -0
- package/dist/cli/launcher.js +55 -0
- package/dist/cli/launcher.js.map +1 -0
- package/dist/cli/reporter.d.ts +17 -0
- package/dist/cli/reporter.js +122 -0
- package/dist/cli/reporter.js.map +1 -0
- package/dist/cli/run.d.ts +5 -0
- package/dist/cli/run.js +52 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/status.d.ts +4 -0
- package/dist/cli/status.js +15 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/ui.d.ts +3 -0
- package/dist/cli/ui.js +25 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -0
- package/dist/system/environment.d.ts +2 -0
- package/dist/system/environment.js +13 -0
- package/dist/system/environment.js.map +1 -0
- package/dist/system/factory.d.ts +16 -0
- package/dist/system/factory.js +62 -0
- package/dist/system/factory.js.map +1 -0
- package/dist/system/templates.d.ts +8 -0
- package/dist/system/templates.js +30 -0
- package/dist/system/templates.js.map +1 -0
- package/package.json +42 -4
- package/templates/init/factory.ts +4 -0
- package/templates/init/gitignore +3 -0
- package/templates/init/tsconfig.json +13 -0
- package/templates/init/workflows/ask/index.ts +57 -0
- package/templates/init/workflows/ask/prompts/answer.md +7 -0
package/dist/cli/args.js
ADDED
|
@@ -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";
|
package/dist/cli/help.js
ADDED
|
@@ -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>;
|
package/dist/cli/init.js
ADDED
|
@@ -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,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>;
|
package/dist/cli/run.js
ADDED
|
@@ -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"}
|
package/dist/cli/ui.d.ts
ADDED
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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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
package/dist/main.js
ADDED
package/dist/main.js.map
ADDED
|
@@ -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,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>>;
|