@forwardimpact/libeval 0.1.14 → 0.1.16

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.
@@ -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. After sending, stop making tool calls to receive responses.",
158
+ { message: z.string() },
159
+ createShareHandler(ctx, { from: "facilitator" }),
160
+ ),
161
+ tool(
162
+ "Tell",
163
+ "Send a direct message to one participant. After sending, stop making tool calls to receive their response.",
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
+ }