feat: make chat-style tasks the default experience (#11101)

This commit is contained in:
scotttong authored and GitHub committed 2026-08-11 09:06:21 -07:00
1 parent 2da6a248c3
commit 815e49bb7c
80 files changed
+3858 -1497

No files matched your search

@@ -6,7 +6,7 @@ import { parseAcpxStdoutLine } from "@paperclipai/adapter-utils/acpx-engine/ui";
import { buildTranscript, type RunLogChunk, type TranscriptEntry } from "../../adapters";
import type { ToolRunDecision } from "@paperclipai/shared";
import { ThemeProvider } from "../../context/ThemeContext";
import { RunTranscriptView, normalizeTranscript } from "./RunTranscriptView";
import { RunTranscriptView, keyTranscriptBlocks, normalizeTranscript } from "./RunTranscriptView";
describe("RunTranscriptView", () => {
it("folds repeated tool_call status updates for the same toolUseId into one block", () => {
@@ -322,4 +322,48 @@ describe("RunTranscriptView", () => {
expect(html).not.toContain("line-250");
expect(html).not.toContain("line-499");
});
it("keeps the streaming tail block's key stable as deltas merge in", () => {
// A streaming assistant message accumulates deltas; each delta advances the
// block's `ts`. The React key must stay anchored to the block's opening
// timestamp so the tail does not unmount/remount (restarting its fade).
const firstDelta: TranscriptEntry[] = [
{ kind: "assistant", ts: "2026-03-12T00:00:00.000Z", text: "Hel", delta: true },
];
const withMoreDeltas: TranscriptEntry[] = [
...firstDelta,
{ kind: "assistant", ts: "2026-03-12T00:00:00.400Z", text: "lo the", delta: true },
{ kind: "assistant", ts: "2026-03-12T00:00:00.900Z", text: "re", delta: true },
];
const keyOf = (entries: TranscriptEntry[]) => {
const keyed = keyTranscriptBlocks(normalizeTranscript(entries, true));
return keyed[keyed.length - 1]!.key;
};
// Same opening timestamp → identical key even though `ts` advanced.
expect(keyOf(withMoreDeltas)).toBe(keyOf(firstDelta));
// And that key is anchored to the opening ts, not the latest one.
expect(keyOf(withMoreDeltas)).toContain("2026-03-12T00:00:00.000Z");
expect(keyOf(withMoreDeltas)).not.toContain("2026-03-12T00:00:00.900Z");
});
it("assigns unique keys and does not remount earlier blocks when a new tail arrives", () => {
const base: TranscriptEntry[] = [
{ kind: "assistant", ts: "2026-03-12T00:00:00.000Z", text: "first message", delta: true },
{ kind: "thinking", ts: "2026-03-12T00:00:01.000Z", text: "pondering", delta: true },
];
const withNewTail: TranscriptEntry[] = [
...base,
{ kind: "assistant", ts: "2026-03-12T00:00:02.000Z", text: "second message", delta: true },
];
const baseKeys = keyTranscriptBlocks(normalizeTranscript(base, true)).map((b) => b.key);
const nextKeys = keyTranscriptBlocks(normalizeTranscript(withNewTail, true)).map((b) => b.key);
// Keys are unique within a render.
expect(new Set(nextKeys).size).toBe(nextKeys.length);
// Existing blocks keep their identity when a new block appends after them.
expect(nextKeys.slice(0, baseKeys.length)).toEqual(baseKeys);
});
});