| 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; |
| 3 | import { createRuntimeNotifications } from "../lib/runtimeNotifications"; |
| 4 | import { runtimeStateStore, type RuntimeSession } from "../lib/runtimeStateStore"; |
| 5 | import { t } from "../lib/i18n"; |
| 6 | |
| 7 | test("same turn, prompt and session IDs on different hosts keep independent notification titles and dedupe", () => { |
| 8 | const sessions: RuntimeSession[] = ["host-a", "host-b"].map(hostId => ({ |
| 9 | hostId, sessionId: "shared-id", tabId: `tab-${hostId}`, scope: "project", workspaceRoot: "/repo", |
| 10 | topicId: "same-topic", sessionPath: "/same/path", sessionGeneration: 1, open: true, |
| 11 | remote: true, freshness: "synced", state: { |
| 12 | schemaVersion: 1, runtimeEpoch: "epoch", activityRevision: 1, revision: 1, |
| 13 | phase: "executing", running: true, turnId: "same-turn", turnStatus: "running", turnEventSeq: 1, |
| 14 | pendingPrompt: true, pendingInteractions: [{ requestId: "1", kind: "ask", turnId: "same-turn", runtimeEpoch: "epoch", headId: "head" }], |
| 15 | cancelRequested: false, cancellable: true, backgroundJobs: 0, activity: "", |
| 16 | }, |
| 17 | })); |
| 18 | runtimeStateStore.commit({ epoch: "independent-host-notifications", revision: 1, sessions, |
| 19 | topics: sessions.map(s => ({ scope: s.scope, workspaceRoot: s.workspaceRoot, node: { |
| 20 | key: "same-key", kind: "topic", topicId: s.topicId, label: s.hostId!, |
| 21 | session: { hostId: s.hostId!, sessionId: s.sessionId! }, |
| 22 | } })), |
| 23 | }); |
| 24 | const titles: string[] = []; |
| 25 | const owner = createRuntimeNotifications(() => ({ activeTabId: "other", t, showToast(message) { titles.push(message); } })); |
| 26 | try { |
| 27 | // Wire first, then snapshot: both hosts alert once, using their own title. |
| 28 | for (const s of sessions) owner.accept({ event: { kind: "ask_request", tabId: s.tabId, turnId: "same-turn", ask: { id: "1" } } }); |
| 29 | assert.equal(titles.length, 2); |
| 30 | assert.match(titles[0]!, /host-a/); |
| 31 | assert.match(titles[1]!, /host-b/); |
| 32 | owner.start(); |
| 33 | assert.equal(titles.length, 2, "authoritative snapshots do not replay either host notification"); |
| 34 | } finally { owner.dispose(); } |
| 35 | }); |
| 36 |