@polpo-ai/core 0.8.0 → 0.9.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/dist/approval-manager.d.ts +1 -0
- package/dist/approval-manager.d.ts.map +1 -1
- package/dist/approval-manager.js +7 -9
- package/dist/approval-manager.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/loop/contract.test.d.ts +2 -0
- package/dist/loop/contract.test.d.ts.map +1 -0
- package/dist/loop/contract.test.js +55 -0
- package/dist/loop/contract.test.js.map +1 -0
- package/dist/loop/expression.d.ts +29 -0
- package/dist/loop/expression.d.ts.map +1 -0
- package/dist/loop/expression.js +215 -0
- package/dist/loop/expression.js.map +1 -0
- package/dist/loop/expression.test.d.ts +2 -0
- package/dist/loop/expression.test.d.ts.map +1 -0
- package/dist/loop/expression.test.js +55 -0
- package/dist/loop/expression.test.js.map +1 -0
- package/dist/loop/hooks.d.ts +132 -0
- package/dist/loop/hooks.d.ts.map +1 -0
- package/dist/loop/hooks.js +85 -0
- package/dist/loop/hooks.js.map +1 -0
- package/dist/loop/pipeline.d.ts +38 -0
- package/dist/loop/pipeline.d.ts.map +1 -0
- package/dist/loop/pipeline.js +101 -0
- package/dist/loop/pipeline.js.map +1 -0
- package/dist/loop/pipeline.test.d.ts +2 -0
- package/dist/loop/pipeline.test.d.ts.map +1 -0
- package/dist/loop/pipeline.test.js +103 -0
- package/dist/loop/pipeline.test.js.map +1 -0
- package/dist/loop/runner.d.ts +44 -0
- package/dist/loop/runner.d.ts.map +1 -0
- package/dist/loop/runner.js +215 -0
- package/dist/loop/runner.js.map +1 -0
- package/dist/loop/runner.test.d.ts +2 -0
- package/dist/loop/runner.test.d.ts.map +1 -0
- package/dist/loop/runner.test.js +124 -0
- package/dist/loop/runner.test.js.map +1 -0
- package/dist/loop/selector.d.ts +12 -0
- package/dist/loop/selector.d.ts.map +1 -0
- package/dist/loop/selector.js +44 -0
- package/dist/loop/selector.js.map +1 -0
- package/dist/loop/selector.test.d.ts +2 -0
- package/dist/loop/selector.test.d.ts.map +1 -0
- package/dist/loop/selector.test.js +45 -0
- package/dist/loop/selector.test.js.map +1 -0
- package/dist/loop/types.d.ts +98 -0
- package/dist/loop/types.d.ts.map +1 -0
- package/dist/loop/types.js +15 -0
- package/dist/loop/types.js.map +1 -0
- package/dist/schemas.d.ts +55 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +99 -0
- package/dist/schemas.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { SafeExpressionEvaluator } from "./expression.js";
|
|
2
|
+
import { LoopHookRegistry, } from "./hooks.js";
|
|
3
|
+
const DEFAULT_MAX_TURNS = 20;
|
|
4
|
+
function normalizeLoop(loop) {
|
|
5
|
+
return {
|
|
6
|
+
...loop,
|
|
7
|
+
name: loop.name ?? "default",
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function shouldStopAfterTurn(loop, context, result, turn, maxTurns, evaluator) {
|
|
11
|
+
const reachedMaxTurns = turn + 1 >= maxTurns;
|
|
12
|
+
if (loop.stopWhen) {
|
|
13
|
+
const matched = evaluator.evaluate(loop.stopWhen.expression, context);
|
|
14
|
+
if (matched)
|
|
15
|
+
return { reason: "completed", shouldStop: true };
|
|
16
|
+
return reachedMaxTurns ? { reason: "max_turns", shouldStop: true } : { reason: "completed", shouldStop: false };
|
|
17
|
+
}
|
|
18
|
+
if ((result.toolCalls ?? []).length === 0)
|
|
19
|
+
return { reason: "completed", shouldStop: true };
|
|
20
|
+
if (reachedMaxTurns)
|
|
21
|
+
return { reason: "max_turns", shouldStop: true };
|
|
22
|
+
return { reason: "completed", shouldStop: false };
|
|
23
|
+
}
|
|
24
|
+
export class LoopRunner {
|
|
25
|
+
hooks;
|
|
26
|
+
evaluator = new SafeExpressionEvaluator();
|
|
27
|
+
constructor(hooks) {
|
|
28
|
+
this.hooks = hooks ?? new LoopHookRegistry();
|
|
29
|
+
}
|
|
30
|
+
async run(options) {
|
|
31
|
+
const hooks = options.hooks ?? this.hooks;
|
|
32
|
+
const loop = normalizeLoop(options.loop);
|
|
33
|
+
const context = options.context ?? {};
|
|
34
|
+
const maxTurns = options.maxTurns ?? loop.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
35
|
+
let finalText = "";
|
|
36
|
+
let turns = 0;
|
|
37
|
+
const allToolResults = [];
|
|
38
|
+
const start = await hooks.runBefore("loop:start", {
|
|
39
|
+
agent: options.agent,
|
|
40
|
+
loop,
|
|
41
|
+
context,
|
|
42
|
+
input: options.input,
|
|
43
|
+
});
|
|
44
|
+
if (start.cancelled) {
|
|
45
|
+
return this.finish(hooks, {
|
|
46
|
+
agent: options.agent,
|
|
47
|
+
loop,
|
|
48
|
+
context,
|
|
49
|
+
status: "cancelled",
|
|
50
|
+
reason: "cancelled",
|
|
51
|
+
turns,
|
|
52
|
+
text: finalText,
|
|
53
|
+
toolResults: allToolResults,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
for (let turn = 0; turn < maxTurns; turn++) {
|
|
57
|
+
turns = turn + 1;
|
|
58
|
+
const step = await hooks.runBefore("step:before", {
|
|
59
|
+
agent: options.agent,
|
|
60
|
+
loop,
|
|
61
|
+
turn,
|
|
62
|
+
context,
|
|
63
|
+
activeTools: loop.tools,
|
|
64
|
+
});
|
|
65
|
+
if (step.cancelled) {
|
|
66
|
+
return this.finish(hooks, {
|
|
67
|
+
agent: options.agent,
|
|
68
|
+
loop,
|
|
69
|
+
context,
|
|
70
|
+
status: "cancelled",
|
|
71
|
+
reason: "cancelled",
|
|
72
|
+
turns,
|
|
73
|
+
text: finalText,
|
|
74
|
+
toolResults: allToolResults,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const modelBefore = await hooks.runBefore("model:before", {
|
|
78
|
+
agent: options.agent,
|
|
79
|
+
loop,
|
|
80
|
+
turn,
|
|
81
|
+
context,
|
|
82
|
+
activeTools: step.data.activeTools,
|
|
83
|
+
toolChoice: step.data.toolChoice,
|
|
84
|
+
});
|
|
85
|
+
if (modelBefore.cancelled) {
|
|
86
|
+
return this.finish(hooks, {
|
|
87
|
+
agent: options.agent,
|
|
88
|
+
loop,
|
|
89
|
+
context,
|
|
90
|
+
status: "cancelled",
|
|
91
|
+
reason: "cancelled",
|
|
92
|
+
turns,
|
|
93
|
+
text: finalText,
|
|
94
|
+
toolResults: allToolResults,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const modelInput = {
|
|
98
|
+
agent: options.agent,
|
|
99
|
+
loop,
|
|
100
|
+
turn,
|
|
101
|
+
context,
|
|
102
|
+
activeTools: modelBefore.data.activeTools,
|
|
103
|
+
toolChoice: modelBefore.data.toolChoice,
|
|
104
|
+
};
|
|
105
|
+
const modelResult = await options.model(modelInput);
|
|
106
|
+
finalText += modelResult.text;
|
|
107
|
+
const toolResults = [];
|
|
108
|
+
for (const rawCall of modelResult.toolCalls ?? []) {
|
|
109
|
+
const before = await hooks.runBefore("tool:before", {
|
|
110
|
+
agent: options.agent,
|
|
111
|
+
loop,
|
|
112
|
+
turn,
|
|
113
|
+
context,
|
|
114
|
+
toolCall: { ...rawCall, args: { ...rawCall.args } },
|
|
115
|
+
});
|
|
116
|
+
const toolCall = before.data.toolCall;
|
|
117
|
+
const skipped = before.cancelled;
|
|
118
|
+
const result = skipped
|
|
119
|
+
? before.data.result ?? `Error: Tool call "${toolCall.name}" denied${before.cancelReason ? `: ${before.cancelReason}` : ""}`
|
|
120
|
+
: await options.executeTool(toolCall, modelInput);
|
|
121
|
+
const toolResult = {
|
|
122
|
+
toolCall,
|
|
123
|
+
result,
|
|
124
|
+
isError: result.startsWith("Error:"),
|
|
125
|
+
skipped,
|
|
126
|
+
};
|
|
127
|
+
toolResults.push(toolResult);
|
|
128
|
+
allToolResults.push(toolResult);
|
|
129
|
+
await hooks.runAfter("tool:after", {
|
|
130
|
+
agent: options.agent,
|
|
131
|
+
loop,
|
|
132
|
+
turn,
|
|
133
|
+
context,
|
|
134
|
+
toolCall,
|
|
135
|
+
result,
|
|
136
|
+
isError: toolResult.isError,
|
|
137
|
+
skipped,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
await hooks.runAfter("step:after", {
|
|
141
|
+
agent: options.agent,
|
|
142
|
+
loop,
|
|
143
|
+
turn,
|
|
144
|
+
context,
|
|
145
|
+
text: modelResult.text,
|
|
146
|
+
toolCalls: modelResult.toolCalls ?? [],
|
|
147
|
+
toolResults,
|
|
148
|
+
usage: modelResult.usage,
|
|
149
|
+
});
|
|
150
|
+
const stop = shouldStopAfterTurn(loop, context, modelResult, turn, maxTurns, this.evaluator);
|
|
151
|
+
const stopResult = await hooks.runBefore("loop:stop", {
|
|
152
|
+
agent: options.agent,
|
|
153
|
+
loop,
|
|
154
|
+
turn,
|
|
155
|
+
context,
|
|
156
|
+
reason: stop.reason,
|
|
157
|
+
shouldStop: stop.shouldStop,
|
|
158
|
+
});
|
|
159
|
+
if (stopResult.cancelled) {
|
|
160
|
+
return this.finish(hooks, {
|
|
161
|
+
agent: options.agent,
|
|
162
|
+
loop,
|
|
163
|
+
context,
|
|
164
|
+
status: "cancelled",
|
|
165
|
+
reason: "cancelled",
|
|
166
|
+
turns,
|
|
167
|
+
text: finalText,
|
|
168
|
+
toolResults: allToolResults,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
if (stopResult.data.shouldStop) {
|
|
172
|
+
return this.finish(hooks, {
|
|
173
|
+
agent: options.agent,
|
|
174
|
+
loop,
|
|
175
|
+
context,
|
|
176
|
+
status: "completed",
|
|
177
|
+
reason: stopResult.data.reason,
|
|
178
|
+
turns,
|
|
179
|
+
text: finalText,
|
|
180
|
+
toolResults: allToolResults,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return this.finish(hooks, {
|
|
185
|
+
agent: options.agent,
|
|
186
|
+
loop,
|
|
187
|
+
context,
|
|
188
|
+
status: "completed",
|
|
189
|
+
reason: "max_turns",
|
|
190
|
+
turns,
|
|
191
|
+
text: finalText,
|
|
192
|
+
toolResults: allToolResults,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
async finish(hooks, result) {
|
|
196
|
+
await hooks.runAfter("loop:end", {
|
|
197
|
+
agent: result.agent,
|
|
198
|
+
loop: result.loop,
|
|
199
|
+
context: result.context,
|
|
200
|
+
status: result.status,
|
|
201
|
+
reason: result.reason,
|
|
202
|
+
turns: result.turns,
|
|
203
|
+
text: result.text,
|
|
204
|
+
});
|
|
205
|
+
return {
|
|
206
|
+
status: result.status,
|
|
207
|
+
reason: result.reason,
|
|
208
|
+
turns: result.turns,
|
|
209
|
+
text: result.text,
|
|
210
|
+
context: result.context,
|
|
211
|
+
toolResults: result.toolResults,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/loop/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.test.d.ts","sourceRoot":"","sources":["../../src/loop/runner.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { LoopHookRegistry } from "./hooks.js";
|
|
3
|
+
import { LoopRunner } from "./runner.js";
|
|
4
|
+
describe("LoopRunner", () => {
|
|
5
|
+
it("runs the implicit loop with ordered lifecycle hooks", async () => {
|
|
6
|
+
const events = [];
|
|
7
|
+
const hooks = new LoopHookRegistry();
|
|
8
|
+
hooks.register({ hook: "loop:start", phase: "before", handler: () => { events.push("loop:start"); } });
|
|
9
|
+
hooks.register({ hook: "step:before", phase: "before", handler: () => { events.push("step:before"); } });
|
|
10
|
+
hooks.register({ hook: "model:before", phase: "before", handler: () => { events.push("model:before"); } });
|
|
11
|
+
hooks.register({ hook: "step:after", phase: "after", handler: () => { events.push("step:after"); } });
|
|
12
|
+
hooks.register({ hook: "loop:stop", phase: "before", handler: () => { events.push("loop:stop"); } });
|
|
13
|
+
hooks.register({ hook: "loop:end", phase: "after", handler: () => { events.push("loop:end"); } });
|
|
14
|
+
const runner = new LoopRunner(hooks);
|
|
15
|
+
const result = await runner.run({
|
|
16
|
+
loop: { name: "default" },
|
|
17
|
+
model: async () => ({ text: "done" }),
|
|
18
|
+
executeTool: async () => "unused",
|
|
19
|
+
});
|
|
20
|
+
expect(result).toMatchObject({ status: "completed", reason: "completed", turns: 1, text: "done" });
|
|
21
|
+
expect(events).toEqual(["loop:start", "step:before", "model:before", "step:after", "loop:stop", "loop:end"]);
|
|
22
|
+
});
|
|
23
|
+
it("lets step hooks constrain active tools before the model call", async () => {
|
|
24
|
+
const hooks = new LoopHookRegistry();
|
|
25
|
+
hooks.register({
|
|
26
|
+
hook: "step:before",
|
|
27
|
+
phase: "before",
|
|
28
|
+
handler: (ctx) => {
|
|
29
|
+
ctx.data.activeTools = ["read"];
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
const seenTools = [];
|
|
33
|
+
const runner = new LoopRunner(hooks);
|
|
34
|
+
await runner.run({
|
|
35
|
+
loop: { name: "plan", tools: ["read", "write"] },
|
|
36
|
+
model: async (input) => {
|
|
37
|
+
seenTools.push(input.activeTools);
|
|
38
|
+
return { text: "planned" };
|
|
39
|
+
},
|
|
40
|
+
executeTool: async () => "unused",
|
|
41
|
+
});
|
|
42
|
+
expect(seenTools).toEqual([["read"]]);
|
|
43
|
+
});
|
|
44
|
+
it("allows tool:before hooks to deny a tool call without invoking the executor", async () => {
|
|
45
|
+
const hooks = new LoopHookRegistry();
|
|
46
|
+
hooks.register({
|
|
47
|
+
hook: "tool:before",
|
|
48
|
+
phase: "before",
|
|
49
|
+
handler: (ctx) => {
|
|
50
|
+
if (ctx.data.toolCall.name === "write")
|
|
51
|
+
ctx.cancel("read-only loop");
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
let executed = false;
|
|
55
|
+
const runner = new LoopRunner(hooks);
|
|
56
|
+
const result = await runner.run({
|
|
57
|
+
loop: { name: "plan", tools: ["read"] },
|
|
58
|
+
maxTurns: 1,
|
|
59
|
+
model: async () => ({
|
|
60
|
+
text: "I will write.",
|
|
61
|
+
toolCalls: [{ id: "call-1", name: "write", args: { path: "x.txt" } }],
|
|
62
|
+
}),
|
|
63
|
+
executeTool: async () => {
|
|
64
|
+
executed = true;
|
|
65
|
+
return "should not run";
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
expect(executed).toBe(false);
|
|
69
|
+
expect(result.toolResults).toHaveLength(1);
|
|
70
|
+
expect(result.toolResults[0]).toMatchObject({
|
|
71
|
+
skipped: true,
|
|
72
|
+
isError: true,
|
|
73
|
+
result: 'Error: Tool call "write" denied: read-only loop',
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
it("continues when loop:stop mutates shouldStop to false", async () => {
|
|
77
|
+
const hooks = new LoopHookRegistry();
|
|
78
|
+
hooks.register({
|
|
79
|
+
hook: "loop:stop",
|
|
80
|
+
phase: "before",
|
|
81
|
+
handler: (ctx) => {
|
|
82
|
+
if (ctx.data.turn === 0)
|
|
83
|
+
ctx.data.shouldStop = false;
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
let calls = 0;
|
|
87
|
+
const runner = new LoopRunner(hooks);
|
|
88
|
+
const result = await runner.run({
|
|
89
|
+
loop: { name: "review" },
|
|
90
|
+
maxTurns: 2,
|
|
91
|
+
model: async () => {
|
|
92
|
+
calls++;
|
|
93
|
+
return { text: String(calls) };
|
|
94
|
+
},
|
|
95
|
+
executeTool: async () => "unused",
|
|
96
|
+
});
|
|
97
|
+
expect(result.text).toBe("12");
|
|
98
|
+
expect(result.turns).toBe(2);
|
|
99
|
+
expect(result.reason).toBe("completed");
|
|
100
|
+
});
|
|
101
|
+
it("uses stopWhen as the deterministic stop condition when configured", async () => {
|
|
102
|
+
const hooks = new LoopHookRegistry();
|
|
103
|
+
hooks.register({
|
|
104
|
+
hook: "step:after",
|
|
105
|
+
phase: "after",
|
|
106
|
+
handler: (ctx) => {
|
|
107
|
+
if (ctx.data.turn === 1)
|
|
108
|
+
ctx.data.context.done = true;
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
const runner = new LoopRunner(hooks);
|
|
112
|
+
const result = await runner.run({
|
|
113
|
+
loop: { name: "build", stopWhen: { expression: "done == true" } },
|
|
114
|
+
maxTurns: 3,
|
|
115
|
+
model: async () => ({ text: "tick" }),
|
|
116
|
+
executeTool: async () => "unused",
|
|
117
|
+
});
|
|
118
|
+
expect(result.text).toBe("ticktick");
|
|
119
|
+
expect(result.turns).toBe(2);
|
|
120
|
+
expect(result.reason).toBe("completed");
|
|
121
|
+
expect(result.context.done).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
//# sourceMappingURL=runner.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.test.js","sourceRoot":"","sources":["../../src/loop/runner.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentConfig } from "../types.js";
|
|
2
|
+
import type { LoopConfig } from "./types.js";
|
|
3
|
+
export interface LoopSelection {
|
|
4
|
+
name: string;
|
|
5
|
+
loop: LoopConfig & {
|
|
6
|
+
name: string;
|
|
7
|
+
};
|
|
8
|
+
agent: AgentConfig;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveActiveLoopTools(agent: AgentConfig, loop?: LoopConfig): string[] | undefined;
|
|
11
|
+
export declare function resolveLoopSelection(agent: AgentConfig, requestedLoop?: string): LoopSelection;
|
|
12
|
+
//# sourceMappingURL=selector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../src/loop/selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,MAAM,EAAE,GAAG,SAAS,CAElG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,aAAa,CAwB9F"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function resolveActiveLoopTools(agent, loop) {
|
|
2
|
+
return loop?.tools ?? agent.allowedTools;
|
|
3
|
+
}
|
|
4
|
+
export function resolveLoopSelection(agent, requestedLoop) {
|
|
5
|
+
if (!requestedLoop) {
|
|
6
|
+
const defaultLoop = agent.loops?.default;
|
|
7
|
+
if (!defaultLoop) {
|
|
8
|
+
return {
|
|
9
|
+
name: "default",
|
|
10
|
+
loop: { name: "default", tools: agent.allowedTools, model: agent.model, reasoning: agent.reasoning, maxTurns: agent.maxTurns },
|
|
11
|
+
agent,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
return materializeLoopSelection(agent, "default", defaultLoop);
|
|
15
|
+
}
|
|
16
|
+
const loop = agent.loops?.[requestedLoop];
|
|
17
|
+
if (!loop) {
|
|
18
|
+
const available = Object.keys(agent.loops ?? {});
|
|
19
|
+
throw new Error(available.length > 0
|
|
20
|
+
? `Unknown loop "${requestedLoop}". Available loops: ${available.join(", ")}`
|
|
21
|
+
: `Agent "${agent.name}" does not define configurable loops`);
|
|
22
|
+
}
|
|
23
|
+
return materializeLoopSelection(agent, requestedLoop, loop);
|
|
24
|
+
}
|
|
25
|
+
function materializeLoopSelection(agent, name, loop) {
|
|
26
|
+
const loopWithName = { ...loop, name: loop.name ?? name };
|
|
27
|
+
const loopPrompt = loop.systemPrompt?.trim();
|
|
28
|
+
const systemPrompt = loopPrompt
|
|
29
|
+
? [agent.systemPrompt, `## Active loop: ${loopWithName.name}`, loopPrompt].filter(Boolean).join("\n\n")
|
|
30
|
+
: agent.systemPrompt;
|
|
31
|
+
return {
|
|
32
|
+
name: loopWithName.name,
|
|
33
|
+
loop: loopWithName,
|
|
34
|
+
agent: {
|
|
35
|
+
...agent,
|
|
36
|
+
systemPrompt,
|
|
37
|
+
allowedTools: resolveActiveLoopTools(agent, loop),
|
|
38
|
+
model: loop.model ?? agent.model,
|
|
39
|
+
reasoning: loop.reasoning ?? agent.reasoning,
|
|
40
|
+
maxTurns: loop.maxTurns ?? agent.maxTurns,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.js","sourceRoot":"","sources":["../../src/loop/selector.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,sBAAsB,CAAC,KAAkB,EAAE,IAAiB;IAC1E,OAAO,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,YAAY,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAkB,EAAE,aAAsB;IAC7E,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC;QACzC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE;gBAC9H,KAAK;aACN,CAAC;QACJ,CAAC;QACD,OAAO,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,aAAa,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,SAAS,CAAC,MAAM,GAAG,CAAC;YAClB,CAAC,CAAC,iBAAiB,aAAa,uBAAuB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC7E,CAAC,CAAC,UAAU,KAAK,CAAC,IAAI,sCAAsC,CAC/D,CAAC;IACJ,CAAC;IAED,OAAO,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAkB,EAAE,IAAY,EAAE,IAAgB;IAClF,MAAM,YAAY,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IAC7C,MAAM,YAAY,GAAG,UAAU;QAC7B,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,EAAE,mBAAmB,YAAY,CAAC,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QACvG,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;IAEvB,OAAO;QACL,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE;YACL,GAAG,KAAK;YACR,YAAY;YACZ,YAAY,EAAE,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC;YACjD,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK;YAChC,SAAS,EAAG,IAAI,CAAC,SAAwC,IAAI,KAAK,CAAC,SAAS;YAC5E,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ;SAC1C;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.test.d.ts","sourceRoot":"","sources":["../../src/loop/selector.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { resolveLoopSelection } from "./selector.js";
|
|
3
|
+
describe("resolveLoopSelection", () => {
|
|
4
|
+
it("keeps current agent behavior when no loop is requested", () => {
|
|
5
|
+
const agent = { name: "agent", model: "base", allowedTools: ["read"], systemPrompt: "base" };
|
|
6
|
+
const selected = resolveLoopSelection(agent);
|
|
7
|
+
expect(selected.name).toBe("default");
|
|
8
|
+
expect(selected.agent).toBe(agent);
|
|
9
|
+
});
|
|
10
|
+
it("applies requested loop overrides to the effective agent", () => {
|
|
11
|
+
const selected = resolveLoopSelection({
|
|
12
|
+
name: "agent",
|
|
13
|
+
model: "base",
|
|
14
|
+
reasoning: "low",
|
|
15
|
+
allowedTools: ["read", "write"],
|
|
16
|
+
systemPrompt: "base prompt",
|
|
17
|
+
loops: {
|
|
18
|
+
plan: {
|
|
19
|
+
systemPrompt: "plan prompt",
|
|
20
|
+
tools: ["read"],
|
|
21
|
+
model: "planner",
|
|
22
|
+
reasoning: "high",
|
|
23
|
+
maxTurns: 3,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}, "plan");
|
|
27
|
+
expect(selected.loop.name).toBe("plan");
|
|
28
|
+
expect(selected.agent).toMatchObject({
|
|
29
|
+
model: "planner",
|
|
30
|
+
reasoning: "high",
|
|
31
|
+
allowedTools: ["read"],
|
|
32
|
+
maxTurns: 3,
|
|
33
|
+
});
|
|
34
|
+
expect(selected.agent.systemPrompt).toContain("base prompt");
|
|
35
|
+
expect(selected.agent.systemPrompt).toContain("## Active loop: plan");
|
|
36
|
+
expect(selected.agent.systemPrompt).toContain("plan prompt");
|
|
37
|
+
});
|
|
38
|
+
it("throws a clear error for unknown requested loops", () => {
|
|
39
|
+
expect(() => resolveLoopSelection({
|
|
40
|
+
name: "agent",
|
|
41
|
+
loops: { plan: {} },
|
|
42
|
+
}, "build")).toThrow('Unknown loop "build". Available loops: plan');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=selector.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selector.test.js","sourceRoot":"","sources":["../../src/loop/selector.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;QAC7F,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAE7C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,QAAQ,GAAG,oBAAoB,CAAC;YACpC,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,MAAM;YACb,SAAS,EAAE,KAAK;YAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;YAC/B,YAAY,EAAE,aAAa;YAC3B,KAAK,EAAE;gBACL,IAAI,EAAE;oBACJ,YAAY,EAAE,aAAa;oBAC3B,KAAK,EAAE,CAAC,MAAM,CAAC;oBACf,KAAK,EAAE,SAAS;oBAChB,SAAS,EAAE,MAAM;oBACjB,QAAQ,EAAE,CAAC;iBACZ;aACF;SACF,EAAE,MAAM,CAAC,CAAC;QAEX,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;YACnC,KAAK,EAAE,SAAS;YAChB,SAAS,EAAE,MAAM;YACjB,YAAY,EAAE,CAAC,MAAM,CAAC;YACtB,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC7D,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACtE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC;YAChC,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;SACpB,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configurable agentic loops — config model (declarative surface).
|
|
3
|
+
*
|
|
4
|
+
* An agent has a collection of named loops (one active at a time) and an
|
|
5
|
+
* optional pipeline: a tree of heterogeneous steps with deterministic
|
|
6
|
+
* conditions over a shared, read-only context bag. Step kinds: loop (LLM),
|
|
7
|
+
* switch (deterministic branch), parallel (fork-join), human (structured human
|
|
8
|
+
* decision). See the loop-architecture design.
|
|
9
|
+
*/
|
|
10
|
+
export interface Condition {
|
|
11
|
+
/** Expression over the context bag, evaluated by SafeExpressionEvaluator. */
|
|
12
|
+
expression: string;
|
|
13
|
+
}
|
|
14
|
+
export type ContextBag = Record<string, unknown>;
|
|
15
|
+
export interface LoopConfig {
|
|
16
|
+
/** Optional — the loops-map key is the canonical name. */
|
|
17
|
+
name?: string;
|
|
18
|
+
systemPrompt?: string;
|
|
19
|
+
/** Tool subset active in this loop (restriction = determinism/safety). */
|
|
20
|
+
tools?: string[];
|
|
21
|
+
model?: string;
|
|
22
|
+
reasoning?: string;
|
|
23
|
+
temperature?: number;
|
|
24
|
+
maxTurns?: number;
|
|
25
|
+
/** Deterministic stop condition over the context bag. */
|
|
26
|
+
stopWhen?: Condition;
|
|
27
|
+
/** Structured output contract — the loop's typed deliverable. */
|
|
28
|
+
output?: {
|
|
29
|
+
schema?: unknown;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface SwitchCase {
|
|
33
|
+
when: string;
|
|
34
|
+
steps: Step[];
|
|
35
|
+
}
|
|
36
|
+
export type Step = {
|
|
37
|
+
loop: string;
|
|
38
|
+
when?: string;
|
|
39
|
+
} | {
|
|
40
|
+
parallel: Step[];
|
|
41
|
+
join?: "all" | "any" | number;
|
|
42
|
+
when?: string;
|
|
43
|
+
} | {
|
|
44
|
+
switch: {
|
|
45
|
+
cases: SwitchCase[];
|
|
46
|
+
default?: {
|
|
47
|
+
steps: Step[];
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
when?: string;
|
|
51
|
+
} | {
|
|
52
|
+
human: string;
|
|
53
|
+
output?: {
|
|
54
|
+
schema?: unknown;
|
|
55
|
+
};
|
|
56
|
+
notify?: string[];
|
|
57
|
+
when?: string;
|
|
58
|
+
};
|
|
59
|
+
export interface Pipeline {
|
|
60
|
+
mode?: "sequential" | "parallel";
|
|
61
|
+
context?: "shared";
|
|
62
|
+
steps: Step[];
|
|
63
|
+
}
|
|
64
|
+
export interface AgentLoopConfig {
|
|
65
|
+
name?: string;
|
|
66
|
+
model?: string;
|
|
67
|
+
/** Out-of-scope runtime/environment ref (default polpo-runner; custom image later). */
|
|
68
|
+
runtime?: string;
|
|
69
|
+
loops: Record<string, LoopConfig>;
|
|
70
|
+
pipeline?: Pipeline;
|
|
71
|
+
}
|
|
72
|
+
export declare const isLoopStep: (s: Step) => s is {
|
|
73
|
+
loop: string;
|
|
74
|
+
when?: string;
|
|
75
|
+
};
|
|
76
|
+
export declare const isParallelStep: (s: Step) => s is {
|
|
77
|
+
parallel: Step[];
|
|
78
|
+
join?: "all" | "any" | number;
|
|
79
|
+
when?: string;
|
|
80
|
+
};
|
|
81
|
+
export declare const isSwitchStep: (s: Step) => s is {
|
|
82
|
+
switch: {
|
|
83
|
+
cases: SwitchCase[];
|
|
84
|
+
default?: {
|
|
85
|
+
steps: Step[];
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
when?: string;
|
|
89
|
+
};
|
|
90
|
+
export declare const isHumanStep: (s: Step) => s is {
|
|
91
|
+
human: string;
|
|
92
|
+
output?: {
|
|
93
|
+
schema?: unknown;
|
|
94
|
+
};
|
|
95
|
+
notify?: string[];
|
|
96
|
+
when?: string;
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/loop/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configurable agentic loops — config model (declarative surface).
|
|
3
|
+
*
|
|
4
|
+
* An agent has a collection of named loops (one active at a time) and an
|
|
5
|
+
* optional pipeline: a tree of heterogeneous steps with deterministic
|
|
6
|
+
* conditions over a shared, read-only context bag. Step kinds: loop (LLM),
|
|
7
|
+
* switch (deterministic branch), parallel (fork-join), human (structured human
|
|
8
|
+
* decision). See the loop-architecture design.
|
|
9
|
+
*/
|
|
10
|
+
// ─── Step type guards ────────────────────────────────────
|
|
11
|
+
export const isLoopStep = (s) => "loop" in s;
|
|
12
|
+
export const isParallelStep = (s) => "parallel" in s;
|
|
13
|
+
export const isSwitchStep = (s) => "switch" in s;
|
|
14
|
+
export const isHumanStep = (s) => "human" in s;
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/loop/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmDH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAO,EAAwC,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC;AACzF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAO,EAA2E,EAAE,CACjH,UAAU,IAAI,CAAC,CAAC;AAClB,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,CAAO,EAC+E,EAAE,CAAC,QAAQ,IAAI,CAAC,CAAC;AACzG,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,CAAO,EACkF,EAAE,CAAC,OAAO,IAAI,CAAC,CAAC"}
|