Skip to content
141 linesCodeBlameRaw
1import { test } from "node:test";
2import assert from "node:assert/strict";
3
4import { MAX_HOPS, type RecentMessage, addressedAgents, chainFor, deliveries, delivery, handOffPlace, handOffRefusal, personalAgentRefusal } from "./delivery.ts";
5
6const ship = { id: "a1", handle: "ship" };
7const docs = { id: "a2", handle: "docs" };
8
9test("a person's direct message with nothing said yet wakes every agent in it, at hop 0", () => {
10 assert.deepEqual(deliveries({ author: "user:u", hops: 3, channelKind: "dm", agents: [ship, docs], mentioned: [] }), [
11 { agent_id: "a1", hops: 0 },
12 { agent_id: "a2", hops: 0 },
13 ]);
14 assert.deepEqual(deliveries({ author: "user:u", hops: 0, channelKind: "dm", agents: [ship, docs], mentioned: [], recent: [] }), [
15 { agent_id: "a1", hops: 0 },
16 { agent_id: "a2", hops: 0 },
17 ]);
18 // With one agent there is nobody else it could be for.
19 assert.deepEqual(deliveries({ author: "user:u", hops: 0, channelKind: "dm", agents: [ship], mentioned: [], recent: [{ author: "user:u", mentioned: ["docs"] }] }), [{ agent_id: "a1", hops: 0 }]);
20});
21
22const mike = { id: "a_mike", handle: "mike" };
23const g1t = { id: "a_g1t", handle: "g1t" };
24const says = (author: string, ...mentioned: string[]): RecentMessage => ({ author, mentioned });
25
26test("in a group DM, an unaddressed message goes to the agent the person is talking with", () => {
27 // The conversation as it happened: Chase, Mike the recruiter and @g1t in one group message.
28 const transcript = [
29 says("user:chase"), // "Are you able to generate PDFs now?"
30 says("agent:a_mike"),
31 says("agent:a_g1t"),
32 says("user:chase", "mike"), // "@Mike Make a PDF of that example resume for me"
33 says("agent:a_mike"),
34 ];
35 // "Let's take that template and make a fake resume for some fake person": Mike was helping.
36 assert.deepEqual(deliveries({ author: "user:chase", hops: 0, channelKind: "dm", agents: [mike, g1t], mentioned: [], recent: transcript }), [{ agent_id: "a_mike", hops: 0 }]);
37 // The first question, with nothing before it, went to both; so does a follow-up to both their answers.
38 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", []), [mike, g1t]);
39 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", transcript.slice(0, 3)), [mike, g1t]);
40 // A mention still goes only to those named, whoever was talking.
41 assert.deepEqual(deliveries({ author: "user:chase", hops: 0, channelKind: "dm", agents: [mike, g1t], mentioned: ["g1t"], recent: transcript }), [{ agent_id: "a_g1t", hops: 0 }]);
42});
43
44test("who is addressed: the last exchange, else the person's last mention, else everyone", () => {
45 // Mentioned but not yet answered: the mention stands, through the person's own follow-ups.
46 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:chase", "Mike"), says("user:chase")]), [mike]);
47 // Answered by a colleague after the mention (a hand-off here, say): the colleague has the conversation now.
48 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:chase", "mike"), says("agent:a_mike", "g1t"), says("user:chase"), says("agent:a_g1t")]), [g1t]);
49 // Both answered the last message: both are in the exchange, in the conversation's order.
50 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:chase", "g1t", "mike"), says("agent:a_g1t"), says("agent:a_mike")]), [mike, g1t]);
51 // A thank-you in between changes nothing: the person's last mention still says who.
52 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:chase", "mike"), says("agent:a_mike"), says("user:chase"), says("user:chase")]), [mike]);
53 // Another person's message ends the exchange without deciding it; only this person's mentions do.
54 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:chase", "mike"), says("agent:a_mike"), says("user:bo", "g1t")]), [mike]);
55 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:bo", "g1t"), says("agent:a_g1t")]), [g1t], "whoever answered last, whoever they answered");
56 // A second message before anyone answers the first goes where the first did.
57 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:bo", "g1t"), says("agent:a_g1t"), says("user:chase")]), [g1t]);
58 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:chase"), says("agent:a_mike"), says("user:chase")]), [mike], "only Mike answered the first");
59 // Mentions of agents that aren't here, and messages of agents that left, decide nothing.
60 assert.deepEqual(addressedAgents([mike, g1t], "user:chase", [says("user:chase", "sam"), says("agent:a_gone")]), [mike, g1t]);
61 assert.deepEqual(addressedAgents([mike], "user:chase", [says("user:chase", "g1t")]), [mike], "one agent: nothing to decide");
62});
63
64test("in a group direct message, a person who mentions some of its agents wakes only those", () => {
65 assert.deepEqual(deliveries({ author: "user:u", hops: 0, channelKind: "dm", agents: [ship, docs], mentioned: ["docs"] }), [{ agent_id: "a2", hops: 0 }]);
66 // Mentioning someone who isn't in it is no mention of its agents: all of them answer.
67 assert.deepEqual(deliveries({ author: "user:u", hops: 0, channelKind: "dm", agents: [ship, docs], mentioned: ["mike"] }), [
68 { agent_id: "a1", hops: 0 },
69 { agent_id: "a2", hops: 0 },
70 ]);
71});
72
73test("in a channel, a person wakes only the agent members they mention", () => {
74 assert.deepEqual(deliveries({ author: "user:u", hops: 0, channelKind: "channel", agents: [ship, docs], mentioned: [] }), []);
75 assert.deepEqual(
76 deliveries({ author: "user:u", hops: 0, channelKind: "channel", agents: [ship, docs], mentioned: ["Ship", "nobody"] }),
77 [{ agent_id: "a1", hops: 0 }],
78 );
79});
80
81test("an agent's message wakes nobody, even when it @mentions an agent member", () => {
82 assert.deepEqual(deliveries({ author: "agent:a1", hops: 0, channelKind: "dm", agents: [ship, docs], mentioned: [] }), []);
83 assert.deepEqual(deliveries({ author: "agent:a1", hops: 0, channelKind: "dm", agents: [ship, docs], mentioned: ["docs"] }), []);
84 assert.deepEqual(deliveries({ author: "agent:a1", hops: 2, channelKind: "channel", agents: [ship, docs], mentioned: ["docs", "ship"] }), []);
85});
86
87test("a delivery carries the chain's asker on g1t's own chat, and the wake's hops", () => {
88 const asker = { username: "ada", role: "member", can_write: false };
89 const place = { workspace: "acme", workspace_id: "w1", channel_id: "c1", channel_kind: "channel", channel_name: "ops" };
90 assert.deepEqual(
91 delivery(place, { agent_id: "a2", hops: 3 }, { id: "m1", thread_root: "m0" }, { hops: 2, asked_by: "u1", asker, chain: ["a1"] }),
92 { ...place, agent_id: "a2", message_id: "m1", thread_root: "m0", asked_by: "u1", asker, chain: ["a1"], hops: 3, surface: "g1t" },
93 );
94 // An agent that passed no asker back hands on none.
95 assert.equal(delivery(place, { agent_id: "a2", hops: 1 }, { id: "m1", thread_root: null }, { hops: 0, asked_by: "u1", asker: null, chain: [] }).asker, null);
96});
97
98test("mentioning @g1t in a channel brings it in once; never into a DM", async () => {
99 const { addsOrchestrator } = await import("./delivery.ts");
100 assert.equal(addsOrchestrator({ channelKind: "channel", mentioned: ["G1T"], orchestratorIsMember: false }), true);
101 assert.equal(addsOrchestrator({ channelKind: "channel", mentioned: ["g1t"], orchestratorIsMember: true }), false, "already in");
102 assert.equal(addsOrchestrator({ channelKind: "channel", mentioned: ["ship"], orchestratorIsMember: false }), false);
103 assert.equal(addsOrchestrator({ channelKind: "dm", mentioned: ["g1t"], orchestratorIsMember: false }), false);
104 // Once in, it is woken like any mentioned agent member.
105 const g1t = { id: "a9", handle: "g1t" };
106 assert.deepEqual(deliveries({ author: "user:u", hops: 0, channelKind: "channel", agents: [ship, g1t], mentioned: ["g1t"] }), [{ agent_id: "a9", hops: 0 }]);
107});
108
109test("a chain is the agents that handled a request, with the poster added", () => {
110 assert.deepEqual(chainFor(["a9"], "a1"), ["a9", "a1"]);
111 assert.deepEqual(chainFor("nonsense", "a1"), ["a1"]);
112});
113
114test("a hand-off goes here when the colleague is in this channel or group DM, else to a group DM", () => {
115 assert.equal(handOffPlace({ channelKind: "channel", members: 40, colleagueHere: true }), "here");
116 assert.equal(handOffPlace({ channelKind: "dm", members: 3, colleagueHere: true }), "here");
117 assert.equal(handOffPlace({ channelKind: "channel", members: 40, colleagueHere: false }), "group_dm");
118 // The 1:1 DM the user saw: @g1t and the person, Mike not in it.
119 assert.equal(handOffPlace({ channelKind: "dm", members: 2, colleagueHere: false }), "group_dm");
120});
121
122test("a hand-off is refused to itself, to @g1t, back along the chain, and past the hop limit", () => {
123 const ok = { agent: "a9", colleague: { id: "a1" }, chain: [], hops: 0 };
124 assert.equal(handOffRefusal(ok), null);
125 assert.match(handOffRefusal({ ...ok, colleague: { id: "a9" } })!, /itself/);
126 assert.match(handOffRefusal({ ...ok, agent: "a1", colleague: { id: "a9", builtin: true } })!, /@g1t/);
127 assert.match(handOffRefusal({ ...ok, agent: "a2", chain: ["a1", "a2"] })!, /already handled/);
128 assert.equal(handOffRefusal({ ...ok, hops: MAX_HOPS - 1 }), null);
129 assert.match(handOffRefusal({ ...ok, hops: MAX_HOPS })!, /too many times/);
130});
131
132test("a personal agent is only in the direct message of it and the person it belongs to", () => {
133 const mine = { id: "a9", handle: "pip", scope: "personal", personal_owner_id: "u1" };
134 assert.equal(personalAgentRefusal(mine, { kind: "dm", members: ["user:u1", "agent:a9"] }), null);
135 assert.match(personalAgentRefusal(mine, { kind: "dm", members: ["user:u2", "agent:a9"] }) ?? "", /personal agent/);
136 assert.match(personalAgentRefusal(mine, { kind: "dm", members: ["user:u1", "user:u2", "agent:a9"] }) ?? "", /personal agent/, "not a group DM");
137 assert.match(personalAgentRefusal(mine, { kind: "channel", members: null }) ?? "", /personal agent/, "never invited to a channel");
138 assert.match(personalAgentRefusal(mine, { kind: "hand_off", members: null }) ?? "", /personal agent/, "never handed work");
139 assert.equal(personalAgentRefusal({ id: "a1", handle: "ship", scope: "workspace" }, { kind: "channel", members: null }), null);
140 assert.equal(personalAgentRefusal({ id: "a1", handle: "ship" }, { kind: "hand_off", members: null }), null, "agents from before personal ones are the workspace's");
141});