@forwardimpact/libeval 0.1.44 → 0.1.45
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/README.md +212 -13
- package/package.json +1 -1
- package/src/agent-runner.js +45 -181
- package/src/benchmark/runner.js +2 -2
- package/src/commands/supervise.js +3 -1
- package/src/discuss-tools.js +72 -140
- package/src/discusser.js +18 -35
- package/src/facilitator.js +26 -43
- package/src/index.js +0 -2
- package/src/judge.js +1 -1
- package/src/message-bus.js +27 -81
- package/src/orchestration-loop.js +176 -229
- package/src/orchestration-toolkit.js +272 -303
- package/src/orchestrator-helpers.js +9 -45
- package/src/redaction.js +2 -0
- package/src/render/orchestrator-filter.js +1 -9
- package/src/supervisor.js +79 -465
package/src/message-bus.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MessageBus — in-memory per-participant message queues
|
|
3
|
-
* supervised modes. The message vocabulary mirrors the orchestration toolkit:
|
|
2
|
+
* MessageBus — in-memory per-participant message queues.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
4
|
+
* Four message kinds, each pushed onto the addressee's queue:
|
|
5
|
+
*
|
|
6
|
+
* - `ask(from, to, text, askId)` — direct question; the toolkit owns the
|
|
7
|
+
* pending-ask state separately. Fan-out (broadcast Ask) happens at the
|
|
8
|
+
* handler level by calling `ask()` once per addressee.
|
|
9
|
+
* - `answer(from, to, text, askId)` — direct reply to the original asker.
|
|
10
|
+
* The orchestrator may inject synthetic answers (`from === "@orchestrator"`)
|
|
11
|
+
* when an Ask times out.
|
|
12
|
+
* - `announce(from, text)` — broadcast, no reply expected; lands on every
|
|
13
|
+
* participant's queue except the sender's.
|
|
14
|
+
* - `synthetic(to, text)` — orchestrator-only reminder injection.
|
|
11
15
|
*
|
|
12
16
|
* Follows OO+DI: constructor injection, factory function, tests bypass factory.
|
|
13
17
|
*/
|
|
14
18
|
|
|
15
|
-
/** In-memory per-participant message queues
|
|
19
|
+
/** In-memory per-participant message queues. */
|
|
16
20
|
export class MessageBus {
|
|
17
21
|
/**
|
|
18
22
|
* @param {object} deps
|
|
19
|
-
* @param {string[]} deps.participants -
|
|
23
|
+
* @param {string[]} deps.participants - Canonical participant names.
|
|
20
24
|
*/
|
|
21
25
|
constructor({ participants }) {
|
|
22
26
|
this.queues = new Map();
|
|
@@ -27,55 +31,30 @@ export class MessageBus {
|
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
/**
|
|
31
|
-
* Send a question to a participant (direct), or broadcast when
|
|
32
|
-
* `to === "@broadcast"`.
|
|
33
|
-
* @param {string} from
|
|
34
|
-
* @param {string} to - Recipient name or "@broadcast"
|
|
35
|
-
* @param {string} text
|
|
36
|
-
* @param {number} askId
|
|
37
|
-
*/
|
|
34
|
+
/** Send a question to one participant. */
|
|
38
35
|
ask(from, to, text, askId) {
|
|
39
36
|
this.#assertParticipant(from);
|
|
40
|
-
if (to === "@broadcast") {
|
|
41
|
-
for (const [name, queue] of this.queues) {
|
|
42
|
-
if (name === from) continue;
|
|
43
|
-
queue.push({ from, text, kind: "ask", askId, direct: false });
|
|
44
|
-
this.#resolveWaiter(name);
|
|
45
|
-
}
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
37
|
this.#assertParticipant(to);
|
|
49
|
-
this.queues.get(to).push({ from, text, kind: "ask", askId
|
|
38
|
+
this.queues.get(to).push({ from, text, kind: "ask", askId });
|
|
50
39
|
this.#resolveWaiter(to);
|
|
51
40
|
}
|
|
52
41
|
|
|
53
42
|
/**
|
|
54
|
-
* Reply to a pending ask.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* @param {string} text
|
|
58
|
-
* @param {number} askId
|
|
43
|
+
* Reply to a pending ask. `from === "@orchestrator"` is allowed for
|
|
44
|
+
* synthetic null answers — the orchestrator is not a real participant
|
|
45
|
+
* but it routes through the bus.
|
|
59
46
|
*/
|
|
60
47
|
answer(from, to, text, askId) {
|
|
61
48
|
this.#assertParticipant(to);
|
|
62
|
-
// Synthetic answers from the orchestrator bypass the participant check
|
|
63
|
-
// on `from` — the orchestrator is not a message-bus participant.
|
|
64
49
|
if (from !== "@orchestrator") this.#assertParticipant(from);
|
|
65
|
-
this.queues
|
|
66
|
-
.get(to)
|
|
67
|
-
.push({ from, text, kind: "answer", askId, direct: true });
|
|
50
|
+
this.queues.get(to).push({ from, text, kind: "answer", askId });
|
|
68
51
|
this.#resolveWaiter(to);
|
|
69
52
|
}
|
|
70
53
|
|
|
71
|
-
/**
|
|
72
|
-
* Broadcast a message to every participant except the sender.
|
|
73
|
-
* @param {string} from
|
|
74
|
-
* @param {string} text
|
|
75
|
-
*/
|
|
54
|
+
/** Broadcast a message to every participant except the sender. */
|
|
76
55
|
announce(from, text) {
|
|
77
56
|
this.#assertParticipant(from);
|
|
78
|
-
const msg = { from, text, kind: "announce"
|
|
57
|
+
const msg = { from, text, kind: "announce" };
|
|
79
58
|
for (const [name, queue] of this.queues) {
|
|
80
59
|
if (name === from) continue;
|
|
81
60
|
queue.push(msg);
|
|
@@ -83,53 +62,24 @@ export class MessageBus {
|
|
|
83
62
|
}
|
|
84
63
|
}
|
|
85
64
|
|
|
86
|
-
/**
|
|
87
|
-
* Send a direct message with no reply expected. Used by the Redirect
|
|
88
|
-
* runtime plumbing (facilitator / supervisor) to deliver replacement
|
|
89
|
-
* instructions to a single participant without engaging the ask/answer
|
|
90
|
-
* contract.
|
|
91
|
-
* @param {string} from
|
|
92
|
-
* @param {string} to
|
|
93
|
-
* @param {string} text
|
|
94
|
-
*/
|
|
95
|
-
direct(from, to, text) {
|
|
96
|
-
this.#assertParticipant(from);
|
|
97
|
-
this.#assertParticipant(to);
|
|
98
|
-
this.queues.get(to).push({ from, text, kind: "direct", direct: true });
|
|
99
|
-
this.#resolveWaiter(to);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Inject an orchestrator-originated reminder onto a single participant's
|
|
104
|
-
* queue. Used by the turn-complete guard.
|
|
105
|
-
* @param {string} to
|
|
106
|
-
* @param {string} text
|
|
107
|
-
*/
|
|
65
|
+
/** Inject an orchestrator-originated reminder onto one participant's queue. */
|
|
108
66
|
synthetic(to, text) {
|
|
109
67
|
this.#assertParticipant(to);
|
|
110
68
|
this.queues
|
|
111
69
|
.get(to)
|
|
112
|
-
.push({ from: "@orchestrator", text, kind: "synthetic"
|
|
70
|
+
.push({ from: "@orchestrator", text, kind: "synthetic" });
|
|
113
71
|
this.#resolveWaiter(to);
|
|
114
72
|
}
|
|
115
73
|
|
|
116
|
-
/**
|
|
117
|
-
* Return and clear pending messages for a participant.
|
|
118
|
-
* @param {string} participant - Participant name
|
|
119
|
-
* @returns {{from: string, text: string, kind: string, direct: boolean, askId?: number}[]}
|
|
120
|
-
*/
|
|
74
|
+
/** Return and clear pending messages for a participant. */
|
|
121
75
|
drain(participant) {
|
|
122
76
|
this.#assertParticipant(participant);
|
|
123
|
-
|
|
124
|
-
const messages = queue.splice(0);
|
|
125
|
-
return messages;
|
|
77
|
+
return this.queues.get(participant).splice(0);
|
|
126
78
|
}
|
|
127
79
|
|
|
128
80
|
/**
|
|
129
81
|
* Return a Promise that resolves when at least one message is pending.
|
|
130
82
|
* Resolves immediately if messages are already queued.
|
|
131
|
-
* @param {string} participant - Participant name
|
|
132
|
-
* @returns {Promise<void>}
|
|
133
83
|
*/
|
|
134
84
|
waitForMessages(participant) {
|
|
135
85
|
this.#assertParticipant(participant);
|
|
@@ -156,11 +106,7 @@ export class MessageBus {
|
|
|
156
106
|
}
|
|
157
107
|
}
|
|
158
108
|
|
|
159
|
-
/**
|
|
160
|
-
* Factory function.
|
|
161
|
-
* @param {object} deps - Same as MessageBus constructor
|
|
162
|
-
* @returns {MessageBus}
|
|
163
|
-
*/
|
|
109
|
+
/** Factory function. */
|
|
164
110
|
export function createMessageBus(deps) {
|
|
165
111
|
return new MessageBus(deps);
|
|
166
112
|
}
|