gabriel / musehub public
agents-coord.ts typescript
119 lines 4.1 KB
Raw
sha256:34035d72cef530c1ab9d6a6f53be18d803dde705fc3157617d70352a96d0747b Merge branch 'fix/wire-push-external-parent-manifest' into dev Human 8 days ago
1 /**
2 * agents-coord.ts — SSE event stream for the Live Coordination page.
3 *
4 * Reads owner, repoSlug, and cursor from the #page-data JSON block and
5 * connects to the /coord/watch SSE endpoint, appending rows to the stream panel.
6 *
7 * Registered as: window.MusePages['agents-coord']
8 */
9
10 interface AgentsCoordData {
11 owner: string;
12 repoSlug: string;
13 cursor: number;
14 }
15
16 const MAX_ROWS = 60;
17
18 const KIND_DOT_CLASS: Record<string, string> = {
19 reservation: 'agents-stream-dot--reservation',
20 heartbeat: 'agents-stream-dot--heartbeat',
21 claim: 'agents-stream-dot--claim',
22 release: 'agents-stream-dot--release',
23 task: 'agents-stream-dot--task',
24 intent: 'agents-stream-dot--intent',
25 };
26
27 function setStatus(state: 'live' | 'error' | 'connecting'): void {
28 const dot = document.getElementById('sse-dot');
29 const label = document.getElementById('sse-label');
30 if (!dot || !label) return;
31 if (state === 'live') {
32 dot.style.background = 'var(--color-success, #3fb950)';
33 dot.style.boxShadow = '0 0 6px var(--color-success, #3fb950)';
34 label.textContent = 'LIVE';
35 } else if (state === 'error') {
36 dot.style.background = 'var(--color-danger, #f85149)';
37 dot.style.boxShadow = 'none';
38 label.textContent = 'RECONNECTING';
39 } else {
40 dot.style.background = 'var(--color-warning, #e3b341)';
41 dot.style.boxShadow = 'none';
42 label.textContent = 'CONNECTING';
43 }
44 }
45
46 function appendRow(body: Element, kind: string, detail: string): void {
47 const row = document.createElement('div');
48 row.className = 'agents-stream-row';
49
50 const dotEl = document.createElement('span');
51 dotEl.className = 'agents-stream-dot ' + (KIND_DOT_CLASS[kind] ?? 'agents-stream-dot--default');
52
53 const kindEl = document.createElement('span');
54 kindEl.className = 'agents-stream-kind';
55 kindEl.textContent = kind;
56
57 const detailEl = document.createElement('span');
58 detailEl.className = 'agents-stream-detail';
59 detailEl.textContent = detail;
60
61 row.appendChild(dotEl);
62 row.appendChild(kindEl);
63 row.appendChild(detailEl);
64 body.appendChild(row);
65
66 while (body.children.length > MAX_ROWS) {
67 body.removeChild(body.firstChild!);
68 }
69 (body as HTMLElement).scrollTop = (body as HTMLElement).scrollHeight;
70 }
71
72 function connect(owner: string, repoSlug: string, initialCursor: number): void {
73 const body = document.getElementById('stream-body');
74 const cursorEl = document.getElementById('stream-cursor');
75 if (!body) return;
76
77 let cursor = initialCursor;
78 let watchUrl = `/${owner}/${repoSlug}/coord/watch?since_id=${cursor}`;
79
80 setStatus('connecting');
81
82 const es = new EventSource(watchUrl);
83
84 es.addEventListener('coord_record', (e: MessageEvent) => {
85 setStatus('live');
86 try {
87 const rec = JSON.parse(e.data as string) as Record<string, unknown>;
88 cursor = (rec['id'] as number) || cursor;
89 if (cursorEl) cursorEl.textContent = `cursor: ${cursor}`;
90 watchUrl = `/${owner}/${repoSlug}/coord/watch?since_id=${cursor}`;
91
92 const kind = (rec['kind'] as string) || 'unknown';
93 const runId = ((rec['run_id'] as string) || '').substring(0, 22);
94 const payload = (rec['payload'] as Record<string, unknown>) || {};
95 let addr = '';
96 const addrs = payload['addresses'] as string[] | undefined;
97 if (addrs && addrs.length) addr = addrs[0];
98 else if (payload['symbol_address']) addr = payload['symbol_address'] as string;
99 else if (payload['task_id']) addr = 'task:' + ((payload['task_id'] as string).substring(0, 8));
100 const detail = runId + (addr ? ' · ' + addr.substring(0, 40) : '');
101 appendRow(body, kind, detail);
102 } catch { /* ignore parse errors */ }
103 });
104
105 es.onerror = () => {
106 setStatus('error');
107 es.close();
108 setTimeout(() => connect(owner, repoSlug, cursor), 3000);
109 };
110 }
111
112 export function initAgentsCoord(data: Record<string, unknown>): void {
113 const cfg = data as unknown as AgentsCoordData;
114 const owner = String(cfg.owner ?? '');
115 const repoSlug = String(cfg.repoSlug ?? '');
116 const cursor = Number(cfg.cursor ?? 0);
117 if (!owner || !repoSlug) return;
118 connect(owner, repoSlug, cursor);
119 }
File History 14 commits
sha256:34035d72cef530c1ab9d6a6f53be18d803dde705fc3157617d70352a96d0747b Merge branch 'fix/wire-push-external-parent-manifest' into dev Human 8 days ago
sha256:fc04e4cae9e1774d6a21b65c45daeed0e6787eb581d13aa1b03bfe9384a34226 Merge branch 'fix/two-column-scroll-layout' into dev Human 8 days ago
sha256:408916fc5973ba59c6e4eebaa80ebdcc801c0a63205651e25009d11548f79454 chore: bump version to 0.2.0.dev2 — nightly.2, matching muse Sonnet 4.6 patch 11 days ago
sha256:d035733f21ccff27735fddebfbbe0ed24565a32a22db8de5885402262671ecd2 chore: bump version to 0.2.0rc15 for musehub#113 fix release Sonnet 4.6 patch 14 days ago
sha256:0032d6cfa33bc3c8367436ad768e7dd0e339b4332153160247da8266cb5fa352 Merge branch 'task/version-tags-phase3-server' into dev Human 17 days ago
sha256:4669620efda9ff41c55bdefd1f7bfe1c239d468428744c84ead9957e5a003a53 merge: rescue snapshot-recovery hardening (c00aa21d) into d… Opus 4.8 minor 29 days ago
sha256:a59da49c4611b970fc4b6ae48678ce4943261c213a07ddbd73ce9201df869b4a fix: remove false-positive proposal_comments index drop fro… Sonnet 4.6 patch 33 days ago
sha256:0a240d6dbff234f07d98a28a4a9a68db702f3f9ff9260196f24219bdb1c0b6f3 feat: render markdown mists as HTML with heading anchor links Sonnet 4.6 patch 34 days ago
sha256:24a7d47486ebc4ebd1832830580e177ec6f877b48dced8c000e198cdec4ce9d6 Merge 'task/bump-version-rc12' into 'dev' — proposal: Bump … Human 35 days ago
sha256:b9ff931d147e0114a1f17060f415b89ed551c170a91ff226c70437aa5c85f9ee Merge 'task/bump-version-rc12' into 'dev' — proposal: Bump … Human 35 days ago
sha256:d1122d21e73471879b460037b22c0b50fded7c423444a176f248428f75dac39c Merge 'task/fix-issue-pagination-cursor' into 'dev' — propo… Human 35 days ago
sha256:01e18975e73d2b3cd5b6db7929c895bef9aa6e0d4391dc5b2adfc548b41318dd Merge 'feat/adding-debug-logs-to-staging' into 'dev' — prop… Human 36 days ago
sha256:6b1949fc2797ca4c1936a637a4cbfec828ef56cf52398a2e74ca3c4f494e728f fix: use wire_bytes not mpack_bytes_raw in compute_object_b… Sonnet 4.6 patch 48 days ago
sha256:b99f2455dc346966d040133f5203297e6e3ef5803a93728a2c30568d0a0f7583 rename: delta_add → delta_upsert across wire format, models… Sonnet 4.6 patch 50 days ago