Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Chat and workspace agents: channels, DMs and named agents you talk to | 1 | import { test } from "node:test"; |
| 2 | import assert from "node:assert/strict"; | |
| 3 | ||
| 4 | import { dmTitle, isUnread, sidebarOrder, tally } from "./unread.ts"; | |
| 5 | ||
| 6 | test("unread is what others wrote after your last read", () => { | |
| 7 | assert.equal(isUnread({ id: "msg_2", author: "user:b" }, "user:a", "msg_1"), true); | |
| 8 | assert.equal(isUnread({ id: "msg_1", author: "user:b" }, "user:a", "msg_1"), false); | |
| 9 | assert.equal(isUnread({ id: "msg_2", author: "user:a" }, "user:a", "msg_1"), false); | |
| 10 | assert.equal(isUnread({ id: "msg_0", author: "agent:x" }, "user:a", null), true); | |
| 11 | }); | |
| 12 | ||
| 13 | test("counts per channel, replies included, with mentions of the viewer", () => { | |
| 14 | const rows = [ | |
| 15 | { channel_id: "c1", id: "m1", author: "user:b", mentions: "" }, | |
| 16 | { channel_id: "c1", id: "m2", author: "agent:x", mentions: " syntaqx " }, | |
| 17 | { channel_id: "c1", id: "m3", author: "user:a", mentions: " syntaqx " }, | |
| 18 | { channel_id: "c2", id: "m4", author: "user:b", mentions: " syntaqxx " }, | |
| 19 | { channel_id: "c2", id: "m0", author: "user:b", mentions: " syntaqx " }, | |
| 20 | ]; | |
| 21 | const counts = tally(rows, "user:a", "syntaqx", new Map([["c1", null], ["c2", "m1"]])); | |
| 22 | assert.deepEqual(counts.get("c1"), { unread: 2, mentions: 1 }); | |
| 23 | // m0 was read already, and @syntaqxx is someone else. | |
| 24 | assert.deepEqual(counts.get("c2"), { unread: 1, mentions: 0 }); | |
| 25 | assert.equal(counts.get("c3"), undefined); | |
| 26 | }); | |
| 27 | ||
| 28 | test("the sidebar puts starred first, then the most recently active", () => { | |
| 29 | const entry = (title: string, starred: boolean, at: string | null) => ({ | |
| 30 | title, | |
| 31 | starred, | |
| 32 | channel: { last_message_at: at, created_at: "2026-10-01T00:00:00.000Z" }, | |
| 33 | }); | |
| 34 | const ordered = sidebarOrder([ | |
| 35 | entry("quiet", false, null), | |
| 36 | entry("busy", false, "2026-10-08T10:00:00.000Z"), | |
| 37 | entry("pinned", true, "2026-10-02T00:00:00.000Z"), | |
| 38 | entry("older", false, "2026-10-05T00:00:00.000Z"), | |
| 39 | ]); | |
| 40 | assert.deepEqual(ordered.map((e) => e.title), ["pinned", "busy", "older", "quiet"]); | |
| 41 | }); | |
| 42 | ||
| 43 | test("a direct message is titled by the others, or by you for notes", () => { | |
| 44 | const p = (display_name: string) => ({ display_name }); | |
| 45 | assert.equal(dmTitle([p("Ada")], p("Me")), "Ada"); | |
| 46 | assert.equal(dmTitle([p("Ada"), p("Ship")], p("Me")), "Ada, Ship"); | |
| 47 | assert.equal(dmTitle([p("A"), p("B"), p("C"), p("D"), p("E")], p("Me")), "A, B, C and 2 more"); | |
| 48 | assert.equal(dmTitle([], p("Chase")), "Chase (you)"); | |
| 49 | }); |