attachment.test.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { describe, expect, test } from "bun:test"
  2. import {
  3. deduplicatePromptImages,
  4. deduplicateVisibleImages,
  5. preserveMentionlessPromptAttachments,
  6. promptAttachmentLabel,
  7. } from "../../src/prompt/attachment"
  8. describe("prompt attachments", () => {
  9. test("deduplicates identical inline images while preserving other attachments", () => {
  10. const files = [
  11. {
  12. uri: "data:image/png;base64,AAA",
  13. name: "first.png",
  14. mention: { start: 0, end: 9, text: "[Image 1]" },
  15. },
  16. { uri: "file:///same", name: "first.txt" },
  17. { uri: "data:application/pdf;base64,CCC", name: "first.pdf" },
  18. {
  19. uri: "data:image/png;base64,BBB",
  20. name: "second.png",
  21. mention: { start: 10, end: 19, text: "[Image 2]" },
  22. },
  23. {
  24. uri: "data:image/png;base64,AAA",
  25. name: "first.png",
  26. mention: { start: 20, end: 29, text: "[Image 1]" },
  27. },
  28. {
  29. uri: "data:image/png;base64,AAA",
  30. name: "first.png",
  31. description: "alternate use",
  32. mention: { start: 30, end: 39, text: "[Image 1]" },
  33. },
  34. { uri: "file:///same", name: "second.txt" },
  35. { uri: "data:application/pdf;base64,CCC", name: "first.pdf" },
  36. ]
  37. expect(deduplicatePromptImages(files)).toEqual([
  38. files[0],
  39. files[1],
  40. files[2],
  41. files[3],
  42. files[5],
  43. files[6],
  44. files[7],
  45. ])
  46. expect(files).toHaveLength(8)
  47. })
  48. test("reuses labels for identical image data", () => {
  49. const first = "data:image/png;base64,AAA"
  50. const second = "data:image/png;base64,BBB"
  51. const files = [{ uri: first, mention: { start: 0, end: 9, text: "[Image 1]" } }]
  52. expect(promptAttachmentLabel(files, { uri: first })).toBe("[Image 1]")
  53. expect(promptAttachmentLabel([...files, { ...files[0], mention: undefined }], { uri: second })).toBe("[Image 2]")
  54. expect(promptAttachmentLabel([{ uri: first }], { uri: first })).toBe("[Image 1]")
  55. })
  56. test("numbers PDFs independently from images", () => {
  57. const files = [{ uri: "data:image/png;base64,AAA" }]
  58. expect(promptAttachmentLabel(files, { uri: "data:application/pdf;base64,BBB" })).toBe("[PDF 1]")
  59. })
  60. test("does not reuse a label when attachment metadata differs", () => {
  61. const uri = "data:image/png;base64,AAA"
  62. const files = [{ uri, name: "one.png", mention: { start: 0, end: 9, text: "[Image 1]" } }]
  63. expect(promptAttachmentLabel(files, { uri, name: "two.png" })).toBe("[Image 2]")
  64. })
  65. test("does not reuse numbers after an earlier attachment is removed", () => {
  66. const files = [{ uri: "data:image/png;base64,BBB", mention: { start: 0, end: 9, text: "[Image 2]" } }]
  67. expect(promptAttachmentLabel(files, { uri: "data:image/png;base64,CCC" })).toBe("[Image 3]")
  68. })
  69. test("preserves mentionless attachments when tracked mentions are synchronized", () => {
  70. const mentionless = { uri: "data:image/png;base64,AAA" }
  71. const emptyMention = {
  72. uri: "data:image/png;base64,CCC",
  73. mention: { start: 0, end: 0, text: "" },
  74. }
  75. const mentioned = {
  76. uri: "data:image/png;base64,BBB",
  77. mention: { start: 0, end: 9, text: "[Image 1]" },
  78. }
  79. const restored = preserveMentionlessPromptAttachments([mentionless, emptyMention, mentioned], [mentioned])
  80. expect(restored).toEqual([mentionless, emptyMention, mentioned])
  81. expect(restored.indexOf(mentioned)).toBe(2)
  82. const another = {
  83. uri: "data:image/png;base64,DDD",
  84. mention: { start: 10, end: 19, text: "[Image 2]" },
  85. }
  86. expect(preserveMentionlessPromptAttachments([mentioned, mentionless, another], [another, mentioned])).toEqual([
  87. another,
  88. mentionless,
  89. mentioned,
  90. ])
  91. })
  92. test("deduplicates visible inline image cards without dropping durable references", () => {
  93. const file = {
  94. data: "AAA",
  95. mime: "image/png",
  96. source: { type: "inline" },
  97. name: "clipboard",
  98. mention: { text: "[Image 1]" },
  99. }
  100. const files = [file, { ...file, mention: { text: "[Image 1]" } }]
  101. expect(deduplicateVisibleImages(files)).toEqual([file])
  102. expect(files).toHaveLength(2)
  103. const distinct = [
  104. { ...file, mention: { text: "[Image 2]" } },
  105. { ...file, mention: undefined },
  106. ]
  107. expect(deduplicateVisibleImages([file, ...distinct])).toEqual([file, ...distinct])
  108. })
  109. })