jest-fuzzy 0.1.1 → 0.1.3

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 +55 -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 +52 -14
  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 +89 -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 +52 -14
  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 +81 -0
  65. package/dist/esm/utils/imageUtils.js.map +1 -0
  66. package/package.json +1 -1
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isUrl = isUrl;
4
+ exports.isFilePath = isFilePath;
5
+ exports.detectMimeTypeFromBase64 = detectMimeTypeFromBase64;
6
+ exports.isBase64Image = isBase64Image;
7
+ exports.detectMimeTypeFromExtension = detectMimeTypeFromExtension;
8
+ exports.normalizeImageInput = normalizeImageInput;
9
+ const promises_1 = require("fs/promises");
10
+ const fs_1 = require("fs");
11
+ function isUrl(input) {
12
+ try {
13
+ const url = new URL(input);
14
+ return url.protocol === "http:" || url.protocol === "https:";
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ function isFilePath(input) {
21
+ return (0, fs_1.existsSync)(input);
22
+ }
23
+ const BASE64_SIGNATURES = {
24
+ "/9j/": "image/jpeg",
25
+ "iVBORw0KGgo": "image/png",
26
+ "R0lGOD": "image/gif",
27
+ "UklGR": "image/webp",
28
+ };
29
+ function detectMimeTypeFromBase64(base64) {
30
+ for (const [signature, type] of Object.entries(BASE64_SIGNATURES)) {
31
+ if (base64.startsWith(signature))
32
+ return type;
33
+ }
34
+ return null;
35
+ }
36
+ function isBase64Image(input) {
37
+ return detectMimeTypeFromBase64(input) !== null;
38
+ }
39
+ function detectMimeTypeFromExtension(path) {
40
+ const ext = path.toLowerCase().split(".").pop();
41
+ switch (ext) {
42
+ case "jpg":
43
+ case "jpeg":
44
+ return "image/jpeg";
45
+ case "png":
46
+ return "image/png";
47
+ case "gif":
48
+ return "image/gif";
49
+ case "webp":
50
+ return "image/webp";
51
+ default:
52
+ return null;
53
+ }
54
+ }
55
+ async function normalizeImageInput(input, mimeTypeOverride) {
56
+ let base64;
57
+ let detectedMimeType = null;
58
+ if (Buffer.isBuffer(input)) {
59
+ base64 = input.toString("base64");
60
+ detectedMimeType = detectMimeTypeFromBase64(base64);
61
+ }
62
+ else if (isUrl(input)) {
63
+ const response = await fetch(input);
64
+ if (!response.ok) {
65
+ throw new Error(`Failed to fetch image from URL: ${response.status} ${response.statusText}`);
66
+ }
67
+ const buffer = Buffer.from(await response.arrayBuffer());
68
+ base64 = buffer.toString("base64");
69
+ detectedMimeType = detectMimeTypeFromBase64(base64);
70
+ }
71
+ else if (isFilePath(input)) {
72
+ const buffer = await (0, promises_1.readFile)(input);
73
+ base64 = buffer.toString("base64");
74
+ detectedMimeType = detectMimeTypeFromExtension(input) ?? detectMimeTypeFromBase64(base64);
75
+ }
76
+ else if (isBase64Image(input)) {
77
+ base64 = input;
78
+ detectedMimeType = detectMimeTypeFromBase64(base64);
79
+ }
80
+ else {
81
+ throw new Error("Invalid image input. Expected a file path, URL, base64 string, or Buffer.");
82
+ }
83
+ const mediaType = mimeTypeOverride ?? detectedMimeType;
84
+ if (!mediaType) {
85
+ throw new Error("Could not detect image MIME type. Please provide it via the mimeType option.");
86
+ }
87
+ return { base64, mediaType };
88
+ }
89
+ //# 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":"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;IAED,KAAK,CAAC,UAAU,CAAC,SAAoB,EAAE,MAAc;QACnD,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;oBACR;wBACE,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,OAAO;gCACb,MAAM,EAAE;oCACN,IAAI,EAAE,QAAQ;oCACd,UAAU,EAAE,SAAS,CAAC,SAAS;oCAC/B,IAAI,EAAE,SAAS,CAAC,MAAM;iCACvB;6BACF;4BACD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;yBAC/B;qBACF;iBACF;gBACD,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,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;CAgDrD"}
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"}
@@ -1,4 +1,4 @@
1
- const OPENAI_API_URL = "https://api.openai.com/v1/chat/completions";
1
+ const OPENAI_API_URL = "https://api.openai.com/v1/responses";
2
2
  const JUDGMENT_SCHEMA = {
3
3
  type: "object",
4
4
  properties: {
@@ -36,19 +36,57 @@ export class OpenAIProvider {
36
36
  },
37
37
  body: JSON.stringify({
38
38
  model: "gpt-4o-mini",
39
- max_tokens: 1024,
40
- messages: [
39
+ max_output_tokens: 1024,
40
+ input: [{ role: "user", content: prompt }],
41
+ text: {
42
+ format: {
43
+ type: "json_schema",
44
+ name: "judgment",
45
+ strict: true,
46
+ schema: JUDGMENT_SCHEMA,
47
+ },
48
+ },
49
+ }),
50
+ });
51
+ if (!response.ok) {
52
+ const errorText = await response.text();
53
+ throw new Error(`jest-fuzzy: OpenAI API error (${response.status}): ${errorText}`);
54
+ }
55
+ const data = (await response.json());
56
+ const text = data.output?.[0]?.content?.[0]?.text;
57
+ if (!text) {
58
+ throw new Error("jest-fuzzy: OpenAI API returned no content");
59
+ }
60
+ const parsed = JSON.parse(text);
61
+ return { verdict: parsed.verdict, explanation: parsed.explanation };
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: [
41
74
  {
42
- role: "system",
43
- content: 'You must respond with valid JSON matching this schema: {"verdict": boolean, "explanation": string}. ' +
44
- '"verdict" should be true if the condition is satisfied, false otherwise. ' +
45
- '"explanation" should briefly explain your reasoning.',
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
+ ],
46
85
  },
47
- { role: "user", content: prompt },
48
86
  ],
49
- response_format: {
50
- type: "json_schema",
51
- json_schema: {
87
+ text: {
88
+ format: {
89
+ type: "json_schema",
52
90
  name: "judgment",
53
91
  strict: true,
54
92
  schema: JUDGMENT_SCHEMA,
@@ -61,11 +99,11 @@ export class OpenAIProvider {
61
99
  throw new Error(`jest-fuzzy: OpenAI API error (${response.status}): ${errorText}`);
62
100
  }
63
101
  const data = (await response.json());
64
- const content = data.choices?.[0]?.message?.content;
65
- if (!content) {
102
+ const text = data.output?.[0]?.content?.[0]?.text;
103
+ if (!text) {
66
104
  throw new Error("jest-fuzzy: OpenAI API returned no content");
67
105
  }
68
- const parsed = JSON.parse(content);
106
+ const parsed = JSON.parse(text);
69
107
  return { verdict: parsed.verdict, explanation: parsed.explanation };
70
108
  }
71
109
  }
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/providers/openai.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,4CAA4C,CAAC;AAEpE,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,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,QAAQ;wBACd,OAAO,EACL,sGAAsG;4BACtG,2EAA2E;4BAC3E,sDAAsD;qBACzD;oBACD,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;iBAClC;gBACD,eAAe,EAAE;oBACf,IAAI,EAAE,aAAa;oBACnB,WAAW,EAAE;wBACX,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,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;QAEpD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA8C,CAAC;QAChF,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"}
@@ -0,0 +1,8 @@
1
+ import type { ImageMediaType, ImageData } from "../types.js";
2
+ export declare function isUrl(input: string): boolean;
3
+ export declare function isFilePath(input: string): boolean;
4
+ export declare function detectMimeTypeFromBase64(base64: string): ImageMediaType | null;
5
+ export declare function isBase64Image(input: string): boolean;
6
+ export declare function detectMimeTypeFromExtension(path: string): ImageMediaType | null;
7
+ export declare function normalizeImageInput(input: string | Buffer, mimeTypeOverride?: ImageMediaType): Promise<ImageData>;
8
+ //# sourceMappingURL=imageUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/imageUtils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7D,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAO5C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD;AASD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAK9E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAe/E;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,gBAAgB,CAAC,EAAE,cAAc,GAChC,OAAO,CAAC,SAAS,CAAC,CAoCpB"}