@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.
@@ -1,22 +1,26 @@
1
1
  /**
2
- * MessageBus — in-memory per-participant message queues for facilitated and
3
- * supervised modes. The message vocabulary mirrors the orchestration toolkit:
2
+ * MessageBus — in-memory per-participant message queues.
4
3
  *
5
- * - ask(from, to, text, askId) — direct question; registers nothing
6
- * itself (the handler's caller owns pending-ask state). `to === "@broadcast"`
7
- * sends an identical entry to every participant except the sender.
8
- * - answer(from, to, text, askId) direct reply to the asker.
9
- * - announce(from, text) broadcast, no reply expected.
10
- * - synthetic(to, text) orchestrator-only reminder injection.
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 for facilitated and supervised orchestration modes. */
19
+ /** In-memory per-participant message queues. */
16
20
  export class MessageBus {
17
21
  /**
18
22
  * @param {object} deps
19
- * @param {string[]} deps.participants - Participant names
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, direct: true });
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
- * @param {string} from - Answerer (or "@orchestrator" for a synthetic answer)
56
- * @param {string} to - Original asker
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", direct: false };
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", direct: true });
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
- const queue = this.queues.get(participant);
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
  }