@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.
- package/LICENSE +21 -0
- package/README.md +198 -2
- package/dist/app/doctor.d.ts +20 -0
- package/dist/app/doctor.js +38 -0
- package/dist/app/doctor.js.map +1 -0
- package/dist/app/factory.d.ts +12 -0
- package/dist/app/factory.js +22 -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/run.d.ts +24 -0
- package/dist/app/run.js +100 -0
- package/dist/app/run.js.map +1 -0
- package/dist/app/runs.d.ts +36 -0
- package/dist/app/runs.js +66 -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 +123 -0
- package/dist/cli/reporter.js.map +1 -0
- package/dist/cli/run.d.ts +9 -0
- package/dist/cli/run.js +39 -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 +18 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/engine/metrics.d.ts +45 -0
- package/dist/engine/metrics.js +60 -0
- package/dist/engine/metrics.js.map +1 -0
- package/dist/engine/primitives.d.ts +34 -0
- package/dist/engine/primitives.js +81 -0
- package/dist/engine/primitives.js.map +1 -0
- package/dist/engine/profiles.d.ts +53 -0
- package/dist/engine/profiles.js +117 -0
- package/dist/engine/profiles.js.map +1 -0
- package/dist/engine/runner.d.ts +13 -0
- package/dist/engine/runner.js +157 -0
- package/dist/engine/runner.js.map +1 -0
- package/dist/engine/types.d.ts +194 -0
- package/dist/engine/types.js +2 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/engine/workflow.d.ts +18 -0
- package/dist/engine/workflow.js +196 -0
- package/dist/engine/workflow.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +9 -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/process.d.ts +21 -0
- package/dist/system/process.js +238 -0
- package/dist/system/process.js.map +1 -0
- package/dist/system/runtimes/adapter.d.ts +90 -0
- package/dist/system/runtimes/adapter.js +20 -0
- package/dist/system/runtimes/adapter.js.map +1 -0
- package/dist/system/runtimes/agent-runtime.d.ts +45 -0
- package/dist/system/runtimes/agent-runtime.js +184 -0
- package/dist/system/runtimes/agent-runtime.js.map +1 -0
- package/dist/system/runtimes/claude-code.d.ts +10 -0
- package/dist/system/runtimes/claude-code.js +383 -0
- package/dist/system/runtimes/claude-code.js.map +1 -0
- package/dist/system/runtimes/inspect.d.ts +25 -0
- package/dist/system/runtimes/inspect.js +129 -0
- package/dist/system/runtimes/inspect.js.map +1 -0
- package/dist/system/runtimes/pi.d.ts +7 -0
- package/dist/system/runtimes/pi.js +235 -0
- package/dist/system/runtimes/pi.js.map +1 -0
- package/dist/system/runtimes/protocol.d.ts +9 -0
- package/dist/system/runtimes/protocol.js +38 -0
- package/dist/system/runtimes/protocol.js.map +1 -0
- package/dist/system/runtimes/registry.d.ts +5 -0
- package/dist/system/runtimes/registry.js +5 -0
- package/dist/system/runtimes/registry.js.map +1 -0
- package/dist/system/store.d.ts +20 -0
- package/dist/system/store.js +126 -0
- package/dist/system/store.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/dist/ui/server.d.ts +8 -0
- package/dist/ui/server.js +111 -0
- package/dist/ui/server.js.map +1 -0
- package/dist/ui/static/dashboard.js +266 -0
- package/dist/ui/static/follow.js +67 -0
- package/dist/ui/static/index.html +20 -0
- package/dist/ui/static/style.css +166 -0
- package/dist/ui/static/timeline.js +180 -0
- package/package.json +52 -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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { openFactory, openFactoryForReading } from "../app/factory.js";
|
|
3
|
+
import { presentResult } from "../app/runs.js";
|
|
4
|
+
import { noOptions, parseArgs } from "./args.js";
|
|
5
|
+
import { doctor } from "./doctor.js";
|
|
6
|
+
import { help } from "./help.js";
|
|
7
|
+
import { TerminalReporter } from "./reporter.js";
|
|
8
|
+
import { run } from "./run.js";
|
|
9
|
+
import { status } from "./status.js";
|
|
10
|
+
import { ui } from "./ui.js";
|
|
11
|
+
/** `--port`: a fixed port, so that an SSH tunnel can forward the same one. */
|
|
12
|
+
function parsePort(value) {
|
|
13
|
+
const port = Number(value);
|
|
14
|
+
if (value === true || !/^\d+$/.test(value) || port < 1 || port > 65535)
|
|
15
|
+
throw new Error(`Invalid --port ${value === true ? "" : value}: expected a port from 1 to 65535`);
|
|
16
|
+
return port;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The command run by the core installed in `.factory/`: the global `factory`
|
|
20
|
+
* calls it with the arguments it received and the `.factory/` it found. This
|
|
21
|
+
* contract only changes with a major version.
|
|
22
|
+
*/
|
|
23
|
+
export async function main(argv, directory) {
|
|
24
|
+
// A run changes the working directory: every path must already be absolute.
|
|
25
|
+
const factoryDir = resolve(directory);
|
|
26
|
+
try {
|
|
27
|
+
const args = parseArgs(argv);
|
|
28
|
+
if (args.help || args.command === "help") {
|
|
29
|
+
process.stdout.write(help);
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
if (args.command === "doctor") {
|
|
33
|
+
noOptions(args);
|
|
34
|
+
return await doctor(factoryDir, args.json);
|
|
35
|
+
}
|
|
36
|
+
if (args.command === "run") {
|
|
37
|
+
const factory = await openFactory(factoryDir);
|
|
38
|
+
const reporter = new TerminalReporter((state) => presentResult(factory, state), args.json);
|
|
39
|
+
return await run(factory, args, reporter);
|
|
40
|
+
}
|
|
41
|
+
if (!["status", "ui"].includes(args.command))
|
|
42
|
+
throw new Error(`Unknown command ${args.command}; see factory help`);
|
|
43
|
+
const { port, ...others } = args.options;
|
|
44
|
+
const dashboardPort = args.command === "ui" && port !== undefined ? parsePort(port) : undefined;
|
|
45
|
+
noOptions({
|
|
46
|
+
...args,
|
|
47
|
+
options: args.command === "ui" ? others : args.options,
|
|
48
|
+
});
|
|
49
|
+
// Runs stay readable while factory.ts is being fixed.
|
|
50
|
+
const { factory, error } = await openFactoryForReading(factoryDir);
|
|
51
|
+
if (error)
|
|
52
|
+
process.stderr.write(`factory: factory.ts cannot be loaded, results use the default rendering: ${error}\n`);
|
|
53
|
+
if (args.command === "ui")
|
|
54
|
+
return await ui(factory, dashboardPort);
|
|
55
|
+
const reporter = new TerminalReporter((state) => presentResult(factory, state), args.json);
|
|
56
|
+
return await status(factory, reporter, args.positional[0]);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
process.stderr.write(`factory: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=application.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"application.js","sourceRoot":"","sources":["../../src/cli/application.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface Arguments {
|
|
2
|
+
command: string;
|
|
3
|
+
positional: string[];
|
|
4
|
+
/** Command options; for `run`, the workflow's input. */
|
|
5
|
+
options: Record<string, string | true>;
|
|
6
|
+
json: boolean;
|
|
7
|
+
help: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** `--name value`, or `--name` alone for true; --json and --help never take a value. */
|
|
10
|
+
export declare function parseArgs(argv: string[]): Arguments;
|
|
11
|
+
/** Commands other than `run` take no option of their own. */
|
|
12
|
+
export declare function noOptions(args: Arguments): void;
|
package/dist/cli/args.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const OPTION = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
|
|
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.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":"AASA,MAAM,MAAM,GAAG,0BAA0B,CAAC;AAE1C,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,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC;YACjE,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 "../engine/types.js";
|
|
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 "../engine/workflow.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 core 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 core 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
|
+
* core 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
|
+
* core 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 core installed in `.factory/`. Node's resolution also
|
|
19
|
+
* searches parent `node_modules`: a core 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 core 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
|
+
* core 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, RunState } from "../engine/types.js";
|
|
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,123 @@
|
|
|
1
|
+
import { elapsedMs } from "../engine/metrics.js";
|
|
2
|
+
import { runtimeLabels } from "../engine/profiles.js";
|
|
3
|
+
function duration(ms) {
|
|
4
|
+
const seconds = Math.max(0, Math.floor(ms / 1000));
|
|
5
|
+
const hours = Math.floor(seconds / 3600);
|
|
6
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
7
|
+
return `${hours ? `${hours} h ` : ""}${minutes} min ${seconds % 60} s`;
|
|
8
|
+
}
|
|
9
|
+
/** The run's duration, then its agents' tokens and estimated cost. */
|
|
10
|
+
export function metricsSummary(state, now = Date.now()) {
|
|
11
|
+
const elapsed = elapsedMs(state, now);
|
|
12
|
+
const usage = state.metrics?.usage;
|
|
13
|
+
const count = (n) => n.toLocaleString("en-US");
|
|
14
|
+
return [
|
|
15
|
+
`Duration: ${elapsed === null ? "unavailable" : duration(elapsed)}`,
|
|
16
|
+
!usage
|
|
17
|
+
? "Agents: unavailable"
|
|
18
|
+
: usage.responses
|
|
19
|
+
? `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)" : ""}`
|
|
20
|
+
: `Agents: ${usage.missing ? "unavailable (partial)" : "no measured call"}`,
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
const icons = { started: "→", passed: "✓", failed: "✗", completed: "✓" };
|
|
24
|
+
const inSeconds = (ms) => `${(ms / 1000).toFixed(1)} s`;
|
|
25
|
+
/** An agent call's start and end, its finished tools and its warnings; not each response. */
|
|
26
|
+
function activityLine(activity) {
|
|
27
|
+
switch (activity.kind) {
|
|
28
|
+
case "call":
|
|
29
|
+
return activity.status === "started"
|
|
30
|
+
? `${runtimeLabels[activity.runtime]} started with ${activity.model}`
|
|
31
|
+
: `${runtimeLabels[activity.runtime]} ${activity.status}`;
|
|
32
|
+
case "tool":
|
|
33
|
+
return activity.status === "started"
|
|
34
|
+
? undefined
|
|
35
|
+
: activity.status === "failed"
|
|
36
|
+
? `${activity.name} failed after ${inSeconds(activity.durationMs)}`
|
|
37
|
+
: `${activity.name} ${inSeconds(activity.durationMs)}`;
|
|
38
|
+
case "warning":
|
|
39
|
+
return activity.message;
|
|
40
|
+
default:
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Stage events and journal on stderr; results on stdout; JSON lines on stdout with --json. */
|
|
45
|
+
export class TerminalReporter {
|
|
46
|
+
#present;
|
|
47
|
+
#json;
|
|
48
|
+
constructor(
|
|
49
|
+
/** The result lines of a run's workflow. */
|
|
50
|
+
present, json = false) {
|
|
51
|
+
this.#present = present;
|
|
52
|
+
this.#json = json;
|
|
53
|
+
}
|
|
54
|
+
event = (event) => {
|
|
55
|
+
if (this.#json) {
|
|
56
|
+
process.stdout.write(`${JSON.stringify(event)}\n`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (event.type === "log") {
|
|
60
|
+
this.detail(event.message);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (event.type === "agent") {
|
|
64
|
+
const line = activityLine(event.activity);
|
|
65
|
+
if (line)
|
|
66
|
+
this.detail(line);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const correction = event.decision?.verdict === "correction";
|
|
70
|
+
const icon = correction && event.status !== "failed" ? "↻" : icons[event.status];
|
|
71
|
+
const color = process.stderr.isTTY && !process.env.NO_COLOR
|
|
72
|
+
? event.status === "failed"
|
|
73
|
+
? "\x1b[31m"
|
|
74
|
+
: correction
|
|
75
|
+
? "\x1b[33m"
|
|
76
|
+
: event.status === "started"
|
|
77
|
+
? "\x1b[36m"
|
|
78
|
+
: "\x1b[32m"
|
|
79
|
+
: "";
|
|
80
|
+
const label = event.decision
|
|
81
|
+
? `${event.decision.verdict}${event.status === "failed" ? " · failed" : ""}`
|
|
82
|
+
: event.status;
|
|
83
|
+
const reasonInDetail = event.decision && event.detail?.includes(event.decision.reason);
|
|
84
|
+
const decision = event.decision
|
|
85
|
+
? `${reasonInDetail ? "" : ` — ${event.decision.reason}`} → ${event.decision.destination ?? "end"}`
|
|
86
|
+
: "";
|
|
87
|
+
const retry = event.retry
|
|
88
|
+
? ` [${event.retry.key} ${event.retry.count}/${event.retry.max}]`
|
|
89
|
+
: "";
|
|
90
|
+
process.stderr.write(`${color}${icon} ${event.kind.padEnd(6)} ${event.stage.padEnd(24)} ${label}${color ? "\x1b[0m" : ""}${decision}${retry}${event.detail ? ` — ${event.detail}` : ""}\n`);
|
|
91
|
+
};
|
|
92
|
+
/** A runtime the run uses, with its version and connection; --json output stays events only. */
|
|
93
|
+
runtime = (detail) => {
|
|
94
|
+
if (!this.#json)
|
|
95
|
+
this.detail(detail);
|
|
96
|
+
};
|
|
97
|
+
/** A line under the current stage: journal messages, agent activity and runtimes. */
|
|
98
|
+
detail = (message) => {
|
|
99
|
+
process.stderr.write(` · ${message}\n`);
|
|
100
|
+
};
|
|
101
|
+
unreadable(runId, message) {
|
|
102
|
+
if (this.#json)
|
|
103
|
+
process.stdout.write(`${JSON.stringify({ type: "unreadable", runId, error: message })}\n`);
|
|
104
|
+
else
|
|
105
|
+
process.stdout.write(`\n${runId} · unreadable\n${message}\n`);
|
|
106
|
+
}
|
|
107
|
+
result(state) {
|
|
108
|
+
if (this.#json) {
|
|
109
|
+
process.stdout.write(`${JSON.stringify({ type: "result", state, elapsedMs: elapsedMs(state) })}\n`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const lines = [
|
|
113
|
+
"",
|
|
114
|
+
`${state.workflow} · ${state.id} · ${state.status}`,
|
|
115
|
+
...(state.error ? [state.error] : []),
|
|
116
|
+
...metricsSummary(state),
|
|
117
|
+
...Object.values(state.runtimes ?? {}).map((runtime) => `Runtime: ${runtime}`),
|
|
118
|
+
...this.#present(state),
|
|
119
|
+
];
|
|
120
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# 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,9 @@
|
|
|
1
|
+
import type { Factory } from "../app/factory.js";
|
|
2
|
+
import type { Arguments } from "./args.js";
|
|
3
|
+
import type { TerminalReporter } from "./reporter.js";
|
|
4
|
+
/**
|
|
5
|
+
* `factory run`: the run executes in the foreground. The first SIGINT or SIGTERM
|
|
6
|
+
* stops it before its next stage (child processes are stopped at once); a second
|
|
7
|
+
* one kills the child process groups and exits with 130.
|
|
8
|
+
*/
|
|
9
|
+
export declare function run(factory: Factory, args: Arguments, reporter: TerminalReporter): Promise<number>;
|
package/dist/cli/run.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { startRun } from "../app/run.js";
|
|
2
|
+
/**
|
|
3
|
+
* `factory run`: the run executes in the foreground. The first SIGINT or SIGTERM
|
|
4
|
+
* stops it before its next stage (child processes are stopped at once); a second
|
|
5
|
+
* one kills the child process groups and exits with 130.
|
|
6
|
+
*/
|
|
7
|
+
export async function run(factory, args, reporter) {
|
|
8
|
+
const name = args.positional[0];
|
|
9
|
+
if (!name)
|
|
10
|
+
throw new Error(`Usage: factory run WORKFLOW [--INPUT VALUE…]; workflows: ${[...factory.workflows.keys()].join(", ") || "none"}`);
|
|
11
|
+
const started = await startRun(factory, name, args.options, {
|
|
12
|
+
onEvent: reporter.event,
|
|
13
|
+
});
|
|
14
|
+
for (const runtime of started.runtimes)
|
|
15
|
+
reporter.runtime(runtime.detail);
|
|
16
|
+
let interrupted = false;
|
|
17
|
+
const interrupt = (signal) => {
|
|
18
|
+
if (interrupted) {
|
|
19
|
+
started.kill();
|
|
20
|
+
process.exit(130);
|
|
21
|
+
}
|
|
22
|
+
interrupted = true;
|
|
23
|
+
reporter.detail(`${signal} received: stopping the run; press Ctrl-C again to quit at once`);
|
|
24
|
+
started.stop(new Error(`Run interrupted by ${signal}`));
|
|
25
|
+
};
|
|
26
|
+
process.on("SIGINT", interrupt);
|
|
27
|
+
process.on("SIGTERM", interrupt);
|
|
28
|
+
let state;
|
|
29
|
+
try {
|
|
30
|
+
state = await started.done;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
process.off("SIGINT", interrupt);
|
|
34
|
+
process.off("SIGTERM", interrupt);
|
|
35
|
+
}
|
|
36
|
+
reporter.result(state);
|
|
37
|
+
return state.status === "completed" ? 0 : 1;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC;;;;GAIG;AACH,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,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE;QAC1D,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,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,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,KAAmC,CAAC;IACxC,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;IAC7B,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;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 "../app/runs.js";
|
|
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, runId));
|
|
6
|
+
return 0;
|
|
7
|
+
}
|
|
8
|
+
for (const entry of await listRuns(factory))
|
|
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":"AACA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGnD,+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,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC;IACX,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,QAAQ,CAAC,OAAO,CAAC;QACzC,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,18 @@
|
|
|
1
|
+
import { startDashboard } from "../ui/server.js";
|
|
2
|
+
/** `factory ui`: serves the dashboard until Ctrl-C, on `port` or one the system chooses. */
|
|
3
|
+
export async function ui(factory, port) {
|
|
4
|
+
const dashboard = await startDashboard(factory, port);
|
|
5
|
+
process.stdout.write(`factory ui: ${dashboard.url} (read-only; Ctrl-C to stop)\n`);
|
|
6
|
+
await new Promise((resolve) => {
|
|
7
|
+
const stop = () => {
|
|
8
|
+
process.off("SIGINT", stop);
|
|
9
|
+
process.off("SIGTERM", stop);
|
|
10
|
+
resolve();
|
|
11
|
+
};
|
|
12
|
+
process.on("SIGINT", stop);
|
|
13
|
+
process.on("SIGTERM", stop);
|
|
14
|
+
});
|
|
15
|
+
await dashboard.close();
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/cli/ui.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,OAAgB,EAAE,IAAa;IACtD,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACtD,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,45 @@
|
|
|
1
|
+
import type { RunState } from "./types.js";
|
|
2
|
+
/** Tokens of a model response or of an agent call. */
|
|
3
|
+
export interface TokenCounts {
|
|
4
|
+
input: number;
|
|
5
|
+
output: number;
|
|
6
|
+
cacheRead: number;
|
|
7
|
+
cacheWrite: number;
|
|
8
|
+
}
|
|
9
|
+
/** Tokens and the runtime's estimated cost. */
|
|
10
|
+
export interface AgentUsage extends TokenCounts {
|
|
11
|
+
costUsd: number;
|
|
12
|
+
}
|
|
13
|
+
export interface RunMetrics {
|
|
14
|
+
/** The run's total, the sum of its sessions; `responses` counts measured reports, `missing` unmeasured ones. */
|
|
15
|
+
usage: AgentUsage & {
|
|
16
|
+
responses: number;
|
|
17
|
+
missing: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Per agent session, `<runtime>:<session>`: the latest total its runtime
|
|
21
|
+
* announced (Claude Code), or the sum of its responses (Pi). Absent from runs
|
|
22
|
+
* recorded before it existed.
|
|
23
|
+
*/
|
|
24
|
+
sessions?: Record<string, AgentUsage>;
|
|
25
|
+
}
|
|
26
|
+
/** A measure as the runtime reports it: one response (Pi), or its session's total so far (Claude Code). */
|
|
27
|
+
export interface UsageReport {
|
|
28
|
+
session: string;
|
|
29
|
+
scope: "response" | "session";
|
|
30
|
+
/** `undefined` when the runtime reported nothing measurable. */
|
|
31
|
+
usage: AgentUsage | undefined;
|
|
32
|
+
}
|
|
33
|
+
/** Tokens and cost of several measures together. */
|
|
34
|
+
export declare function sumUsage(measures: AgentUsage[]): AgentUsage;
|
|
35
|
+
export declare function emptyMetrics(): RunMetrics;
|
|
36
|
+
/**
|
|
37
|
+
* Records a measure as its runtime reports it: a session total replaces the
|
|
38
|
+
* previous one, a response adds to its session. The run's total is the sum of
|
|
39
|
+
* its sessions; nothing else is computed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function recordUsage(metrics: RunMetrics, report: UsageReport): void;
|
|
42
|
+
/** Why a run past its budget must stop: its announced cost exceeds it, or a call announced none. */
|
|
43
|
+
export declare function budgetProblem(metrics: RunMetrics, maxCostUsd: number): string | undefined;
|
|
44
|
+
/** From creation to now while running, to the last update once completed or failed. */
|
|
45
|
+
export declare function elapsedMs(state: RunState, now?: number): number | null;
|