jest-fuzzy 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +65 -5
  2. package/dist/cjs/index.d.ts +2 -2
  3. package/dist/cjs/index.d.ts.map +1 -1
  4. package/dist/cjs/index.js +2 -0
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/matchers/index.d.ts +1 -0
  7. package/dist/cjs/matchers/index.d.ts.map +1 -1
  8. package/dist/cjs/matchers/index.js +3 -1
  9. package/dist/cjs/matchers/index.js.map +1 -1
  10. package/dist/cjs/matchers/toSemanticallyMatch.js +1 -1
  11. package/dist/cjs/matchers/toSemanticallyMatch.js.map +1 -1
  12. package/dist/cjs/matchers/toVisuallyMatch.d.ts +3 -0
  13. package/dist/cjs/matchers/toVisuallyMatch.d.ts.map +1 -0
  14. package/dist/cjs/matchers/toVisuallyMatch.js +62 -0
  15. package/dist/cjs/matchers/toVisuallyMatch.js.map +1 -0
  16. package/dist/cjs/providers/anthropic.d.ts +2 -1
  17. package/dist/cjs/providers/anthropic.d.ts.map +1 -1
  18. package/dist/cjs/providers/anthropic.js +46 -0
  19. package/dist/cjs/providers/anthropic.js.map +1 -1
  20. package/dist/cjs/providers/google.d.ts +2 -1
  21. package/dist/cjs/providers/google.d.ts.map +1 -1
  22. package/dist/cjs/providers/google.js +39 -0
  23. package/dist/cjs/providers/google.js.map +1 -1
  24. package/dist/cjs/providers/openai.d.ts +2 -1
  25. package/dist/cjs/providers/openai.d.ts.map +1 -1
  26. package/dist/cjs/providers/openai.js +46 -0
  27. package/dist/cjs/providers/openai.js.map +1 -1
  28. package/dist/cjs/types.d.ts +13 -1
  29. package/dist/cjs/types.d.ts.map +1 -1
  30. package/dist/cjs/utils/imageUtils.d.ts +8 -0
  31. package/dist/cjs/utils/imageUtils.d.ts.map +1 -0
  32. package/dist/cjs/utils/imageUtils.js +172 -0
  33. package/dist/cjs/utils/imageUtils.js.map +1 -0
  34. package/dist/esm/index.d.ts +2 -2
  35. package/dist/esm/index.d.ts.map +1 -1
  36. package/dist/esm/index.js +2 -0
  37. package/dist/esm/index.js.map +1 -1
  38. package/dist/esm/matchers/index.d.ts +1 -0
  39. package/dist/esm/matchers/index.d.ts.map +1 -1
  40. package/dist/esm/matchers/index.js +1 -0
  41. package/dist/esm/matchers/index.js.map +1 -1
  42. package/dist/esm/matchers/toSemanticallyMatch.js +1 -1
  43. package/dist/esm/matchers/toSemanticallyMatch.js.map +1 -1
  44. package/dist/esm/matchers/toVisuallyMatch.d.ts +3 -0
  45. package/dist/esm/matchers/toVisuallyMatch.d.ts.map +1 -0
  46. package/dist/esm/matchers/toVisuallyMatch.js +59 -0
  47. package/dist/esm/matchers/toVisuallyMatch.js.map +1 -0
  48. package/dist/esm/providers/anthropic.d.ts +2 -1
  49. package/dist/esm/providers/anthropic.d.ts.map +1 -1
  50. package/dist/esm/providers/anthropic.js +46 -0
  51. package/dist/esm/providers/anthropic.js.map +1 -1
  52. package/dist/esm/providers/google.d.ts +2 -1
  53. package/dist/esm/providers/google.d.ts.map +1 -1
  54. package/dist/esm/providers/google.js +39 -0
  55. package/dist/esm/providers/google.js.map +1 -1
  56. package/dist/esm/providers/openai.d.ts +2 -1
  57. package/dist/esm/providers/openai.d.ts.map +1 -1
  58. package/dist/esm/providers/openai.js +46 -0
  59. package/dist/esm/providers/openai.js.map +1 -1
  60. package/dist/esm/types.d.ts +13 -1
  61. package/dist/esm/types.d.ts.map +1 -1
  62. package/dist/esm/utils/imageUtils.d.ts +8 -0
  63. package/dist/esm/utils/imageUtils.d.ts.map +1 -0
  64. package/dist/esm/utils/imageUtils.js +131 -0
  65. package/dist/esm/utils/imageUtils.js.map +1 -0
  66. package/package.json +10 -1
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.isUrl = isUrl;
37
+ exports.isFilePath = isFilePath;
38
+ exports.detectMimeTypeFromBase64 = detectMimeTypeFromBase64;
39
+ exports.isBase64Image = isBase64Image;
40
+ exports.detectMimeTypeFromExtension = detectMimeTypeFromExtension;
41
+ exports.normalizeImageInput = normalizeImageInput;
42
+ const promises_1 = require("fs/promises");
43
+ const fs_1 = require("fs");
44
+ // 4MB limit (Anthropic's limit is 5MB, leaving buffer)
45
+ const MAX_IMAGE_SIZE_BYTES = 4 * 1024 * 1024;
46
+ let sharpModule = undefined;
47
+ async function getSharp() {
48
+ if (sharpModule === undefined) {
49
+ try {
50
+ const mod = await Promise.resolve().then(() => __importStar(require("sharp")));
51
+ sharpModule = mod.default;
52
+ }
53
+ catch {
54
+ sharpModule = null;
55
+ }
56
+ }
57
+ return sharpModule;
58
+ }
59
+ async function resizeImageIfNeeded(buffer, mediaType) {
60
+ const base64Size = Math.ceil(buffer.length * 4 / 3);
61
+ if (base64Size <= MAX_IMAGE_SIZE_BYTES) {
62
+ return buffer;
63
+ }
64
+ const sharp = await getSharp();
65
+ if (!sharp) {
66
+ const sizeMB = (base64Size / (1024 * 1024)).toFixed(1);
67
+ throw new Error(`Image size (${sizeMB}MB) exceeds the 4MB limit for vision APIs. ` +
68
+ `Install 'sharp' to enable automatic resizing: npm install sharp`);
69
+ }
70
+ let currentBuffer = buffer;
71
+ let quality = 85;
72
+ while (Math.ceil(currentBuffer.length * 4 / 3) > MAX_IMAGE_SIZE_BYTES && quality >= 20) {
73
+ const image = sharp(buffer);
74
+ const metadata = await image.metadata();
75
+ const currentWidth = metadata.width ?? 1920;
76
+ // Calculate scale factor based on how much we need to reduce
77
+ const currentSize = Math.ceil(currentBuffer.length * 4 / 3);
78
+ const scaleFactor = Math.sqrt(MAX_IMAGE_SIZE_BYTES / currentSize) * 0.9;
79
+ const newWidth = Math.floor(currentWidth * scaleFactor);
80
+ currentBuffer = await sharp(buffer)
81
+ .resize(newWidth, null, { withoutEnlargement: true })
82
+ .jpeg({ quality })
83
+ .toBuffer();
84
+ quality -= 10;
85
+ }
86
+ return currentBuffer;
87
+ }
88
+ function isUrl(input) {
89
+ try {
90
+ const url = new URL(input);
91
+ return url.protocol === "http:" || url.protocol === "https:";
92
+ }
93
+ catch {
94
+ return false;
95
+ }
96
+ }
97
+ function isFilePath(input) {
98
+ return (0, fs_1.existsSync)(input);
99
+ }
100
+ const BASE64_SIGNATURES = {
101
+ "/9j/": "image/jpeg",
102
+ "iVBORw0KGgo": "image/png",
103
+ "R0lGOD": "image/gif",
104
+ "UklGR": "image/webp",
105
+ };
106
+ function detectMimeTypeFromBase64(base64) {
107
+ for (const [signature, type] of Object.entries(BASE64_SIGNATURES)) {
108
+ if (base64.startsWith(signature))
109
+ return type;
110
+ }
111
+ return null;
112
+ }
113
+ function isBase64Image(input) {
114
+ return detectMimeTypeFromBase64(input) !== null;
115
+ }
116
+ function detectMimeTypeFromExtension(path) {
117
+ const ext = path.toLowerCase().split(".").pop();
118
+ switch (ext) {
119
+ case "jpg":
120
+ case "jpeg":
121
+ return "image/jpeg";
122
+ case "png":
123
+ return "image/png";
124
+ case "gif":
125
+ return "image/gif";
126
+ case "webp":
127
+ return "image/webp";
128
+ default:
129
+ return null;
130
+ }
131
+ }
132
+ async function normalizeImageInput(input, mimeTypeOverride) {
133
+ let buffer;
134
+ let detectedMimeType = null;
135
+ if (Buffer.isBuffer(input)) {
136
+ buffer = input;
137
+ detectedMimeType = detectMimeTypeFromBase64(buffer.toString("base64").slice(0, 20));
138
+ }
139
+ else if (isUrl(input)) {
140
+ const response = await fetch(input);
141
+ if (!response.ok) {
142
+ throw new Error(`Failed to fetch image from URL: ${response.status} ${response.statusText}`);
143
+ }
144
+ buffer = Buffer.from(await response.arrayBuffer());
145
+ detectedMimeType = detectMimeTypeFromBase64(buffer.toString("base64").slice(0, 20));
146
+ }
147
+ else if (isFilePath(input)) {
148
+ buffer = await (0, promises_1.readFile)(input);
149
+ detectedMimeType = detectMimeTypeFromExtension(input) ??
150
+ detectMimeTypeFromBase64(buffer.toString("base64").slice(0, 20));
151
+ }
152
+ else if (isBase64Image(input)) {
153
+ buffer = Buffer.from(input, "base64");
154
+ detectedMimeType = detectMimeTypeFromBase64(input);
155
+ }
156
+ else {
157
+ throw new Error("Invalid image input. Expected a file path, URL, base64 string, or Buffer.");
158
+ }
159
+ let mediaType = mimeTypeOverride ?? detectedMimeType;
160
+ if (!mediaType) {
161
+ throw new Error("Could not detect image MIME type. Please provide it via the mimeType option.");
162
+ }
163
+ // Resize if needed (converts to JPEG if resizing occurs)
164
+ const originalSize = buffer.length;
165
+ const resizedBuffer = await resizeImageIfNeeded(buffer, mediaType);
166
+ if (resizedBuffer.length !== originalSize) {
167
+ // Image was resized, it's now JPEG
168
+ mediaType = "image/jpeg";
169
+ }
170
+ return { base64: resizedBuffer.toString("base64"), mediaType };
171
+ }
172
+ //# sourceMappingURL=imageUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageUtils.js","sourceRoot":"","sources":["../../../src/utils/imageUtils.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { configure, getConfig, getProvider } from "./config.js";
2
- import type { JestFuzzyConfig, SemanticMatchOptions, ModelName, ApiKeys, LLMProvider } from "./types.js";
2
+ import type { JestFuzzyConfig, SemanticMatchOptions, VisualMatchOptions, ModelName, ApiKeys, LLMProvider } from "./types.js";
3
3
  export { configure, getConfig, getProvider };
