Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

117 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { ChatLiveEvent, ChatMessage } from "@g1t/contracts";
5
6import { askedFrom, answerLabel, anyAnswering, applyLive, cutOff, fromG1t, isClearCommand, refTarget, suggestions } from "./g1t-chat.ts";
7
8const g1t = { kind: "system" as const, id: "g1t", name: "g1t", display_name: "g1t", avatar: null, role: null };
9const ana = { kind: "user" as const, id: "u1", name: "ana", display_name: "Ana", avatar: null, role: null };
10
11function message(id: string, extra: Partial<ChatMessage> = {}): ChatMessage {
12 return {
13 id,
14 channel_id: "chn_1",
15 author: ana,
16 kind: "text",
17 body: "",
18 card: null,
19 thread_root: null,
20 reply_count: 0,
21 last_reply_at: null,
22 created_at: "2026-10-12T00:00:00Z",
23 edited_at: null,
24 deleted_at: null,
25 ...extra,
26 };
27}
28
29test("an answer streams into its message, then the stored one takes over", () => {
30 let list = [message("msg_1", { body: "What shipped?" })];
31 const placeholder = message("msg_2", { author: g1t, answer: { state: "thinking" } });
32 list = applyLive(list, { type: "message.created", message: placeholder }, "chn_1");
33 assert.ok(anyAnswering(list));
34 list = applyLive(list, { type: "message.streaming", channel_id: "chn_1", id: "msg_2", body: "Two", answer: { state: "streaming" } }, "chn_1");
35 assert.equal(list[1]!.body, "Two");
36 const done: ChatMessage = { ...placeholder, body: "Two pull requests.", answer: { state: "done", provider_label: "Anthropic", model: "m" } };
37 list = applyLive(list, { type: "message.updated", message: done }, "chn_1");
38 assert.equal(list[1]!.body, "Two pull requests.");
39 assert.ok(!anyAnswering(list));
40 // A frame that arrives after the end changes nothing.
41 list = applyLive(list, { type: "message.streaming", channel_id: "chn_1", id: "msg_2", body: "Tw", answer: { state: "streaming" } }, "chn_1");
42 assert.equal(list[1]!.body, "Two pull requests.");
43 assert.equal(answerLabel(list[1]!.answer), "Anthropic · m");
44 // Auto names the model it chose.
45 assert.equal(answerLabel({ state: "done", provider_label: "Anthropic", model: "claude-sonnet-5-5", auto: true }), "Anthropic · Auto · claude-sonnet-5-5");
46 assert.equal(answerLabel({ state: "thinking" }), null);
47});
48
49test("other conversations, thread replies and deletions", () => {
50 const list = [message("msg_1"), message("msg_2")];
51 const elsewhere: ChatLiveEvent = { type: "message.created", message: message("msg_3", { channel_id: "chn_2" }) };
52 assert.equal(applyLive(list, elsewhere, "chn_1").length, 2);
53 assert.equal(applyLive(list, { type: "message.created", message: message("msg_3", { thread_root: "msg_1" }) }, "chn_1").length, 2);
54 assert.deepEqual(
55 applyLive(list, { type: "message.deleted", channel_id: "chn_1", id: "msg_1" }, "chn_1").map((m) => m.id),
56 ["msg_2"],
57 );
58 // Out of order arrivals land in order.
59 assert.deepEqual(
60 applyLive([message("msg_3")], { type: "message.created", message: message("msg_2") }, "chn_1").map((m) => m.id),
61 ["msg_2", "msg_3"],
62 );
63});
64
65test("a cleared conversation empties, and only that one", () => {
66 const list = [message("msg_1"), message("msg_2", { author: g1t, answer: { state: "streaming" } })];
67 assert.deepEqual(applyLive(list, { type: "channel.cleared", channel_id: "chn_1" }, "chn_1"), []);
68 assert.equal(applyLive(list, { type: "channel.cleared", channel_id: "chn_2" }, "chn_1").length, 2);
69 // An answer's late frame after the clear brings nothing back.
70 assert.deepEqual(applyLive([], { type: "message.streaming", channel_id: "chn_1", id: "msg_2", body: "Two", answer: { state: "streaming" } }, "chn_1"), []);
71});
72
73test("/clear, typed to g1t, is the command and nothing else is", () => {
74 assert.ok(isClearCommand("/clear"));
75 assert.ok(isClearCommand(" /CLEAR \n"));
76 assert.ok(!isClearCommand("/clear the cache for me"));
77 assert.ok(!isClearCommand("clear"));
78});
79
80test("who g1t is, and answers cut off at their limit", () => {
81 assert.ok(fromG1t({ author: g1t }));
82 assert.ok(!fromG1t({ author: ana }));
83 assert.ok(cutOff({ state: "done", stop_reason: "max_tokens" }));
84 assert.equal(answerLabel({ state: "thinking" }), null);
85});
86
87test("suggestions fit the page", () => {
88 assert.match(suggestions({ pull: 4, repo: { namespace: "acme", name: "web" } })[0]!, /#4/);
89 assert.match(suggestions({ item: 12 }).join(" "), /blocking #12/);
90 assert.match(suggestions({ path: "/acme/-/work/12" }).join(" "), /work item #12/);
91 assert.match(suggestions({ repo: { namespace: "acme", name: "web" } })[0]!, /web/);
92 assert.equal(suggestions({}).length, 4);
93});
94
95test("links into the site show as what they lead to", () => {
96 // An old issue's address reads as `#12` in its repository, as `ref` does.
97 assert.deepEqual(refTarget("/acme/web/issues/12"), { kind: "ref", repo: "acme/web", number: 12, href: "/acme/web/issues/12" });
98 assert.deepEqual(refTarget("/acme/web/ref/12"), { kind: "ref", repo: "acme/web", number: 12, href: "/acme/web/ref/12" });
99 assert.deepEqual(refTarget("/Acme/-/work/12"), { kind: "item", workspace: "acme", number: 12, href: "/Acme/-/work/12" });
100 assert.deepEqual(refTarget("https://g1t.sh/Acme/web/pull/7#discussion"), { kind: "pull", repo: "acme/web", number: 7, href: "/Acme/web/pull/7#discussion" });
101 assert.deepEqual(refTarget("/acme/web/commit/0123abcd"), { kind: "commit", repo: "acme/web", sha: "0123abcd", href: "/acme/web/commit/0123abcd" });
102 assert.deepEqual(refTarget("https://g1t.example/acme/-/chat", "https://g1t.example"), { kind: "page", href: "/acme/-/chat" });
103 assert.equal(refTarget("https://example.com/acme/web/issues/1"), null);
104 assert.equal(refTarget("//evil.example/x"), null);
105 assert.equal(refTarget("javascript:alert(1)"), null);
106});
107
108test("a question asked on a page says which, and one written in Chat says nothing", () => {
109 const repo = { namespace: "flagon-io", name: "g1t" };
110 assert.deepEqual(askedFrom({ path: "/flagon-io/g1t/pull/8", repo, pull: 8 }), { label: "pull request #8 in flagon-io/g1t", href: "/flagon-io/g1t/pull/8" });
111 assert.deepEqual(askedFrom({ workspace: "flagon-io", item: 21 }), { label: "work item #21 in flagon-io", href: "/flagon-io/-/work/21" });
112 assert.deepEqual(askedFrom({ path: "/flagon-io/-/work/21" }), { label: "work item #21 in flagon-io", href: "/flagon-io/-/work/21" });
113 assert.equal(askedFrom({ path: "/flagon-io/g1t", repo })?.label, "flagon-io/g1t");
114 assert.equal(askedFrom({ path: "/flagon-io/-/chat/dm/chn_1" }), null);
115 assert.equal(askedFrom({ time_zone: "America/Denver" }), null);
116 assert.equal(askedFrom(null), null);
117});