ai-output-assert 0.3.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 +183 -0
- package/dist/__tests__/matchers/content.test.d.ts +2 -0
- package/dist/__tests__/matchers/content.test.d.ts.map +1 -0
- package/dist/__tests__/matchers/content.test.js +66 -0
- package/dist/__tests__/matchers/content.test.js.map +1 -0
- package/dist/__tests__/matchers/format.test.d.ts +2 -0
- package/dist/__tests__/matchers/format.test.d.ts.map +1 -0
- package/dist/__tests__/matchers/format.test.js +100 -0
- package/dist/__tests__/matchers/format.test.js.map +1 -0
- package/dist/__tests__/matchers/quality.test.d.ts +2 -0
- package/dist/__tests__/matchers/quality.test.d.ts.map +1 -0
- package/dist/__tests__/matchers/quality.test.js +98 -0
- package/dist/__tests__/matchers/quality.test.js.map +1 -0
- package/dist/__tests__/matchers/safety.test.d.ts +2 -0
- package/dist/__tests__/matchers/safety.test.d.ts.map +1 -0
- package/dist/__tests__/matchers/safety.test.js +120 -0
- package/dist/__tests__/matchers/safety.test.js.map +1 -0
- package/dist/__tests__/setup.test.d.ts +2 -0
- package/dist/__tests__/setup.test.d.ts.map +1 -0
- package/dist/__tests__/setup.test.js +49 -0
- package/dist/__tests__/setup.test.js.map +1 -0
- package/dist/__tests__/types.test.d.ts +2 -0
- package/dist/__tests__/types.test.d.ts.map +1 -0
- package/dist/__tests__/types.test.js +50 -0
- package/dist/__tests__/types.test.js.map +1 -0
- package/dist/__tests__/utils/cosine-similarity.test.d.ts +2 -0
- package/dist/__tests__/utils/cosine-similarity.test.d.ts.map +1 -0
- package/dist/__tests__/utils/cosine-similarity.test.js +30 -0
- package/dist/__tests__/utils/cosine-similarity.test.js.map +1 -0
- package/dist/__tests__/utils/embedding-cache.test.d.ts +2 -0
- package/dist/__tests__/utils/embedding-cache.test.d.ts.map +1 -0
- package/dist/__tests__/utils/embedding-cache.test.js +41 -0
- package/dist/__tests__/utils/embedding-cache.test.js.map +1 -0
- package/dist/__tests__/utils/json-extract.test.d.ts +2 -0
- package/dist/__tests__/utils/json-extract.test.d.ts.map +1 -0
- package/dist/__tests__/utils/json-extract.test.js +32 -0
- package/dist/__tests__/utils/json-extract.test.js.map +1 -0
- package/dist/__tests__/utils/luhn.test.d.ts +2 -0
- package/dist/__tests__/utils/luhn.test.d.ts.map +1 -0
- package/dist/__tests__/utils/luhn.test.js +25 -0
- package/dist/__tests__/utils/luhn.test.js.map +1 -0
- package/dist/__tests__/utils/ngrams.test.d.ts +2 -0
- package/dist/__tests__/utils/ngrams.test.d.ts.map +1 -0
- package/dist/__tests__/utils/ngrams.test.js +28 -0
- package/dist/__tests__/utils/ngrams.test.js.map +1 -0
- package/dist/__tests__/utils/regex-escape.test.d.ts +2 -0
- package/dist/__tests__/utils/regex-escape.test.d.ts.map +1 -0
- package/dist/__tests__/utils/regex-escape.test.js +48 -0
- package/dist/__tests__/utils/regex-escape.test.js.map +1 -0
- package/dist/__tests__/utils/sentences.test.d.ts +2 -0
- package/dist/__tests__/utils/sentences.test.d.ts.map +1 -0
- package/dist/__tests__/utils/sentences.test.js +39 -0
- package/dist/__tests__/utils/sentences.test.js.map +1 -0
- package/dist/__tests__/utils/tokenizer.test.d.ts +2 -0
- package/dist/__tests__/utils/tokenizer.test.d.ts.map +1 -0
- package/dist/__tests__/utils/tokenizer.test.js +25 -0
- package/dist/__tests__/utils/tokenizer.test.js.map +1 -0
- package/dist/catalogs/hedging-phrases.d.ts +4 -0
- package/dist/catalogs/hedging-phrases.d.ts.map +1 -0
- package/dist/catalogs/hedging-phrases.js +49 -0
- package/dist/catalogs/hedging-phrases.js.map +1 -0
- package/dist/catalogs/pii-patterns.d.ts +3 -0
- package/dist/catalogs/pii-patterns.d.ts.map +1 -0
- package/dist/catalogs/pii-patterns.js +35 -0
- package/dist/catalogs/pii-patterns.js.map +1 -0
- package/dist/catalogs/toxic-words.d.ts +3 -0
- package/dist/catalogs/toxic-words.d.ts.map +1 -0
- package/dist/catalogs/toxic-words.js +32 -0
- package/dist/catalogs/toxic-words.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/matchers/content.d.ts +6 -0
- package/dist/matchers/content.d.ts.map +1 -0
- package/dist/matchers/content.js +54 -0
- package/dist/matchers/content.js.map +1 -0
- package/dist/matchers/format.d.ts +6 -0
- package/dist/matchers/format.d.ts.map +1 -0
- package/dist/matchers/format.js +121 -0
- package/dist/matchers/format.js.map +1 -0
- package/dist/matchers/quality.d.ts +9 -0
- package/dist/matchers/quality.d.ts.map +1 -0
- package/dist/matchers/quality.js +107 -0
- package/dist/matchers/quality.js.map +1 -0
- package/dist/matchers/safety.d.ts +6 -0
- package/dist/matchers/safety.d.ts.map +1 -0
- package/dist/matchers/safety.js +87 -0
- package/dist/matchers/safety.js.map +1 -0
- package/dist/matchers/semantic.d.ts +12 -0
- package/dist/matchers/semantic.d.ts.map +1 -0
- package/dist/matchers/semantic.js +79 -0
- package/dist/matchers/semantic.js.map +1 -0
- package/dist/matchers/structural.d.ts +7 -0
- package/dist/matchers/structural.d.ts.map +1 -0
- package/dist/matchers/structural.js +154 -0
- package/dist/matchers/structural.js.map +1 -0
- package/dist/matchers/tone.d.ts +9 -0
- package/dist/matchers/tone.d.ts.map +1 -0
- package/dist/matchers/tone.js +138 -0
- package/dist/matchers/tone.js.map +1 -0
- package/dist/setup.d.ts +4 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +92 -0
- package/dist/setup.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cosine-similarity.d.ts +2 -0
- package/dist/utils/cosine-similarity.d.ts.map +1 -0
- package/dist/utils/cosine-similarity.js +18 -0
- package/dist/utils/cosine-similarity.js.map +1 -0
- package/dist/utils/embedding-cache.d.ts +3 -0
- package/dist/utils/embedding-cache.d.ts.map +1 -0
- package/dist/utils/embedding-cache.js +14 -0
- package/dist/utils/embedding-cache.js.map +1 -0
- package/dist/utils/json-extract.d.ts +2 -0
- package/dist/utils/json-extract.d.ts.map +1 -0
- package/dist/utils/json-extract.js +8 -0
- package/dist/utils/json-extract.js.map +1 -0
- package/dist/utils/luhn.d.ts +2 -0
- package/dist/utils/luhn.d.ts.map +1 -0
- package/dist/utils/luhn.js +22 -0
- package/dist/utils/luhn.js.map +1 -0
- package/dist/utils/ngrams.d.ts +2 -0
- package/dist/utils/ngrams.d.ts.map +1 -0
- package/dist/utils/ngrams.js +13 -0
- package/dist/utils/ngrams.js.map +1 -0
- package/dist/utils/regex-escape.d.ts +2 -0
- package/dist/utils/regex-escape.d.ts.map +1 -0
- package/dist/utils/regex-escape.js +7 -0
- package/dist/utils/regex-escape.js.map +1 -0
- package/dist/utils/sentences.d.ts +2 -0
- package/dist/utils/sentences.d.ts.map +1 -0
- package/dist/utils/sentences.js +36 -0
- package/dist/utils/sentences.js.map +1 -0
- package/dist/utils/tokenizer.d.ts +2 -0
- package/dist/utils/tokenizer.d.ts.map +1 -0
- package/dist/utils/tokenizer.js +7 -0
- package/dist/utils/tokenizer.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_PII_PATTERNS = void 0;
|
|
4
|
+
const luhn_1 = require("../utils/luhn");
|
|
5
|
+
exports.DEFAULT_PII_PATTERNS = [
|
|
6
|
+
{
|
|
7
|
+
type: 'email',
|
|
8
|
+
pattern: /[\w.+-]+@[\w-]+\.[\w.]+/,
|
|
9
|
+
label: 'Email Address',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
type: 'ssn',
|
|
13
|
+
pattern: /\b\d{3}-\d{2}-\d{4}\b/,
|
|
14
|
+
label: 'SSN',
|
|
15
|
+
validate: (v) => v.replace(/-/g, '').length === 9,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
type: 'credit-card',
|
|
19
|
+
pattern: /\b(?:\d{4}[\s-]?){3}\d{4}\b/,
|
|
20
|
+
label: 'Credit Card',
|
|
21
|
+
validate: (v) => (0, luhn_1.luhnCheck)(v.replace(/[\s-]/g, '')),
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'phone',
|
|
25
|
+
pattern: /\b(?:\+1[\s-]?)?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}\b/,
|
|
26
|
+
label: 'Phone Number',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: 'ip-address',
|
|
30
|
+
pattern: /\b(?:\d{1,3}\.){3}\d{1,3}\b/,
|
|
31
|
+
label: 'IP Address',
|
|
32
|
+
validate: (v) => v.split('.').every((n) => parseInt(n, 10) <= 255),
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
//# sourceMappingURL=pii-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pii-patterns.js","sourceRoot":"","sources":["../../src/catalogs/pii-patterns.ts"],"names":[],"mappings":";;;AAAA,wCAA0C;AAG7B,QAAA,oBAAoB,GAAiB;IAChD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,yBAAyB;QAClC,KAAK,EAAE,eAAe;KACvB;IACD;QACE,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,uBAAuB;QAChC,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC;KAClD;IACD;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,6BAA6B;QACtC,KAAK,EAAE,aAAa;QACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,gBAAS,EAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;KACpD;IACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,qDAAqD;QAC9D,KAAK,EAAE,cAAc;KACtB;IACD;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,6BAA6B;QACtC,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;KACnE;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toxic-words.d.ts","sourceRoot":"","sources":["../../src/catalogs/toxic-words.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,eAAO,MAAM,mBAAmB,EAAE,SAAS,EA2B1C,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_TOXIC_WORDS = void 0;
|
|
4
|
+
exports.DEFAULT_TOXIC_WORDS = [
|
|
5
|
+
// critical — slurs
|
|
6
|
+
{ word: 'nigger', severity: 'critical' },
|
|
7
|
+
{ word: 'nigga', severity: 'critical' },
|
|
8
|
+
{ word: 'faggot', severity: 'critical' },
|
|
9
|
+
{ word: 'kike', severity: 'critical' },
|
|
10
|
+
{ word: 'spic', severity: 'critical' },
|
|
11
|
+
{ word: 'chink', severity: 'critical' },
|
|
12
|
+
{ word: 'wetback', severity: 'critical' },
|
|
13
|
+
{ word: 'cunt', severity: 'critical' },
|
|
14
|
+
// warning — profanity
|
|
15
|
+
{ word: 'fuck', severity: 'warning' },
|
|
16
|
+
{ word: 'shit', severity: 'warning' },
|
|
17
|
+
{ word: 'asshole', severity: 'warning' },
|
|
18
|
+
{ word: 'bitch', severity: 'warning' },
|
|
19
|
+
{ word: 'bastard', severity: 'warning' },
|
|
20
|
+
{ word: 'damn', severity: 'warning' },
|
|
21
|
+
{ word: 'hell', severity: 'warning' },
|
|
22
|
+
{ word: 'piss', severity: 'warning' },
|
|
23
|
+
// info — mild
|
|
24
|
+
{ word: 'crap', severity: 'info' },
|
|
25
|
+
{ word: 'sucks', severity: 'info' },
|
|
26
|
+
{ word: 'idiot', severity: 'info' },
|
|
27
|
+
{ word: 'stupid', severity: 'info' },
|
|
28
|
+
{ word: 'moron', severity: 'info' },
|
|
29
|
+
{ word: 'dumb', severity: 'info' },
|
|
30
|
+
{ word: 'loser', severity: 'info' },
|
|
31
|
+
];
|
|
32
|
+
//# sourceMappingURL=toxic-words.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toxic-words.js","sourceRoot":"","sources":["../../src/catalogs/toxic-words.ts"],"names":[],"mappings":";;;AAEa,QAAA,mBAAmB,GAAgB;IAC9C,mBAAmB;IACnB,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE;IACxC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE;IACvC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE;IACxC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE;IACtC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE;IACtC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE;IACvC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE;IACzC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE;IACtC,sBAAsB;IACtB,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IACrC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IACrC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;IACxC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE;IACtC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE;IACxC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IACrC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IACrC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE;IACrC,cAAc;IACd,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;IAClC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;IACnC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;IACnC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE;IACpC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;IACnC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;IAClC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE;CACpC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type { MatcherResult, EmbedFn, Tone, ToneScores, Sentiment, OutputFormat, PIIPattern, ToxicWord, PIIMatch, AIAssertionOptions, } from './types';
|
|
2
|
+
export { cosineSimilarity } from './utils/cosine-similarity';
|
|
3
|
+
export { tokenize } from './utils/tokenizer';
|
|
4
|
+
export { splitSentences } from './utils/sentences';
|
|
5
|
+
export { extractNgrams } from './utils/ngrams';
|
|
6
|
+
export { escapeRegex } from './utils/regex-escape';
|
|
7
|
+
export { luhnCheck } from './utils/luhn';
|
|
8
|
+
export { extractJSONFromCodeFence } from './utils/json-extract';
|
|
9
|
+
export { createCachedEmbedFn } from './utils/embedding-cache';
|
|
10
|
+
export { DEFAULT_PII_PATTERNS } from './catalogs/pii-patterns';
|
|
11
|
+
export { DEFAULT_TOXIC_WORDS } from './catalogs/toxic-words';
|
|
12
|
+
export { DEFAULT_HEDGING_PHRASES, DEFAULT_REFUSAL_PHRASES, DEFAULT_SYSTEM_PROMPT_PATTERNS, } from './catalogs/hedging-phrases';
|
|
13
|
+
export { setupAIAssertions, getGlobalOptions } from './setup';
|
|
14
|
+
export { toStartWith, toEndWith, toBeFormattedAs, toHaveListItems } from './matchers/format';
|
|
15
|
+
export { toContainAllOf, toContainAnyOf, toNotContain, toMentionEntity } from './matchers/content';
|
|
16
|
+
export { toHaveSentiment, toHaveTone, toBeConcise, toNotBeVerbose } from './matchers/tone';
|
|
17
|
+
export { toBeValidJSON, toMatchSchema, toHaveJSONFields, toBeValidMarkdown, toContainCodeBlock, } from './matchers/structural';
|
|
18
|
+
export { toNotContainPII, toNotContainToxicContent, toNotLeakSystemPrompt, toNotBeRefusal, } from './matchers/safety';
|
|
19
|
+
export { toNotBeTruncated, toNotBeHedged, toBeCompleteJSON, toNotRepeat } from './matchers/quality';
|
|
20
|
+
export { toBeSemanticallySimilarTo, toAnswerQuestion, toBeFactuallyConsistentWith, } from './matchers/semantic';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,aAAa,EACb,OAAO,EACP,IAAI,EACJ,UAAU,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,QAAQ,EACR,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG7F,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGnG,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG3F,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,qBAAqB,EACrB,cAAc,GACf,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGpG,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toBeFactuallyConsistentWith = exports.toAnswerQuestion = exports.toBeSemanticallySimilarTo = exports.toNotRepeat = exports.toBeCompleteJSON = exports.toNotBeHedged = exports.toNotBeTruncated = exports.toNotBeRefusal = exports.toNotLeakSystemPrompt = exports.toNotContainToxicContent = exports.toNotContainPII = exports.toContainCodeBlock = exports.toBeValidMarkdown = exports.toHaveJSONFields = exports.toMatchSchema = exports.toBeValidJSON = exports.toNotBeVerbose = exports.toBeConcise = exports.toHaveTone = exports.toHaveSentiment = exports.toMentionEntity = exports.toNotContain = exports.toContainAnyOf = exports.toContainAllOf = exports.toHaveListItems = exports.toBeFormattedAs = exports.toEndWith = exports.toStartWith = exports.getGlobalOptions = exports.setupAIAssertions = exports.DEFAULT_SYSTEM_PROMPT_PATTERNS = exports.DEFAULT_REFUSAL_PHRASES = exports.DEFAULT_HEDGING_PHRASES = exports.DEFAULT_TOXIC_WORDS = exports.DEFAULT_PII_PATTERNS = exports.createCachedEmbedFn = exports.extractJSONFromCodeFence = exports.luhnCheck = exports.escapeRegex = exports.extractNgrams = exports.splitSentences = exports.tokenize = exports.cosineSimilarity = void 0;
|
|
4
|
+
// Utilities
|
|
5
|
+
var cosine_similarity_1 = require("./utils/cosine-similarity");
|
|
6
|
+
Object.defineProperty(exports, "cosineSimilarity", { enumerable: true, get: function () { return cosine_similarity_1.cosineSimilarity; } });
|
|
7
|
+
var tokenizer_1 = require("./utils/tokenizer");
|
|
8
|
+
Object.defineProperty(exports, "tokenize", { enumerable: true, get: function () { return tokenizer_1.tokenize; } });
|
|
9
|
+
var sentences_1 = require("./utils/sentences");
|
|
10
|
+
Object.defineProperty(exports, "splitSentences", { enumerable: true, get: function () { return sentences_1.splitSentences; } });
|
|
11
|
+
var ngrams_1 = require("./utils/ngrams");
|
|
12
|
+
Object.defineProperty(exports, "extractNgrams", { enumerable: true, get: function () { return ngrams_1.extractNgrams; } });
|
|
13
|
+
var regex_escape_1 = require("./utils/regex-escape");
|
|
14
|
+
Object.defineProperty(exports, "escapeRegex", { enumerable: true, get: function () { return regex_escape_1.escapeRegex; } });
|
|
15
|
+
var luhn_1 = require("./utils/luhn");
|
|
16
|
+
Object.defineProperty(exports, "luhnCheck", { enumerable: true, get: function () { return luhn_1.luhnCheck; } });
|
|
17
|
+
var json_extract_1 = require("./utils/json-extract");
|
|
18
|
+
Object.defineProperty(exports, "extractJSONFromCodeFence", { enumerable: true, get: function () { return json_extract_1.extractJSONFromCodeFence; } });
|
|
19
|
+
var embedding_cache_1 = require("./utils/embedding-cache");
|
|
20
|
+
Object.defineProperty(exports, "createCachedEmbedFn", { enumerable: true, get: function () { return embedding_cache_1.createCachedEmbedFn; } });
|
|
21
|
+
// Catalogs
|
|
22
|
+
var pii_patterns_1 = require("./catalogs/pii-patterns");
|
|
23
|
+
Object.defineProperty(exports, "DEFAULT_PII_PATTERNS", { enumerable: true, get: function () { return pii_patterns_1.DEFAULT_PII_PATTERNS; } });
|
|
24
|
+
var toxic_words_1 = require("./catalogs/toxic-words");
|
|
25
|
+
Object.defineProperty(exports, "DEFAULT_TOXIC_WORDS", { enumerable: true, get: function () { return toxic_words_1.DEFAULT_TOXIC_WORDS; } });
|
|
26
|
+
var hedging_phrases_1 = require("./catalogs/hedging-phrases");
|
|
27
|
+
Object.defineProperty(exports, "DEFAULT_HEDGING_PHRASES", { enumerable: true, get: function () { return hedging_phrases_1.DEFAULT_HEDGING_PHRASES; } });
|
|
28
|
+
Object.defineProperty(exports, "DEFAULT_REFUSAL_PHRASES", { enumerable: true, get: function () { return hedging_phrases_1.DEFAULT_REFUSAL_PHRASES; } });
|
|
29
|
+
Object.defineProperty(exports, "DEFAULT_SYSTEM_PROMPT_PATTERNS", { enumerable: true, get: function () { return hedging_phrases_1.DEFAULT_SYSTEM_PROMPT_PATTERNS; } });
|
|
30
|
+
// Setup
|
|
31
|
+
var setup_1 = require("./setup");
|
|
32
|
+
Object.defineProperty(exports, "setupAIAssertions", { enumerable: true, get: function () { return setup_1.setupAIAssertions; } });
|
|
33
|
+
Object.defineProperty(exports, "getGlobalOptions", { enumerable: true, get: function () { return setup_1.getGlobalOptions; } });
|
|
34
|
+
// Format matchers
|
|
35
|
+
var format_1 = require("./matchers/format");
|
|
36
|
+
Object.defineProperty(exports, "toStartWith", { enumerable: true, get: function () { return format_1.toStartWith; } });
|
|
37
|
+
Object.defineProperty(exports, "toEndWith", { enumerable: true, get: function () { return format_1.toEndWith; } });
|
|
38
|
+
Object.defineProperty(exports, "toBeFormattedAs", { enumerable: true, get: function () { return format_1.toBeFormattedAs; } });
|
|
39
|
+
Object.defineProperty(exports, "toHaveListItems", { enumerable: true, get: function () { return format_1.toHaveListItems; } });
|
|
40
|
+
// Content matchers
|
|
41
|
+
var content_1 = require("./matchers/content");
|
|
42
|
+
Object.defineProperty(exports, "toContainAllOf", { enumerable: true, get: function () { return content_1.toContainAllOf; } });
|
|
43
|
+
Object.defineProperty(exports, "toContainAnyOf", { enumerable: true, get: function () { return content_1.toContainAnyOf; } });
|
|
44
|
+
Object.defineProperty(exports, "toNotContain", { enumerable: true, get: function () { return content_1.toNotContain; } });
|
|
45
|
+
Object.defineProperty(exports, "toMentionEntity", { enumerable: true, get: function () { return content_1.toMentionEntity; } });
|
|
46
|
+
// Tone matchers
|
|
47
|
+
var tone_1 = require("./matchers/tone");
|
|
48
|
+
Object.defineProperty(exports, "toHaveSentiment", { enumerable: true, get: function () { return tone_1.toHaveSentiment; } });
|
|
49
|
+
Object.defineProperty(exports, "toHaveTone", { enumerable: true, get: function () { return tone_1.toHaveTone; } });
|
|
50
|
+
Object.defineProperty(exports, "toBeConcise", { enumerable: true, get: function () { return tone_1.toBeConcise; } });
|
|
51
|
+
Object.defineProperty(exports, "toNotBeVerbose", { enumerable: true, get: function () { return tone_1.toNotBeVerbose; } });
|
|
52
|
+
// Structural matchers
|
|
53
|
+
var structural_1 = require("./matchers/structural");
|
|
54
|
+
Object.defineProperty(exports, "toBeValidJSON", { enumerable: true, get: function () { return structural_1.toBeValidJSON; } });
|
|
55
|
+
Object.defineProperty(exports, "toMatchSchema", { enumerable: true, get: function () { return structural_1.toMatchSchema; } });
|
|
56
|
+
Object.defineProperty(exports, "toHaveJSONFields", { enumerable: true, get: function () { return structural_1.toHaveJSONFields; } });
|
|
57
|
+
Object.defineProperty(exports, "toBeValidMarkdown", { enumerable: true, get: function () { return structural_1.toBeValidMarkdown; } });
|
|
58
|
+
Object.defineProperty(exports, "toContainCodeBlock", { enumerable: true, get: function () { return structural_1.toContainCodeBlock; } });
|
|
59
|
+
// Safety matchers
|
|
60
|
+
var safety_1 = require("./matchers/safety");
|
|
61
|
+
Object.defineProperty(exports, "toNotContainPII", { enumerable: true, get: function () { return safety_1.toNotContainPII; } });
|
|
62
|
+
Object.defineProperty(exports, "toNotContainToxicContent", { enumerable: true, get: function () { return safety_1.toNotContainToxicContent; } });
|
|
63
|
+
Object.defineProperty(exports, "toNotLeakSystemPrompt", { enumerable: true, get: function () { return safety_1.toNotLeakSystemPrompt; } });
|
|
64
|
+
Object.defineProperty(exports, "toNotBeRefusal", { enumerable: true, get: function () { return safety_1.toNotBeRefusal; } });
|
|
65
|
+
// Quality matchers
|
|
66
|
+
var quality_1 = require("./matchers/quality");
|
|
67
|
+
Object.defineProperty(exports, "toNotBeTruncated", { enumerable: true, get: function () { return quality_1.toNotBeTruncated; } });
|
|
68
|
+
Object.defineProperty(exports, "toNotBeHedged", { enumerable: true, get: function () { return quality_1.toNotBeHedged; } });
|
|
69
|
+
Object.defineProperty(exports, "toBeCompleteJSON", { enumerable: true, get: function () { return quality_1.toBeCompleteJSON; } });
|
|
70
|
+
Object.defineProperty(exports, "toNotRepeat", { enumerable: true, get: function () { return quality_1.toNotRepeat; } });
|
|
71
|
+
// Semantic matchers
|
|
72
|
+
var semantic_1 = require("./matchers/semantic");
|
|
73
|
+
Object.defineProperty(exports, "toBeSemanticallySimilarTo", { enumerable: true, get: function () { return semantic_1.toBeSemanticallySimilarTo; } });
|
|
74
|
+
Object.defineProperty(exports, "toAnswerQuestion", { enumerable: true, get: function () { return semantic_1.toAnswerQuestion; } });
|
|
75
|
+
Object.defineProperty(exports, "toBeFactuallyConsistentWith", { enumerable: true, get: function () { return semantic_1.toBeFactuallyConsistentWith; } });
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAcA,YAAY;AACZ,+DAA6D;AAApD,qHAAA,gBAAgB,OAAA;AACzB,+CAA6C;AAApC,qGAAA,QAAQ,OAAA;AACjB,+CAAmD;AAA1C,2GAAA,cAAc,OAAA;AACvB,yCAA+C;AAAtC,uGAAA,aAAa,OAAA;AACtB,qDAAmD;AAA1C,2GAAA,WAAW,OAAA;AACpB,qCAAyC;AAAhC,iGAAA,SAAS,OAAA;AAClB,qDAAgE;AAAvD,wHAAA,wBAAwB,OAAA;AACjC,2DAA8D;AAArD,sHAAA,mBAAmB,OAAA;AAE5B,WAAW;AACX,wDAA+D;AAAtD,oHAAA,oBAAoB,OAAA;AAC7B,sDAA6D;AAApD,kHAAA,mBAAmB,OAAA;AAC5B,8DAIoC;AAHlC,0HAAA,uBAAuB,OAAA;AACvB,0HAAA,uBAAuB,OAAA;AACvB,iIAAA,8BAA8B,OAAA;AAGhC,QAAQ;AACR,iCAA8D;AAArD,0GAAA,iBAAiB,OAAA;AAAE,yGAAA,gBAAgB,OAAA;AAE5C,kBAAkB;AAClB,4CAA6F;AAApF,qGAAA,WAAW,OAAA;AAAE,mGAAA,SAAS,OAAA;AAAE,yGAAA,eAAe,OAAA;AAAE,yGAAA,eAAe,OAAA;AAEjE,mBAAmB;AACnB,8CAAmG;AAA1F,yGAAA,cAAc,OAAA;AAAE,yGAAA,cAAc,OAAA;AAAE,uGAAA,YAAY,OAAA;AAAE,0GAAA,eAAe,OAAA;AAEtE,gBAAgB;AAChB,wCAA2F;AAAlF,uGAAA,eAAe,OAAA;AAAE,kGAAA,UAAU,OAAA;AAAE,mGAAA,WAAW,OAAA;AAAE,sGAAA,cAAc,OAAA;AAEjE,sBAAsB;AACtB,oDAM+B;AAL7B,2GAAA,aAAa,OAAA;AACb,2GAAA,aAAa,OAAA;AACb,8GAAA,gBAAgB,OAAA;AAChB,+GAAA,iBAAiB,OAAA;AACjB,gHAAA,kBAAkB,OAAA;AAGpB,kBAAkB;AAClB,4CAK2B;AAJzB,yGAAA,eAAe,OAAA;AACf,kHAAA,wBAAwB,OAAA;AACxB,+GAAA,qBAAqB,OAAA;AACrB,wGAAA,cAAc,OAAA;AAGhB,mBAAmB;AACnB,8CAAoG;AAA3F,2GAAA,gBAAgB,OAAA;AAAE,wGAAA,aAAa,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAAE,sGAAA,WAAW,OAAA;AAEvE,oBAAoB;AACpB,gDAI6B;AAH3B,qHAAA,yBAAyB,OAAA;AACzB,4GAAA,gBAAgB,OAAA;AAChB,uHAAA,2BAA2B,OAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MatcherResult } from '../types';
|
|
2
|
+
export declare function toContainAllOf(received: string, phrases: string[]): MatcherResult;
|
|
3
|
+
export declare function toContainAnyOf(received: string, phrases: string[]): MatcherResult;
|
|
4
|
+
export declare function toNotContain(received: string, phrase: string): MatcherResult;
|
|
5
|
+
export declare function toMentionEntity(received: string, entity: string, aliases?: string[]): MatcherResult;
|
|
6
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/matchers/content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAYjF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAYjF;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAU5E;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,aAAa,CAanG"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toContainAllOf = toContainAllOf;
|
|
4
|
+
exports.toContainAnyOf = toContainAnyOf;
|
|
5
|
+
exports.toNotContain = toNotContain;
|
|
6
|
+
exports.toMentionEntity = toMentionEntity;
|
|
7
|
+
function toContainAllOf(received, phrases) {
|
|
8
|
+
const lower = received.toLowerCase();
|
|
9
|
+
const missing = phrases.filter((p) => !lower.includes(p.toLowerCase()));
|
|
10
|
+
const pass = missing.length === 0;
|
|
11
|
+
return {
|
|
12
|
+
pass,
|
|
13
|
+
message: () => pass
|
|
14
|
+
? `Expected output not to contain all of: ${phrases.join(', ')}`
|
|
15
|
+
: `Expected output to contain all of: ${phrases.join(', ')}, but missing: ${missing.join(', ')}`,
|
|
16
|
+
details: { phrases, missing },
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function toContainAnyOf(received, phrases) {
|
|
20
|
+
const lower = received.toLowerCase();
|
|
21
|
+
const found = phrases.filter((p) => lower.includes(p.toLowerCase()));
|
|
22
|
+
const pass = found.length > 0;
|
|
23
|
+
return {
|
|
24
|
+
pass,
|
|
25
|
+
message: () => pass
|
|
26
|
+
? `Expected output not to contain any of: ${phrases.join(', ')}`
|
|
27
|
+
: `Expected output to contain at least one of: ${phrases.join(', ')}, but none were found`,
|
|
28
|
+
details: { phrases, found },
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function toNotContain(received, phrase) {
|
|
32
|
+
const pass = !received.toLowerCase().includes(phrase.toLowerCase());
|
|
33
|
+
return {
|
|
34
|
+
pass,
|
|
35
|
+
message: () => pass
|
|
36
|
+
? `Expected output to contain "${phrase}", but it did not`
|
|
37
|
+
: `Expected output not to contain "${phrase}", but it was found`,
|
|
38
|
+
details: { phrase, found: !pass },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function toMentionEntity(received, entity, aliases) {
|
|
42
|
+
const lower = received.toLowerCase();
|
|
43
|
+
const terms = [entity, ...(aliases ?? [])];
|
|
44
|
+
const found = terms.find((t) => lower.includes(t.toLowerCase()));
|
|
45
|
+
const pass = found !== undefined;
|
|
46
|
+
return {
|
|
47
|
+
pass,
|
|
48
|
+
message: () => pass
|
|
49
|
+
? `Expected output not to mention "${entity}" (or aliases)`
|
|
50
|
+
: `Expected output to mention "${entity}"${aliases?.length ? ` or aliases [${aliases.join(', ')}]` : ''}, but none were found`,
|
|
51
|
+
details: { entity, aliases, foundTerm: found ?? null },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/matchers/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MatcherResult, OutputFormat } from '../types';
|
|
2
|
+
export declare function toStartWith(received: string, prefix: string): MatcherResult;
|
|
3
|
+
export declare function toEndWith(received: string, suffix: string): MatcherResult;
|
|
4
|
+
export declare function toBeFormattedAs(received: string, format: OutputFormat): MatcherResult;
|
|
5
|
+
export declare function toHaveListItems(received: string, items: string[]): MatcherResult;
|
|
6
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/matchers/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE5D,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAU3E;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAUzE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,aAAa,CAsErF;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,aAAa,CAmBhF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toStartWith = toStartWith;
|
|
4
|
+
exports.toEndWith = toEndWith;
|
|
5
|
+
exports.toBeFormattedAs = toBeFormattedAs;
|
|
6
|
+
exports.toHaveListItems = toHaveListItems;
|
|
7
|
+
function toStartWith(received, prefix) {
|
|
8
|
+
const pass = received.startsWith(prefix);
|
|
9
|
+
return {
|
|
10
|
+
pass,
|
|
11
|
+
message: () => pass
|
|
12
|
+
? `Expected string not to start with "${prefix}"`
|
|
13
|
+
: `Expected string to start with "${prefix}", but got "${received.slice(0, 50)}"`,
|
|
14
|
+
details: { prefix, receivedStart: received.slice(0, prefix.length) },
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function toEndWith(received, suffix) {
|
|
18
|
+
const pass = received.endsWith(suffix);
|
|
19
|
+
return {
|
|
20
|
+
pass,
|
|
21
|
+
message: () => pass
|
|
22
|
+
? `Expected string not to end with "${suffix}"`
|
|
23
|
+
: `Expected string to end with "${suffix}", but got "...${received.slice(-50)}"`,
|
|
24
|
+
details: { suffix, receivedEnd: received.slice(-suffix.length) },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function toBeFormattedAs(received, format) {
|
|
28
|
+
let pass = false;
|
|
29
|
+
let reason = '';
|
|
30
|
+
switch (format) {
|
|
31
|
+
case 'json': {
|
|
32
|
+
const text = received.trim();
|
|
33
|
+
try {
|
|
34
|
+
JSON.parse(text);
|
|
35
|
+
pass = true;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
reason = e.message;
|
|
39
|
+
}
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case 'markdown': {
|
|
43
|
+
const hasHeading = /^#{1,6}\s/m.test(received);
|
|
44
|
+
const hasBold = /\*\*[^*]+\*\*/.test(received);
|
|
45
|
+
const hasItalic = /\*[^*]+\*/.test(received);
|
|
46
|
+
const hasCodeFence = /```/.test(received);
|
|
47
|
+
const hasList = /^[-*]\s|^\d+\.\s/m.test(received);
|
|
48
|
+
const hasBlockquote = /^>\s/m.test(received);
|
|
49
|
+
pass = hasHeading || hasBold || hasItalic || hasCodeFence || hasList || hasBlockquote;
|
|
50
|
+
if (!pass)
|
|
51
|
+
reason = 'No markdown patterns detected (headings, bold, code, lists, blockquotes)';
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case 'list': {
|
|
55
|
+
const lines = received.split('\n').filter((l) => l.trim().length > 0);
|
|
56
|
+
const listLines = lines.filter((l) => /^\s*[-*]\s|^\s*\d+[.)]\s/.test(l));
|
|
57
|
+
pass = lines.length > 0 && listLines.length / lines.length >= 0.5;
|
|
58
|
+
if (!pass)
|
|
59
|
+
reason = `Only ${listLines.length}/${lines.length} lines are list items`;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case 'csv': {
|
|
63
|
+
const lines = received.trim().split('\n').filter((l) => l.trim().length > 0);
|
|
64
|
+
if (lines.length >= 2) {
|
|
65
|
+
const colCounts = lines.map((l) => l.split(',').length);
|
|
66
|
+
const first = colCounts[0];
|
|
67
|
+
pass = first >= 2 && colCounts.every((c) => c === first);
|
|
68
|
+
}
|
|
69
|
+
if (!pass)
|
|
70
|
+
reason = 'CSV requires consistent comma-separated columns across all lines';
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case 'xml': {
|
|
74
|
+
pass = /<[a-zA-Z][^>]*>[\s\S]*<\/[a-zA-Z][^>]*>/.test(received);
|
|
75
|
+
if (!pass)
|
|
76
|
+
reason = 'No XML tag pairs detected';
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case 'yaml': {
|
|
80
|
+
const lines = received.trim().split('\n').filter((l) => l.trim().length > 0 && !l.trim().startsWith('#'));
|
|
81
|
+
const keyValueLines = lines.filter((l) => /^\s*[\w-]+\s*:/.test(l));
|
|
82
|
+
pass = lines.length > 0 && keyValueLines.length / lines.length >= 0.5;
|
|
83
|
+
if (!pass)
|
|
84
|
+
reason = 'Fewer than 50% of lines match YAML key: value pattern';
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case 'table': {
|
|
88
|
+
pass = /\|[^|]+\|/.test(received) && received.includes('|');
|
|
89
|
+
if (!pass)
|
|
90
|
+
reason = 'No table pipe (|) patterns detected';
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
pass,
|
|
96
|
+
message: () => pass
|
|
97
|
+
? `Expected output not to be formatted as ${format}`
|
|
98
|
+
: `Expected output to be formatted as ${format}${reason ? ': ' + reason : ''}`,
|
|
99
|
+
details: { format, reason },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function toHaveListItems(received, items) {
|
|
103
|
+
const missing = [];
|
|
104
|
+
for (const item of items) {
|
|
105
|
+
// Item must appear on a line that starts with a bullet or number
|
|
106
|
+
const escaped = item.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
107
|
+
const pattern = new RegExp(`^\\s*(?:[-*]|\\d+[.)])\\s+.*${escaped}`, 'm');
|
|
108
|
+
if (!pattern.test(received)) {
|
|
109
|
+
missing.push(item);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const pass = missing.length === 0;
|
|
113
|
+
return {
|
|
114
|
+
pass,
|
|
115
|
+
message: () => pass
|
|
116
|
+
? `Expected output not to have all list items: ${items.join(', ')}`
|
|
117
|
+
: `Expected output to have list items, but missing: ${missing.join(', ')}`,
|
|
118
|
+
details: { items, missing },
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/matchers/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MatcherResult } from '../types';
|
|
2
|
+
export declare function toNotBeTruncated(received: string): MatcherResult;
|
|
3
|
+
export declare function toNotBeHedged(received: string, phrases?: string[], threshold?: number): MatcherResult;
|
|
4
|
+
export declare function toBeCompleteJSON(received: string): MatcherResult;
|
|
5
|
+
export declare function toNotRepeat(received: string, options?: {
|
|
6
|
+
windowSize?: number;
|
|
7
|
+
threshold?: number;
|
|
8
|
+
}): MatcherResult;
|
|
9
|
+
//# sourceMappingURL=quality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality.d.ts","sourceRoot":"","sources":["../../src/matchers/quality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAM9C,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CA8BhE;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EAAE,EAClB,SAAS,SAAM,GACd,aAAa,CAuBf;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CA0BhE;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACxD,aAAa,CAwBf"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toNotBeTruncated = toNotBeTruncated;
|
|
4
|
+
exports.toNotBeHedged = toNotBeHedged;
|
|
5
|
+
exports.toBeCompleteJSON = toBeCompleteJSON;
|
|
6
|
+
exports.toNotRepeat = toNotRepeat;
|
|
7
|
+
const tokenizer_1 = require("../utils/tokenizer");
|
|
8
|
+
const sentences_1 = require("../utils/sentences");
|
|
9
|
+
const ngrams_1 = require("../utils/ngrams");
|
|
10
|
+
const hedging_phrases_1 = require("../catalogs/hedging-phrases");
|
|
11
|
+
function toNotBeTruncated(received) {
|
|
12
|
+
const issues = [];
|
|
13
|
+
const trimmed = received.trim();
|
|
14
|
+
// Check ends with sentence-terminal punctuation
|
|
15
|
+
if (trimmed.length > 0 && !/[.!?'")\]>]$/.test(trimmed)) {
|
|
16
|
+
issues.push('Does not end with terminal punctuation');
|
|
17
|
+
}
|
|
18
|
+
// Check for unclosed code fences
|
|
19
|
+
const codeFences = (trimmed.match(/```/g) ?? []).length;
|
|
20
|
+
if (codeFences % 2 !== 0) {
|
|
21
|
+
issues.push('Unclosed code fence');
|
|
22
|
+
}
|
|
23
|
+
// Check for hanging list items (list item with no content after bullet)
|
|
24
|
+
const hangingList = /^[-*]\s*$|^\d+[.)]\s*$/m.test(trimmed);
|
|
25
|
+
if (hangingList) {
|
|
26
|
+
issues.push('Hanging list item with no content');
|
|
27
|
+
}
|
|
28
|
+
const pass = issues.length === 0;
|
|
29
|
+
return {
|
|
30
|
+
pass,
|
|
31
|
+
message: () => pass
|
|
32
|
+
? `Expected output to appear truncated, but it looks complete`
|
|
33
|
+
: `Expected output not to be truncated, but found issues: ${issues.join('; ')}`,
|
|
34
|
+
details: { issues },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function toNotBeHedged(received, phrases, threshold = 0.3) {
|
|
38
|
+
const allPhrases = [...hedging_phrases_1.DEFAULT_HEDGING_PHRASES, ...(phrases ?? [])];
|
|
39
|
+
const lower = received.toLowerCase();
|
|
40
|
+
const sentences = (0, sentences_1.splitSentences)(received);
|
|
41
|
+
const sentenceCount = Math.max(sentences.length, 1);
|
|
42
|
+
const foundPhrases = [];
|
|
43
|
+
for (const phrase of allPhrases) {
|
|
44
|
+
if (lower.includes(phrase.toLowerCase())) {
|
|
45
|
+
foundPhrases.push(phrase);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const ratio = foundPhrases.length / sentenceCount;
|
|
49
|
+
const pass = ratio < threshold;
|
|
50
|
+
return {
|
|
51
|
+
pass,
|
|
52
|
+
message: () => pass
|
|
53
|
+
? `Expected output to be hedged, but hedging ratio ${ratio.toFixed(2)} < threshold ${threshold}`
|
|
54
|
+
: `Expected output not to be hedged, but hedging ratio ${ratio.toFixed(2)} >= threshold ${threshold} (phrases: ${foundPhrases.join(', ')})`,
|
|
55
|
+
details: { foundPhrases, ratio, threshold, sentenceCount },
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function toBeCompleteJSON(received) {
|
|
59
|
+
const trimmed = received.trim();
|
|
60
|
+
try {
|
|
61
|
+
JSON.parse(trimmed);
|
|
62
|
+
return {
|
|
63
|
+
pass: true,
|
|
64
|
+
message: () => `Expected output not to be complete JSON`,
|
|
65
|
+
details: { complete: true },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (parseError) {
|
|
69
|
+
// Check if it looks like truncated JSON
|
|
70
|
+
const looksLikeJSON = trimmed.startsWith('{') || trimmed.startsWith('[');
|
|
71
|
+
const properlyTerminated = (trimmed.startsWith('{') && trimmed.endsWith('}')) ||
|
|
72
|
+
(trimmed.startsWith('[') && trimmed.endsWith(']'));
|
|
73
|
+
const truncated = looksLikeJSON && !properlyTerminated;
|
|
74
|
+
return {
|
|
75
|
+
pass: false,
|
|
76
|
+
message: () => truncated
|
|
77
|
+
? `Expected output to be complete JSON, but it appears truncated (starts with ${trimmed[0]} but does not end with matching bracket)`
|
|
78
|
+
: `Expected output to be complete JSON, but it is not valid JSON: ${parseError.message}`,
|
|
79
|
+
details: { truncated, parseError: parseError.message },
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function toNotRepeat(received, options = {}) {
|
|
84
|
+
const windowSize = options.windowSize ?? 4;
|
|
85
|
+
const threshold = options.threshold ?? 3;
|
|
86
|
+
const tokens = (0, tokenizer_1.tokenize)(received.toLowerCase());
|
|
87
|
+
const ngrams = (0, ngrams_1.extractNgrams)(tokens, windowSize);
|
|
88
|
+
const counts = new Map();
|
|
89
|
+
for (const ng of ngrams) {
|
|
90
|
+
counts.set(ng, (counts.get(ng) ?? 0) + 1);
|
|
91
|
+
}
|
|
92
|
+
const repeated = [];
|
|
93
|
+
for (const [ngram, count] of counts.entries()) {
|
|
94
|
+
if (count > threshold) {
|
|
95
|
+
repeated.push({ ngram, count });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const pass = repeated.length === 0;
|
|
99
|
+
return {
|
|
100
|
+
pass,
|
|
101
|
+
message: () => pass
|
|
102
|
+
? `Expected output to have repetitions, but none exceeded threshold ${threshold}`
|
|
103
|
+
: `Expected output not to repeat, but found ${repeated.length} repeated ${windowSize}-gram(s): ${repeated.map((r) => `"${r.ngram}" (${r.count}x)`).join(', ')}`,
|
|
104
|
+
details: { repeated, windowSize, threshold },
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=quality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality.js","sourceRoot":"","sources":["../../src/matchers/quality.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MatcherResult, PIIPattern, ToxicWord } from '../types';
|
|
2
|
+
export declare function toNotContainPII(received: string, patterns?: PIIPattern[]): MatcherResult;
|
|
3
|
+
export declare function toNotContainToxicContent(received: string, words?: ToxicWord[]): MatcherResult;
|
|
4
|
+
export declare function toNotLeakSystemPrompt(received: string, patterns?: RegExp[]): MatcherResult;
|
|
5
|
+
export declare function toNotBeRefusal(received: string, phrases?: string[]): MatcherResult;
|
|
6
|
+
//# sourceMappingURL=safety.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/matchers/safety.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAY,MAAM,UAAU,CAAC;AAK/E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,UAAU,EAAE,GAAG,aAAa,CA4BxF;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,GAAG,aAAa,CAuB7F;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,aAAa,CAmB1F;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,aAAa,CAalF"}
|