jest-fuzzy 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +249 -0
- package/dist/cjs/config.d.ts +5 -0
- package/dist/cjs/config.d.ts.map +1 -0
- package/dist/cjs/config.js +38 -0
- package/dist/cjs/config.js.map +1 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +17 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/matchers/index.d.ts +3 -0
- package/dist/cjs/matchers/index.d.ts.map +1 -0
- package/dist/cjs/matchers/index.js +8 -0
- package/dist/cjs/matchers/index.js.map +1 -0
- package/dist/cjs/matchers/toSatisfy.d.ts +3 -0
- package/dist/cjs/matchers/toSatisfy.d.ts.map +1 -0
- package/dist/cjs/matchers/toSatisfy.js +43 -0
- package/dist/cjs/matchers/toSatisfy.js.map +1 -0
- package/dist/cjs/matchers/toSemanticallyMatch.d.ts +3 -0
- package/dist/cjs/matchers/toSemanticallyMatch.d.ts.map +1 -0
- package/dist/cjs/matchers/toSemanticallyMatch.js +46 -0
- package/dist/cjs/matchers/toSemanticallyMatch.js.map +1 -0
- package/dist/cjs/providers/anthropic.d.ts +8 -0
- package/dist/cjs/providers/anthropic.d.ts.map +1 -0
- package/dist/cjs/providers/anthropic.js +94 -0
- package/dist/cjs/providers/anthropic.js.map +1 -0
- package/dist/cjs/providers/google.d.ts +8 -0
- package/dist/cjs/providers/google.d.ts.map +1 -0
- package/dist/cjs/providers/google.js +90 -0
- package/dist/cjs/providers/google.js.map +1 -0
- package/dist/cjs/providers/index.d.ts +8 -0
- package/dist/cjs/providers/index.d.ts.map +1 -0
- package/dist/cjs/providers/index.js +23 -0
- package/dist/cjs/providers/index.js.map +1 -0
- package/dist/cjs/providers/openai.d.ts +8 -0
- package/dist/cjs/providers/openai.d.ts.map +1 -0
- package/dist/cjs/providers/openai.js +97 -0
- package/dist/cjs/providers/openai.js.map +1 -0
- package/dist/cjs/types.d.ts +28 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/config.d.ts +5 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +33 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +12 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/matchers/index.d.ts +3 -0
- package/dist/esm/matchers/index.d.ts.map +1 -0
- package/dist/esm/matchers/index.js +3 -0
- package/dist/esm/matchers/index.js.map +1 -0
- package/dist/esm/matchers/toSatisfy.d.ts +3 -0
- package/dist/esm/matchers/toSatisfy.d.ts.map +1 -0
- package/dist/esm/matchers/toSatisfy.js +40 -0
- package/dist/esm/matchers/toSatisfy.js.map +1 -0
- package/dist/esm/matchers/toSemanticallyMatch.d.ts +3 -0
- package/dist/esm/matchers/toSemanticallyMatch.d.ts.map +1 -0
- package/dist/esm/matchers/toSemanticallyMatch.js +43 -0
- package/dist/esm/matchers/toSemanticallyMatch.js.map +1 -0
- package/dist/esm/providers/anthropic.d.ts +8 -0
- package/dist/esm/providers/anthropic.d.ts.map +1 -0
- package/dist/esm/providers/anthropic.js +57 -0
- package/dist/esm/providers/anthropic.js.map +1 -0
- package/dist/esm/providers/google.d.ts +8 -0
- package/dist/esm/providers/google.d.ts.map +1 -0
- package/dist/esm/providers/google.js +53 -0
- package/dist/esm/providers/google.js.map +1 -0
- package/dist/esm/providers/index.d.ts +8 -0
- package/dist/esm/providers/index.d.ts.map +1 -0
- package/dist/esm/providers/index.js +17 -0
- package/dist/esm/providers/index.js.map +1 -0
- package/dist/esm/providers/openai.d.ts +8 -0
- package/dist/esm/providers/openai.d.ts.map +1 -0
- package/dist/esm/providers/openai.js +60 -0
- package/dist/esm/providers/openai.js.map +1 -0
- package/dist/esm/types.d.ts +28 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,90 @@
|
|
|
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.GoogleProvider = void 0;
|
|
37
|
+
class GoogleProvider {
|
|
38
|
+
model;
|
|
39
|
+
constructor(model) {
|
|
40
|
+
this.model = model;
|
|
41
|
+
}
|
|
42
|
+
static async create() {
|
|
43
|
+
const apiKey = process.env.GOOGLE_API_KEY;
|
|
44
|
+
if (!apiKey) {
|
|
45
|
+
throw new Error("jest-fuzzy: Missing GOOGLE_API_KEY environment variable for gemini-3-flash-preview model");
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const module = await Promise.resolve().then(() => __importStar(require("@google/generative-ai")));
|
|
49
|
+
const { GoogleGenerativeAI, SchemaType } = module;
|
|
50
|
+
const genAI = new GoogleGenerativeAI(apiKey);
|
|
51
|
+
const model = genAI.getGenerativeModel({
|
|
52
|
+
model: "gemini-2.0-flash",
|
|
53
|
+
generationConfig: {
|
|
54
|
+
responseMimeType: "application/json",
|
|
55
|
+
responseSchema: {
|
|
56
|
+
type: SchemaType.OBJECT,
|
|
57
|
+
properties: {
|
|
58
|
+
verdict: {
|
|
59
|
+
type: SchemaType.BOOLEAN,
|
|
60
|
+
description: "true if the condition is satisfied, false otherwise",
|
|
61
|
+
},
|
|
62
|
+
explanation: {
|
|
63
|
+
type: SchemaType.STRING,
|
|
64
|
+
description: "Brief explanation of the reasoning",
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
required: ["verdict", "explanation"],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
return new GoogleProvider(model);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
throw new Error("jest-fuzzy: To use gemini-3-flash-preview, install @google/generative-ai");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async judge(prompt) {
|
|
78
|
+
try {
|
|
79
|
+
const result = await this.model.generateContent(prompt);
|
|
80
|
+
const text = result.response.text();
|
|
81
|
+
const parsed = JSON.parse(text);
|
|
82
|
+
return { verdict: parsed.verdict, explanation: parsed.explanation };
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
throw new Error(`jest-fuzzy: LLM API call failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.GoogleProvider = GoogleProvider;
|
|
90
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../../src/providers/google.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,MAAa,cAAc;IACjB,KAAK,CAAM;IAEnB,YAAoB,KAAU;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM;QACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,0FAA0F,CAC3F,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,wDAAa,uBAAuB,GAAC,CAAC;YACrD,MAAM,EAAE,kBAAkB,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC;YAClD,MAAM,KAAK,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,kBAAkB,CAAC;gBACrC,KAAK,EAAE,kBAAkB;gBACzB,gBAAgB,EAAE;oBAChB,gBAAgB,EAAE,kBAAkB;oBACpC,cAAc,EAAE;wBACd,IAAI,EAAE,UAAU,CAAC,MAAM;wBACvB,UAAU,EAAE;4BACV,OAAO,EAAE;gCACP,IAAI,EAAE,UAAU,CAAC,OAAO;gCACxB,WAAW,EACT,qDAAqD;6BACxD;4BACD,WAAW,EAAE;gCACX,IAAI,EAAE,UAAU,CAAC,MAAM;gCACvB,WAAW,EAAE,oCAAoC;6BAClD;yBACF;wBACD,QAAQ,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;qBACrC;iBACF;aACF,CAAC,CAAC;YACH,OAAO,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YACxD,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA8C,CAAC;YAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,oCACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AA9DD,wCA8DC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ModelName, LLMProvider } from "../types.js";
|
|
2
|
+
import { AnthropicProvider } from "./anthropic.js";
|
|
3
|
+
import { GoogleProvider } from "./google.js";
|
|
4
|
+
import { OpenAIProvider } from "./openai.js";
|
|
5
|
+
export declare function createProvider(model: ModelName): Promise<LLMProvider>;
|
|
6
|
+
export { AnthropicProvider, GoogleProvider, OpenAIProvider };
|
|
7
|
+
export type { LLMProvider };
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAW3E;AAED,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenAIProvider = exports.GoogleProvider = exports.AnthropicProvider = void 0;
|
|
4
|
+
exports.createProvider = createProvider;
|
|
5
|
+
const anthropic_js_1 = require("./anthropic.js");
|
|
6
|
+
Object.defineProperty(exports, "AnthropicProvider", { enumerable: true, get: function () { return anthropic_js_1.AnthropicProvider; } });
|
|
7
|
+
const google_js_1 = require("./google.js");
|
|
8
|
+
Object.defineProperty(exports, "GoogleProvider", { enumerable: true, get: function () { return google_js_1.GoogleProvider; } });
|
|
9
|
+
const openai_js_1 = require("./openai.js");
|
|
10
|
+
Object.defineProperty(exports, "OpenAIProvider", { enumerable: true, get: function () { return openai_js_1.OpenAIProvider; } });
|
|
11
|
+
async function createProvider(model) {
|
|
12
|
+
switch (model) {
|
|
13
|
+
case "claude-haiku-4-5":
|
|
14
|
+
return anthropic_js_1.AnthropicProvider.create();
|
|
15
|
+
case "gemini-3-flash-preview":
|
|
16
|
+
return google_js_1.GoogleProvider.create();
|
|
17
|
+
case "gpt-5-nano":
|
|
18
|
+
return openai_js_1.OpenAIProvider.create();
|
|
19
|
+
default:
|
|
20
|
+
throw new Error(`jest-fuzzy: Unknown model: ${model}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/index.ts"],"names":[],"mappings":";;;AAKA,wCAWC;AAfD,iDAAmD;AAiB1C,kGAjBA,gCAAiB,OAiBA;AAhB1B,2CAA6C;AAgBjB,+FAhBnB,0BAAc,OAgBmB;AAf1C,2CAA6C;AAeD,+FAfnC,0BAAc,OAemC;AAbnD,KAAK,UAAU,cAAc,CAAC,KAAgB;IACnD,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,kBAAkB;YACrB,OAAO,gCAAiB,CAAC,MAAM,EAAE,CAAC;QACpC,KAAK,wBAAwB;YAC3B,OAAO,0BAAc,CAAC,MAAM,EAAE,CAAC;QACjC,KAAK,YAAY;YACf,OAAO,0BAAc,CAAC,MAAM,EAAE,CAAC;QACjC;YACE,MAAM,IAAI,KAAK,CAAC,8BAA8B,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LLMProvider, JudgmentResult } from "../types.js";
|
|
2
|
+
export declare class OpenAIProvider implements LLMProvider {
|
|
3
|
+
private client;
|
|
4
|
+
private constructor();
|
|
5
|
+
static create(): Promise<OpenAIProvider>;
|
|
6
|
+
judge(prompt: string): Promise<JudgmentResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +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;AAkB/D,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,MAAM,CAAM;IAEpB,OAAO;WAIM,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAkBxC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CA8BrD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
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.OpenAIProvider = void 0;
|
|
37
|
+
const JUDGMENT_SCHEMA = {
|
|
38
|
+
type: "object",
|
|
39
|
+
properties: {
|
|
40
|
+
verdict: {
|
|
41
|
+
type: "boolean",
|
|
42
|
+
description: "true if the condition is satisfied, false otherwise",
|
|
43
|
+
},
|
|
44
|
+
explanation: {
|
|
45
|
+
type: "string",
|
|
46
|
+
description: "Brief explanation of the reasoning",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ["verdict", "explanation"],
|
|
50
|
+
additionalProperties: false,
|
|
51
|
+
};
|
|
52
|
+
class OpenAIProvider {
|
|
53
|
+
client;
|
|
54
|
+
constructor(client) {
|
|
55
|
+
this.client = client;
|
|
56
|
+
}
|
|
57
|
+
static async create() {
|
|
58
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
59
|
+
if (!apiKey) {
|
|
60
|
+
throw new Error("jest-fuzzy: Missing OPENAI_API_KEY environment variable for gpt-5-nano model");
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
const module = await Promise.resolve().then(() => __importStar(require("openai")));
|
|
64
|
+
const OpenAI = module.default;
|
|
65
|
+
const client = new OpenAI({ apiKey });
|
|
66
|
+
return new OpenAIProvider(client);
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
throw new Error("jest-fuzzy: To use gpt-5-nano, install openai");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async judge(prompt) {
|
|
73
|
+
try {
|
|
74
|
+
const response = await this.client.chat.completions.create({
|
|
75
|
+
model: "gpt-4o-mini",
|
|
76
|
+
messages: [{ role: "user", content: prompt }],
|
|
77
|
+
max_tokens: 1024,
|
|
78
|
+
response_format: {
|
|
79
|
+
type: "json_schema",
|
|
80
|
+
json_schema: {
|
|
81
|
+
name: "judgment",
|
|
82
|
+
strict: true,
|
|
83
|
+
schema: JUDGMENT_SCHEMA,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const content = response.choices[0].message.content ?? "{}";
|
|
88
|
+
const parsed = JSON.parse(content);
|
|
89
|
+
return { verdict: parsed.verdict, explanation: parsed.explanation };
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
throw new Error(`jest-fuzzy: LLM API call failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.OpenAIProvider = OpenAIProvider;
|
|
97
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/providers/openai.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,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,MAAa,cAAc;IACjB,MAAM,CAAM;IAEpB,YAAoB,MAAW;QAC7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM;QACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,wDAAa,QAAQ,GAAC,CAAC;YACtC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;YAC9B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACtC,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;gBACzD,KAAK,EAAE,aAAa;gBACpB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;gBAC7C,UAAU,EAAE,IAAI;gBAChB,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,CAAC;YAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC;YAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAGhC,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,oCACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AAvDD,wCAuDC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type ModelName = "claude-haiku-4-5" | "gemini-3-flash-preview" | "gpt-5-nano";
|
|
2
|
+
export interface JestFuzzyConfig {
|
|
3
|
+
model?: ModelName;
|
|
4
|
+
}
|
|
5
|
+
export interface SemanticMatchOptions {
|
|
6
|
+
threshold?: "strict" | "loose";
|
|
7
|
+
context?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface JudgmentResult {
|
|
10
|
+
verdict: boolean;
|
|
11
|
+
explanation: string;
|
|
12
|
+
}
|
|
13
|
+
export interface LLMProvider {
|
|
14
|
+
judge(prompt: string): Promise<JudgmentResult>;
|
|
15
|
+
}
|
|
16
|
+
export interface MatcherResult {
|
|
17
|
+
pass: boolean;
|
|
18
|
+
message: () => string;
|
|
19
|
+
}
|
|
20
|
+
declare global {
|
|
21
|
+
namespace jest {
|
|
22
|
+
interface Matchers<R> {
|
|
23
|
+
toSemanticallyMatch(expected: string, options?: SemanticMatchOptions): Promise<R>;
|
|
24
|
+
toSatisfy(criteria: string): Promise<R>;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +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,eAAe;IAC9B,KAAK,CAAC,EAAE,SAAS,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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { JestFuzzyConfig, LLMProvider } from "./types.js";
|
|
2
|
+
export declare function configure(config?: JestFuzzyConfig): void;
|
|
3
|
+
export declare function getConfig(): Required<JestFuzzyConfig>;
|
|
4
|
+
export declare function getProvider(): Promise<LLMProvider>;
|
|
5
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAa,WAAW,EAAE,MAAM,YAAY,CAAC;AAY1E,wBAAgB,SAAS,CAAC,MAAM,GAAE,eAAoB,GAAG,IAAI,CAQ5D;AAED,wBAAgB,SAAS,IAAI,QAAQ,CAAC,eAAe,CAAC,CAIrD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,CAaxD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createProvider } from "./providers/index.js";
|
|
2
|
+
const DEFAULT_MODEL = "claude-haiku-4-5";
|
|
3
|
+
let currentConfig = {
|
|
4
|
+
model: DEFAULT_MODEL,
|
|
5
|
+
};
|
|
6
|
+
let providerInstance = null;
|
|
7
|
+
let providerPromise = null;
|
|
8
|
+
export function configure(config = {}) {
|
|
9
|
+
currentConfig = {
|
|
10
|
+
model: config.model ?? DEFAULT_MODEL,
|
|
11
|
+
};
|
|
12
|
+
// Reset provider so it will be re-created with new config
|
|
13
|
+
providerInstance = null;
|
|
14
|
+
providerPromise = null;
|
|
15
|
+
}
|
|
16
|
+
export function getConfig() {
|
|
17
|
+
return {
|
|
18
|
+
model: currentConfig.model ?? DEFAULT_MODEL,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export async function getProvider() {
|
|
22
|
+
if (providerInstance) {
|
|
23
|
+
return providerInstance;
|
|
24
|
+
}
|
|
25
|
+
if (!providerPromise) {
|
|
26
|
+
providerPromise = createProvider(getConfig().model).then((provider) => {
|
|
27
|
+
providerInstance = provider;
|
|
28
|
+
return provider;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return providerPromise;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,aAAa,GAAc,kBAAkB,CAAC;AAEpD,IAAI,aAAa,GAAoB;IACnC,KAAK,EAAE,aAAa;CACrB,CAAC;AAEF,IAAI,gBAAgB,GAAuB,IAAI,CAAC;AAChD,IAAI,eAAe,GAAgC,IAAI,CAAC;AAExD,MAAM,UAAU,SAAS,CAAC,SAA0B,EAAE;IACpD,aAAa,GAAG;QACd,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,aAAa;KACrC,CAAC;IAEF,0DAA0D;IAC1D,gBAAgB,GAAG,IAAI,CAAC;IACxB,eAAe,GAAG,IAAI,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO;QACL,KAAK,EAAE,aAAa,CAAC,KAAK,IAAI,aAAa;KAC5C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,cAAc,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;YACpE,gBAAgB,GAAG,QAAQ,CAAC;YAC5B,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,eAAe,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { configure, getConfig, getProvider } from "./config.js";
|
|
2
|
+
import type { JestFuzzyConfig, SemanticMatchOptions, ModelName, LLMProvider } from "./types.js";
|
|
3
|
+
export { configure, getConfig, getProvider };
|
|
4
|
+
export type { JestFuzzyConfig, SemanticMatchOptions, ModelName, LLMProvider, };
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,WAAW,EACZ,MAAM,YAAY,CAAC;AAUpB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;AAC7C,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,WAAW,GACZ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { configure, getConfig, getProvider } from "./config.js";
|
|
2
|
+
import { toSemanticallyMatch } from "./matchers/toSemanticallyMatch.js";
|
|
3
|
+
import { toSatisfy } from "./matchers/toSatisfy.js";
|
|
4
|
+
// Register matchers with Jest
|
|
5
|
+
if (typeof expect !== "undefined" && expect.extend) {
|
|
6
|
+
expect.extend({
|
|
7
|
+
toSemanticallyMatch,
|
|
8
|
+
toSatisfy,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export { configure, getConfig, getProvider };
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AAQpD,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"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSatisfy.d.ts","sourceRoot":"","sources":["../../../src/matchers/toSatisfy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD,wBAAsB,SAAS,CAC7B,IAAI,EAAE,IAAI,CAAC,cAAc,EACzB,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,aAAa,CAAC,CAgCxB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { getProvider } from "../config.js";
|
|
2
|
+
function buildPrompt(received, criteria) {
|
|
3
|
+
return `Does the following text satisfy the given criteria?
|
|
4
|
+
|
|
5
|
+
Text: "${received}"
|
|
6
|
+
Criteria: ${criteria}
|
|
7
|
+
|
|
8
|
+
Return verdict=true if the text satisfies the criteria, false otherwise.`;
|
|
9
|
+
}
|
|
10
|
+
export async function toSatisfy(received, criteria) {
|
|
11
|
+
if (typeof received !== "string") {
|
|
12
|
+
return {
|
|
13
|
+
pass: false,
|
|
14
|
+
message: () => `Expected a string but received ${typeof received}: ${JSON.stringify(received)}`,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const provider = await getProvider();
|
|
18
|
+
const prompt = buildPrompt(received, criteria);
|
|
19
|
+
try {
|
|
20
|
+
const { verdict, explanation } = await provider.judge(prompt);
|
|
21
|
+
return {
|
|
22
|
+
pass: verdict,
|
|
23
|
+
message: () => {
|
|
24
|
+
if (verdict) {
|
|
25
|
+
return `Expected "${received}" NOT to satisfy "${criteria}"\n\nLLM reasoning: ${explanation}`;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return `Expected "${received}" to satisfy "${criteria}"\n\nLLM reasoning: ${explanation}`;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return {
|
|
35
|
+
pass: false,
|
|
36
|
+
message: () => `Failed to evaluate criteria: ${error instanceof Error ? error.message : String(error)}`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=toSatisfy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSatisfy.js","sourceRoot":"","sources":["../../../src/matchers/toSatisfy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,SAAS,WAAW,CAAC,QAAgB,EAAE,QAAgB;IACrD,OAAO;;SAEA,QAAQ;YACL,QAAQ;;yEAEqD,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAE7B,QAAiB,EACjB,QAAgB;IAEhB,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,CAAC,CAAC;IAE/C,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,qBAAqB,QAAQ,uBAAuB,WAAW,EAAE,CAAC;gBAChG,CAAC;qBAAM,CAAC;oBACN,OAAO,aAAa,QAAQ,iBAAiB,QAAQ,uBAAuB,WAAW,EAAE,CAAC;gBAC5F,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,KAAK;YACX,OAAO,EAAE,GAAG,EAAE,CACZ,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SAC3F,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SemanticMatchOptions, MatcherResult } from "../types.js";
|
|
2
|
+
export declare function toSemanticallyMatch(this: jest.MatcherContext, received: unknown, expected: string, options?: SemanticMatchOptions): Promise<MatcherResult>;
|
|
3
|
+
//# sourceMappingURL=toSemanticallyMatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSemanticallyMatch.d.ts","sourceRoot":"","sources":["../../../src/matchers/toSemanticallyMatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAoBvE,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,CAAC,cAAc,EACzB,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,aAAa,CAAC,CAgCxB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { getProvider } from "../config.js";
|
|
2
|
+
function buildPrompt(received, expected, options) {
|
|
3
|
+
const contextLine = options.context ? `Context: ${options.context}\n` : "";
|
|
4
|
+
const threshold = options.threshold ?? "loose";
|
|
5
|
+
return `Do these two texts have the same semantic meaning?
|
|
6
|
+
${contextLine}Strictness: ${threshold}
|
|
7
|
+
|
|
8
|
+
Text A: "${received}"
|
|
9
|
+
Text B: "${expected}"
|
|
10
|
+
|
|
11
|
+
Return verdict=true if they have the same semantic meaning, false otherwise.`;
|
|
12
|
+
}
|
|
13
|
+
export async function toSemanticallyMatch(received, expected, options = {}) {
|
|
14
|
+
if (typeof received !== "string") {
|
|
15
|
+
return {
|
|
16
|
+
pass: false,
|
|
17
|
+
message: () => `Expected a string but received ${typeof received}: ${JSON.stringify(received)}`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const provider = await getProvider();
|
|
21
|
+
const prompt = buildPrompt(received, expected, options);
|
|
22
|
+
try {
|
|
23
|
+
const { verdict, explanation } = await provider.judge(prompt);
|
|
24
|
+
return {
|
|
25
|
+
pass: verdict,
|
|
26
|
+
message: () => {
|
|
27
|
+
if (verdict) {
|
|
28
|
+
return `Expected "${received}" NOT to semantically match "${expected}"\n\nLLM reasoning: ${explanation}`;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return `Expected "${received}" to semantically match "${expected}"\n\nLLM reasoning: ${explanation}`;
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return {
|
|
38
|
+
pass: false,
|
|
39
|
+
message: () => `Failed to evaluate semantic match: ${error instanceof Error ? error.message : String(error)}`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=toSemanticallyMatch.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LLMProvider, JudgmentResult } from "../types.js";
|
|
2
|
+
export declare class AnthropicProvider implements LLMProvider {
|
|
3
|
+
private client;
|
|
4
|
+
private constructor();
|
|
5
|
+
static create(): Promise<AnthropicProvider>;
|
|
6
|
+
judge(prompt: string): Promise<JudgmentResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -0,0 +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;AAqB/D,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAM;IAEpB,OAAO;WAIM,MAAM,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAoB3C,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAyBrD"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const JUDGMENT_SCHEMA = {
|
|
2
|
+
type: "json_schema",
|
|
3
|
+
schema: {
|
|
4
|
+
type: "object",
|
|
5
|
+
properties: {
|
|
6
|
+
verdict: {
|
|
7
|
+
type: "boolean",
|
|
8
|
+
description: "true if the condition is satisfied, false otherwise",
|
|
9
|
+
},
|
|
10
|
+
explanation: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Brief explanation of the reasoning",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
required: ["verdict", "explanation"],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
export class AnthropicProvider {
|
|
20
|
+
client;
|
|
21
|
+
constructor(client) {
|
|
22
|
+
this.client = client;
|
|
23
|
+
}
|
|
24
|
+
static async create() {
|
|
25
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
26
|
+
if (!apiKey) {
|
|
27
|
+
throw new Error("jest-fuzzy: Missing ANTHROPIC_API_KEY environment variable for claude-haiku-4-5 model");
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const module = await import("@anthropic-ai/sdk");
|
|
31
|
+
const Anthropic = module.default;
|
|
32
|
+
const client = new Anthropic({ apiKey });
|
|
33
|
+
return new AnthropicProvider(client);
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
throw new Error("jest-fuzzy: To use claude-haiku-4-5, install @anthropic-ai/sdk");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async judge(prompt) {
|
|
40
|
+
try {
|
|
41
|
+
const response = await this.client.beta.messages.create({
|
|
42
|
+
model: "claude-haiku-4-5",
|
|
43
|
+
max_tokens: 1024,
|
|
44
|
+
betas: ["structured-outputs-2025-11-13"],
|
|
45
|
+
messages: [{ role: "user", content: prompt }],
|
|
46
|
+
output_format: JUDGMENT_SCHEMA,
|
|
47
|
+
});
|
|
48
|
+
const text = response.content[0].text;
|
|
49
|
+
const parsed = JSON.parse(text);
|
|
50
|
+
return { verdict: parsed.verdict, explanation: parsed.explanation };
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw new Error(`jest-fuzzy: LLM API call failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/providers/anthropic.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG;IACtB,IAAI,EAAE,aAAsB;IAC5B,MAAM,EAAE;QACN,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,SAAkB;gBACxB,WAAW,EAAE,qDAAqD;aACnE;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAiB;gBACvB,WAAW,EAAE,oCAAoC;aAClD;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC;QACpC,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAM;IAEpB,YAAoB,MAAW;QAC7B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM;QACjB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YACjD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YACzC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,MAAc;QACxB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBACtD,KAAK,EAAE,kBAAkB;gBACzB,UAAU,EAAE,IAAI;gBAChB,KAAK,EAAE,CAAC,+BAA+B,CAAC;gBACxC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;gBAC7C,aAAa,EAAE,eAAe;aAC/B,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAG7B,CAAC;YAEF,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,oCACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LLMProvider, JudgmentResult } from "../types.js";
|
|
2
|
+
export declare class GoogleProvider implements LLMProvider {
|
|
3
|
+
private model;
|
|
4
|
+
private constructor();
|
|
5
|
+
static create(): Promise<GoogleProvider>;
|
|
6
|
+
judge(prompt: string): Promise<JudgmentResult>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=google.d.ts.map
|
|
@@ -0,0 +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;AAE/D,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,KAAK,CAAM;IAEnB,OAAO;WAIM,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC;IAyCxC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAcrD"}
|