@pi-archimedes/core 2.10.4 → 2.11.1

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/src/bus.ts DELETED
@@ -1,137 +0,0 @@
1
- // ── Bus (pub/sub via globalThis Symbol) ──────────────────────────────────────
2
-
3
- const BUS_KEY = Symbol.for("archimedes:bus");
4
- const QUEUE_KEY = Symbol.for("archimedes:busQueue");
5
-
6
- interface Bus {
7
- emit(event: string, payload: unknown): void;
8
- on(event: string, listener: (payload: unknown) => void): () => void;
9
- }
10
-
11
- interface CostUpdatePayload {
12
- source: string;
13
- inputTokens?: number;
14
- outputTokens?: number;
15
- cacheReadTokens?: number;
16
- cacheWriteTokens?: number;
17
- cost?: number;
18
- }
19
-
20
- // Type-safe globalThis access — avoids `as unknown as` casts
21
- function getGlobal<T>(key: symbol): T | undefined {
22
- return (globalThis as Record<symbol, unknown>)[key] as T | undefined;
23
- }
24
- function setGlobal<T>(key: symbol, value: T): void {
25
- (globalThis as Record<symbol, unknown>)[key] = value;
26
- }
27
-
28
- function createBus(): Bus {
29
- const listeners = new Map<string, Array<(payload: unknown) => void>>();
30
-
31
- return {
32
- emit(event: string, payload: unknown): void {
33
- const subs = listeners.get(event);
34
- if (subs) {
35
- for (const fn of subs) {
36
- try {
37
- Promise.resolve(fn(payload)).catch((err) =>
38
- console.error(`[archimedes:bus] Async error in listener for "${event}":`, err));
39
- } catch (err) {
40
- // Listener errors should not crash other listeners
41
- console.error(`[archimedes:bus] Error in listener for "${event}":`, err);
42
- }
43
- }
44
- } else {
45
- // Queue event for future subscribers
46
- const queue = getGlobal<Array<{ event: string; payload: unknown }>>(QUEUE_KEY) ?? [];
47
- queue.push({ event, payload });
48
- setGlobal(QUEUE_KEY, queue);
49
- }
50
- },
51
- on(event: string, listener: (payload: unknown) => void): () => void {
52
- if (!listeners.has(event)) {
53
- listeners.set(event, []);
54
- }
55
- const subs = listeners.get(event)!;
56
- subs.push(listener);
57
-
58
- // Drain any queued events for this specific event
59
- const queue = getGlobal<Array<{ event: string; payload: unknown }>>(QUEUE_KEY);
60
- if (queue) {
61
- for (const { event: queuedEvent, payload } of queue) {
62
- if (queuedEvent === event) {
63
- try {
64
- Promise.resolve(listener(payload)).catch((err) =>
65
- console.error(`[archimedes:bus] Async error in listener for "${event}":`, err));
66
- } catch (err) {
67
- console.error(`[archimedes:bus] Error in listener for "${event}":`, err);
68
- }
69
- }
70
- }
71
- }
72
-
73
- return () => {
74
- const idx = subs.indexOf(listener);
75
- if (idx !== -1) subs.splice(idx, 1);
76
- };
77
- },
78
- };
79
- }
80
-
81
- export function getBus(): Bus {
82
- let bus = getGlobal<Bus>(BUS_KEY);
83
- if (!bus) {
84
- bus = createBus();
85
- setGlobal(BUS_KEY, bus);
86
- }
87
- return bus;
88
- }
89
-
90
- export function initBus(): void {
91
- const bus = getBus();
92
- // Flush queued events (if any were emitted before init)
93
- // Snapshot and clear before iterating to prevent infinite loops from re-queueing
94
- const queue = getGlobal<Array<{ event: string; payload: unknown }>>(QUEUE_KEY) ?? [];
95
- setGlobal(QUEUE_KEY, []);
96
- for (const { event, payload } of queue) {
97
- bus.emit(event, payload);
98
- }
99
- }
100
-
101
- export const Events = {
102
- COST_UPDATE: "archimedes:cost_update",
103
- TODOS_UPDATE: "archimedes:todos_update",
104
- TODOS_CLEAR: "archimedes:todos_clear",
105
- ASK_REQUEST: "archimedes:ask_request",
106
- ASK_RESPONSE: "archimedes:ask_response",
107
- ASK_CANCEL: "archimedes:ask_cancel",
108
- } as const;
109
-
110
- interface TodoUpdatePayload {
111
- source: string; // "main" or "subagent:<agent-name>"
112
- todos: Array<{ content: string; description?: string; status: "pending" | "in_progress" | "completed" }>;
113
- }
114
-
115
- interface TodoClearPayload {
116
- source: string;
117
- }
118
-
119
- interface AskRequestPayload {
120
- source: string; // "subagent:<agent-name>"
121
- requestId: string; // unique id to match request → response
122
- toolCallId?: string; // the tool-call id of the process that invoked the tool (carried for Client correlation)
123
- questions: Array<{ id: string; question: string; description?: string; options: Array<{ label: string }>; multi?: boolean; recommended?: number }>;
124
- }
125
-
126
- interface AskResponsePayload {
127
- requestId: string;
128
- cancelled: boolean;
129
- results: Array<{ id: string; selectedOptions: string[]; customInput?: string }>;
130
- }
131
-
132
- interface AskCancelPayload {
133
- requestId: string;
134
- source: string;
135
- }
136
-
137
- export type { CostUpdatePayload, TodoUpdatePayload, TodoClearPayload, AskRequestPayload, AskResponsePayload, AskCancelPayload };