4
- export type { JestFuzzyConfig, SemanticMatchOptions, ModelName, ApiKeys, LLMProvider, };
4
+ export type { JestFuzzyConfig, SemanticMatchOptions, VisualMatchOptions, ModelName, ApiKeys, LLMProvider, };
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,OAAO,EACP,WAAW,EACZ,MAAM,YAAY,CAAC;AAUpB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AAC7C,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,OAAO,EACP,WAAW,GACZ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIhE,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,SAAS,EACT,OAAO,EACP,WAAW,EACZ,MAAM,YAAY,CAAC;AAWpB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AAC7C,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,SAAS,EACT,OAAO,EACP,WAAW,GACZ,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { configure, getConfig, getProvider } from "./config.js";
2
2
  import { toSemanticallyMatch } from "./matchers/toSemanticallyMatch.js";
3
3
  import { toSatisfy } from "./matchers/toSatisfy.js";
4
+ import { toVisuallyMatch } from "./matchers/toVisuallyMatch.js";
4
5
  // Register matchers with Jest
5
6
  if (typeof expect !== "undefined" && expect.extend) {
6
7
  expect.extend({
7
8
  toSemanticallyMatch,
8
9
  toSatisfy,
10
+ toVisuallyMatch,
9
11
  });
10
12
  }
