Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline (Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/* packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
122 lines
3.5 KiB
TypeScript
122 lines
3.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
hasMentionToken,
|
|
inferHandoffTargetBotId,
|
|
inferHandoffTargetName,
|
|
resolveGroupTargetBotIds,
|
|
} from "./group-mentions.js";
|
|
|
|
const members = [
|
|
{ id: "a", name: "BotA" },
|
|
{ id: "b", name: "BotB" },
|
|
{ id: "c", name: "Writer" },
|
|
];
|
|
|
|
describe("hasMentionToken", () => {
|
|
it("requires a boundary after the complete member name", () => {
|
|
expect(hasMentionToken("Ask @Ann to review", "Ann")).toBe(true);
|
|
expect(hasMentionToken("Ask @Ann, then continue", "Ann")).toBe(true);
|
|
expect(hasMentionToken("Ask @Anna to review", "Ann")).toBe(false);
|
|
expect(hasMentionToken("name@Ann", "Ann")).toBe(false);
|
|
expect(hasMentionToken("contact@everyone", "everyone")).toBe(false);
|
|
});
|
|
|
|
it("supports multi-word and Unicode member names", () => {
|
|
expect(hasMentionToken("Ask @Research Writer and @Éditeur", "Research Writer")).toBe(true);
|
|
expect(hasMentionToken("Ask @Research Writer and @Éditeur", "Éditeur")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("resolveGroupTargetBotIds", () => {
|
|
it("returns mentioned bots from text", () => {
|
|
expect(
|
|
resolveGroupTargetBotIds({
|
|
text: "@BotA gather sources. @BotB summarize.",
|
|
members,
|
|
}),
|
|
).toEqual(["a", "b"]);
|
|
});
|
|
|
|
it("returns all members for @everyone", () => {
|
|
expect(
|
|
resolveGroupTargetBotIds({
|
|
text: "@everyone please review",
|
|
members,
|
|
}),
|
|
).toEqual(["a", "b", "c"]);
|
|
});
|
|
|
|
it("merges explicit mentions", () => {
|
|
expect(
|
|
resolveGroupTargetBotIds({
|
|
text: "hello",
|
|
members,
|
|
explicitMentions: ["b"],
|
|
}),
|
|
).toEqual(["b"]);
|
|
});
|
|
|
|
it("matches multi-word and Unicode names without prefix collisions", () => {
|
|
const namedMembers = [
|
|
{ id: "research", name: "Research Writer" },
|
|
{ id: "edit", name: "Éditeur" },
|
|
{ id: "ann", name: "Ann" },
|
|
{ id: "anna", name: "Anna" },
|
|
];
|
|
expect(
|
|
resolveGroupTargetBotIds({
|
|
text: "@Research Writer compare this with @Éditeur and @Anna.",
|
|
members: namedMembers,
|
|
}),
|
|
).toEqual(["research", "edit", "anna"]);
|
|
});
|
|
|
|
it("ignores explicit mentions for bots that are not group members", () => {
|
|
expect(
|
|
resolveGroupTargetBotIds({
|
|
text: "hello",
|
|
members,
|
|
explicitMentions: ["b", "outsider"],
|
|
}),
|
|
).toEqual(["b"]);
|
|
});
|
|
|
|
it("picks the first member when unmentioned", () => {
|
|
expect(
|
|
resolveGroupTargetBotIds({
|
|
text: "hello team",
|
|
members,
|
|
}),
|
|
).toEqual(["a"]);
|
|
});
|
|
});
|
|
|
|
describe("inferHandoffTargetName", () => {
|
|
it("picks Writer when BotA is also mentioned", () => {
|
|
expect(inferHandoffTargetName("@BotA hand this to Writer for the draft")).toBe("Writer");
|
|
});
|
|
});
|
|
|
|
describe("inferHandoffTargetBotId", () => {
|
|
it("recognizes hand this to Writer", () => {
|
|
expect(inferHandoffTargetBotId("hand this to Writer for the draft", members)).toBe("c");
|
|
});
|
|
|
|
it("recognizes @Writer take the draft", () => {
|
|
expect(inferHandoffTargetBotId("@Writer take the draft", members)).toBe("c");
|
|
});
|
|
|
|
it("resolves Writer from mixed mention prompt", () => {
|
|
expect(inferHandoffTargetBotId("@BotA hand this to Writer for the draft", members)).toBe("c");
|
|
});
|
|
|
|
it("resolves multi-word handoff targets", () => {
|
|
expect(
|
|
inferHandoffTargetBotId("hand this to Research Writer for the draft", [
|
|
...members,
|
|
{ id: "research", name: "Research Writer" },
|
|
]),
|
|
).toBe("research");
|
|
});
|
|
});
|