196 lines · 6.4 KB · TypeScript
RawDownload
import { ThreadId } from "@t3tools/contracts";import { describe, expect, it } from "vite-plus/test"; import {  appendTerminalContextsToPrompt,  buildTerminalContextBlock,  countInlineTerminalContextPlaceholders,  deriveDisplayedUserMessageState,  ensureInlineTerminalContextPlaceholders,  extractTrailingTerminalContexts,  filterTerminalContextsWithText,  formatInlineTerminalContextLabel,  formatTerminalContextLabel,  hasTerminalContextText,  INLINE_TERMINAL_CONTEXT_PLACEHOLDER,  insertInlineTerminalContextPlaceholder,  isTerminalContextExpired,  materializeInlineTerminalContextPrompt,  removeInlineTerminalContextPlaceholder,  stripInlineTerminalContextPlaceholders,  type TerminalContextDraft,} from "./terminalContext"; function makeContext(overrides?: Partial<TerminalContextDraft>): TerminalContextDraft {  return {    id: "context-1",    threadId: ThreadId.make("thread-1"),    terminalId: "default",    terminalLabel: "Terminal 1",    lineStart: 12,    lineEnd: 13,    text: "git status\nOn branch main",    createdAt: "2026-03-13T12:00:00.000Z",    ...overrides,  };} describe("terminalContext", () => {  it("formats terminal labels with line ranges", () => {    expect(formatTerminalContextLabel(makeContext())).toBe("Terminal 1 lines 12-13");    expect(      formatTerminalContextLabel(        makeContext({          lineStart: 9,          lineEnd: 9,        }),      ),    ).toBe("Terminal 1 line 9");  });   it("builds a numbered terminal context block", () => {    expect(buildTerminalContextBlock([makeContext()])).toBe(      [        "<terminal_context>",        "- Terminal 1 lines 12-13:",        "  12 | git status",        "  13 | On branch main",        "</terminal_context>",      ].join("\n"),    );  });   it("appends terminal context blocks after prompt text", () => {    expect(appendTerminalContextsToPrompt("Investigate this", [makeContext()])).toBe(      [        "Investigate this",        "",        "<terminal_context>",        "- Terminal 1 lines 12-13:",        "  12 | git status",        "  13 | On branch main",        "</terminal_context>",      ].join("\n"),    );  });   it("replaces inline placeholders with inline terminal labels before appending context blocks", () => {    expect(      appendTerminalContextsToPrompt(        `Investigate ${INLINE_TERMINAL_CONTEXT_PLACEHOLDER} carefully`,        [makeContext()],      ),    ).toBe(      [        "Investigate @terminal-1:12-13 carefully",        "",        "<terminal_context>",        "- Terminal 1 lines 12-13:",        "  12 | git status",        "  13 | On branch main",        "</terminal_context>",      ].join("\n"),    );  });   it("extracts terminal context blocks from message text", () => {    const prompt = appendTerminalContextsToPrompt("Investigate this", [makeContext()]);    expect(extractTrailingTerminalContexts(prompt)).toEqual({      promptText: "Investigate this",      contextCount: 1,      previewTitle: "Terminal 1 lines 12-13\n12 | git status\n13 | On branch main",      contexts: [        {          header: "Terminal 1 lines 12-13",          body: "12 | git status\n13 | On branch main",        },      ],    });  });   it("derives displayed user message state from terminal context prompts", () => {    const prompt = appendTerminalContextsToPrompt("Investigate this", [makeContext()]);    expect(deriveDisplayedUserMessageState(prompt)).toEqual({      visibleText: "Investigate this",      copyText: prompt,      contextCount: 1,      previewTitle: "Terminal 1 lines 12-13\n12 | git status\n13 | On branch main",      contexts: [        {          header: "Terminal 1 lines 12-13",          body: "12 | git status\n13 | On branch main",        },      ],      elementContexts: [],    });  });   it("preserves prompt text when no trailing terminal context block exists", () => {    expect(extractTrailingTerminalContexts("No attached context")).toEqual({      promptText: "No attached context",      contextCount: 0,      previewTitle: null,      contexts: [],    });  });   it("tracks inline terminal context placeholders in prompt text", () => {    const placeholder = INLINE_TERMINAL_CONTEXT_PLACEHOLDER;    expect(countInlineTerminalContextPlaceholders(`a${placeholder}b${placeholder}`)).toBe(2);    expect(ensureInlineTerminalContextPlaceholders("Investigate this", 2)).toBe(      `${placeholder}${placeholder}Investigate this`,    );    expect(insertInlineTerminalContextPlaceholder("abc", 1)).toEqual({      prompt: `a ${placeholder} bc`,      cursor: 4,      contextIndex: 0,    });    expect(removeInlineTerminalContextPlaceholder(`a${placeholder}b${placeholder}c`, 1)).toEqual({      prompt: `a${placeholder}bc`,      cursor: 3,    });    expect(stripInlineTerminalContextPlaceholders(`a${placeholder}b`)).toBe("ab");  });   it("inserts a placeholder after a file mention when given the expanded prompt cursor", () => {    const placeholder = INLINE_TERMINAL_CONTEXT_PLACEHOLDER;    expect(insertInlineTerminalContextPlaceholder("Inspect @package.json ", 22)).toEqual({      prompt: `Inspect @package.json ${placeholder} `,      cursor: 24,      contextIndex: 0,    });  });   it("adds a trailing space and consumes an existing trailing space at the insertion point", () => {    const placeholder = INLINE_TERMINAL_CONTEXT_PLACEHOLDER;    expect(insertInlineTerminalContextPlaceholder("yo whats", 3)).toEqual({      prompt: `yo ${placeholder} whats`,      cursor: 5,      contextIndex: 0,    });  });   it("marks contexts without snapshot text as expired and filters them from sendable contexts", () => {    const liveContext = makeContext();    const expiredContext = makeContext({      id: "context-2",      text: "",    });     expect(hasTerminalContextText(liveContext)).toBe(true);    expect(isTerminalContextExpired(liveContext)).toBe(false);    expect(hasTerminalContextText(expiredContext)).toBe(false);    expect(isTerminalContextExpired(expiredContext)).toBe(true);    expect(filterTerminalContextsWithText([expiredContext, liveContext])).toEqual([liveContext]);  });   it("formats and materializes inline terminal labels from placeholder positions", () => {    expect(formatInlineTerminalContextLabel(makeContext())).toBe("@terminal-1:12-13");    expect(      materializeInlineTerminalContextPrompt(        `Investigate ${INLINE_TERMINAL_CONTEXT_PLACEHOLDER} carefully`,        [makeContext()],      ),    ).toBe("Investigate @terminal-1:12-13 carefully");  });});