/** * Both request shapes JanitorAI sends, and a continued conversation. * Run with `npm test` — no test framework, just node's built-in runner. */ import { test } from "node:test"; import assert from "node:assert/strict"; import { selectMessageSlots } from "../src/lib/messages.ts"; const CARD = "<.>\na tired innkeeper."; const GREETING = "The clink of bottles is the only greeting you get."; const NAME = "{{user}}: Gaius"; /** What most clients send: a throwaway "." user turn before the greeting. */ const withProbe = [ { role: "system", content: CARD }, { role: "user", content: "." }, { role: "assistant", content: GREETING }, { role: "user", content: NAME }, ]; /** What some clients send: no "." turn, so every index shifts by one. */ const withoutProbe = [ { role: "system", content: CARD }, { role: "assistant", content: GREETING }, { role: "user", content: NAME }, ]; test("both shapes resolve to the same slots", () => { for (const [label, messages] of [ ["with probe", withProbe], ["without probe", withoutProbe], ] as const) { const slots = selectMessageSlots(messages); assert.equal(slots.system?.content, CARD, `${label}: card`); assert.equal(slots.greeting?.content, GREETING, `${label}: greeting`); assert.equal(slots.lastUser?.content, NAME, `${label}: name slot`); } }); test("the greeting stays the first assistant turn as a chat continues", () => { const continued = [ ...withProbe, { role: "assistant", content: "Character updated (v2)." }, { role: "user", content: "{{user}}: [sucker:conv=abc123]" }, ]; const slots = selectMessageSlots(continued); assert.equal(slots.greeting?.content, GREETING); // Sucker's own reply, where a conversation token would be found. assert.equal(slots.lastAssistant?.content, "Character updated (v2)."); assert.equal(slots.lastUser?.content, "{{user}}: [sucker:conv=abc123]"); }); test("a card with no role on the system turn still resolves", () => { const slots = selectMessageSlots([ { content: CARD }, { role: "assistant", content: GREETING }, { role: "user", content: NAME }, ]); assert.equal(slots.system?.content, CARD); }); test("nothing throws on empty or malformed input", () => { for (const input of [[], undefined, [{}, { role: "user" }]]) { assert.doesNotThrow(() => selectMessageSlots(input as never)); } assert.equal(selectMessageSlots([]).greeting, undefined); });