vibe-match 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/README.md +296 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17782 -0
- package/dist/matchers/toBeSimilarTo.d.ts +25 -0
- package/dist/matchers/toBeSimilarTo.d.ts.map +1 -0
- package/dist/matchers/toBeVectorSimilarTo.d.ts +21 -0
- package/dist/matchers/toBeVectorSimilarTo.d.ts.map +1 -0
- package/dist/matchers/toMention.d.ts +24 -0
- package/dist/matchers/toMention.d.ts.map +1 -0
- package/dist/matchers/toSatisfyCriteria.d.ts +40 -0
- package/dist/matchers/toSatisfyCriteria.d.ts.map +1 -0
- package/dist/matchers.d.ts +20 -0
- package/dist/matchers.d.ts.map +1 -0
- package/dist/providers.d.ts +38 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/types.d.ts +210 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type LanguageModelV1 } from "ai";
|
|
2
|
+
import type { VibeMatcher } from "../types";
|
|
3
|
+
/** Re-export for inline model overrides */
|
|
4
|
+
export type { LanguageModelV1 };
|
|
5
|
+
export declare const DEFAULT_SIMILARITY_PROMPT = "You have a singular task. You will be given two strings of text and you need to make a determination if they are meaningfully semantically similar. There are 3 levels of similarity: loose, normal, and strict.\n\n## Loose Matches:\nThe strings mean roughly the same thing. As long as the main idea gets across, it's a loose match.\n\nExample of a loose match that should pass:\nActual: \"I enjoy eating pizza with cheese\"\nPassing:\n- \"Cheese pizza is my preference personally\"\n- \"I like pizza with cheese\"\n- \"I love cheese pizza!\"\n- \"Pizza with cheese is my favorite\"\n\nNot Passing:\n- \"Pizza with tomatoes are my favorite\" // Doesn't match the original meaning\n- \"I HATE cheese pizza\" // Not the same meaning\n- \"Cheese pizza\" // Not enough information\n\n## Normal Matches:\nThe strings are more meaningfully similar than loose however there may be some small ambiguities.\n\nExample of a normal match that should pass:\nActual: \"There are 1000 people in the room\"\nPassing:\n- \"There are one thousand folks in the room\"\n- \"There's 1000 people here\"\n\nNot Passing:\n- \"There are 500 people in the room\" // Wrong number\n- \"There's not 1000 people in the room\" // Inverted logic\n- \"Why are there 1000 people in the room?\" // Doesn't match the original meaning\n\n## Strict Matches:\nThe strings are functionally identical. They do not need to be word for word the same but the meaning should be unambiguously the same and in the same order.\n\nExample of a strict match that should pass:\nActual: \"Hi, how are you?\"\n\nPassing:\n- \"Hello, how are you?\"\n- \"Hi, how are you?\"\n- \"Hi, how are you doing?\"\n\nNot Passing:\n- \"Hello sir, what's up?\" // Doesn't match the tone\n- \"Hi\" // Too short\n- \"How are you hello?\" // Wrong order\n\nThe user will provide the two strings and the level of similarity they want to test. You will use that level of similarity to determine if the two strings pass or fail.";
|
|
6
|
+
export interface ToBeSimilarToOptions {
|
|
7
|
+
level?: "loose" | "normal" | "strict";
|
|
8
|
+
threshold?: number;
|
|
9
|
+
samples?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Custom system prompt for the LLM. Overrides both the default prompt
|
|
12
|
+
* and any global prompt set in vibeMatchers config.
|
|
13
|
+
*/
|
|
14
|
+
systemPrompt?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Override the language model for this specific matcher call.
|
|
17
|
+
* If not provided, uses the model from vibeMatchers config.
|
|
18
|
+
*/
|
|
19
|
+
languageModel?: LanguageModelV1;
|
|
20
|
+
}
|
|
21
|
+
export declare const toBeSimilarTo: VibeMatcher<[
|
|
22
|
+
similarTo: unknown,
|
|
23
|
+
options?: ToBeSimilarToOptions
|
|
24
|
+
]>;
|
|
25
|
+
//# sourceMappingURL=toBeSimilarTo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toBeSimilarTo.d.ts","sourceRoot":"","sources":["../../src/matchers/toBeSimilarTo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,IAAI,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,2CAA2C;AAC3C,YAAY,EAAE,eAAe,EAAE,CAAC;AAOhC,eAAO,MAAM,yBAAyB,s6DAgDmI,CAAC;AA0B1K,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,aAAa,CAAC,EAAE,eAAe,CAAC;CACjC;AAED,eAAO,MAAM,aAAa,EAAE,WAAW,CACrC;IAAC,SAAS,EAAE,OAAO;IAAE,OAAO,CAAC,EAAE,oBAAoB;CAAC,CA6CnD,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type EmbeddingModel } from "ai";
|
|
2
|
+
import type { VibeMatcher } from "../types";
|
|
3
|
+
/** Re-export for inline model overrides */
|
|
4
|
+
export type { EmbeddingModel };
|
|
5
|
+
export interface VectorSimilarityOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The minimum cosine similarity score required to pass (0-1).
|
|
8
|
+
* @default 0.85
|
|
9
|
+
*/
|
|
10
|
+
threshold?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Override the embedding model for this specific matcher call.
|
|
13
|
+
* If not provided, uses the model from vibeMatchers config.
|
|
14
|
+
*/
|
|
15
|
+
embeddingModel?: EmbeddingModel<string>;
|
|
16
|
+
}
|
|
17
|
+
export declare const toBeVectorSimilarTo: VibeMatcher<[
|
|
18
|
+
expected: unknown,
|
|
19
|
+
options?: VectorSimilarityOptions
|
|
20
|
+
]>;
|
|
21
|
+
//# sourceMappingURL=toBeVectorSimilarTo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toBeVectorSimilarTo.d.ts","sourceRoot":"","sources":["../../src/matchers/toBeVectorSimilarTo.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,IAAI,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,2CAA2C;AAC3C,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;CACzC;AAED,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAC3C;IAAC,QAAQ,EAAE,OAAO;IAAE,OAAO,CAAC,EAAE,uBAAuB;CAAC,CAiCrD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type LanguageModelV1 } from "ai";
|
|
2
|
+
import type { VibeMatcher } from "../types";
|
|
3
|
+
/** Re-export for inline model overrides */
|
|
4
|
+
export type { LanguageModelV1 };
|
|
5
|
+
export declare const DEFAULT_MENTION_PROMPT = "You have a singular task. You will be given a text and a concept, and you need to determine if the text mentions the concept.\n\nA text \"mentions\" a concept if it:\n- Directly references the concept by name\n- Describes the concept without necessarily naming it\n- Alludes to or implies the concept\n- Contains synonyms or related terms for the concept\n\nExamples that would PASS:\nText: \"I love programming in JavaScript\"\nConcept: \"JavaScript\" \u2192 PASS (direct mention)\n\nText: \"The cat sat on the mat\"\nConcept: \"animals\" \u2192 PASS (cat is an animal)\n\nText: \"We need to optimize our database queries\"\nConcept: \"performance\" \u2192 PASS (optimization implies performance)\n\nText: \"She was feeling blue today\"\nConcept: \"sadness\" \u2192 PASS (feeling blue implies sadness)\n\nExamples that would FAIL:\nText: \"I love programming in JavaScript\"\nConcept: \"Python\" \u2192 FAIL (different programming language, not mentioned)\n\nText: \"The weather is nice today\"\nConcept: \"sports\" \u2192 FAIL (no connection to sports)\n\nBe generous but accurate in your interpretation. The goal is to catch meaningful mentions for reliability testing purposes.";
|
|
6
|
+
export interface ToMentionOptions {
|
|
7
|
+
threshold?: number;
|
|
8
|
+
samples?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Custom system prompt for the LLM. Overrides both the default prompt
|
|
11
|
+
* and any global prompt set in vibeMatchers config.
|
|
12
|
+
*/
|
|
13
|
+
systemPrompt?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Override the language model for this specific matcher call.
|
|
16
|
+
* If not provided, uses the model from vibeMatchers config.
|
|
17
|
+
*/
|
|
18
|
+
languageModel?: LanguageModelV1;
|
|
19
|
+
}
|
|
20
|
+
export declare const toMention: VibeMatcher<[
|
|
21
|
+
concept: unknown,
|
|
22
|
+
options?: ToMentionOptions
|
|
23
|
+
]>;
|
|
24
|
+
//# sourceMappingURL=toMention.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toMention.d.ts","sourceRoot":"","sources":["../../src/matchers/toMention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,IAAI,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,2CAA2C;AAC3C,YAAY,EAAE,eAAe,EAAE,CAAC;AAOhC,eAAO,MAAM,sBAAsB,kqCA4ByF,CAAC;AAwB7H,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,aAAa,CAAC,EAAE,eAAe,CAAC;CACjC;AAED,eAAO,MAAM,SAAS,EAAE,WAAW,CACjC;IAAC,OAAO,EAAE,OAAO;IAAE,OAAO,CAAC,EAAE,gBAAgB;CAAC,CAyC7C,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type LanguageModelV1 } from "ai";
|
|
2
|
+
import type { VibeMatcher } from "../types";
|
|
3
|
+
/** Re-export for inline model overrides */
|
|
4
|
+
export type { LanguageModelV1 };
|
|
5
|
+
export declare const DEFAULT_SATISFY_CRITERIA_PROMPT = "You have a singular task. You will be given a text and a criterion, and you must determine if the text satisfies the criterion.\n\nYour job is to make a binary YES/NO decision:\n- YES (pass: true): The text clearly meets the criterion\n- NO (pass: false): The text does not meet the criterion or it's ambiguous\n\nBe strict but fair. The criterion must be clearly satisfied, not just partially or arguably met.\n\nExamples:\n\nText: \"Hi John, I understand you're having trouble with your login. Here's how to reset your password: go to Settings > Security > Reset Password.\"\nCriterion: \"Addresses the user by name\"\n\u2192 PASS (the text says \"Hi John\")\n\nText: \"Hi John, I understand you're having trouble with your login. Here's how to reset your password: go to Settings > Security > Reset Password.\"\nCriterion: \"Provides a specific solution\"\n\u2192 PASS (gives clear steps to reset password)\n\nText: \"I'm sorry you're having issues. Let me know if you need help.\"\nCriterion: \"Provides a specific solution\"\n\u2192 FAIL (no specific solution is offered, just a vague offer to help)\n\nText: \"Thanks for reaching out! We'll look into this.\"\nCriterion: \"Acknowledges the specific issue reported\"\n\u2192 FAIL (generic acknowledgment, doesn't reference the specific issue)\n\nProvide a brief explanation for your decision.";
|
|
6
|
+
export interface ToSatisfyCriteriaOptions {
|
|
7
|
+
/**
|
|
8
|
+
* How to aggregate results across criteria (only applies when multiple criteria are provided).
|
|
9
|
+
* - "all": Every criterion must pass (default)
|
|
10
|
+
* - "any": At least one criterion must pass
|
|
11
|
+
* - "threshold": A percentage of criteria must pass
|
|
12
|
+
*/
|
|
13
|
+
mode?: "all" | "any" | "threshold";
|
|
14
|
+
/**
|
|
15
|
+
* For "threshold" mode: the minimum percentage of criteria that must pass (0-1).
|
|
16
|
+
* @default 0.75
|
|
17
|
+
*/
|
|
18
|
+
threshold?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Number of times to evaluate each criterion for reliability.
|
|
21
|
+
* The criterion passes if the majority of samples pass.
|
|
22
|
+
* @default 3
|
|
23
|
+
*/
|
|
24
|
+
samples?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Custom system prompt for the LLM. Overrides both the default prompt
|
|
27
|
+
* and any global prompt set in vibeMatchers config.
|
|
28
|
+
*/
|
|
29
|
+
systemPrompt?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Override the language model for this specific matcher call.
|
|
32
|
+
* If not provided, uses the model from vibeMatchers config.
|
|
33
|
+
*/
|
|
34
|
+
languageModel?: LanguageModelV1;
|
|
35
|
+
}
|
|
36
|
+
export declare const toSatisfyCriteria: VibeMatcher<[
|
|
37
|
+
criteria: unknown,
|
|
38
|
+
options?: ToSatisfyCriteriaOptions
|
|
39
|
+
]>;
|
|
40
|
+
//# sourceMappingURL=toSatisfyCriteria.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toSatisfyCriteria.d.ts","sourceRoot":"","sources":["../../src/matchers/toSatisfyCriteria.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,IAAI,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,2CAA2C;AAC3C,YAAY,EAAE,eAAe,EAAE,CAAC;AAOhC,eAAO,MAAM,+BAA+B,w0CA0BG,CAAC;AAgChD,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,WAAW,CAAC;IAEnC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,eAAe,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,EAAE,WAAW,CACzC;IAAC,QAAQ,EAAE,OAAO;IAAE,OAAO,CAAC,EAAE,wBAAwB;CAAC,CAiHtD,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MatcherFunction } from "expect";
|
|
2
|
+
import type { VibeMatchConfig } from "./types";
|
|
3
|
+
export declare const vibeMatchers: (config: VibeMatchConfig) => {
|
|
4
|
+
toBeSimilarTo: MatcherFunction<[similarTo: unknown, options?: import(".").ToBeSimilarToOptions | undefined]>;
|
|
5
|
+
toBeVectorSimilarTo: MatcherFunction<[expected: unknown, options?: import(".").VectorSimilarityOptions | undefined]>;
|
|
6
|
+
toMention: MatcherFunction<[concept: unknown, options?: import(".").ToMentionOptions | undefined]>;
|
|
7
|
+
toSatisfyCriteria: MatcherFunction<[criteria: unknown, options?: import(".").ToSatisfyCriteriaOptions | undefined]>;
|
|
8
|
+
};
|
|
9
|
+
type VibeMatchersReturnType = ReturnType<typeof vibeMatchers>;
|
|
10
|
+
type VibeMatchersToJest<T, R> = {
|
|
11
|
+
[K in keyof T]: T[K] extends MatcherFunction<infer Args> ? (...args: Args) => R : never;
|
|
12
|
+
};
|
|
13
|
+
declare global {
|
|
14
|
+
namespace jest {
|
|
15
|
+
interface Matchers<R> extends VibeMatchersToJest<VibeMatchersReturnType, R> {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=matchers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../src/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,SAAS,CAAC;AA6CjB,eAAO,MAAM,YAAY,GAAI,QAAQ,eAAe;;;;;CASnD,CAAC;AAGF,KAAK,sBAAsB,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AAG9D,KAAK,kBAAkB,CAAC,CAAC,EAAE,CAAC,IAAI;KAC7B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,eAAe,CAAC,MAAM,IAAI,CAAC,GACpD,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,CAAC,GACpB,KAAK;CACV,CAAC;AAGF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,IAAI,CAAC;QACb,UAAU,QAAQ,CAAC,CAAC,CAClB,SAAQ,kBAAkB,CAAC,sBAAsB,EAAE,CAAC,CAAC;SAAG;KAC3D;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { LanguageModelV1, EmbeddingModel } from "ai";
|
|
2
|
+
import type { VibeMatchApiKeys } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Providers supported by vibe-match for language models.
|
|
5
|
+
*/
|
|
6
|
+
type LanguageProvider = "openai" | "anthropic" | "google" | "mistral" | "xai";
|
|
7
|
+
/**
|
|
8
|
+
* Providers that support embedding models.
|
|
9
|
+
* Note: Anthropic and xAI do not provide embedding models.
|
|
10
|
+
*/
|
|
11
|
+
type EmbeddingProvider = "openai" | "google" | "mistral";
|
|
12
|
+
/**
|
|
13
|
+
* Language model string in the format "provider:model-name".
|
|
14
|
+
*
|
|
15
|
+
* The model name is validated at runtime by the AI SDK provider.
|
|
16
|
+
*
|
|
17
|
+
* @example "openai:gpt-4o-mini"
|
|
18
|
+
* @example "anthropic:claude-sonnet-4-20250514"
|
|
19
|
+
* @example "google:gemini-2.0-flash"
|
|
20
|
+
* @example "mistral:mistral-small-latest"
|
|
21
|
+
* @example "xai:grok-2-1212"
|
|
22
|
+
*/
|
|
23
|
+
export type LanguageModelString = `${LanguageProvider}:${string}`;
|
|
24
|
+
/**
|
|
25
|
+
* Embedding model string in the format "provider:model-name".
|
|
26
|
+
*
|
|
27
|
+
* The model name is validated at runtime by the AI SDK provider.
|
|
28
|
+
* Only openai, google, and mistral support embedding models.
|
|
29
|
+
*
|
|
30
|
+
* @example "openai:text-embedding-3-small"
|
|
31
|
+
* @example "google:text-embedding-004"
|
|
32
|
+
* @example "mistral:mistral-embed"
|
|
33
|
+
*/
|
|
34
|
+
export type EmbeddingModelString = `${EmbeddingProvider}:${string}`;
|
|
35
|
+
export declare function resolveLanguageModel(modelString: LanguageModelString, apiKeys: VibeMatchApiKeys): LanguageModelV1;
|
|
36
|
+
export declare function resolveEmbeddingModel(modelString: EmbeddingModelString, apiKeys: VibeMatchApiKeys): EmbeddingModel<string>;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,IAAI,CAAC;AAM1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;GAEG;AACH,KAAK,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC;AAE9E;;;GAGG;AACH,KAAK,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG,GAAG,gBAAgB,IAAI,MAAM,EAAE,CAAC;AAElE;;;;;;;;;GASG;AACH,MAAM,MAAM,oBAAoB,GAAG,GAAG,iBAAiB,IAAI,MAAM,EAAE,CAAC;AAkCpE,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,mBAAmB,EAChC,OAAO,EAAE,gBAAgB,GACxB,eAAe,CAkDjB;AAED,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,oBAAoB,EACjC,OAAO,EAAE,gBAAgB,GACxB,cAAc,CAAC,MAAM,CAAC,CAmCxB"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import type { MatcherFunction } from "expect";
|
|
2
|
+
import type { LanguageModelV1, EmbeddingModel } from "ai";
|
|
3
|
+
import type { LanguageModelString, EmbeddingModelString } from "./providers";
|
|
4
|
+
/**
|
|
5
|
+
* Prompt configuration for customizing LLM behavior.
|
|
6
|
+
* Each matcher can have its default prompt overridden globally here,
|
|
7
|
+
* and can be further overridden per-call via matcher options.
|
|
8
|
+
*/
|
|
9
|
+
export interface VibeMatchPrompts {
|
|
10
|
+
/**
|
|
11
|
+
* System prompt for the toBeSimilarTo matcher.
|
|
12
|
+
* Receives: actual, similarTo, level
|
|
13
|
+
*/
|
|
14
|
+
toBeSimilarTo?: string;
|
|
15
|
+
/**
|
|
16
|
+
* System prompt for the toMention matcher.
|
|
17
|
+
* Receives: actual, concept
|
|
18
|
+
*/
|
|
19
|
+
toMention?: string;
|
|
20
|
+
/**
|
|
21
|
+
* System prompt for the toSatisfyCriteria matcher.
|
|
22
|
+
* Receives: text, criterion
|
|
23
|
+
*/
|
|
24
|
+
toSatisfyCriteria?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* API keys for each provider.
|
|
28
|
+
* Only provide keys for the providers you intend to use.
|
|
29
|
+
*/
|
|
30
|
+
export interface VibeMatchApiKeys {
|
|
31
|
+
/**
|
|
32
|
+
* OpenAI API key.
|
|
33
|
+
* Required if using openai models.
|
|
34
|
+
*/
|
|
35
|
+
openai?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Anthropic API key.
|
|
38
|
+
* Required if using anthropic models.
|
|
39
|
+
*/
|
|
40
|
+
anthropic?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Google Generative AI API key.
|
|
43
|
+
* Required if using google models.
|
|
44
|
+
*/
|
|
45
|
+
google?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Mistral API key.
|
|
48
|
+
* Required if using mistral models.
|
|
49
|
+
*/
|
|
50
|
+
mistral?: string;
|
|
51
|
+
/**
|
|
52
|
+
* xAI API key.
|
|
53
|
+
* Required if using xai models.
|
|
54
|
+
*/
|
|
55
|
+
xai?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Configuration for vibe-match
|
|
59
|
+
*
|
|
60
|
+
* Models are specified as strings in the format "provider:model-name".
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const config: VibeMatchConfig = {
|
|
65
|
+
* apiKeys: {
|
|
66
|
+
* openai: process.env.OPENAI_API_KEY,
|
|
67
|
+
* },
|
|
68
|
+
* languageModel: "openai:gpt-4o-mini",
|
|
69
|
+
* embeddingModel: "openai:text-embedding-3-small",
|
|
70
|
+
* };
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export interface VibeMatchStringConfig {
|
|
74
|
+
/**
|
|
75
|
+
* API keys for each provider.
|
|
76
|
+
* Only provide keys for the providers you intend to use.
|
|
77
|
+
*/
|
|
78
|
+
apiKeys: VibeMatchApiKeys;
|
|
79
|
+
/**
|
|
80
|
+
* The language model to use for semantic matching.
|
|
81
|
+
*
|
|
82
|
+
* Format: "provider:model-name"
|
|
83
|
+
*
|
|
84
|
+
* Supported providers: openai, anthropic, google, mistral, xai
|
|
85
|
+
*
|
|
86
|
+
* @example "openai:gpt-4o-mini"
|
|
87
|
+
* @example "anthropic:claude-sonnet-4-20250514"
|
|
88
|
+
* @example "google:gemini-2.0-flash"
|
|
89
|
+
*/
|
|
90
|
+
languageModel: LanguageModelString;
|
|
91
|
+
/**
|
|
92
|
+
* The embedding model to use for vector similarity.
|
|
93
|
+
*
|
|
94
|
+
* Format: "provider:model-name"
|
|
95
|
+
*
|
|
96
|
+
* Supported providers: openai, google, mistral
|
|
97
|
+
* (anthropic and xai do not provide embedding models)
|
|
98
|
+
*
|
|
99
|
+
* @example "openai:text-embedding-3-small"
|
|
100
|
+
* @example "google:text-embedding-004"
|
|
101
|
+
*/
|
|
102
|
+
embeddingModel: EmbeddingModelString;
|
|
103
|
+
/**
|
|
104
|
+
* Optional prompt overrides for each matcher.
|
|
105
|
+
* These serve as defaults that can be further overridden per-call.
|
|
106
|
+
*/
|
|
107
|
+
prompts?: VibeMatchPrompts;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Configuration for vibe-match using custom AI SDK model instances.
|
|
111
|
+
*
|
|
112
|
+
* Use this when you need to use a custom provider, OpenAI-compatible API,
|
|
113
|
+
* or configure models with custom options.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import { createOpenAI } from "@ai-sdk/openai";
|
|
118
|
+
*
|
|
119
|
+
* // Use OpenRouter with custom models
|
|
120
|
+
* const openrouter = createOpenAI({
|
|
121
|
+
* baseURL: "https://openrouter.ai/api/v1",
|
|
122
|
+
* apiKey: process.env.OPENROUTER_API_KEY,
|
|
123
|
+
* });
|
|
124
|
+
*
|
|
125
|
+
* const config: VibeMatchConfig = {
|
|
126
|
+
* languageModel: openrouter("anthropic/claude-sonnet-4"),
|
|
127
|
+
* embeddingModel: openrouter.embedding("openai/text-embedding-3-small"),
|
|
128
|
+
* };
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
export interface VibeMatchCustomModelConfig {
|
|
132
|
+
/**
|
|
133
|
+
* A custom language model instance from the AI SDK.
|
|
134
|
+
*
|
|
135
|
+
* Create using any AI SDK provider (built-in or custom).
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* import { createOpenAI } from "@ai-sdk/openai";
|
|
140
|
+
* const openai = createOpenAI({ apiKey: "..." });
|
|
141
|
+
* const languageModel = openai("gpt-4o-mini");
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
languageModel: LanguageModelV1;
|
|
145
|
+
/**
|
|
146
|
+
* A custom embedding model instance from the AI SDK.
|
|
147
|
+
*
|
|
148
|
+
* Create using any AI SDK provider that supports embeddings.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* import { createOpenAI } from "@ai-sdk/openai";
|
|
153
|
+
* const openai = createOpenAI({ apiKey: "..." });
|
|
154
|
+
* const embeddingModel = openai.embedding("text-embedding-3-small");
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
embeddingModel: EmbeddingModel<string>;
|
|
158
|
+
/**
|
|
159
|
+
* Optional prompt overrides for each matcher.
|
|
160
|
+
* These serve as defaults that can be further overridden per-call.
|
|
161
|
+
*/
|
|
162
|
+
prompts?: VibeMatchPrompts;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Configuration for vibe-match.
|
|
166
|
+
*
|
|
167
|
+
* Supports two configuration styles:
|
|
168
|
+
*
|
|
169
|
+
* 1. **String-based** (built-in providers): Use model strings like "openai:gpt-4o-mini"
|
|
170
|
+
* with API keys for automatic model resolution.
|
|
171
|
+
*
|
|
172
|
+
* 2. **Custom models**: Pass AI SDK model instances directly for custom providers,
|
|
173
|
+
* OpenAI-compatible APIs (OpenRouter, Together AI, etc.), or advanced configuration.
|
|
174
|
+
*
|
|
175
|
+
* @example String-based configuration
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const config: VibeMatchConfig = {
|
|
178
|
+
* apiKeys: { openai: process.env.OPENAI_API_KEY },
|
|
179
|
+
* languageModel: "openai:gpt-4o-mini",
|
|
180
|
+
* embeddingModel: "openai:text-embedding-3-small",
|
|
181
|
+
* };
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @example Custom model configuration
|
|
185
|
+
* ```typescript
|
|
186
|
+
* import { createOpenAI } from "@ai-sdk/openai";
|
|
187
|
+
*
|
|
188
|
+
* const openrouter = createOpenAI({
|
|
189
|
+
* baseURL: "https://openrouter.ai/api/v1",
|
|
190
|
+
* apiKey: process.env.OPENROUTER_API_KEY,
|
|
191
|
+
* });
|
|
192
|
+
*
|
|
193
|
+
* const config: VibeMatchConfig = {
|
|
194
|
+
* languageModel: openrouter("anthropic/claude-sonnet-4"),
|
|
195
|
+
* embeddingModel: openrouter.embedding("openai/text-embedding-3-small"),
|
|
196
|
+
* };
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export type VibeMatchConfig = VibeMatchStringConfig | VibeMatchCustomModelConfig;
|
|
200
|
+
/**
|
|
201
|
+
* Internal resolved configuration with actual model instances.
|
|
202
|
+
* Used by matchers after string configs are resolved.
|
|
203
|
+
*/
|
|
204
|
+
export interface ResolvedVibeMatchConfig {
|
|
205
|
+
languageModel: LanguageModelV1;
|
|
206
|
+
embeddingModel: EmbeddingModel<string>;
|
|
207
|
+
prompts?: VibeMatchPrompts;
|
|
208
|
+
}
|
|
209
|
+
export type VibeMatcher<T extends any[]> = (config: ResolvedVibeMatchConfig) => MatcherFunction<T>;
|
|
210
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE7E;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,OAAO,EAAE,gBAAgB,CAAC;IAC1B;;;;;;;;;;OAUG;IACH,aAAa,EAAE,mBAAmB,CAAC;IAEnC;;;;;;;;;;OAUG;IACH,cAAc,EAAE,oBAAoB,CAAC;IAErC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;;;;OAWG;IACH,aAAa,EAAE,eAAe,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvC;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,MAAM,eAAe,GACvB,qBAAqB,GACrB,0BAA0B,CAAC;AAE/B;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,eAAe,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,GAAG,EAAE,IAAI,CACzC,MAAM,EAAE,uBAAuB,KAC5B,eAAe,CAAC,CAAC,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vibe-match",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI-powered semantic matchers for testing with vitest and jest",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "bun build ./src/index.ts --outdir ./dist --target node && bun run build:types",
|
|
21
|
+
"build:types": "tsc --declaration --emitDeclarationOnly --outDir ./dist",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"prepublishOnly": "bun run build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"testing",
|
|
29
|
+
"vitest",
|
|
30
|
+
"jest",
|
|
31
|
+
"ai",
|
|
32
|
+
"semantic",
|
|
33
|
+
"llm",
|
|
34
|
+
"matcher",
|
|
35
|
+
"assertions"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "git+https://github.com/your-username/vibe-match.git"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"author": "",
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/bun": "latest",
|
|
45
|
+
"@types/jest": "latest",
|
|
46
|
+
"prettier": "^3.6.2",
|
|
47
|
+
"vitest": "^4.0.16"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"typescript": "^5"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@ai-sdk/anthropic": "^1.2.0",
|
|
54
|
+
"@ai-sdk/google": "^1.2.0",
|
|
55
|
+
"@ai-sdk/mistral": "^1.2.0",
|
|
56
|
+
"@ai-sdk/openai": "^1.3.0",
|
|
57
|
+
"@ai-sdk/xai": "^1.2.0",
|
|
58
|
+
"ai": "^4.3.0",
|
|
59
|
+
"zod": "^3.23.8"
|
|
60
|
+
}
|
|
61
|
+
}
|