@clemrig/flow 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 +55 -2
- package/dist/app/run.d.ts +38 -0
- package/dist/app/run.js +104 -0
- package/dist/app/run.js.map +1 -0
- package/dist/app/runs.d.ts +43 -0
- package/dist/app/runs.js +70 -0
- package/dist/app/runs.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 +24 -0
- package/dist/engine/workflow.js +179 -0
- package/dist/engine/workflow.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/system/process.d.ts +27 -0
- package/dist/system/process.js +261 -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 +27 -0
- package/dist/system/runtimes/inspect.js +131 -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 +26 -0
- package/dist/system/store.js +157 -0
- package/dist/system/store.js.map +1 -0
- package/package.json +34 -4
|
@@ -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 files 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 files 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 run's environment, so secrets stay out of workflows.
|
|
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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"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { AgentUsage, RunMetrics, TokenCounts } from "./metrics.js";
|
|
3
|
+
import type { AgentProfile, ResolvedProfile, Runtime } from "./profiles.js";
|
|
4
|
+
export type StageKind = "AGENT" | "CODE" | "GATE";
|
|
5
|
+
/** What an agent stage asks of the agent runtime. */
|
|
6
|
+
export interface AgentRequest {
|
|
7
|
+
/** The stage's profile as declared; the runtime validates it and applies its defaults. */
|
|
8
|
+
profile: AgentProfile;
|
|
9
|
+
/** Name of the prompt file the runtime appends to its system prompt. */
|
|
10
|
+
prompt: string;
|
|
11
|
+
/** The run-local conversation the request continues. */
|
|
12
|
+
session: string;
|
|
13
|
+
context: unknown;
|
|
14
|
+
schema: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
/** Adds a message to the run journal (`events.jsonl`), with optional data. */
|
|
17
|
+
export type Log = (message: string, data?: Record<string, unknown>) => void;
|
|
18
|
+
/** What an agent call does, as its runtime reports it; never the messages themselves. */
|
|
19
|
+
export type AgentActivity = {
|
|
20
|
+
kind: "call";
|
|
21
|
+
status: "started";
|
|
22
|
+
runtime: Runtime;
|
|
23
|
+
model: string;
|
|
24
|
+
session: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "call";
|
|
27
|
+
status: "completed" | "failed";
|
|
28
|
+
runtime: Runtime;
|
|
29
|
+
/** As the runtime announced it at the end of the call: the call's own, or its session's total. */
|
|
30
|
+
usage?: AgentUsage;
|
|
31
|
+
scope?: "call" | "session";
|
|
32
|
+
} | {
|
|
33
|
+
kind: "tool";
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
status: "started";
|
|
37
|
+
} | {
|
|
38
|
+
kind: "tool";
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
status: "completed" | "failed";
|
|
42
|
+
durationMs: number;
|
|
43
|
+
} | {
|
|
44
|
+
kind: "response";
|
|
45
|
+
tokens: TokenCounts;
|
|
46
|
+
costUsd?: number;
|
|
47
|
+
/** Reported while the call runs and replaced by the figures announced at its end. */
|
|
48
|
+
provisional: boolean;
|
|
49
|
+
} | {
|
|
50
|
+
kind: "warning";
|
|
51
|
+
message: string;
|
|
52
|
+
};
|
|
53
|
+
/** Records an agent call's activity under the calling stage. */
|
|
54
|
+
export type RecordActivity = (activity: AgentActivity) => void;
|
|
55
|
+
/** Agent execution managed by the core runtime; `record` journals its activity under the calling stage. */
|
|
56
|
+
export interface AgentPort {
|
|
57
|
+
execute(request: AgentRequest, record?: RecordActivity): Promise<unknown>;
|
|
58
|
+
}
|
|
59
|
+
export interface RunState {
|
|
60
|
+
/** 4 since workflows declare their inputs, agent profiles and retry maximums. */
|
|
61
|
+
version: 4;
|
|
62
|
+
id: string;
|
|
63
|
+
workflow: string;
|
|
64
|
+
/** Options validated by the workflow's input object. */
|
|
65
|
+
input: Record<string, unknown>;
|
|
66
|
+
stage: string;
|
|
67
|
+
status: "running" | "completed" | "failed";
|
|
68
|
+
/** Validated values written by the workflow's stages. */
|
|
69
|
+
data: Record<string, unknown>;
|
|
70
|
+
/** Owned by the engine: untrusted output of the last agent, cleared when a gate accepts. */
|
|
71
|
+
output?: unknown;
|
|
72
|
+
/** Owned by the engine: correction routed by the last retry edge, cleared when a gate accepts. */
|
|
73
|
+
feedback?: unknown;
|
|
74
|
+
/** Corrections taken per retry edge, keyed `<stage>.<outcome>`. */
|
|
75
|
+
retries?: Record<string, number>;
|
|
76
|
+
error?: string;
|
|
77
|
+
createdAt: string;
|
|
78
|
+
updatedAt: string;
|
|
79
|
+
metrics?: RunMetrics;
|
|
80
|
+
/** Each runtime the run used, with its version and connection, as checked before it started. */
|
|
81
|
+
runtimes?: Partial<Record<Runtime, string>>;
|
|
82
|
+
}
|
|
83
|
+
export interface WorkflowDecision {
|
|
84
|
+
verdict: "accepted" | "correction";
|
|
85
|
+
reason: string;
|
|
86
|
+
destination: string | null;
|
|
87
|
+
}
|
|
88
|
+
/** What a stage receives: its run, the agent runtime, the run journal and the working directory. */
|
|
89
|
+
export interface StageContext {
|
|
90
|
+
state: Readonly<RunState>;
|
|
91
|
+
agent: AgentPort;
|
|
92
|
+
log: Log;
|
|
93
|
+
/** The directory the workflow works in. */
|
|
94
|
+
dir: string;
|
|
95
|
+
}
|
|
96
|
+
/** A stage reports a named outcome; the workflow graph decides where it leads. */
|
|
97
|
+
export interface StageResult<O extends string = string> {
|
|
98
|
+
outcome: O;
|
|
99
|
+
/** Why this outcome was chosen; becomes the decision reason. */
|
|
100
|
+
reason?: string;
|
|
101
|
+
/** Correction carried by a retry edge to the next stage; defaults to the reason. */
|
|
102
|
+
feedback?: unknown;
|
|
103
|
+
/** Validated values merged into the run's data. */
|
|
104
|
+
data?: Record<string, unknown>;
|
|
105
|
+
/** Untrusted agent output, kept for the next gate. */
|
|
106
|
+
output?: unknown;
|
|
107
|
+
detail?: string;
|
|
108
|
+
}
|
|
109
|
+
/** What an agent stage declares, checked by `defineWorkflow`. */
|
|
110
|
+
export interface AgentDeclaration {
|
|
111
|
+
profile: AgentProfile;
|
|
112
|
+
/** Name of the prompt text the run supplies; defaults to the stage name. Letters, digits, - or _, so that a caller can keep each prompt in a file of that name. */
|
|
113
|
+
prompt?: string;
|
|
114
|
+
/** Conversation name; defaults to the stage name. */
|
|
115
|
+
session?: string | ((state: Readonly<RunState>) => string);
|
|
116
|
+
}
|
|
117
|
+
export interface Stage<O extends string = string> {
|
|
118
|
+
kind: StageKind;
|
|
119
|
+
outcomes: readonly O[];
|
|
120
|
+
agent?: AgentDeclaration;
|
|
121
|
+
run: (context: StageContext) => Promise<StageResult<O>>;
|
|
122
|
+
}
|
|
123
|
+
/** A correction route, taken at most `max` times per run. */
|
|
124
|
+
export interface RetryEdge {
|
|
125
|
+
to: string;
|
|
126
|
+
max: number;
|
|
127
|
+
}
|
|
128
|
+
/** Next stage name, END (null) or a bounded correction route. */
|
|
129
|
+
export type Edge = string | null | RetryEdge;
|
|
130
|
+
export interface WorkflowNode<O extends string = string> {
|
|
131
|
+
stage: Stage<O>;
|
|
132
|
+
on: Record<O, Edge>;
|
|
133
|
+
}
|
|
134
|
+
/** What a workflow author writes: inputs, graph and an optional rendering. */
|
|
135
|
+
export interface WorkflowDefinition {
|
|
136
|
+
/** Letters, digits, - or _, so that a caller can name a folder after it. */
|
|
137
|
+
name: string;
|
|
138
|
+
/** Validates each run's input, strictly. */
|
|
139
|
+
input?: z.ZodObject;
|
|
140
|
+
initial: string;
|
|
141
|
+
nodes: Record<string, WorkflowNode>;
|
|
142
|
+
/** Fails a run once its agents' announced cost exceeds it, in USD; a run's own budget replaces it. */
|
|
143
|
+
maxCostUsd?: number;
|
|
144
|
+
/** Result lines; by default the run's validated data as JSON. */
|
|
145
|
+
presentResult?(state: Readonly<RunState>): string[];
|
|
146
|
+
}
|
|
147
|
+
/** An agent stage as `defineWorkflow` resolves it. */
|
|
148
|
+
export interface AgentStage {
|
|
149
|
+
profile: ResolvedProfile;
|
|
150
|
+
prompt: string;
|
|
151
|
+
}
|
|
152
|
+
/** A workflow validated by `defineWorkflow`. */
|
|
153
|
+
export interface Workflow extends WorkflowDefinition {
|
|
154
|
+
/** Agent stages by stage name. */
|
|
155
|
+
agents: Record<string, AgentStage>;
|
|
156
|
+
presentResult(state: Readonly<RunState>): string[];
|
|
157
|
+
}
|
|
158
|
+
export interface RetryContext {
|
|
159
|
+
/** The retry edge, `<stage>.<outcome>`. */
|
|
160
|
+
key: string;
|
|
161
|
+
count: number;
|
|
162
|
+
max: number;
|
|
163
|
+
}
|
|
164
|
+
interface EventBase {
|
|
165
|
+
runId: string;
|
|
166
|
+
stage: string;
|
|
167
|
+
kind: StageKind;
|
|
168
|
+
at: string;
|
|
169
|
+
}
|
|
170
|
+
/** Recorded by the engine when a stage starts and when it ends. */
|
|
171
|
+
export interface StageEvent extends EventBase {
|
|
172
|
+
type: "stage";
|
|
173
|
+
status: "started" | "passed" | "failed" | "completed";
|
|
174
|
+
retry?: RetryContext;
|
|
175
|
+
decision?: WorkflowDecision;
|
|
176
|
+
detail?: string;
|
|
177
|
+
}
|
|
178
|
+
/** Recorded by a stage, or by the agent runtime on its behalf, while it runs. */
|
|
179
|
+
export interface LogEvent extends EventBase {
|
|
180
|
+
type: "log";
|
|
181
|
+
message: string;
|
|
182
|
+
data?: Record<string, unknown>;
|
|
183
|
+
}
|
|
184
|
+
/** Recorded by the agent runtime for the calling stage while it runs. */
|
|
185
|
+
export interface AgentEvent extends EventBase {
|
|
186
|
+
type: "agent";
|
|
187
|
+
activity: AgentActivity;
|
|
188
|
+
}
|
|
189
|
+
export type RunEvent = StageEvent | LogEvent | AgentEvent;
|
|
190
|
+
export interface RunStore {
|
|
191
|
+
save(state: RunState): Promise<void>;
|
|
192
|
+
event(event: RunEvent): Promise<void>;
|
|
193
|
+
}
|
|
194
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RunState, Workflow, WorkflowDefinition } from "./types.js";
|
|
2
|
+
/** True for a workflow returned by `defineWorkflow`. */
|
|
3
|
+
export declare function isWorkflow(value: unknown): value is Workflow;
|
|
4
|
+
/** By default a run shows its validated data, never raw agent output. */
|
|
5
|
+
export declare function presentData(state: Readonly<RunState>): string[];
|
|
6
|
+
/**
|
|
7
|
+
* Validates a workflow when it is declared: graph, retry maximums, loops, agent
|
|
8
|
+
* stages and inputs. Agent profiles are returned with their defaults applied.
|
|
9
|
+
*/
|
|
10
|
+
export declare function defineWorkflow(definition: WorkflowDefinition): Workflow;
|
|
11
|
+
/** A problem of a run's input: an unknown field, or an invalid or missing one, by its path. */
|
|
12
|
+
export interface InputProblem {
|
|
13
|
+
kind: "unknown" | "invalid";
|
|
14
|
+
/** The field's path, its names joined by `.`. */
|
|
15
|
+
field: string;
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
/** A run's input refused by its workflow's input object, with every problem. */
|
|
19
|
+
export declare class InvalidInputError extends Error {
|
|
20
|
+
readonly problems: InputProblem[];
|
|
21
|
+
constructor(workflow: string, problems: InputProblem[]);
|
|
22
|
+
}
|
|
23
|
+
/** Validates a run's input against the workflow's input object, strictly; every problem is listed. */
|
|
24
|
+
export declare function parseInput(workflow: Pick<Workflow, "name" | "input">, input: Record<string, unknown>): Record<string, unknown>;
|