@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,60 @@
|
|
|
1
|
+
const fields = [
|
|
2
|
+
"input",
|
|
3
|
+
"output",
|
|
4
|
+
"cacheRead",
|
|
5
|
+
"cacheWrite",
|
|
6
|
+
"costUsd",
|
|
7
|
+
];
|
|
8
|
+
const noUsage = () => ({
|
|
9
|
+
input: 0,
|
|
10
|
+
output: 0,
|
|
11
|
+
cacheRead: 0,
|
|
12
|
+
cacheWrite: 0,
|
|
13
|
+
costUsd: 0,
|
|
14
|
+
});
|
|
15
|
+
/** Tokens and cost of several measures together. */
|
|
16
|
+
export function sumUsage(measures) {
|
|
17
|
+
const total = noUsage();
|
|
18
|
+
for (const measure of measures)
|
|
19
|
+
for (const field of fields)
|
|
20
|
+
total[field] += measure[field];
|
|
21
|
+
return total;
|
|
22
|
+
}
|
|
23
|
+
export function emptyMetrics() {
|
|
24
|
+
return { usage: { ...noUsage(), responses: 0, missing: 0 }, sessions: {} };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Records a measure as its runtime reports it: a session total replaces the
|
|
28
|
+
* previous one, a response adds to its session. The run's total is the sum of
|
|
29
|
+
* its sessions; nothing else is computed.
|
|
30
|
+
*/
|
|
31
|
+
export function recordUsage(metrics, report) {
|
|
32
|
+
if (!report.usage) {
|
|
33
|
+
metrics.usage.missing++;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
metrics.usage.responses++;
|
|
37
|
+
metrics.sessions ??= {};
|
|
38
|
+
const { sessions } = metrics;
|
|
39
|
+
const previous = sessions[report.session];
|
|
40
|
+
sessions[report.session] =
|
|
41
|
+
report.scope === "session" || !previous
|
|
42
|
+
? report.usage
|
|
43
|
+
: sumUsage([previous, report.usage]);
|
|
44
|
+
Object.assign(metrics.usage, sumUsage(Object.values(sessions)));
|
|
45
|
+
}
|
|
46
|
+
/** Why a run past its budget must stop: its announced cost exceeds it, or a call announced none. */
|
|
47
|
+
export function budgetProblem(metrics, maxCostUsd) {
|
|
48
|
+
if (metrics.usage.missing)
|
|
49
|
+
return `Budget of ${maxCostUsd} USD cannot be checked: an agent call announced no cost`;
|
|
50
|
+
if (metrics.usage.costUsd > maxCostUsd)
|
|
51
|
+
return `Budget exceeded: ${metrics.usage.costUsd.toFixed(6)} USD spent, maximum ${maxCostUsd.toFixed(6)} USD`;
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
/** From creation to now while running, to the last update once completed or failed. */
|
|
55
|
+
export function elapsedMs(state, now = Date.now()) {
|
|
56
|
+
const end = state.status === "running" ? now : Date.parse(state.updatedAt);
|
|
57
|
+
const elapsed = end - Date.parse(state.createdAt);
|
|
58
|
+
return Number.isFinite(elapsed) && elapsed >= 0 ? elapsed : null;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/engine/metrics.ts"],"names":[],"mappings":"AAqCA,MAAM,MAAM,GAAG;IACb,OAAO;IACP,QAAQ;IACR,WAAW;IACX,YAAY;IACZ,SAAS;CACD,CAAC;AAEX,MAAM,OAAO,GAAG,GAAe,EAAE,CAAC,CAAC;IACjC,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;IACT,SAAS,EAAE,CAAC;IACZ,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,CAAC;CACX,CAAC,CAAC;AAEH,oDAAoD;AACpD,MAAM,UAAU,QAAQ,CAAC,QAAsB;IAC7C,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,KAAK,MAAM,OAAO,IAAI,QAAQ;QAC5B,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,KAAK,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,OAAmB,EAAE,MAAmB;IAClE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO;IACT,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;IAC1B,OAAO,CAAC,QAAQ,KAAK,EAAE,CAAC;IACxB,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC;QACtB,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,QAAQ;YACrC,CAAC,CAAC,MAAM,CAAC,KAAK;YACd,CAAC,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,aAAa,CAC3B,OAAmB,EACnB,UAAkB;IAElB,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO;QACvB,OAAO,aAAa,UAAU,yDAAyD,CAAC;IAC1F,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,UAAU;QACpC,OAAO,oBAAoB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAChH,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,SAAS,CAAC,KAAe,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IACzD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAClD,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { AgentDeclaration, Edge, RetryEdge, Stage, StageContext, StageResult, WorkflowNode } from "./types.js";
|
|
3
|
+
type Awaitable<T> = T | Promise<T>;
|
|
4
|
+
export declare const END: null;
|
|
5
|
+
/** A correction route, taken at most `max` times per run. */
|
|
6
|
+
export declare function retry(to: string, max: number): RetryEdge;
|
|
7
|
+
/** Binds a stage to its routes; every declared outcome must be routed. */
|
|
8
|
+
export declare function node<O extends string>(stage: Stage<O>, on: Record<O, Edge>): WorkflowNode;
|
|
9
|
+
/** Selects explicit agent context from the run input and workflow data. */
|
|
10
|
+
export declare function pick(...keys: string[]): (context: StageContext) => Record<string, unknown>;
|
|
11
|
+
/** AGENT primitive: one structured request; its untrusted output waits for a gate. */
|
|
12
|
+
export declare function agent(options: AgentDeclaration & {
|
|
13
|
+
schema: z.ZodType;
|
|
14
|
+
context: (context: StageContext) => Awaitable<Record<string, unknown>>;
|
|
15
|
+
}): Stage<"ok">;
|
|
16
|
+
/** CODE primitive: deterministic work with named outcomes. */
|
|
17
|
+
export declare function code<O extends string = "ok">(outcomes: readonly O[], run: (context: StageContext) => Promise<StageResult<O>>): Stage<O>;
|
|
18
|
+
/** What a step records: data, or nothing. */
|
|
19
|
+
type StepData = Record<string, unknown> | void;
|
|
20
|
+
/** CODE primitive with a single successful outcome. */
|
|
21
|
+
export declare function step(run: (context: StageContext) => Promise<StepData>): Stage<"ok">;
|
|
22
|
+
/** GATE primitive: decides acceptance or correction from saved facts. */
|
|
23
|
+
export declare function gate<O extends string>(outcomes: readonly O[], run: (context: StageContext) => Promise<StageResult<O>>): Stage<O>;
|
|
24
|
+
export type Check<T> = (value: T, context: StageContext) => Awaitable<string | undefined | {
|
|
25
|
+
data: Record<string, unknown>;
|
|
26
|
+
}>;
|
|
27
|
+
/** GATE over the last agent output: schema, then business invariants; failures are corrections. */
|
|
28
|
+
export declare function schemaGate<S extends z.ZodType>(options: {
|
|
29
|
+
schema: S;
|
|
30
|
+
/** Data key of the validated output. */
|
|
31
|
+
into: string;
|
|
32
|
+
check?: Check<z.output<S>>;
|
|
33
|
+
}): Stage<"ok" | "invalid">;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const END = null;
|
|
3
|
+
/** A correction route, taken at most `max` times per run. */
|
|
4
|
+
export function retry(to, max) {
|
|
5
|
+
return { to, max };
|
|
6
|
+
}
|
|
7
|
+
/** Binds a stage to its routes; every declared outcome must be routed. */
|
|
8
|
+
export function node(stage, on) {
|
|
9
|
+
return { stage, on };
|
|
10
|
+
}
|
|
11
|
+
/** Selects explicit agent context from the run input and workflow data. */
|
|
12
|
+
export function pick(...keys) {
|
|
13
|
+
return ({ state }) => Object.fromEntries(keys.flatMap((key) => {
|
|
14
|
+
const value = key === "input" ? state.input : state.data[key];
|
|
15
|
+
return value === undefined ? [] : [[key, value]];
|
|
16
|
+
}));
|
|
17
|
+
}
|
|
18
|
+
/** AGENT primitive: one structured request; its untrusted output waits for a gate. */
|
|
19
|
+
export function agent(options) {
|
|
20
|
+
const { profile, prompt, session } = options;
|
|
21
|
+
return {
|
|
22
|
+
kind: "AGENT",
|
|
23
|
+
outcomes: ["ok"],
|
|
24
|
+
agent: {
|
|
25
|
+
profile,
|
|
26
|
+
...(prompt === undefined ? {} : { prompt }),
|
|
27
|
+
...(session === undefined ? {} : { session }),
|
|
28
|
+
},
|
|
29
|
+
async run(context) {
|
|
30
|
+
const { state } = context;
|
|
31
|
+
const output = await context.agent.execute({
|
|
32
|
+
profile,
|
|
33
|
+
prompt: prompt ?? state.stage,
|
|
34
|
+
session: typeof session === "function"
|
|
35
|
+
? session(state)
|
|
36
|
+
: (session ?? state.stage),
|
|
37
|
+
context: {
|
|
38
|
+
...(await options.context(context)),
|
|
39
|
+
...(state.feedback === undefined ? {} : { feedback: state.feedback }),
|
|
40
|
+
},
|
|
41
|
+
schema: z.toJSONSchema(options.schema),
|
|
42
|
+
});
|
|
43
|
+
return { outcome: "ok", output };
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** CODE primitive: deterministic work with named outcomes. */
|
|
48
|
+
export function code(outcomes, run) {
|
|
49
|
+
return { kind: "CODE", outcomes, run };
|
|
50
|
+
}
|
|
51
|
+
/** CODE primitive with a single successful outcome. */
|
|
52
|
+
export function step(run) {
|
|
53
|
+
return code(["ok"], async (context) => {
|
|
54
|
+
const data = await run(context);
|
|
55
|
+
return { outcome: "ok", ...(data ? { data } : {}) };
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/** GATE primitive: decides acceptance or correction from saved facts. */
|
|
59
|
+
export function gate(outcomes, run) {
|
|
60
|
+
return { kind: "GATE", outcomes, run };
|
|
61
|
+
}
|
|
62
|
+
/** GATE over the last agent output: schema, then business invariants; failures are corrections. */
|
|
63
|
+
export function schemaGate(options) {
|
|
64
|
+
return gate(["ok", "invalid"], async (context) => {
|
|
65
|
+
const parsed = options.schema.safeParse(context.state.output);
|
|
66
|
+
if (!parsed.success)
|
|
67
|
+
return {
|
|
68
|
+
outcome: "invalid",
|
|
69
|
+
reason: `Invalid structured output:\n${z.prettifyError(parsed.error)}`,
|
|
70
|
+
};
|
|
71
|
+
const checked = await options.check?.(parsed.data, context);
|
|
72
|
+
if (typeof checked === "string")
|
|
73
|
+
return { outcome: "invalid", reason: checked };
|
|
74
|
+
return {
|
|
75
|
+
outcome: "ok",
|
|
76
|
+
reason: `Structured output and invariants valid: ${options.into}`,
|
|
77
|
+
data: { ...(checked?.data ?? {}), [options.into]: parsed.data },
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=primitives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../src/engine/primitives.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** An agent stage's runtime, settings and access, declared in full by its workflow. */
|
|
3
|
+
export declare const profileSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
4
|
+
runtime: z.ZodLiteral<"pi">;
|
|
5
|
+
access: z.ZodDefault<z.ZodEnum<{
|
|
6
|
+
read: "read";
|
|
7
|
+
write: "write";
|
|
8
|
+
}>>;
|
|
9
|
+
provider: z.ZodString;
|
|
10
|
+
model: z.ZodString;
|
|
11
|
+
thinking: z.ZodEnum<{
|
|
12
|
+
high: "high";
|
|
13
|
+
low: "low";
|
|
14
|
+
max: "max";
|
|
15
|
+
medium: "medium";
|
|
16
|
+
minimal: "minimal";
|
|
17
|
+
off: "off";
|
|
18
|
+
xhigh: "xhigh";
|
|
19
|
+
}>;
|
|
20
|
+
tools: z.ZodArray<z.ZodString>;
|
|
21
|
+
skills: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
22
|
+
extensions: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
23
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
24
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
25
|
+
runtime: z.ZodLiteral<"claude-code">;
|
|
26
|
+
access: z.ZodDefault<z.ZodEnum<{
|
|
27
|
+
read: "read";
|
|
28
|
+
write: "write";
|
|
29
|
+
}>>;
|
|
30
|
+
model: z.ZodString;
|
|
31
|
+
thinking: z.ZodEnum<{
|
|
32
|
+
high: "high";
|
|
33
|
+
low: "low";
|
|
34
|
+
max: "max";
|
|
35
|
+
medium: "medium";
|
|
36
|
+
xhigh: "xhigh";
|
|
37
|
+
}>;
|
|
38
|
+
tools: z.ZodArray<z.ZodString>;
|
|
39
|
+
mcpServers: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
40
|
+
command: z.ZodString;
|
|
41
|
+
args: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
42
|
+
}, z.core.$strict>>>;
|
|
43
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
44
|
+
}, z.core.$strict>], "runtime">;
|
|
45
|
+
/** A profile as a workflow declares it. */
|
|
46
|
+
export type AgentProfile = z.input<typeof profileSchema>;
|
|
47
|
+
/** A profile with its defaults applied. */
|
|
48
|
+
export type ResolvedProfile = z.output<typeof profileSchema>;
|
|
49
|
+
export type Runtime = ResolvedProfile["runtime"];
|
|
50
|
+
/** Each runtime's name as the operator reads it. */
|
|
51
|
+
export declare const runtimeLabels: Record<Runtime, string>;
|
|
52
|
+
/** The profile with its defaults applied; an invalid profile is refused with its problems. */
|
|
53
|
+
export declare function resolveProfile(profile: AgentProfile): ResolvedProfile;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Pi native tools; any other tool name must come from an explicitly trusted extension. */
|
|
3
|
+
const piBuiltinTools = new Set([
|
|
4
|
+
"read",
|
|
5
|
+
"bash",
|
|
6
|
+
"powershell",
|
|
7
|
+
"edit",
|
|
8
|
+
"write",
|
|
9
|
+
"grep",
|
|
10
|
+
"find",
|
|
11
|
+
"ls",
|
|
12
|
+
]);
|
|
13
|
+
/** Pi native tools that can change the repository or run commands. */
|
|
14
|
+
const piWriteTools = new Set(["bash", "powershell", "edit", "write"]);
|
|
15
|
+
/**
|
|
16
|
+
* The only Claude Code tools a read-only profile may use. Its native set grows with
|
|
17
|
+
* each version (worktrees, monitors, schedules…), so anything else is refused.
|
|
18
|
+
*/
|
|
19
|
+
const claudeCodeReadTools = new Set([
|
|
20
|
+
"Read",
|
|
21
|
+
"Grep",
|
|
22
|
+
"Glob",
|
|
23
|
+
"WebFetch",
|
|
24
|
+
"WebSearch",
|
|
25
|
+
]);
|
|
26
|
+
const timeoutMs = z.number().int().min(1000).max(7_200_000).default(900_000);
|
|
27
|
+
/** `read` by default; `write` allows tools that change the repository or run commands. */
|
|
28
|
+
const access = z.enum(["read", "write"]).default("read");
|
|
29
|
+
const piProfileSchema = z
|
|
30
|
+
.strictObject({
|
|
31
|
+
runtime: z.literal("pi"),
|
|
32
|
+
access,
|
|
33
|
+
// No default: a profile names the provider whose connection it uses.
|
|
34
|
+
provider: z.string().min(1),
|
|
35
|
+
model: z.string().min(1),
|
|
36
|
+
thinking: z.enum([
|
|
37
|
+
"off",
|
|
38
|
+
"minimal",
|
|
39
|
+
"low",
|
|
40
|
+
"medium",
|
|
41
|
+
"high",
|
|
42
|
+
"xhigh",
|
|
43
|
+
"max",
|
|
44
|
+
]),
|
|
45
|
+
// Exact names only: Pi allowlist patterns could accidentally grant mutation tools.
|
|
46
|
+
tools: z.array(z.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/)),
|
|
47
|
+
skills: z.array(z.string().min(1)).default([]),
|
|
48
|
+
extensions: z.array(z.string().min(1)).default([]),
|
|
49
|
+
timeoutMs,
|
|
50
|
+
})
|
|
51
|
+
.refine((profile) => profile.extensions.length > 0 ||
|
|
52
|
+
profile.tools.every((tool) => piBuiltinTools.has(tool)), {
|
|
53
|
+
path: ["tools"],
|
|
54
|
+
message: "Custom tools require explicitly trusted extensions",
|
|
55
|
+
});
|
|
56
|
+
const mcpTool = /^mcp__([a-zA-Z0-9][a-zA-Z0-9-]*)__[a-zA-Z0-9_-]+$/;
|
|
57
|
+
/** The server a Claude Code MCP tool name (`mcp__<server>__<tool>`) belongs to. */
|
|
58
|
+
function mcpToolServer(tool) {
|
|
59
|
+
return mcpTool.exec(tool)?.[1];
|
|
60
|
+
}
|
|
61
|
+
const claudeCodeProfileSchema = z
|
|
62
|
+
.strictObject({
|
|
63
|
+
runtime: z.literal("claude-code"),
|
|
64
|
+
access,
|
|
65
|
+
model: z.string().min(1),
|
|
66
|
+
/** Claude Code effort levels. */
|
|
67
|
+
thinking: z.enum(["low", "medium", "high", "xhigh", "max"]),
|
|
68
|
+
// Exact names only: rules such as Bash(git *) or "default" would change the tool set.
|
|
69
|
+
tools: z.array(z
|
|
70
|
+
.string()
|
|
71
|
+
.refine((tool) => /^[A-Z][a-zA-Z0-9]*$/.test(tool) || mcpTool.test(tool))),
|
|
72
|
+
// Without "_": `mcp__<server>__<tool>` names must split one way only.
|
|
73
|
+
mcpServers: z
|
|
74
|
+
.record(z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9-]*$/),
|
|
75
|
+
// No env: servers inherit the factory's environment, so secrets stay in .env.
|
|
76
|
+
z.strictObject({
|
|
77
|
+
command: z.string().min(1),
|
|
78
|
+
args: z.array(z.string()).default([]),
|
|
79
|
+
}))
|
|
80
|
+
.default({}),
|
|
81
|
+
timeoutMs,
|
|
82
|
+
})
|
|
83
|
+
.refine((profile) => profile.tools.every((tool) => {
|
|
84
|
+
const server = mcpToolServer(tool);
|
|
85
|
+
return (server === undefined || Object.hasOwn(profile.mcpServers, server));
|
|
86
|
+
}), { path: ["tools"], message: "MCP tools require a declared server" });
|
|
87
|
+
/** Tools a read-only profile must not have; tools of a declared MCP server are trusted like Pi extension tools. */
|
|
88
|
+
function writeTools(profile) {
|
|
89
|
+
return profile.tools.filter((tool) => profile.runtime === "pi"
|
|
90
|
+
? piWriteTools.has(tool)
|
|
91
|
+
: !claudeCodeReadTools.has(tool) && mcpToolServer(tool) === undefined);
|
|
92
|
+
}
|
|
93
|
+
/** An agent stage's runtime, settings and access, declared in full by its workflow. */
|
|
94
|
+
export const profileSchema = z
|
|
95
|
+
.discriminatedUnion("runtime", [piProfileSchema, claudeCodeProfileSchema])
|
|
96
|
+
.superRefine((profile, context) => {
|
|
97
|
+
const refused = profile.access === "read" ? writeTools(profile) : [];
|
|
98
|
+
if (refused.length)
|
|
99
|
+
context.addIssue({
|
|
100
|
+
code: "custom",
|
|
101
|
+
path: ["tools"],
|
|
102
|
+
message: `read-only profile must not include ${refused.join(", ")}; set access: "write" to allow it`,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
/** Each runtime's name as the operator reads it. */
|
|
106
|
+
export const runtimeLabels = {
|
|
107
|
+
"claude-code": "Claude Code",
|
|
108
|
+
pi: "Pi",
|
|
109
|
+
};
|
|
110
|
+
/** The profile with its defaults applied; an invalid profile is refused with its problems. */
|
|
111
|
+
export function resolveProfile(profile) {
|
|
112
|
+
const parsed = profileSchema.safeParse(profile);
|
|
113
|
+
if (!parsed.success)
|
|
114
|
+
throw new Error(`Invalid agent profile:\n${z.prettifyError(parsed.error)}`);
|
|
115
|
+
return parsed.data;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/engine/profiles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AgentPort, RunEvent, RunState, RunStore, Workflow } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic graph runner. Stages report outcomes; the graph routes them.
|
|
4
|
+
* Each retry edge is taken at most its maximum; an aborted run stops before its
|
|
5
|
+
* next stage, or fails instead of completing.
|
|
6
|
+
*/
|
|
7
|
+
export declare function executeWorkflow(workflow: Pick<Workflow, "nodes">, state: RunState, runtime: {
|
|
8
|
+
agent: AgentPort;
|
|
9
|
+
dir: string;
|
|
10
|
+
}, store: RunStore, options?: {
|
|
11
|
+
onEvent?: (event: RunEvent) => void;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
}): Promise<RunState>;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The journal of one stage run: its messages and its agent's activity. Writes
|
|
3
|
+
* keep their call order and are awaited before the stage is routed; the first
|
|
4
|
+
* write failure fails the stage.
|
|
5
|
+
*/
|
|
6
|
+
function stageJournal(write, stage, kind) {
|
|
7
|
+
let pending = Promise.resolve();
|
|
8
|
+
let failure;
|
|
9
|
+
let closed = false;
|
|
10
|
+
const append = (event) => {
|
|
11
|
+
if (closed)
|
|
12
|
+
throw new Error(`Stage ${stage} logged after it ended`);
|
|
13
|
+
pending = pending
|
|
14
|
+
.then(() => write(event))
|
|
15
|
+
.catch((error) => {
|
|
16
|
+
failure ??= { error };
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
log(message, data) {
|
|
21
|
+
append({ type: "log", stage, kind, message, ...(data ? { data } : {}) });
|
|
22
|
+
},
|
|
23
|
+
activity(activity) {
|
|
24
|
+
append({ type: "agent", stage, kind, activity });
|
|
25
|
+
},
|
|
26
|
+
async flush() {
|
|
27
|
+
closed = true;
|
|
28
|
+
await pending;
|
|
29
|
+
if (failure)
|
|
30
|
+
throw failure.error;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function errorMessage(error) {
|
|
35
|
+
return error instanceof Error ? error.message : String(error);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Deterministic graph runner. Stages report outcomes; the graph routes them.
|
|
39
|
+
* Each retry edge is taken at most its maximum; an aborted run stops before its
|
|
40
|
+
* next stage, or fails instead of completing.
|
|
41
|
+
*/
|
|
42
|
+
export async function executeWorkflow(workflow, state, runtime, store, options = {}) {
|
|
43
|
+
const emit = async (event) => {
|
|
44
|
+
const full = {
|
|
45
|
+
...event,
|
|
46
|
+
runId: state.id,
|
|
47
|
+
at: new Date().toISOString(),
|
|
48
|
+
};
|
|
49
|
+
await store.event(full);
|
|
50
|
+
options.onEvent?.(full);
|
|
51
|
+
};
|
|
52
|
+
while (state.status === "running") {
|
|
53
|
+
const node = workflow.nodes[state.stage];
|
|
54
|
+
if (!node)
|
|
55
|
+
throw new Error(`Unknown stage: ${state.stage}`);
|
|
56
|
+
const current = state.stage;
|
|
57
|
+
const kind = node.stage.kind;
|
|
58
|
+
let outcome = {};
|
|
59
|
+
const journal = stageJournal(emit, current, kind);
|
|
60
|
+
try {
|
|
61
|
+
if (options.signal?.aborted)
|
|
62
|
+
throw options.signal.reason ?? new Error("Run aborted");
|
|
63
|
+
await emit({ type: "stage", stage: current, kind, status: "started" });
|
|
64
|
+
const context = {
|
|
65
|
+
state,
|
|
66
|
+
dir: runtime.dir,
|
|
67
|
+
agent: {
|
|
68
|
+
execute: (request) => runtime.agent.execute(request, journal.activity),
|
|
69
|
+
},
|
|
70
|
+
log: journal.log,
|
|
71
|
+
};
|
|
72
|
+
const result = await node.stage.run(context);
|
|
73
|
+
await journal.flush();
|
|
74
|
+
if (!node.stage.outcomes.includes(result.outcome) ||
|
|
75
|
+
!Object.hasOwn(node.on, result.outcome))
|
|
76
|
+
throw new Error(`Stage ${current} returned unrouted outcome ${result.outcome}`);
|
|
77
|
+
const edge = node.on[result.outcome] ?? null;
|
|
78
|
+
const correction = typeof edge === "object" && edge !== null ? edge : undefined;
|
|
79
|
+
const next = correction ? correction.to : edge;
|
|
80
|
+
if (next !== null && !workflow.nodes[next])
|
|
81
|
+
throw new Error(`Unknown route: ${next}`);
|
|
82
|
+
const decision = kind === "GATE" || correction || result.reason
|
|
83
|
+
? {
|
|
84
|
+
verdict: correction ? "correction" : "accepted",
|
|
85
|
+
reason: result.reason ?? result.outcome,
|
|
86
|
+
destination: next,
|
|
87
|
+
}
|
|
88
|
+
: undefined;
|
|
89
|
+
outcome = {
|
|
90
|
+
...(decision ? { decision } : {}),
|
|
91
|
+
...(result.detail ? { detail: result.detail } : {}),
|
|
92
|
+
};
|
|
93
|
+
let retry;
|
|
94
|
+
if (correction) {
|
|
95
|
+
const key = `${current}.${result.outcome}`;
|
|
96
|
+
state.retries ??= {};
|
|
97
|
+
const count = (state.retries[key] ?? 0) + 1;
|
|
98
|
+
state.retries[key] = count;
|
|
99
|
+
retry = { key, count, max: correction.max };
|
|
100
|
+
outcome.retry = retry;
|
|
101
|
+
}
|
|
102
|
+
Object.assign(state.data, result.data);
|
|
103
|
+
if (Object.hasOwn(result, "output"))
|
|
104
|
+
state.output = result.output;
|
|
105
|
+
if (correction)
|
|
106
|
+
state.feedback = result.feedback ?? result.reason;
|
|
107
|
+
else if (kind === "GATE") {
|
|
108
|
+
delete state.feedback;
|
|
109
|
+
delete state.output;
|
|
110
|
+
}
|
|
111
|
+
if (retry && retry.count > retry.max)
|
|
112
|
+
throw new Error(`Retry ${retry.key} → ${next} exceeded its maximum of ${retry.max}`);
|
|
113
|
+
// The end of the run is a stage boundary too: an interrupted run never completes.
|
|
114
|
+
if (next === null && options.signal?.aborted)
|
|
115
|
+
throw options.signal.reason ?? new Error("Run aborted");
|
|
116
|
+
if (next === null)
|
|
117
|
+
state.status = "completed";
|
|
118
|
+
else
|
|
119
|
+
state.stage = next;
|
|
120
|
+
state.updatedAt = new Date().toISOString();
|
|
121
|
+
// The event first: a reader that sees the run ended has every event.
|
|
122
|
+
await emit({
|
|
123
|
+
type: "stage",
|
|
124
|
+
stage: current,
|
|
125
|
+
kind,
|
|
126
|
+
status: state.status === "running" ? "passed" : state.status,
|
|
127
|
+
...outcome,
|
|
128
|
+
});
|
|
129
|
+
await store.save(state);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
// The stage's own failure takes precedence over a journal write failure.
|
|
133
|
+
await journal.flush().catch(() => undefined);
|
|
134
|
+
state.status = "failed";
|
|
135
|
+
state.error = errorMessage(error);
|
|
136
|
+
state.updatedAt = new Date().toISOString();
|
|
137
|
+
try {
|
|
138
|
+
await emit({
|
|
139
|
+
type: "stage",
|
|
140
|
+
stage: current,
|
|
141
|
+
kind,
|
|
142
|
+
status: "failed",
|
|
143
|
+
...outcome,
|
|
144
|
+
detail: outcome.detail
|
|
145
|
+
? `${outcome.detail}\n${state.error}`
|
|
146
|
+
: state.error,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
// The failed state is kept even if its event cannot be written.
|
|
151
|
+
await store.save(state);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return state;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/engine/runner.ts"],"names":[],"mappings":"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"}
|