@forwardimpact/libeval 0.1.13 → 0.1.15
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/bin/fit-eval.js +92 -44
- package/package.json +3 -2
- package/src/agent-runner.js +29 -40
- package/src/commands/facilitate.js +109 -0
- package/src/commands/run.js +17 -1
- package/src/facilitator.js +492 -0
- package/src/index.js +15 -2
- package/src/message-bus.js +100 -0
- package/src/orchestration-toolkit.js +209 -0
- package/src/sequence-counter.js +17 -0
- package/src/supervisor.js +128 -210
- package/src/tee-writer.js +20 -26
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OrchestrationToolkit — tool schemas, per-role tool sets, and handler
|
|
3
|
+
* factories for orchestration between supervisors, facilitators, and agents.
|
|
4
|
+
*
|
|
5
|
+
* Handlers communicate via a shared context object. The orchestrator reads
|
|
6
|
+
* context at natural checkpoints (after resume(), after onBatch).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Create a fresh orchestration context object.
|
|
14
|
+
* @returns {object}
|
|
15
|
+
*/
|
|
16
|
+
export function createOrchestrationContext() {
|
|
17
|
+
return {
|
|
18
|
+
concluded: false,
|
|
19
|
+
summary: null,
|
|
20
|
+
redirect: null,
|
|
21
|
+
participants: [],
|
|
22
|
+
messageBus: null,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// --- Handler factories ---
|
|
27
|
+
|
|
28
|
+
export function createConcludeHandler(ctx) {
|
|
29
|
+
return async ({ summary }) => {
|
|
30
|
+
ctx.concluded = true;
|
|
31
|
+
ctx.summary = summary;
|
|
32
|
+
return { content: [{ type: "text", text: "Session concluded." }] };
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function createRedirectHandler(ctx) {
|
|
37
|
+
return async ({ message, to }) => {
|
|
38
|
+
ctx.redirect = { message, to: to ?? null };
|
|
39
|
+
return { content: [{ type: "text", text: "Redirect queued." }] };
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function createAskHandler(ctx, { onAsk }) {
|
|
44
|
+
return async ({ question }) => {
|
|
45
|
+
try {
|
|
46
|
+
const answer = await onAsk(question);
|
|
47
|
+
return { content: [{ type: "text", text: answer }] };
|
|
48
|
+
} catch (err) {
|
|
49
|
+
return {
|
|
50
|
+
content: [{ type: "text", text: `Error: ${err.message}` }],
|
|
51
|
+
isError: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function createRollCallHandler(ctx) {
|
|
58
|
+
return async () => {
|
|
59
|
+
return {
|
|
60
|
+
content: [{ type: "text", text: JSON.stringify(ctx.participants) }],
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function createShareHandler(ctx, { from }) {
|
|
66
|
+
return async ({ message }) => {
|
|
67
|
+
ctx.messageBus.share(from, message);
|
|
68
|
+
return { content: [{ type: "text", text: "Message shared." }] };
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function createTellHandler(ctx, { from }) {
|
|
73
|
+
return async ({ message, to }) => {
|
|
74
|
+
ctx.messageBus.tell(from, to, message);
|
|
75
|
+
return { content: [{ type: "text", text: "Message sent." }] };
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// --- Per-role MCP server factories ---
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Supervisor tools: Conclude + Redirect.
|
|
83
|
+
* @param {object} ctx - Orchestration context
|
|
84
|
+
* @returns {object} MCP server config (type: "sdk")
|
|
85
|
+
*/
|
|
86
|
+
export function createSupervisorToolServer(ctx) {
|
|
87
|
+
return createSdkMcpServer({
|
|
88
|
+
name: "orchestration",
|
|
89
|
+
tools: [
|
|
90
|
+
tool(
|
|
91
|
+
"Conclude",
|
|
92
|
+
"Signal that the evaluation is done. Provide a summary.",
|
|
93
|
+
{ summary: z.string() },
|
|
94
|
+
createConcludeHandler(ctx),
|
|
95
|
+
),
|
|
96
|
+
tool(
|
|
97
|
+
"Redirect",
|
|
98
|
+
"Interrupt the agent with a corrective message.",
|
|
99
|
+
{ message: z.string(), to: z.string().optional() },
|
|
100
|
+
createRedirectHandler(ctx),
|
|
101
|
+
),
|
|
102
|
+
],
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Supervised agent tools: Ask.
|
|
108
|
+
* @param {object} ctx - Orchestration context
|
|
109
|
+
* @param {object} opts
|
|
110
|
+
* @param {function} opts.onAsk - Async callback: (question) → answer string
|
|
111
|
+
* @returns {object} MCP server config (type: "sdk")
|
|
112
|
+
*/
|
|
113
|
+
export function createSupervisedAgentToolServer(ctx, { onAsk }) {
|
|
114
|
+
return createSdkMcpServer({
|
|
115
|
+
name: "orchestration",
|
|
116
|
+
tools: [
|
|
117
|
+
tool(
|
|
118
|
+
"Ask",
|
|
119
|
+
"Ask the supervisor a clarifying question. Blocks until answered.",
|
|
120
|
+
{ question: z.string() },
|
|
121
|
+
createAskHandler(ctx, { onAsk }),
|
|
122
|
+
),
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Facilitator tools: Conclude + Redirect + RollCall + Share + Tell.
|
|
129
|
+
* No Ask — the facilitator answers Ask calls, not issues them.
|
|
130
|
+
* @param {object} ctx - Orchestration context
|
|
131
|
+
* @returns {object} MCP server config (type: "sdk")
|
|
132
|
+
*/
|
|
133
|
+
export function createFacilitatorToolServer(ctx) {
|
|
134
|
+
return createSdkMcpServer({
|
|
135
|
+
name: "orchestration",
|
|
136
|
+
tools: [
|
|
137
|
+
tool(
|
|
138
|
+
"Conclude",
|
|
139
|
+
"Signal that the task is done. Provide a summary.",
|
|
140
|
+
{ summary: z.string() },
|
|
141
|
+
createConcludeHandler(ctx),
|
|
142
|
+
),
|
|
143
|
+
tool(
|
|
144
|
+
"Redirect",
|
|
145
|
+
"Interrupt agents with a corrective message. Use to='all' for all agents or a specific agent name.",
|
|
146
|
+
{ message: z.string(), to: z.string().optional() },
|
|
147
|
+
createRedirectHandler(ctx),
|
|
148
|
+
),
|
|
149
|
+
tool(
|
|
150
|
+
"RollCall",
|
|
151
|
+
"List all participants in the session.",
|
|
152
|
+
{},
|
|
153
|
+
createRollCallHandler(ctx),
|
|
154
|
+
),
|
|
155
|
+
tool(
|
|
156
|
+
"Share",
|
|
157
|
+
"Broadcast a message to all participants.",
|
|
158
|
+
{ message: z.string() },
|
|
159
|
+
createShareHandler(ctx, { from: "facilitator" }),
|
|
160
|
+
),
|
|
161
|
+
tool(
|
|
162
|
+
"Tell",
|
|
163
|
+
"Send a direct message to one participant.",
|
|
164
|
+
{ message: z.string(), to: z.string() },
|
|
165
|
+
createTellHandler(ctx, { from: "facilitator" }),
|
|
166
|
+
),
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Facilitated agent tools: Ask + RollCall + Share + Tell.
|
|
173
|
+
* @param {object} ctx - Orchestration context
|
|
174
|
+
* @param {object} opts
|
|
175
|
+
* @param {string} opts.from - Agent name (for Share/Tell)
|
|
176
|
+
* @param {function} opts.onAsk - Async callback: (question) → answer string
|
|
177
|
+
* @returns {object} MCP server config (type: "sdk")
|
|
178
|
+
*/
|
|
179
|
+
export function createFacilitatedAgentToolServer(ctx, { from, onAsk }) {
|
|
180
|
+
return createSdkMcpServer({
|
|
181
|
+
name: "orchestration",
|
|
182
|
+
tools: [
|
|
183
|
+
tool(
|
|
184
|
+
"Ask",
|
|
185
|
+
"Ask the facilitator a clarifying question. Blocks until answered.",
|
|
186
|
+
{ question: z.string() },
|
|
187
|
+
createAskHandler(ctx, { onAsk }),
|
|
188
|
+
),
|
|
189
|
+
tool(
|
|
190
|
+
"RollCall",
|
|
191
|
+
"List all participants in the session.",
|
|
192
|
+
{},
|
|
193
|
+
createRollCallHandler(ctx),
|
|
194
|
+
),
|
|
195
|
+
tool(
|
|
196
|
+
"Share",
|
|
197
|
+
"Broadcast a message to all participants.",
|
|
198
|
+
{ message: z.string() },
|
|
199
|
+
createShareHandler(ctx, { from }),
|
|
200
|
+
),
|
|
201
|
+
tool(
|
|
202
|
+
"Tell",
|
|
203
|
+
"Send a direct message to one participant.",
|
|
204
|
+
{ message: z.string(), to: z.string() },
|
|
205
|
+
createTellHandler(ctx, { from }),
|
|
206
|
+
),
|
|
207
|
+
],
|
|
208
|
+
});
|
|
209
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SequenceCounter — global monotonic counter shared across all participants
|
|
3
|
+
* in a session. Single-threaded JS means no synchronization needed.
|
|
4
|
+
*/
|
|
5
|
+
export class SequenceCounter {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.value = 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
next() {
|
|
11
|
+
return this.value++;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function createSequenceCounter() {
|
|
16
|
+
return new SequenceCounter();
|
|
17
|
+
}
|