11
13
  export { configure, getConfig, getProvider };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AASpD,8BAA8B;AAC9B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;IACnD,MAAM,CAAC,MAAM,CAAC;QACZ,mBAAmB;QACnB,SAAS;KACV,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAUhE,8BAA8B;AAC9B,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;IACnD,MAAM,CAAC,MAAM,CAAC;QACZ,mBAAmB;QACnB,SAAS;QACT,eAAe;KAChB,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export { toSemanticallyMatch } from "./toSemanticallyMatch.js";
2
2
  export { toSatisfy } from "./toSatisfy.js";
3
+ export { toVisuallyMatch } from "./toVisuallyMatch.js";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/matchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/matchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export { toSemanticallyMatch } from "./toSemanticallyMatch.js";
2
2
  export { toSatisfy } from "./toSatisfy.js";
3
+ export { toVisuallyMatch } from "./toVisuallyMatch.js";
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/matchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/matchers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { getProvider } from "../config.js";
2
2
  function buildPrompt(received, expected, options) {
3
- const contextLine = options.context ? `Context: ${options.context}\n` : "";
3
+ const contextLine = options.additionalContext ? `Additional Context: ${options.additionalContext}\n` : "";
4
4
  const threshold = options.threshold ?? "loose";
5
5
  return `Do these two texts have the same semantic meaning?
6
6
  ${contextLine}Strictness: ${threshold}
@@ -1 +1 @@
1
- {"version":3,"file":"toSemanticallyMatch.js","sourceRoot":"","sources":["../../../src/matchers/toSemanticallyMatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,SAAS,WAAW,CAClB,QAAgB,EAChB,QAAgB,EAChB,OAA6B;IAE7B,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3E,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC;IAE/C,OAAO;EACP,WAAW,eAAe,SAAS;;WAE1B,QAAQ;WACR,QAAQ;;6EAE0D,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAEvC,QAAiB,EACjB,QAAgB,EAChB,UAAgC,EAAE;IAElC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,kCAAkC,OAAO,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;SACnF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE9D,OAAO;YACL,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,GAAG,EAAE;gBACZ,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,aAAa,QAAQ,gCAAgC,QAAQ,uBAAuB,WAAW,EAAE,CAAC;gBAC3G,CAAC;qBAAM,CAAC;oBACN,OAAO,aAAa,QAAQ,4BAA4B,QAAQ,uBAAuB,WAAW,EAAE,CAAC;gBACvG,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,sCAAsC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACjG,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"toSemanticallyMatch.js","sourceRoot":"","sources":["../../../src/matchers/toSemanticallyMatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,SAAS,WAAW,CAClB,QAAgB,EAChB,QAAgB,EAChB,OAA6B;IAE7B,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,uBAAuB,OAAO,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1G,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC;IAE/C,OAAO;EACP,WAAW,eAAe,SAAS;;WAE1B,QAAQ;WACR,QAAQ;;6EAE0D,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAEvC,QAAiB,EACjB,QAAgB,EAChB,UAAgC,EAAE;IAElC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,kCAAkC,OAAO,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;SACnF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAE9D,OAAO;YACL,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,GAAG,EAAE;gBACZ,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,aAAa,QAAQ,gCAAgC,QAAQ,uBAAuB,WAAW,EAAE,CAAC;gBAC3G,CAAC;qBAAM,CAAC;oBACN,OAAO,aAAa,QAAQ,4BAA4B,QAAQ,uBAAuB,WAAW,EAAE,CAAC;gBACvG,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,sCAAsC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACjG,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { VisualMatchOptions, MatcherResult } from "../types.js";
2
+ export declare function toVisuallyMatch(this: jest.MatcherContext, received: unknown, description: string, options?: VisualMatchOptions): Promise<MatcherResult>;
3
+ //# sourceMappingURL=toVisuallyMatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toVisuallyMatch.d.ts","sourceRoot":"","sources":["../../../src/matchers/toVisuallyMatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAa,MAAM,aAAa,CAAC;AAiBhF,wBAAsB,eAAe,CACnC,IAAI,EAAE,IAAI,CAAC,cAAc,EACzB,QAAQ,EAAE,OAAO,EACjB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC,CAkDxB"}
@@ -0,0 +1,59 @@
1
+ import { getProvider } from "../config.js";
2
+ import { normalizeImageInput } from "../utils/imageUtils.js";
3
+ function buildPrompt(description, options) {
4
+ const contextLine = options.additionalContext ? `Additional Context: ${options.additionalContext}\n` : "";
5
+ const threshold = options.threshold ?? "loose";
6
+ return `Does this image match the following description?
7
+
8
+ Description: "${description}"
9
+
10
+ ${contextLine}Strictness: ${threshold}
11
+
12
+ Return verdict=true if the image matches the description, false otherwise.`;
13
+ }
14
+ export async function toVisuallyMatch(received, description, options = {}) {
15
+ if (typeof received !== "string" && !Buffer.isBuffer(received)) {
16
+ return {
17
+ pass: false,
18
+ message: () => `Expected a string (file path, URL, or base64) or Buffer but received ${typeof received}`,
19
+ };
20
+ }
21
+ let imageData;
22
+ try {
23
+ imageData = await normalizeImageInput(received, options.mimeType);
24
+ }
25
+ catch (error) {
26
+ return {
27
+ pass: false,
28
+ message: () => `Failed to process image: ${error instanceof Error ? error.message : String(error)}`,
29
+ };
30
+ }
31
+ const provider = await getProvider();
32
+ const prompt = buildPrompt(description, options);
33
+ try {
34
+ const { verdict, explanation } = await provider.judgeImage(imageData, prompt);
35
+ return {
36
+ pass: verdict,
37
+ message: () => {
38
+ const inputDesc = typeof received === "string"
39
+ ? received.length > 50
40
+ ? `${received.slice(0, 50)}...`
41
+ : received
42
+ : "[Buffer]";
43
+ if (verdict) {
44
+ return `Expected image (${inputDesc}) NOT to visually match "${description}"\n\nLLM reasoning: ${explanation}`;
45
+ }
46
+ else {
47
+ return `Expected image (${inputDesc}) to visually match "${description}"\n\nLLM reasoning: ${explanation}`;
48
+ }
49
+ },
50
+ };
51
+ }
52
+ catch (error) {
53
+ return {
54
+ pass: false,
55
+ message: () => `Failed to evaluate visual match: ${error instanceof Error ? error.message : String(error)}`,
56
+ };
57
+ }
58
+ }
59
+ //# sourceMappingURL=toVisuallyMatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toVisuallyMatch.js","sourceRoot":"","sources":["../../../src/matchers/toVisuallyMatch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,SAAS,WAAW,CAAC,WAAmB,EAAE,OAA2B;IACnE,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,uBAAuB,OAAO,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1G,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC;IAE/C,OAAO;;gBAEO,WAAW;;EAEzB,WAAW,eAAe,SAAS;;2EAEsC,CAAC;AAC5E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAEnC,QAAiB,EACjB,WAAmB,EACnB,UAA8B,EAAE;IAEhC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/D,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,wEAAwE,OAAO,QAAQ,EAAE;SAC5F,CAAC;IACJ,CAAC;IAED,IAAI,SAAoB,CAAC;IACzB,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,4BAA4B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACvF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAE9E,OAAO;YACL,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,GAAG,EAAE;gBACZ,MAAM,SAAS,GACb,OAAO,QAAQ,KAAK,QAAQ;oBAC1B,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE;wBACpB,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK;wBAC/B,CAAC,CAAC,QAAQ;oBACZ,CAAC,CAAC,UAAU,CAAC;gBAEjB,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,mBAAmB,SAAS,4BAA4B,WAAW,uBAAuB,WAAW,EAAE,CAAC;gBACjH,CAAC;qBAAM,CAAC;oBACN,OAAO,mBAAmB,SAAS,wBAAwB,WAAW,uBAAuB,WAAW,EAAE,CAAC;gBAC7G,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,oCAAoC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SAC/F,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -1,8 +1,9 @@
1
- import type { LLMProvider, JudgmentResult } from "../types.js";
1
+ import type { LLMProvider, JudgmentResult, ImageData } from "../types.js";
2
2
  export declare class AnthropicProvider implements LLMProvider {
3
3
  private apiKey;
4
4
  private constructor();
5
5
  static create(apiKey?: string): Promise<AnthropicProvider>;
6
6
  judge(prompt: string): Promise<JudgmentResult>;
7
+ judgeImage(imageData: ImageData, prompt: string): Promise<JudgmentResult>;
7
8
  }
8
9
  //# sourceMappingURL=anthropic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAoB/D,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;WAIM,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAW1D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAmCrD"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoB1E,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;WAIM,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAW1D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAoC9C,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAkDhF"}
@@ -58,5 +58,51 @@ export class AnthropicProvider {
58
58
  const parsed = JSON.parse(text);
59
59
  return { verdict: parsed.verdict, explanation: parsed.explanation };
60
60
  }
61
+ async judgeImage(imageData, prompt) {
62
+ const response = await fetch(ANTHROPIC_API_URL, {
63
+ method: "POST",
64
+ headers: {
65
+ "content-type": "application/json",
66
+ "x-api-key": this.apiKey,
67
+ "anthropic-version": "2023-06-01",
68
+ "anthropic-beta": "structured-outputs-2025-11-13",
69
+ },
70
+ body: JSON.stringify({
71
+ model: "claude-haiku-4-5",
72
+ max_tokens: 1024,
73
+ messages: [
74
+ {
75
+ role: "user",
76
+ content: [
77
+ {
78
+ type: "image",
79
+ source: {
80
+ type: "base64",
81
+ media_type: imageData.mediaType,
82
+ data: imageData.base64,
83
+ },
84
+ },
85
+ { type: "text", text: prompt },
86
+ ],
87
+ },
88
+ ],
89
+ output_format: {
90
+ type: "json_schema",
91
+ schema: JUDGMENT_SCHEMA,
92
+ },
93
+ }),
94
+ });
95
+ if (!response.ok) {
96
+ const errorText = await response.text();
97
+ throw new Error(`jest-fuzzy: Anthropic API error (${response.status}): ${errorText}`);
98
+ }
99
+ const data = (await response.json());
100
+ const text = data.content?.[0]?.text;
101
+ if (!text) {
102
+ throw new Error("jest-fuzzy: Anthropic API returned no content");
103
+ }
104
+ const parsed = JSON.parse(text);
105
+ return { verdict: parsed.verdict, explanation: parsed.explanation };
106
+ }
61
107
  }
62
108
  //# sourceMappingURL=anthropic.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/providers/anthropic.ts"],"names":[],"mappings":"AAEA,MAAM,iBAAiB,GAAG,uCAAuC,CAAC;AAElE,MAAM,eAAe,GAAG;IACtB,IAAI,EAAE,QAAiB;IACvB,UAAU,EAAE;QACV,OAAO,EAAE;YACP,IAAI,EAAE,SAAkB;YACxB,WAAW,EAAE,qDAAqD;SACnE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAiB;YACvB,WAAW,EAAE,oCAAoC;SAClD;KACF;IACD,QAAQ,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;IACpC,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAS;IAEvB,YAAoB,MAAc;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAe;QACjC,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACpD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,0DAA0D;gBACxD,gHAAgH,CACnH,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;gBACxB,mBAAmB,EAAE,YAAY;gBACjC,gBAAgB,EAAE,+BAA+B;aAClD;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,kBAAkB;gBACzB,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;gBAC7C,aAAa,EAAE;oBACb,IAAI,EAAE,aAAa;oBACnB,MAAM,EAAE,eAAe;iBACxB;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA2C,CAAC;QAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAErC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA8C,CAAC;QAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;IACtE,CAAC;CACF"}
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/providers/anthropic.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import type { LLMProvider, JudgmentResult } from "../types.js";
1
+ import type { LLMProvider, JudgmentResult, ImageData } from "../types.js";
2
2
  export declare class GoogleProvider implements LLMProvider {
3
3
  private apiKey;
4
4
  private constructor();
5
5
  static create(apiKey?: string): Promise<GoogleProvider>;
6
6
  judge(prompt: string): Promise<JudgmentResult>;
7
+ judgeImage(imageData: ImageData, prompt: string): Promise<JudgmentResult>;
7
8
  }
8
9
  //# sourceMappingURL=google.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../src/providers/google.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAmB/D,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;WAIM,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAWvD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAsCrD"}
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../src/providers/google.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAmB1E,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;WAIM,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAWvD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuC9C,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CA8ChF"}
@@ -57,5 +57,44 @@ export class GoogleProvider {
57
57
  const parsed = JSON.parse(text);
58
58
  return { verdict: parsed.verdict, explanation: parsed.explanation };
59
59
  }
60
+ async judgeImage(imageData, prompt) {
61
+ const url = `${GEMINI_API_URL}?key=${this.apiKey}`;
62
+ const response = await fetch(url, {
63
+ method: "POST",
64
+ headers: {
65
+ "Content-Type": "application/json",
66
+ },
67
+ body: JSON.stringify({
68
+ contents: [
69
+ {
70
+ parts: [
71
+ { text: prompt },
72
+ {
73
+ inline_data: {
74
+ mime_type: imageData.mediaType,
75
+ data: imageData.base64,
76
+ },
77
+ },
78
+ ],
79
+ },
80
+ ],
81
+ generationConfig: {
82
+ responseMimeType: "application/json",
83
+ responseSchema: JUDGMENT_SCHEMA,
84
+ },
85
+ }),
86
+ });
87
+ if (!response.ok) {
88
+ const errorText = await response.text();
89
+ throw new Error(`jest-fuzzy: Google API error (${response.status}): ${errorText}`);
90
+ }
91
+ const data = (await response.json());
92
+ const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
93
+ if (!text) {
94
+ throw new Error("jest-fuzzy: Google API returned no content");
95
+ }
96
+ const parsed = JSON.parse(text);
97
+ return { verdict: parsed.verdict, explanation: parsed.explanation };
98
+ }
60
99
  }
61
100
  //# sourceMappingURL=google.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"google.js","sourceRoot":"","sources":["../../../src/providers/google.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,0FAA0F,CAAC;AAElH,MAAM,eAAe,GAAG;IACtB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,OAAO,EAAE;YACP,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,qDAAqD;SACnE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,oCAAoC;SAClD;KACF;IACD,QAAQ,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;CACrC,CAAC;AAEF,MAAM,OAAO,cAAc;IACjB,MAAM,CAAS;IAEvB,YAAoB,MAAc;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAe;QACjC,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACjD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,gEAAgE;gBAC9D,0GAA0G,CAC7G,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,MAAM,GAAG,GAAG,GAAG,cAAc,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QAEnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EAAE;oBACR;wBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;qBAC1B;iBACF;gBACD,gBAAgB,EAAE;oBAChB,gBAAgB,EAAE,kBAAkB;oBACpC,cAAc,EAAE,eAAe;iBAChC;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAE7D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA8C,CAAC;QAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;IACtE,CAAC;CACF"}
1
+ {"version":3,"file":"google.js","sourceRoot":"","sources":["../../../src/providers/google.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import type { LLMProvider, JudgmentResult } from "../types.js";
1
+ import type { LLMProvider, JudgmentResult, ImageData } from "../types.js";
2
2
  export declare class OpenAIProvider implements LLMProvider {
3
3
  private apiKey;
4
4
  private constructor();
5
5
  static create(apiKey?: string): Promise<OpenAIProvider>;
6
6
  judge(prompt: string): Promise<JudgmentResult>;
7
+ judgeImage(imageData: ImageData, prompt: string): Promise<JudgmentResult>;
7
8
  }
8
9
  //# sourceMappingURL=openai.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAoB/D,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;WAIM,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAWvD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAuCrD"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoB1E,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO;WAIM,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAWvD,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAwC9C,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAoDhF"}
@@ -60,5 +60,51 @@ export class OpenAIProvider {
60
60
  const parsed = JSON.parse(text);
61
61
  return { verdict: parsed.verdict, explanation: parsed.explanation };
62
62
  }
63
+ async judgeImage(imageData, prompt) {
64
+ const response = await fetch(OPENAI_API_URL, {
65
+ method: "POST",
66
+ headers: {
67
+ "Content-Type": "application/json",
68
+ Authorization: `Bearer ${this.apiKey}`,
69
+ },
70
+ body: JSON.stringify({
71
+ model: "gpt-4o-mini",
72
+ max_output_tokens: 1024,
73
+ input: [
74
+ {
75
+ role: "user",
76
+ content: [
77
+ { type: "text", text: prompt },
78
+ {
79
+ type: "image_url",
80
+ image_url: {
81
+ url: `data:${imageData.mediaType};base64,${imageData.base64}`,
82
+ },
83
+ },
84
+ ],
85
+ },
86
+ ],
87
+ text: {
88
+ format: {
89
+ type: "json_schema",
90
+ name: "judgment",
91
+ strict: true,
92
+ schema: JUDGMENT_SCHEMA,
93
+ },
94
+ },
95
+ }),
96
+ });
97
+ if (!response.ok) {
98
+ const errorText = await response.text();
99
+ throw new Error(`jest-fuzzy: OpenAI API error (${response.status}): ${errorText}`);
100
+ }
101
+ const data = (await response.json());
102
+ const text = data.output?.[0]?.content?.[0]?.text;
103
+ if (!text) {
104
+ throw new Error("jest-fuzzy: OpenAI API returned no content");
105
+ }
106
+ const parsed = JSON.parse(text);
107
+ return { verdict: parsed.verdict, explanation: parsed.explanation };
108
+ }
63
109
  }
64
110
  //# sourceMappingURL=openai.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/providers/openai.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,qCAAqC,CAAC;AAE7D,MAAM,eAAe,GAAG;IACtB,IAAI,EAAE,QAAiB;IACvB,UAAU,EAAE;QACV,OAAO,EAAE;YACP,IAAI,EAAE,SAAkB;YACxB,WAAW,EAAE,qDAAqD;SACnE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAiB;YACvB,WAAW,EAAE,oCAAoC;SAClD;KACF;IACD,QAAQ,EAAE,CAAC,SAAS,EAAE,aAAa,CAAU;IAC7C,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,OAAO,cAAc;IACjB,MAAM,CAAS;IAEvB,YAAoB,MAAc;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAe;QACjC,MAAM,GAAG,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACjD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CACb,oDAAoD;gBAClD,0GAA0G,CAC7G,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,cAAc,EAAE;YAC3C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,aAAa;gBACpB,iBAAiB,EAAE,IAAI;gBACvB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;gBAC1C,IAAI,EAAE;oBACJ,MAAM,EAAE;wBACN,IAAI,EAAE,aAAa;wBACnB,IAAI,EAAE,UAAU;wBAChB,MAAM,EAAE,IAAI;wBACZ,MAAM,EAAE,eAAe;qBACxB;iBACF;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;QAElD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA8C,CAAC;QAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;IACtE,CAAC;CACF"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/providers/openai.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,9 @@
1
1
  export type ModelName = "claude-haiku-4-5" | "gemini-3-flash-preview" | "gpt-5-nano";
2
+ export type ImageMediaType = "image/jpeg" | "image/png" | "image/gif" | "image/webp";
3
+ export interface ImageData {
4
+ base64: string;
5
+ mediaType: ImageMediaType;
6
+ }
2
7
  export interface ApiKeys {
3
8
  anthropic?: string;
4
9
  google?: string;
@@ -10,7 +15,12 @@ export interface JestFuzzyConfig {
10
15
  }
11
16
  export interface SemanticMatchOptions {
12
17
  threshold?: "strict" | "loose";
13
- context?: string;
18
+ additionalContext?: string;
19
+ }
20
+ export interface VisualMatchOptions {
21
+ threshold?: "strict" | "loose";
22
+ additionalContext?: string;
23
+ mimeType?: ImageMediaType;
14
24
  }
15
25
  export interface JudgmentResult {
16
26
  verdict: boolean;
@@ -18,6 +28,7 @@ export interface JudgmentResult {
18
28
  }
19
29
  export interface LLMProvider {
20
30
  judge(prompt: string): Promise<JudgmentResult>;
31
+ judgeImage(imageData: ImageData, prompt: string): Promise<JudgmentResult>;
21
32
  }
22
33
  export interface MatcherResult {
23
34
  pass: boolean;
@@ -28,6 +39,7 @@ declare global {
28
39
  interface Matchers<R> {
29
40
  toSemanticallyMatch(expected: string, options?: SemanticMatchOptions): Promise<R>;
30
41
  toSatisfy(criteria: string): Promise<R>;
42
+ toVisuallyMatch(description: string, options?: VisualMatchOptions): Promise<R>;
31
43
  }
32
44
  }
33
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,kBAAkB,GAClB,wBAAwB,GACxB,YAAY,CAAC;AAEjB,MAAM,WAAW,OAAO;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,MAAM,CAAC;CACvB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,IAAI,CAAC;QACb,UAAU,QAAQ,CAAC,CAAC;YAClB,mBAAmB,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAAC;YACd,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;SACzC;KACF;CACF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,kBAAkB,GAClB,wBAAwB,GACxB,YAAY,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY,CAAC;AAErF,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,OAAO;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC3E;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,MAAM,CAAC;CACvB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,IAAI,CAAC;QACb,UAAU,QAAQ,CAAC,CAAC;YAClB,mBAAmB,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAAC;YACd,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACxC,eAAe,CACb,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAAC;SACf;KACF;CACF"}