0cb5e41faf
- Fix: an errored session alerted on every update, and Clear alerts only dropped it in memory, so its next update (or a reload) brought the alert straight back. An error now alerts on the transition into error only; cleared sessions are remembered (agenthub.pet.dismissedErrors) and stay quiet until they recover and fail anew. - Quips, greetings, notifications and Ask answers move to i18n (EN/VI); Ask understands Vietnamese keywords and names the sessions it counts. - The pet goes by the worn pet's name; click it in the panel to rename (agenthub.pet.names, synced to the account). - Bubbles name the session they are about, with an Open button (never a resume); a burst of the same event coalesces into one count. - Moments: a new session waves, a finish hops, a subagent peeks, a wait taps, an error flinches — on Sagi, Codex sprites and still images. Idle fidgets, a once-per-session greeting, a "Needs you" list, an amber waiting dot. - Pat (heart button, Ask, or stroking the pet) reacts on the pet itself, so it shows while the panel or chat is open. - Panel drops Run Claude / Activity / Sessions / Errored. - Ask hands off to a chat window (PetChat) on the default AI tool (Claude/Codex): transcript as bubbles, follow-ups and CLI menus through an off-screen attached terminal; no new server route. Verified on HEAD + this diff in a clean worktree: tsc -b, the full client suite (1334/1335; the one failure, ConversationView.follow, is flaky under load and passes 3/3 alone) and server me-prefs.test.js. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
/**
|
|
* @file PetChat.test.ts
|
|
* @description Unit tests for the pet chat's transcript-to-bubbles folding (`chatLines`).
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
import { describe, it, expect } from "vitest";
|
|
import { chatLines } from "../PetChat";
|
|
import type { TranscriptMessage } from "../../../lib/types";
|
|
|
|
const msg = (m: Partial<TranscriptMessage>): TranscriptMessage =>
|
|
({ type: "user", timestamp: null, content: [], ...m }) as TranscriptMessage;
|
|
|
|
describe("chatLines", () => {
|
|
it("keeps the user's words and the assistant's prose, folding tool calls into one chip", () => {
|
|
const lines = chatLines([
|
|
msg({ type: "user", sender: "user", content: [{ type: "text", text: "hi" }] }),
|
|
msg({
|
|
type: "assistant",
|
|
content: [
|
|
{ type: "thinking", text: "hmm" },
|
|
{ type: "tool_use", name: "Read" },
|
|
],
|
|
}),
|
|
msg({ type: "user", sender: "tool", content: [{ type: "tool_result", output: "x" }] }),
|
|
msg({
|
|
type: "assistant",
|
|
content: [
|
|
{ type: "tool_use", name: "Read" },
|
|
{ type: "text", text: "hello!" },
|
|
],
|
|
}),
|
|
]);
|
|
expect(lines.map((l) => (l.role === "tools" ? l.names : l.text))).toEqual([
|
|
"hi",
|
|
["Read", "Read"],
|
|
"hello!",
|
|
]);
|
|
});
|
|
|
|
it("drops Claude Code's own injected lines", () => {
|
|
const lines = chatLines([
|
|
msg({ sender: "user", content: [{ type: "text", text: "<command-name>/clear</command-name>" }] }),
|
|
]);
|
|
expect(lines).toEqual([]);
|
|
});
|
|
});
|