history.test.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { describe, expect, test } from "bun:test"
  2. import { isDuplicateEntry, MAX_HISTORY_ENTRIES, parsePromptHistory, type PromptInfo } from "../../src/prompt/history"
  3. const entry = (text: string, files: PromptInfo["files"] = []): PromptInfo => ({
  4. text,
  5. files,
  6. agents: [],
  7. pasted: [],
  8. })
  9. describe("prompt history", () => {
  10. test("recovers valid JSONL entries around corruption", () => {
  11. expect(parsePromptHistory(`${JSON.stringify(entry("one"))}\nnot-json\n${JSON.stringify(entry("two"))}\n`)).toEqual([
  12. entry("one"),
  13. entry("two"),
  14. ])
  15. })
  16. test("ignores the legacy parts shape", () => {
  17. expect(parsePromptHistory(JSON.stringify({ input: "old", parts: [] }))).toEqual([])
  18. })
  19. test("retains only the newest entries", () => {
  20. const input = Array.from({ length: MAX_HISTORY_ENTRIES + 5 }, (_, index) =>
  21. JSON.stringify(entry(String(index))),
  22. ).join("\n")
  23. const result = parsePromptHistory(input)
  24. expect(result).toHaveLength(MAX_HISTORY_ENTRIES)
  25. expect(result[0]?.text).toBe("5")
  26. })
  27. test("dedupes only identical consecutive entries", () => {
  28. expect(isDuplicateEntry(undefined, entry("hello"))).toBe(false)
  29. expect(isDuplicateEntry(entry("hello"), entry("hello"))).toBe(true)
  30. expect(isDuplicateEntry(entry("foo"), entry("bar"))).toBe(false)
  31. expect(isDuplicateEntry({ ...entry("ls"), mode: "normal" }, { ...entry("ls"), mode: "shell" })).toBe(false)
  32. })
  33. test("does not dedupe entries with different attachments", () => {
  34. const a = entry("describe this", [{ name: "a.png", uri: "data:image/png;base64,AAA" }])
  35. const b = entry("describe this", [{ name: "b.png", uri: "data:image/png;base64,BBB" }])
  36. expect(isDuplicateEntry(a, b)).toBe(false)
  37. })
  38. test("preserves duplicate attachment mentions for prompt restoration", () => {
  39. const value = entry("[Image 1] [Image 1]", [
  40. {
  41. name: "clipboard",
  42. uri: "data:image/png;base64,AAA",
  43. mention: { start: 0, end: 9, text: "[Image 1]" },
  44. },
  45. {
  46. name: "clipboard",
  47. uri: "data:image/png;base64,AAA",
  48. mention: { start: 10, end: 19, text: "[Image 1]" },
  49. },
  50. ])
  51. expect(parsePromptHistory(JSON.stringify(value))).toEqual([value])
  52. })
  53. })