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.
Files changed (142) hide show
  1. package/README.md +183 -0
  2. package/dist/__tests__/matchers/content.test.d.ts +2 -0
  3. package/dist/__tests__/matchers/content.test.d.ts.map +1 -0
  4. package/dist/__tests__/matchers/content.test.js +66 -0
  5. package/dist/__tests__/matchers/content.test.js.map +1 -0
  6. package/dist/__tests__/matchers/format.test.d.ts +2 -0
  7. package/dist/__tests__/matchers/format.test.d.ts.map +1 -0
  8. package/dist/__tests__/matchers/format.test.js +100 -0
  9. package/dist/__tests__/matchers/format.test.js.map +1 -0
  10. package/dist/__tests__/matchers/quality.test.d.ts +2 -0
  11. package/dist/__tests__/matchers/quality.test.d.ts.map +1 -0
  12. package/dist/__tests__/matchers/quality.test.js +98 -0
  13. package/dist/__tests__/matchers/quality.test.js.map +1 -0
  14. package/dist/__tests__/matchers/safety.test.d.ts +2 -0
  15. package/dist/__tests__/matchers/safety.test.d.ts.map +1 -0
  16. package/dist/__tests__/matchers/safety.test.js +120 -0
  17. package/dist/__tests__/matchers/safety.test.js.map +1 -0
  18. package/dist/__tests__/setup.test.d.ts +2 -0
  19. package/dist/__tests__/setup.test.d.ts.map +1 -0
  20. package/dist/__tests__/setup.test.js +49 -0
  21. package/dist/__tests__/setup.test.js.map +1 -0
  22. package/dist/__tests__/types.test.d.ts +2 -0
  23. package/dist/__tests__/types.test.d.ts.map +1 -0
  24. package/dist/__tests__/types.test.js +50 -0
  25. package/dist/__tests__/types.test.js.map +1 -0
  26. package/dist/__tests__/utils/cosine-similarity.test.d.ts +2 -0
  27. package/dist/__tests__/utils/cosine-similarity.test.d.ts.map +1 -0
  28. package/dist/__tests__/utils/cosine-similarity.test.js +30 -0
  29. package/dist/__tests__/utils/cosine-similarity.test.js.map +1 -0
  30. package/dist/__tests__/utils/embedding-cache.test.d.ts +2 -0
  31. package/dist/__tests__/utils/embedding-cache.test.d.ts.map +1 -0
  32. package/dist/__tests__/utils/embedding-cache.test.js +41 -0
  33. package/dist/__tests__/utils/embedding-cache.test.js.map +1 -0
  34. package/dist/__tests__/utils/json-extract.test.d.ts +2 -0
  35. package/dist/__tests__/utils/json-extract.test.d.ts.map +1 -0
  36. package/dist/__tests__/utils/json-extract.test.js +32 -0
  37. package/dist/__tests__/utils/json-extract.test.js.map +1 -0
  38. package/dist/__tests__/utils/luhn.test.d.ts +2 -0
  39. package/dist/__tests__/utils/luhn.test.d.ts.map +1 -0
  40. package/dist/__tests__/utils/luhn.test.js +25 -0
  41. package/dist/__tests__/utils/luhn.test.js.map +1 -0
  42. package/dist/__tests__/utils/ngrams.test.d.ts +2 -0
  43. package/dist/__tests__/utils/ngrams.test.d.ts.map +1 -0
  44. package/dist/__tests__/utils/ngrams.test.js +28 -0
  45. package/dist/__tests__/utils/ngrams.test.js.map +1 -0
  46. package/dist/__tests__/utils/regex-escape.test.d.ts +2 -0
  47. package/dist/__tests__/utils/regex-escape.test.d.ts.map +1 -0
  48. package/dist/__tests__/utils/regex-escape.test.js +48 -0
  49. package/dist/__tests__/utils/regex-escape.test.js.map +1 -0
  50. package/dist/__tests__/utils/sentences.test.d.ts +2 -0
  51. package/dist/__tests__/utils/sentences.test.d.ts.map +1 -0
  52. package/dist/__tests__/utils/sentences.test.js +39 -0
  53. package/dist/__tests__/utils/sentences.test.js.map +1 -0
  54. package/dist/__tests__/utils/tokenizer.test.d.ts +2 -0
  55. package/dist/__tests__/utils/tokenizer.test.d.ts.map +1 -0
  56. package/dist/__tests__/utils/tokenizer.test.js +25 -0
  57. package/dist/__tests__/utils/tokenizer.test.js.map +1 -0
  58. package/dist/catalogs/hedging-phrases.d.ts +4 -0
  59. package/dist/catalogs/hedging-phrases.d.ts.map +1 -0
  60. package/dist/catalogs/hedging-phrases.js +49 -0
  61. package/dist/catalogs/hedging-phrases.js.map +1 -0
  62. package/dist/catalogs/pii-patterns.d.ts +3 -0
  63. package/dist/catalogs/pii-patterns.d.ts.map +1 -0
  64. package/dist/catalogs/pii-patterns.js +35 -0
  65. package/dist/catalogs/pii-patterns.js.map +1 -0
  66. package/dist/catalogs/toxic-words.d.ts +3 -0
  67. package/dist/catalogs/toxic-words.d.ts.map +1 -0
  68. package/dist/catalogs/toxic-words.js +32 -0
  69. package/dist/catalogs/toxic-words.js.map +1 -0
  70. package/dist/index.d.ts +21 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +76 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/matchers/content.d.ts +6 -0
  75. package/dist/matchers/content.d.ts.map +1 -0
  76. package/dist/matchers/content.js +54 -0
  77. package/dist/matchers/content.js.map +1 -0
  78. package/dist/matchers/format.d.ts +6 -0
  79. package/dist/matchers/format.d.ts.map +1 -0
  80. package/dist/matchers/format.js +121 -0
  81. package/dist/matchers/format.js.map +1 -0
  82. package/dist/matchers/quality.d.ts +9 -0
  83. package/dist/matchers/quality.d.ts.map +1 -0
  84. package/dist/matchers/quality.js +107 -0
  85. package/dist/matchers/quality.js.map +1 -0
  86. package/dist/matchers/safety.d.ts +6 -0
  87. package/dist/matchers/safety.d.ts.map +1 -0
  88. package/dist/matchers/safety.js +87 -0
  89. package/dist/matchers/safety.js.map +1 -0
  90. package/dist/matchers/semantic.d.ts +12 -0
  91. package/dist/matchers/semantic.d.ts.map +1 -0
  92. package/dist/matchers/semantic.js +79 -0
  93. package/dist/matchers/semantic.js.map +1 -0
  94. package/dist/matchers/structural.d.ts +7 -0
  95. package/dist/matchers/structural.d.ts.map +1 -0
  96. package/dist/matchers/structural.js +154 -0
  97. package/dist/matchers/structural.js.map +1 -0
  98. package/dist/matchers/tone.d.ts +9 -0
  99. package/dist/matchers/tone.d.ts.map +1 -0
  100. package/dist/matchers/tone.js +138 -0
  101. package/dist/matchers/tone.js.map +1 -0
  102. package/dist/setup.d.ts +4 -0
  103. package/dist/setup.d.ts.map +1 -0
  104. package/dist/setup.js +92 -0
  105. package/dist/setup.js.map +1 -0
  106. package/dist/types.d.ts +43 -0
  107. package/dist/types.d.ts.map +1 -0
  108. package/dist/types.js +3 -0
  109. package/dist/types.js.map +1 -0
  110. package/dist/utils/cosine-similarity.d.ts +2 -0
  111. package/dist/utils/cosine-similarity.d.ts.map +1 -0
  112. package/dist/utils/cosine-similarity.js +18 -0
  113. package/dist/utils/cosine-similarity.js.map +1 -0
  114. package/dist/utils/embedding-cache.d.ts +3 -0
  115. package/dist/utils/embedding-cache.d.ts.map +1 -0
  116. package/dist/utils/embedding-cache.js +14 -0
  117. package/dist/utils/embedding-cache.js.map +1 -0
  118. package/dist/utils/json-extract.d.ts +2 -0
  119. package/dist/utils/json-extract.d.ts.map +1 -0
  120. package/dist/utils/json-extract.js +8 -0
  121. package/dist/utils/json-extract.js.map +1 -0
  122. package/dist/utils/luhn.d.ts +2 -0
  123. package/dist/utils/luhn.d.ts.map +1 -0
  124. package/dist/utils/luhn.js +22 -0
  125. package/dist/utils/luhn.js.map +1 -0
  126. package/dist/utils/ngrams.d.ts +2 -0
  127. package/dist/utils/ngrams.d.ts.map +1 -0
  128. package/dist/utils/ngrams.js +13 -0
  129. package/dist/utils/ngrams.js.map +1 -0
  130. package/dist/utils/regex-escape.d.ts +2 -0
  131. package/dist/utils/regex-escape.d.ts.map +1 -0
  132. package/dist/utils/regex-escape.js +7 -0
  133. package/dist/utils/regex-escape.js.map +1 -0
  134. package/dist/utils/sentences.d.ts +2 -0
  135. package/dist/utils/sentences.d.ts.map +1 -0
  136. package/dist/utils/sentences.js +36 -0
  137. package/dist/utils/sentences.js.map +1 -0
  138. package/dist/utils/tokenizer.d.ts +2 -0
  139. package/dist/utils/tokenizer.d.ts.map +1 -0
  140. package/dist/utils/tokenizer.js +7 -0
  141. package/dist/utils/tokenizer.js.map +1 -0
  142. package/package.json +36 -0
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toNotContainPII = toNotContainPII;
4
+ exports.toNotContainToxicContent = toNotContainToxicContent;
5
+ exports.toNotLeakSystemPrompt = toNotLeakSystemPrompt;
6
+ exports.toNotBeRefusal = toNotBeRefusal;
7
+ const pii_patterns_1 = require("../catalogs/pii-patterns");
8
+ const toxic_words_1 = require("../catalogs/toxic-words");
9
+ const hedging_phrases_1 = require("../catalogs/hedging-phrases");
10
+ function toNotContainPII(received, patterns) {
11
+ const allPatterns = [...pii_patterns_1.DEFAULT_PII_PATTERNS, ...(patterns ?? [])];
12
+ const found = [];
13
+ for (const piiPattern of allPatterns) {
14
+ const regex = new RegExp(piiPattern.pattern.source, piiPattern.pattern.flags.includes('g') ? piiPattern.pattern.flags : piiPattern.pattern.flags + 'g');
15
+ let match;
16
+ while ((match = regex.exec(received)) !== null) {
17
+ const value = match[0];
18
+ if (!piiPattern.validate || piiPattern.validate(value)) {
19
+ found.push({
20
+ type: piiPattern.type,
21
+ value,
22
+ position: [match.index, match.index + value.length],
23
+ });
24
+ }
25
+ }
26
+ }
27
+ const pass = found.length === 0;
28
+ return {
29
+ pass,
30
+ message: () => pass
31
+ ? `Expected output to contain PII, but none was found`
32
+ : `Expected output not to contain PII, but found ${found.length} instance(s): ${found.map((f) => `${f.type}("${f.value}")`).join(', ')}`,
33
+ details: { found },
34
+ };
35
+ }
36
+ function toNotContainToxicContent(received, words) {
37
+ const allWords = [...toxic_words_1.DEFAULT_TOXIC_WORDS, ...(words ?? [])];
38
+ const lower = received.toLowerCase();
39
+ const found = [];
40
+ for (const entry of allWords) {
41
+ const wordLower = entry.word.toLowerCase();
42
+ // Use word boundary check
43
+ const pattern = new RegExp(`\\b${wordLower.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i');
44
+ if (pattern.test(lower)) {
45
+ found.push({ word: entry.word, severity: entry.severity });
46
+ }
47
+ }
48
+ const pass = found.length === 0;
49
+ return {
50
+ pass,
51
+ message: () => pass
52
+ ? `Expected output to contain toxic content, but none was found`
53
+ : `Expected output not to contain toxic content, but found: ${found.map((f) => `${f.word}(${f.severity})`).join(', ')}`,
54
+ details: { found },
55
+ };
56
+ }
57
+ function toNotLeakSystemPrompt(received, patterns) {
58
+ const allPatterns = [...hedging_phrases_1.DEFAULT_SYSTEM_PROMPT_PATTERNS, ...(patterns ?? [])];
59
+ const matched = [];
60
+ for (const pattern of allPatterns) {
61
+ if (pattern.test(received)) {
62
+ matched.push(pattern.toString());
63
+ }
64
+ }
65
+ const pass = matched.length === 0;
66
+ return {
67
+ pass,
68
+ message: () => pass
69
+ ? `Expected output to contain system prompt indicators, but none found`
70
+ : `Expected output not to leak system prompt, but matched patterns: ${matched.join(', ')}`,
71
+ details: { matchedPatterns: matched },
72
+ };
73
+ }
74
+ function toNotBeRefusal(received, phrases) {
75
+ const allPhrases = [...hedging_phrases_1.DEFAULT_REFUSAL_PHRASES, ...(phrases ?? [])];
76
+ const lower = received.toLowerCase();
77
+ const found = allPhrases.filter((p) => lower.includes(p.toLowerCase()));
78
+ const pass = found.length === 0;
79
+ return {
80
+ pass,
81
+ message: () => pass
82
+ ? `Expected output to be a refusal, but no refusal phrases found`
83
+ : `Expected output not to be a refusal, but found: ${found.join(', ')}`,
84
+ details: { foundPhrases: found },
85
+ };
86
+ }
87
+ //# sourceMappingURL=safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety.js","sourceRoot":"","sources":["../../src/matchers/safety.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { MatcherResult, EmbedFn } from '../types';
2
+ export declare function toBeSemanticallySimilarTo(received: string, expected: string, options?: {
3
+ threshold?: number;
4
+ embedFn?: EmbedFn;
5
+ }): Promise<MatcherResult>;
6
+ export declare function toAnswerQuestion(received: string, question: string, options?: {
7
+ embedFn?: EmbedFn;
8
+ }): Promise<MatcherResult>;
9
+ export declare function toBeFactuallyConsistentWith(received: string, reference: string, options?: {
10
+ embedFn?: EmbedFn;
11
+ }): Promise<MatcherResult>;
12
+ //# sourceMappingURL=semantic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic.d.ts","sourceRoot":"","sources":["../../src/matchers/semantic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AA8BvD,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GACtD,OAAO,CAAC,aAAa,CAAC,CAYxB;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,aAAa,CAAC,CAYxB;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,aAAa,CAAC,CA2BxB"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toBeSemanticallySimilarTo = toBeSemanticallySimilarTo;
4
+ exports.toAnswerQuestion = toAnswerQuestion;
5
+ exports.toBeFactuallyConsistentWith = toBeFactuallyConsistentWith;
6
+ const tokenizer_1 = require("../utils/tokenizer");
7
+ const ngrams_1 = require("../utils/ngrams");
8
+ const cosine_similarity_1 = require("../utils/cosine-similarity");
9
+ const sentences_1 = require("../utils/sentences");
10
+ function ngramJaccardSimilarity(a, b, n = 3) {
11
+ const tokensA = (0, tokenizer_1.tokenize)(a.toLowerCase());
12
+ const tokensB = (0, tokenizer_1.tokenize)(b.toLowerCase());
13
+ const ngramsA = new Set((0, ngrams_1.extractNgrams)(tokensA, n));
14
+ const ngramsB = new Set((0, ngrams_1.extractNgrams)(tokensB, n));
15
+ if (ngramsA.size === 0 && ngramsB.size === 0)
16
+ return 1;
17
+ if (ngramsA.size === 0 || ngramsB.size === 0)
18
+ return 0;
19
+ const intersection = new Set([...ngramsA].filter((x) => ngramsB.has(x)));
20
+ const union = new Set([...ngramsA, ...ngramsB]);
21
+ return intersection.size / union.size;
22
+ }
23
+ async function computeSimilarity(a, b, embedFn) {
24
+ if (embedFn) {
25
+ const [vecA, vecB] = await Promise.all([embedFn(a), embedFn(b)]);
26
+ return (0, cosine_similarity_1.cosineSimilarity)(vecA, vecB);
27
+ }
28
+ return ngramJaccardSimilarity(a, b);
29
+ }
30
+ async function toBeSemanticallySimilarTo(received, expected, options = {}) {
31
+ const threshold = options.threshold ?? 0.8;
32
+ const similarity = await computeSimilarity(received, expected, options.embedFn);
33
+ const pass = similarity >= threshold;
34
+ return {
35
+ pass,
36
+ message: () => pass
37
+ ? `Expected output not to be semantically similar to reference (similarity: ${similarity.toFixed(3)}, threshold: ${threshold})`
38
+ : `Expected output to be semantically similar to reference, but similarity ${similarity.toFixed(3)} < threshold ${threshold}`,
39
+ details: { similarity, threshold, method: options.embedFn ? 'embedding' : 'ngram-jaccard' },
40
+ };
41
+ }
42
+ async function toAnswerQuestion(received, question, options = {}) {
43
+ const threshold = 0.5;
44
+ const similarity = await computeSimilarity(received, question, options.embedFn);
45
+ const pass = similarity >= threshold;
46
+ return {
47
+ pass,
48
+ message: () => pass
49
+ ? `Expected output not to answer the question (similarity: ${similarity.toFixed(3)})`
50
+ : `Expected output to answer the question, but semantic similarity ${similarity.toFixed(3)} < threshold ${threshold}`,
51
+ details: { similarity, threshold, question },
52
+ };
53
+ }
54
+ async function toBeFactuallyConsistentWith(received, reference, options = {}) {
55
+ const threshold = 0.3;
56
+ const sentences = (0, sentences_1.splitSentences)(received);
57
+ if (sentences.length === 0) {
58
+ return {
59
+ pass: true,
60
+ message: () => `Expected output to be factually inconsistent, but output has no sentences`,
61
+ details: { sentences: 0, coverageScores: [] },
62
+ };
63
+ }
64
+ const coverageScores = [];
65
+ for (const sentence of sentences) {
66
+ const score = await computeSimilarity(sentence, reference, options.embedFn);
67
+ coverageScores.push(score);
68
+ }
69
+ const avgCoverage = coverageScores.reduce((a, b) => a + b, 0) / coverageScores.length;
70
+ const pass = avgCoverage >= threshold;
71
+ return {
72
+ pass,
73
+ message: () => pass
74
+ ? `Expected output not to be factually consistent with reference (avg coverage: ${avgCoverage.toFixed(3)})`
75
+ : `Expected output to be factually consistent with reference, but avg coverage ${avgCoverage.toFixed(3)} < threshold ${threshold}`,
76
+ details: { avgCoverage, threshold, coverageScores, sentenceCount: sentences.length },
77
+ };
78
+ }
79
+ //# sourceMappingURL=semantic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../src/matchers/semantic.ts"],"names":[],"mappings":";;AA8BA,8DAgBC;AAED,4CAgBC;AAED,kEA+BC;AAhGD,kDAA8C;AAC9C,4CAAgD;AAChD,kEAA8D;AAC9D,kDAAoD;AAEpD,SAAS,sBAAsB,CAAC,CAAS,EAAE,CAAS,EAAE,CAAC,GAAG,CAAC;IACzD,MAAM,OAAO,GAAG,IAAA,oBAAQ,EAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAA,oBAAQ,EAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAA,sBAAa,EAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACvD,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACvD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAChD,OAAO,YAAY,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,CAAS,EACT,CAAS,EACT,OAAiB;IAEjB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,OAAO,IAAA,oCAAgB,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACtC,CAAC;AAEM,KAAK,UAAU,yBAAyB,CAC7C,QAAgB,EAChB,QAAgB,EAChB,UAAqD,EAAE;IAEvD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,UAAU,IAAI,SAAS,CAAC;IACrC,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,GAAG,EAAE,CACZ,IAAI;YACF,CAAC,CAAC,4EAA4E,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,SAAS,GAAG;YAC/H,CAAC,CAAC,2EAA2E,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,SAAS,EAAE;QACjI,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,EAAE;KAC5F,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,QAAgB,EAChB,UAAiC,EAAE;IAEnC,MAAM,SAAS,GAAG,GAAG,CAAC;IACtB,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,UAAU,IAAI,SAAS,CAAC;IACrC,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,GAAG,EAAE,CACZ,IAAI;YACF,CAAC,CAAC,2DAA2D,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YACrF,CAAC,CAAC,mEAAmE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,SAAS,EAAE;QACzH,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE;KAC7C,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,2BAA2B,CAC/C,QAAgB,EAChB,SAAiB,EACjB,UAAiC,EAAE;IAEnC,MAAM,SAAS,GAAG,GAAG,CAAC;IACtB,MAAM,SAAS,GAAG,IAAA,0BAAc,EAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,GAAG,EAAE,CAAC,2EAA2E;YAC1F,OAAO,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE;SAC9C,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5E,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC;IACtF,MAAM,IAAI,GAAG,WAAW,IAAI,SAAS,CAAC;IACtC,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,GAAG,EAAE,CACZ,IAAI;YACF,CAAC,CAAC,gFAAgF,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YAC3G,CAAC,CAAC,+EAA+E,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,SAAS,EAAE;QACtI,OAAO,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,CAAC,MAAM,EAAE;KACrF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { MatcherResult } from '../types';
2
+ export declare function toBeValidJSON(received: string): MatcherResult;
3
+ export declare function toMatchSchema(received: string, schema: object): MatcherResult;
4
+ export declare function toHaveJSONFields(received: string, fields: string[]): MatcherResult;
5
+ export declare function toBeValidMarkdown(received: string): MatcherResult;
6
+ export declare function toContainCodeBlock(received: string, language?: string): MatcherResult;
7
+ //# sourceMappingURL=structural.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structural.d.ts","sourceRoot":"","sources":["../../src/matchers/structural.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAiC9C,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAW7D;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CA+B7E;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,CAmBlF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAkCjE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,aAAa,CAqBrF"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.toBeValidJSON = toBeValidJSON;
7
+ exports.toMatchSchema = toMatchSchema;
8
+ exports.toHaveJSONFields = toHaveJSONFields;
9
+ exports.toBeValidMarkdown = toBeValidMarkdown;
10
+ exports.toContainCodeBlock = toContainCodeBlock;
11
+ const ajv_1 = __importDefault(require("ajv"));
12
+ const json_extract_1 = require("../utils/json-extract");
13
+ const ajv = new ajv_1.default({ allErrors: true });
14
+ function tryParseJSON(received) {
15
+ const trimmed = received.trim();
16
+ try {
17
+ return { value: JSON.parse(trimmed) };
18
+ }
19
+ catch {
20
+ // Try extracting from code fence
21
+ const extracted = (0, json_extract_1.extractJSONFromCodeFence)(trimmed);
22
+ if (extracted) {
23
+ try {
24
+ return { value: JSON.parse(extracted) };
25
+ }
26
+ catch (e2) {
27
+ return { value: undefined, error: e2.message };
28
+ }
29
+ }
30
+ return { value: undefined, error: `Not valid JSON: ${trimmed.slice(0, 60)}` };
31
+ }
32
+ }
33
+ function getNestedValue(obj, path) {
34
+ const parts = path.split('.');
35
+ let current = obj;
36
+ for (const part of parts) {
37
+ if (current === null || current === undefined || typeof current !== 'object')
38
+ return false;
39
+ current = current[part];
40
+ }
41
+ return current !== undefined;
42
+ }
43
+ function toBeValidJSON(received) {
44
+ const { value, error } = tryParseJSON(received);
45
+ const pass = value !== undefined;
46
+ return {
47
+ pass,
48
+ message: () => pass
49
+ ? `Expected output not to be valid JSON`
50
+ : `Expected output to be valid JSON, but got error: ${error ?? 'unknown'}`,
51
+ details: { error: error ?? null },
52
+ };
53
+ }
54
+ function toMatchSchema(received, schema) {
55
+ const { value, error: parseError } = tryParseJSON(received);
56
+ if (value === undefined) {
57
+ return {
58
+ pass: false,
59
+ message: () => `Expected output to match schema, but it is not valid JSON: ${parseError}`,
60
+ details: { parseError },
61
+ };
62
+ }
63
+ let pass = false;
64
+ let validationErrors = [];
65
+ try {
66
+ const validate = ajv.compile(schema);
67
+ pass = validate(value);
68
+ validationErrors = (validate.errors ?? []).map((e) => `${e.instancePath} ${e.message}`);
69
+ }
70
+ catch (e) {
71
+ // Fallback: basic type checking if Ajv fails
72
+ pass = true;
73
+ validationErrors = [`Schema compilation error: ${e.message}`];
74
+ }
75
+ return {
76
+ pass,
77
+ message: () => pass
78
+ ? `Expected output not to match the provided schema`
79
+ : `Expected output to match schema, but validation failed: ${validationErrors.join('; ')}`,
80
+ details: { validationErrors },
81
+ };
82
+ }
83
+ function toHaveJSONFields(received, fields) {
84
+ const { value, error } = tryParseJSON(received);
85
+ if (value === undefined) {
86
+ return {
87
+ pass: false,
88
+ message: () => `Expected output to have JSON fields, but it is not valid JSON: ${error}`,
89
+ details: { fields, parseError: error },
90
+ };
91
+ }
92
+ const missing = fields.filter((f) => !getNestedValue(value, f));
93
+ const pass = missing.length === 0;
94
+ return {
95
+ pass,
96
+ message: () => pass
97
+ ? `Expected output not to have all JSON fields: ${fields.join(', ')}`
98
+ : `Expected output to have JSON fields, but missing: ${missing.join(', ')}`,
99
+ details: { fields, missing },
100
+ };
101
+ }
102
+ function toBeValidMarkdown(received) {
103
+ const issues = [];
104
+ // Check for unclosed code fences
105
+ const codeFenceMatches = received.match(/```/g) ?? [];
106
+ if (codeFenceMatches.length % 2 !== 0) {
107
+ issues.push('Unclosed code fence (odd number of ```)');
108
+ }
109
+ // Check heading hierarchy (no skipping levels: h1 -> h3 without h2)
110
+ const headings = [...received.matchAll(/^(#{1,6})\s/gm)].map((m) => m[1].length);
111
+ for (let i = 1; i < headings.length; i++) {
112
+ if (headings[i] - headings[i - 1] > 1) {
113
+ issues.push(`Heading hierarchy skip: h${headings[i - 1]} -> h${headings[i]}`);
114
+ break;
115
+ }
116
+ }
117
+ // Check for unbalanced brackets in links [text](url)
118
+ const openBrackets = (received.match(/\[/g) ?? []).length;
119
+ const closeBrackets = (received.match(/\]/g) ?? []).length;
120
+ if (openBrackets !== closeBrackets) {
121
+ issues.push(`Unbalanced brackets: ${openBrackets} [ vs ${closeBrackets} ]`);
122
+ }
123
+ const pass = issues.length === 0;
124
+ return {
125
+ pass,
126
+ message: () => pass
127
+ ? `Expected output not to be valid markdown`
128
+ : `Expected output to be valid markdown, but found issues: ${issues.join('; ')}`,
129
+ details: { issues },
130
+ };
131
+ }
132
+ function toContainCodeBlock(received, language) {
133
+ let pass;
134
+ let reason = '';
135
+ if (language) {
136
+ const pattern = new RegExp('```' + language + '\\s*\\n[\\s\\S]*?\\n```', 'i');
137
+ pass = pattern.test(received);
138
+ if (!pass)
139
+ reason = `No code block with language "${language}" found`;
140
+ }
141
+ else {
142
+ pass = /```[\s\S]*?```/.test(received);
143
+ if (!pass)
144
+ reason = 'No code block (```) found';
145
+ }
146
+ return {
147
+ pass,
148
+ message: () => pass
149
+ ? `Expected output not to contain a code block${language ? ` (${language})` : ''}`
150
+ : `Expected output to contain a code block${language ? ` (${language})` : ''}: ${reason}`,
151
+ details: { language: language ?? null, reason },
152
+ };
153
+ }
154
+ //# sourceMappingURL=structural.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structural.js","sourceRoot":"","sources":["../../src/matchers/structural.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { MatcherResult, Sentiment, Tone } from '../types';
2
+ export declare function toHaveSentiment(received: string, expected: Sentiment): MatcherResult;
3
+ export declare function toHaveTone(received: string, expected: Tone): MatcherResult;
4
+ export declare function toBeConcise(received: string, maxWords?: number): MatcherResult;
5
+ export declare function toNotBeVerbose(received: string, options?: {
6
+ maxWords?: number;
7
+ maxSentences?: number;
8
+ }): MatcherResult;
9
+ //# sourceMappingURL=tone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tone.d.ts","sourceRoot":"","sources":["../../src/matchers/tone.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AA0B/D,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,GAAG,aAAa,CA0BpF;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,aAAa,CAkD1E;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAM,GAAG,aAAa,CAW3E;AAED,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,GACzD,aAAa,CAmBf"}
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toHaveSentiment = toHaveSentiment;
4
+ exports.toHaveTone = toHaveTone;
5
+ exports.toBeConcise = toBeConcise;
6
+ exports.toNotBeVerbose = toNotBeVerbose;
7
+ const tokenizer_1 = require("../utils/tokenizer");
8
+ const sentences_1 = require("../utils/sentences");
9
+ const POSITIVE_WORDS = new Set([
10
+ 'good', 'great', 'excellent', 'amazing', 'happy', 'love', 'wonderful', 'fantastic',
11
+ 'positive', 'best', 'better', 'improve', 'superb', 'outstanding', 'brilliant',
12
+ 'perfect', 'awesome', 'delightful', 'enjoy', 'glad', 'pleased', 'helpful',
13
+ 'beautiful', 'success', 'successful', 'well', 'nice', 'clear', 'easy',
14
+ ]);
15
+ const NEGATIVE_WORDS = new Set([
16
+ 'bad', 'terrible', 'awful', 'horrible', 'poor', 'worst', 'hate', 'negative',
17
+ 'fail', 'wrong', 'problem', 'broken', 'error', 'issue', 'painful', 'difficult',
18
+ 'ugly', 'boring', 'useless', 'ineffective', 'disappointing', 'frustrated',
19
+ 'confusing', 'complicated', 'failure', 'crash', 'bug', 'defect',
20
+ ]);
21
+ const INFORMAL_WORDS = new Set([
22
+ 'gonna', 'wanna', 'gotta', 'kinda', 'sorta', 'yeah', 'yep', 'nope',
23
+ 'hey', 'ok', 'okay', 'cool', 'stuff', 'thing', 'things', 'got', 'get',
24
+ 'cause', 'cuz', 'tbh', 'imo', 'lol', 'btw', 'fyi',
25
+ ]);
26
+ const CONTRACTIONS = /\b(?:I'm|I've|I'll|I'd|you're|you've|you'll|you'd|he's|she's|it's|we're|we've|we'll|they're|they've|don't|doesn't|didn't|can't|couldn't|won't|wouldn't|isn't|aren't|wasn't|weren't|haven't|hasn't|hadn't)\b/gi;
27
+ function toHaveSentiment(received, expected) {
28
+ const tokens = (0, tokenizer_1.tokenize)(received.toLowerCase());
29
+ let posCount = 0;
30
+ let negCount = 0;
31
+ for (const t of tokens) {
32
+ const word = t.replace(/[^a-z]/g, '');
33
+ if (POSITIVE_WORDS.has(word))
34
+ posCount++;
35
+ if (NEGATIVE_WORDS.has(word))
36
+ negCount++;
37
+ }
38
+ const total = posCount + negCount;
39
+ let detected;
40
+ if (total === 0) {
41
+ detected = 'neutral';
42
+ }
43
+ else {
44
+ const ratio = posCount / total;
45
+ detected = ratio > 0.6 ? 'positive' : ratio < 0.4 ? 'negative' : 'neutral';
46
+ }
47
+ const pass = detected === expected;
48
+ return {
49
+ pass,
50
+ message: () => pass
51
+ ? `Expected output not to have ${expected} sentiment`
52
+ : `Expected ${expected} sentiment, but detected ${detected} (positive: ${posCount}, negative: ${negCount})`,
53
+ details: { expected, detected, positiveCount: posCount, negativeCount: negCount },
54
+ };
55
+ }
56
+ function toHaveTone(received, expected) {
57
+ const tokens = (0, tokenizer_1.tokenize)(received);
58
+ const sentences = (0, sentences_1.splitSentences)(received);
59
+ const wordCount = tokens.length;
60
+ let detected;
61
+ let score = 0;
62
+ let reason = '';
63
+ if (expected === 'formal') {
64
+ const contractionCount = (received.match(CONTRACTIONS) ?? []).length;
65
+ const contractionRate = wordCount > 0 ? contractionCount / wordCount : 0;
66
+ const avgSentenceLen = sentences.length > 0 ? wordCount / sentences.length : 0;
67
+ score = (1 - contractionRate) * 0.5 + (Math.min(avgSentenceLen, 20) / 20) * 0.5;
68
+ detected = score >= 0.6 ? 'formal' : 'casual';
69
+ reason = `contraction rate: ${contractionRate.toFixed(2)}, avg sentence len: ${avgSentenceLen.toFixed(1)}`;
70
+ }
71
+ else if (expected === 'casual') {
72
+ const contractionCount = (received.match(CONTRACTIONS) ?? []).length;
73
+ const contractionRate = wordCount > 0 ? contractionCount / wordCount : 0;
74
+ const informalCount = tokens.filter((t) => INFORMAL_WORDS.has(t.toLowerCase())).length;
75
+ const informalRate = wordCount > 0 ? informalCount / wordCount : 0;
76
+ score = contractionRate * 0.5 + informalRate * 10 * 0.5;
77
+ detected = score >= 0.1 ? 'casual' : 'formal';
78
+ reason = `contraction rate: ${contractionRate.toFixed(2)}, informal word rate: ${informalRate.toFixed(2)}`;
79
+ }
80
+ else if (expected === 'technical') {
81
+ const longWords = tokens.filter((t) => t.replace(/[^a-zA-Z]/g, '').length > 8).length;
82
+ const longWordRate = wordCount > 0 ? longWords / wordCount : 0;
83
+ const hasCode = /`[^`]+`|```[\s\S]*?```/.test(received);
84
+ score = longWordRate * 0.7 + (hasCode ? 0.3 : 0);
85
+ detected = score >= 0.15 ? 'technical' : 'formal';
86
+ reason = `long word rate: ${longWordRate.toFixed(2)}, has code: ${hasCode}`;
87
+ }
88
+ else {
89
+ // friendly
90
+ const exclamations = (received.match(/!/g) ?? []).length;
91
+ const youCount = tokens.filter((t) => t.toLowerCase() === 'you').length;
92
+ const positiveCount = tokens.filter((t) => POSITIVE_WORDS.has(t.toLowerCase().replace(/[^a-z]/g, ''))).length;
93
+ score = (exclamations * 0.1 + (youCount / Math.max(wordCount, 1)) * 5 + (positiveCount / Math.max(wordCount, 1)) * 3);
94
+ detected = score >= 0.15 ? 'friendly' : 'formal';
95
+ reason = `exclamations: ${exclamations}, you-frequency: ${(youCount / Math.max(wordCount, 1)).toFixed(2)}, positive rate: ${(positiveCount / Math.max(wordCount, 1)).toFixed(2)}`;
96
+ }
97
+ const pass = detected === expected;
98
+ return {
99
+ pass,
100
+ message: () => pass
101
+ ? `Expected output not to have ${expected} tone`
102
+ : `Expected ${expected} tone, but detected ${detected} (${reason})`,
103
+ details: { expected, detected, score, reason },
104
+ };
105
+ }
106
+ function toBeConcise(received, maxWords = 100) {
107
+ const wordCount = (0, tokenizer_1.tokenize)(received).length;
108
+ const pass = wordCount <= maxWords;
109
+ return {
110
+ pass,
111
+ message: () => pass
112
+ ? `Expected output not to be concise (max ${maxWords} words), but it had only ${wordCount} words`
113
+ : `Expected output to be concise (max ${maxWords} words), but it had ${wordCount} words`,
114
+ details: { wordCount, maxWords },
115
+ };
116
+ }
117
+ function toNotBeVerbose(received, options = {}) {
118
+ const maxWords = options.maxWords ?? 200;
119
+ const maxSentences = options.maxSentences ?? 10;
120
+ const wordCount = (0, tokenizer_1.tokenize)(received).length;
121
+ const sentenceCount = (0, sentences_1.splitSentences)(received).length;
122
+ const tooManyWords = wordCount > maxWords;
123
+ const tooManySentences = sentenceCount > maxSentences;
124
+ const pass = !tooManyWords && !tooManySentences;
125
+ const reasons = [];
126
+ if (tooManyWords)
127
+ reasons.push(`${wordCount} words (max ${maxWords})`);
128
+ if (tooManySentences)
129
+ reasons.push(`${sentenceCount} sentences (max ${maxSentences})`);
130
+ return {
131
+ pass,
132
+ message: () => pass
133
+ ? `Expected output to be verbose, but it was within limits`
134
+ : `Expected output not to be verbose, but: ${reasons.join(', ')}`,
135
+ details: { wordCount, sentenceCount, maxWords, maxSentences },
136
+ };
137
+ }
138
+ //# sourceMappingURL=tone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tone.js","sourceRoot":"","sources":["../../src/matchers/tone.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AIAssertionOptions } from './types';
2
+ export declare function setupAIAssertions(options?: AIAssertionOptions): void;
3
+ export declare function getGlobalOptions(): AIAssertionOptions;
4
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAiB,MAAM,SAAS,CAAC;AA+BjE,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAapE;AAED,wBAAgB,gBAAgB,IAAI,kBAAkB,CAErD"}