@pauly4010/evalai-sdk 1.4.1 → 1.5.5

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 (95) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +205 -543
  3. package/dist/assertions.d.ts +2 -2
  4. package/dist/assertions.js +104 -71
  5. package/dist/batch.js +12 -17
  6. package/dist/cache.js +7 -11
  7. package/dist/cli/api.d.ts +108 -0
  8. package/dist/cli/api.js +130 -0
  9. package/dist/cli/check.d.ts +28 -13
  10. package/dist/cli/check.js +249 -142
  11. package/dist/cli/ci-context.d.ts +6 -0
  12. package/dist/cli/ci-context.js +110 -0
  13. package/dist/cli/config.d.ts +30 -0
  14. package/dist/cli/config.js +207 -0
  15. package/dist/cli/constants.d.ts +15 -0
  16. package/dist/cli/constants.js +18 -0
  17. package/dist/cli/doctor.d.ts +11 -0
  18. package/dist/cli/doctor.js +82 -0
  19. package/dist/cli/formatters/github.d.ts +8 -0
  20. package/dist/cli/formatters/github.js +130 -0
  21. package/dist/cli/formatters/human.d.ts +6 -0
  22. package/dist/cli/formatters/human.js +107 -0
  23. package/dist/cli/formatters/json.d.ts +6 -0
  24. package/dist/cli/formatters/json.js +10 -0
  25. package/dist/cli/formatters/pr-comment.d.ts +12 -0
  26. package/dist/cli/formatters/pr-comment.js +101 -0
  27. package/dist/cli/formatters/types.d.ts +100 -0
  28. package/dist/cli/formatters/types.js +5 -0
  29. package/dist/cli/gate.d.ts +21 -0
  30. package/dist/cli/gate.js +175 -0
  31. package/dist/cli/index.d.ts +1 -0
  32. package/dist/cli/index.js +67 -23
  33. package/dist/cli/init.d.ts +7 -0
  34. package/dist/cli/init.js +69 -0
  35. package/dist/cli/policy-packs.d.ts +23 -0
  36. package/dist/cli/policy-packs.js +83 -0
  37. package/dist/cli/profiles.d.ts +28 -0
  38. package/dist/cli/profiles.js +30 -0
  39. package/dist/cli/reason-codes.d.ts +17 -0
  40. package/dist/cli/reason-codes.js +19 -0
  41. package/dist/cli/render/snippet.d.ts +5 -0
  42. package/dist/cli/render/snippet.js +15 -0
  43. package/dist/cli/render/sort.d.ts +10 -0
  44. package/dist/cli/render/sort.js +24 -0
  45. package/dist/cli/report/build-check-report.d.ts +19 -0
  46. package/dist/cli/report/build-check-report.js +124 -0
  47. package/dist/cli/share.d.ts +17 -0
  48. package/dist/cli/share.js +83 -0
  49. package/dist/client.d.ts +2 -2
  50. package/dist/client.js +144 -132
  51. package/dist/context.d.ts +1 -1
  52. package/dist/context.js +4 -6
  53. package/dist/errors.d.ts +2 -0
  54. package/dist/errors.js +116 -107
  55. package/dist/export.d.ts +6 -6
  56. package/dist/export.js +39 -33
  57. package/dist/index.d.ts +25 -24
  58. package/dist/index.js +62 -56
  59. package/dist/integrations/anthropic.d.ts +1 -1
  60. package/dist/integrations/anthropic.js +23 -19
  61. package/dist/integrations/openai-eval.d.ts +57 -0
  62. package/dist/integrations/openai-eval.js +230 -0
  63. package/dist/integrations/openai.d.ts +1 -1
  64. package/dist/integrations/openai.js +23 -19
  65. package/dist/local.d.ts +2 -2
  66. package/dist/local.js +25 -25
  67. package/dist/logger.d.ts +1 -1
  68. package/dist/logger.js +24 -28
  69. package/dist/matchers/index.d.ts +1 -0
  70. package/dist/matchers/index.js +6 -0
  71. package/dist/matchers/to-pass-gate.d.ts +29 -0
  72. package/dist/matchers/to-pass-gate.js +35 -0
  73. package/dist/pagination.d.ts +1 -1
  74. package/dist/pagination.js +6 -6
  75. package/dist/snapshot.js +24 -24
  76. package/dist/streaming.js +11 -11
  77. package/dist/testing.d.ts +6 -2
  78. package/dist/testing.js +30 -12
  79. package/dist/types.d.ts +22 -22
  80. package/dist/types.js +13 -13
  81. package/dist/utils/input-hash.d.ts +8 -0
  82. package/dist/utils/input-hash.js +38 -0
  83. package/dist/version.d.ts +7 -0
  84. package/dist/version.js +10 -0
  85. package/dist/workflows.d.ts +7 -7
  86. package/dist/workflows.js +44 -44
  87. package/package.json +102 -90
  88. package/dist/__tests__/assertions.test.d.ts +0 -1
  89. package/dist/__tests__/assertions.test.js +0 -288
  90. package/dist/__tests__/client.test.d.ts +0 -1
  91. package/dist/__tests__/client.test.js +0 -185
  92. package/dist/__tests__/testing.test.d.ts +0 -1
  93. package/dist/__tests__/testing.test.js +0 -230
  94. package/dist/__tests__/workflows.test.d.ts +0 -1
  95. package/dist/__tests__/workflows.test.js +0 -222
@@ -76,7 +76,7 @@ export declare class Expectation {
76
76
  * Assert value has expected sentiment
77
77
  * @example expect(output).toHaveSentiment('positive')
78
78
  */
79
- toHaveSentiment(expected: 'positive' | 'negative' | 'neutral', message?: string): AssertionResult;
79
+ toHaveSentiment(expected: "positive" | "negative" | "neutral", message?: string): AssertionResult;
80
80
  /**
81
81
  * Assert string length is within range
82
82
  * @example expect(output).toHaveLength({ min: 10, max: 100 })
@@ -172,7 +172,7 @@ export declare function hasLength(text: string, range: {
172
172
  }): boolean;
173
173
  export declare function containsJSON(text: string): boolean;
174
174
  export declare function notContainsPII(text: string): boolean;
175
- export declare function hasSentiment(text: string, expected: 'positive' | 'negative' | 'neutral'): boolean;
175
+ export declare function hasSentiment(text: string, expected: "positive" | "negative" | "neutral"): boolean;
176
176
  export declare function similarTo(text1: string, text2: string, threshold?: number): boolean;
177
177
  export declare function withinRange(value: number, min: number, max: number): boolean;
178
178
  export declare function isValidEmail(email: string): boolean;
@@ -67,7 +67,10 @@ class Expectation {
67
67
  passed,
68
68
  expected,
69
69
  actual: this.value,
70
- message: message || (passed ? "Values are equal" : `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(this.value)}`)
70
+ message: message ||
71
+ (passed
72
+ ? "Values are equal"
73
+ : `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(this.value)}`),
71
74
  };
72
75
  }
73
76
  /**
@@ -82,7 +85,8 @@ class Expectation {
82
85
  passed,
83
86
  expected: substring,
84
87
  actual: text,
85
- message: message || (passed ? `Text contains "${substring}"` : `Text does not contain "${substring}"`)
88
+ message: message ||
89
+ (passed ? `Text contains "${substring}"` : `Text does not contain "${substring}"`),
86
90
  };
87
91
  }
88
92
  /**
@@ -91,14 +95,15 @@ class Expectation {
91
95
  */
92
96
  toContainKeywords(keywords, message) {
93
97
  const text = String(this.value).toLowerCase();
94
- const missingKeywords = keywords.filter(k => !text.includes(k.toLowerCase()));
98
+ const missingKeywords = keywords.filter((k) => !text.includes(k.toLowerCase()));
95
99
  const passed = missingKeywords.length === 0;
96
100
  return {
97
101
  name: "toContainKeywords",
98
102
  passed,
99
103
  expected: keywords,
100
104
  actual: text,
101
- message: message || (passed ? `Contains all keywords` : `Missing keywords: ${missingKeywords.join(', ')}`)
105
+ message: message ||
106
+ (passed ? `Contains all keywords` : `Missing keywords: ${missingKeywords.join(", ")}`),
102
107
  };
103
108
  }
104
109
  /**
@@ -113,7 +118,8 @@ class Expectation {
113
118
  passed,
114
119
  expected: `not containing "${substring}"`,
115
120
  actual: text,
116
- message: message || (passed ? `Text does not contain "${substring}"` : `Text contains "${substring}"`)
121
+ message: message ||
122
+ (passed ? `Text does not contain "${substring}"` : `Text contains "${substring}"`),
117
123
  };
118
124
  }
119
125
  /**
@@ -127,18 +133,18 @@ class Expectation {
127
133
  const ssnPattern = /\b\d{3}-\d{2}-\d{4}\b/;
128
134
  const foundPII = [];
129
135
  if (emailPattern.test(text))
130
- foundPII.push('email');
136
+ foundPII.push("email");
131
137
  if (phonePattern.test(text))
132
- foundPII.push('phone number');
138
+ foundPII.push("phone number");
133
139
  if (ssnPattern.test(text))
134
- foundPII.push('SSN');
140
+ foundPII.push("SSN");
135
141
  const passed = foundPII.length === 0;
136
142
  return {
137
143
  name: "toNotContainPII",
138
144
  passed,
139
145
  expected: "no PII",
140
- actual: foundPII.length > 0 ? `Found: ${foundPII.join(', ')}` : "no PII",
141
- message: message || (passed ? "No PII detected" : `PII detected: ${foundPII.join(', ')}`)
146
+ actual: foundPII.length > 0 ? `Found: ${foundPII.join(", ")}` : "no PII",
147
+ message: message || (passed ? "No PII detected" : `PII detected: ${foundPII.join(", ")}`),
142
148
  };
143
149
  }
144
150
  /**
@@ -153,7 +159,7 @@ class Expectation {
153
159
  passed,
154
160
  expected: pattern.toString(),
155
161
  actual: text,
156
- message: message || (passed ? `Matches pattern ${pattern}` : `Does not match pattern ${pattern}`)
162
+ message: message || (passed ? `Matches pattern ${pattern}` : `Does not match pattern ${pattern}`),
157
163
  };
158
164
  }
159
165
  /**
@@ -167,7 +173,7 @@ class Expectation {
167
173
  parsedJson = JSON.parse(String(this.value));
168
174
  passed = true;
169
175
  }
170
- catch (e) {
176
+ catch (_e) {
171
177
  passed = false;
172
178
  }
173
179
  return {
@@ -175,7 +181,7 @@ class Expectation {
175
181
  passed,
176
182
  expected: "valid JSON",
177
183
  actual: passed ? parsedJson : this.value,
178
- message: message || (passed ? "Valid JSON" : "Invalid JSON")
184
+ message: message || (passed ? "Valid JSON" : "Invalid JSON"),
179
185
  };
180
186
  }
181
187
  /**
@@ -189,9 +195,9 @@ class Expectation {
189
195
  parsedJson = JSON.parse(String(this.value));
190
196
  const requiredKeys = Object.keys(schema);
191
197
  const actualKeys = Object.keys(parsedJson);
192
- passed = requiredKeys.every(key => actualKeys.includes(key));
198
+ passed = requiredKeys.every((key) => actualKeys.includes(key));
193
199
  }
194
- catch (e) {
200
+ catch (_e) {
195
201
  passed = false;
196
202
  }
197
203
  return {
@@ -199,7 +205,7 @@ class Expectation {
199
205
  passed,
200
206
  expected: schema,
201
207
  actual: parsedJson,
202
- message: message || (passed ? "JSON matches schema" : "JSON does not match schema")
208
+ message: message || (passed ? "JSON matches schema" : "JSON does not match schema"),
203
209
  };
204
210
  }
205
211
  /**
@@ -208,24 +214,46 @@ class Expectation {
208
214
  */
209
215
  toHaveSentiment(expected, message) {
210
216
  const text = String(this.value).toLowerCase();
211
- const positiveWords = ['good', 'great', 'excellent', 'amazing', 'wonderful', 'fantastic', 'love', 'best', 'happy', 'helpful'];
212
- const negativeWords = ['bad', 'terrible', 'awful', 'horrible', 'worst', 'hate', 'poor', 'disappointing', 'sad', 'useless'];
213
- const positiveCount = positiveWords.filter(w => text.includes(w)).length;
214
- const negativeCount = negativeWords.filter(w => text.includes(w)).length;
217
+ const positiveWords = [
218
+ "good",
219
+ "great",
220
+ "excellent",
221
+ "amazing",
222
+ "wonderful",
223
+ "fantastic",
224
+ "love",
225
+ "best",
226
+ "happy",
227
+ "helpful",
228
+ ];
229
+ const negativeWords = [
230
+ "bad",
231
+ "terrible",
232
+ "awful",
233
+ "horrible",
234
+ "worst",
235
+ "hate",
236
+ "poor",
237
+ "disappointing",
238
+ "sad",
239
+ "useless",
240
+ ];
241
+ const positiveCount = positiveWords.filter((w) => text.includes(w)).length;
242
+ const negativeCount = negativeWords.filter((w) => text.includes(w)).length;
215
243
  let actual;
216
244
  if (positiveCount > negativeCount)
217
- actual = 'positive';
245
+ actual = "positive";
218
246
  else if (negativeCount > positiveCount)
219
- actual = 'negative';
247
+ actual = "negative";
220
248
  else
221
- actual = 'neutral';
249
+ actual = "neutral";
222
250
  const passed = actual === expected;
223
251
  return {
224
252
  name: "toHaveSentiment",
225
253
  passed,
226
254
  expected,
227
255
  actual,
228
- message: message || (passed ? `Sentiment is ${expected}` : `Expected ${expected}, got ${actual}`)
256
+ message: message || (passed ? `Sentiment is ${expected}` : `Expected ${expected}, got ${actual}`),
229
257
  };
230
258
  }
231
259
  /**
@@ -241,7 +269,7 @@ class Expectation {
241
269
  passed,
242
270
  expected: range,
243
271
  actual: length,
244
- message: message || (passed ? `Length ${length} is within range` : `Length ${length} not in range`)
272
+ message: message || (passed ? `Length ${length} is within range` : `Length ${length} not in range`),
245
273
  };
246
274
  }
247
275
  /**
@@ -250,14 +278,15 @@ class Expectation {
250
278
  */
251
279
  toNotHallucinate(groundTruth, message) {
252
280
  const text = String(this.value).toLowerCase();
253
- const missingFacts = groundTruth.filter(fact => !text.includes(fact.toLowerCase()));
281
+ const missingFacts = groundTruth.filter((fact) => !text.includes(fact.toLowerCase()));
254
282
  const passed = missingFacts.length === 0;
255
283
  return {
256
284
  name: "toNotHallucinate",
257
285
  passed,
258
286
  expected: "all ground truth facts",
259
- actual: missingFacts.length > 0 ? `Missing: ${missingFacts.join(', ')}` : "all facts present",
260
- message: message || (passed ? "No hallucinations detected" : `Missing facts: ${missingFacts.join(', ')}`)
287
+ actual: missingFacts.length > 0 ? `Missing: ${missingFacts.join(", ")}` : "all facts present",
288
+ message: message ||
289
+ (passed ? "No hallucinations detected" : `Missing facts: ${missingFacts.join(", ")}`),
261
290
  };
262
291
  }
263
292
  /**
@@ -272,7 +301,7 @@ class Expectation {
272
301
  passed,
273
302
  expected: `<= ${maxMs}ms`,
274
303
  actual: `${duration}ms`,
275
- message: message || (passed ? `${duration}ms within limit` : `${duration}ms exceeds ${maxMs}ms`)
304
+ message: message || (passed ? `${duration}ms within limit` : `${duration}ms exceeds ${maxMs}ms`),
276
305
  };
277
306
  }
278
307
  /**
@@ -286,7 +315,7 @@ class Expectation {
286
315
  passed,
287
316
  expected: "truthy value",
288
317
  actual: this.value,
289
- message: message || (passed ? "Value is truthy" : "Value is falsy")
318
+ message: message || (passed ? "Value is truthy" : "Value is falsy"),
290
319
  };
291
320
  }
292
321
  /**
@@ -294,13 +323,13 @@ class Expectation {
294
323
  * @example expect(error).toBeFalsy()
295
324
  */
296
325
  toBeFalsy(message) {
297
- const passed = !Boolean(this.value);
326
+ const passed = !this.value;
298
327
  return {
299
328
  name: "toBeFalsy",
300
329
  passed,
301
330
  expected: "falsy value",
302
331
  actual: this.value,
303
- message: message || (passed ? "Value is falsy" : "Value is truthy")
332
+ message: message || (passed ? "Value is falsy" : "Value is truthy"),
304
333
  };
305
334
  }
306
335
  /**
@@ -315,7 +344,7 @@ class Expectation {
315
344
  passed,
316
345
  expected: `> ${expected}`,
317
346
  actual: value,
318
- message: message || (passed ? `${value} > ${expected}` : `${value} <= ${expected}`)
347
+ message: message || (passed ? `${value} > ${expected}` : `${value} <= ${expected}`),
319
348
  };
320
349
  }
321
350
  /**
@@ -330,7 +359,7 @@ class Expectation {
330
359
  passed,
331
360
  expected: `< ${expected}`,
332
361
  actual: value,
333
- message: message || (passed ? `${value} < ${expected}` : `${value} >= ${expected}`)
362
+ message: message || (passed ? `${value} < ${expected}` : `${value} >= ${expected}`),
334
363
  };
335
364
  }
336
365
  /**
@@ -345,7 +374,7 @@ class Expectation {
345
374
  passed,
346
375
  expected: `between ${min} and ${max}`,
347
376
  actual: value,
348
- message: message || (passed ? `${value} is within range` : `${value} is outside range`)
377
+ message: message || (passed ? `${value} is within range` : `${value} is outside range`),
349
378
  };
350
379
  }
351
380
  /**
@@ -360,7 +389,7 @@ class Expectation {
360
389
  passed: hasCodeBlock,
361
390
  expected: "code block",
362
391
  actual: text,
363
- message: message || (hasCodeBlock ? "Contains code block" : "No code block found")
392
+ message: message || (hasCodeBlock ? "Contains code block" : "No code block found"),
364
393
  };
365
394
  }
366
395
  /**
@@ -369,15 +398,16 @@ class Expectation {
369
398
  */
370
399
  toBeProfessional(message) {
371
400
  const text = String(this.value).toLowerCase();
372
- const profanity = ['damn', 'hell', 'shit', 'fuck', 'ass', 'bitch', 'crap'];
373
- const foundProfanity = profanity.filter(word => text.includes(word));
401
+ const profanity = ["damn", "hell", "shit", "fuck", "ass", "bitch", "crap"];
402
+ const foundProfanity = profanity.filter((word) => text.includes(word));
374
403
  const passed = foundProfanity.length === 0;
375
404
  return {
376
405
  name: "toBeProfessional",
377
406
  passed,
378
407
  expected: "professional tone",
379
- actual: foundProfanity.length > 0 ? `Found: ${foundProfanity.join(', ')}` : "professional",
380
- message: message || (passed ? "Professional tone" : `Unprofessional language: ${foundProfanity.join(', ')}`)
408
+ actual: foundProfanity.length > 0 ? `Found: ${foundProfanity.join(", ")}` : "professional",
409
+ message: message ||
410
+ (passed ? "Professional tone" : `Unprofessional language: ${foundProfanity.join(", ")}`),
381
411
  };
382
412
  }
383
413
  /**
@@ -388,21 +418,21 @@ class Expectation {
388
418
  const text = String(this.value);
389
419
  const issues = [];
390
420
  // Check for double spaces
391
- if (/ +/.test(text))
392
- issues.push('double spaces');
421
+ if (/ {2,}/.test(text))
422
+ issues.push("double spaces");
393
423
  // Check for missing periods at end
394
424
  if (text.length > 10 && !/[.!?]$/.test(text.trim()))
395
- issues.push('missing ending punctuation');
425
+ issues.push("missing ending punctuation");
396
426
  // Check for lowercase sentence starts
397
427
  if (/\.\s+[a-z]/.test(text))
398
- issues.push('lowercase after period');
428
+ issues.push("lowercase after period");
399
429
  const passed = issues.length === 0;
400
430
  return {
401
431
  name: "toHaveProperGrammar",
402
432
  passed,
403
433
  expected: "proper grammar",
404
- actual: issues.length > 0 ? `Issues: ${issues.join(', ')}` : "proper grammar",
405
- message: message || (passed ? "Proper grammar" : `Grammar issues: ${issues.join(', ')}`)
434
+ actual: issues.length > 0 ? `Issues: ${issues.join(", ")}` : "proper grammar",
435
+ message: message || (passed ? "Proper grammar" : `Grammar issues: ${issues.join(", ")}`),
406
436
  };
407
437
  }
408
438
  }
@@ -447,14 +477,14 @@ function runAssertions(assertions) {
447
477
  passed: false,
448
478
  expected: null,
449
479
  actual: null,
450
- message: error instanceof Error ? error.message : "Unknown error"
480
+ message: error instanceof Error ? error.message : "Unknown error",
451
481
  };
452
482
  }
453
483
  });
454
484
  }
455
485
  // Standalone assertion functions
456
486
  function containsKeywords(text, keywords) {
457
- return keywords.every(keyword => text.toLowerCase().includes(keyword.toLowerCase()));
487
+ return keywords.every((keyword) => text.toLowerCase().includes(keyword.toLowerCase()));
458
488
  }
459
489
  function matchesPattern(text, pattern) {
460
490
  return pattern.test(text);
@@ -485,18 +515,18 @@ function notContainsPII(text) {
485
515
  /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/, // Email
486
516
  /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/, // IP address
487
517
  ];
488
- return !piiPatterns.some(pattern => pattern.test(text));
518
+ return !piiPatterns.some((pattern) => pattern.test(text));
489
519
  }
490
520
  function hasSentiment(text, expected) {
491
521
  // This is a simplified implementation
492
- const positiveWords = ['good', 'great', 'excellent', 'awesome'];
493
- const negativeWords = ['bad', 'terrible', 'awful', 'poor'];
522
+ const positiveWords = ["good", "great", "excellent", "awesome"];
523
+ const negativeWords = ["bad", "terrible", "awful", "poor"];
494
524
  const words = text.toLowerCase().split(/\s+/);
495
- const positiveCount = words.filter(word => positiveWords.includes(word)).length;
496
- const negativeCount = words.filter(word => negativeWords.includes(word)).length;
497
- if (expected === 'positive')
525
+ const positiveCount = words.filter((word) => positiveWords.includes(word)).length;
526
+ const negativeCount = words.filter((word) => negativeWords.includes(word)).length;
527
+ if (expected === "positive")
498
528
  return positiveCount > negativeCount;
499
- if (expected === 'negative')
529
+ if (expected === "negative")
500
530
  return negativeCount > positiveCount;
501
531
  return positiveCount === negativeCount; // neutral
502
532
  }
@@ -504,7 +534,7 @@ function similarTo(text1, text2, threshold = 0.8) {
504
534
  // Simple similarity check - in a real app, you'd use a proper string similarity algorithm
505
535
  const words1 = new Set(text1.toLowerCase().split(/\s+/));
506
536
  const words2 = new Set(text2.toLowerCase().split(/\s+/));
507
- const intersection = new Set([...words1].filter(word => words2.has(word)));
537
+ const intersection = new Set([...words1].filter((word) => words2.has(word)));
508
538
  const union = new Set([...words1, ...words2]);
509
539
  return intersection.size / union.size >= threshold;
510
540
  }
@@ -525,13 +555,13 @@ function isValidURL(url) {
525
555
  }
526
556
  function hasNoHallucinations(text, groundTruth) {
527
557
  // This is a simplified implementation
528
- return groundTruth.every(truth => text.includes(truth));
558
+ return groundTruth.every((truth) => text.includes(truth));
529
559
  }
530
560
  function matchesSchema(value, schema) {
531
561
  // This is a simplified implementation
532
- if (typeof value !== 'object' || value === null)
562
+ if (typeof value !== "object" || value === null)
533
563
  return false;
534
- return Object.keys(schema).every(key => key in value);
564
+ return Object.keys(schema).every((key) => key in value);
535
565
  }
536
566
  function hasReadabilityScore(text, minScore) {
537
567
  // This is a simplified implementation
@@ -545,47 +575,50 @@ function syllables(word) {
545
575
  word = word.toLowerCase();
546
576
  if (word.length <= 3)
547
577
  return 1;
548
- return word.replace(/[^aeiouy]+/g, ' ').trim().split(/\s+/).length;
578
+ return word
579
+ .replace(/[^aeiouy]+/g, " ")
580
+ .trim()
581
+ .split(/\s+/).length;
549
582
  }
550
583
  function containsLanguage(text, language) {
551
584
  // This is a simplified implementation
552
585
  // In a real app, you'd use a language detection library
553
586
  const languageKeywords = {
554
- 'en': ['the', 'and', 'you', 'that', 'was', 'for', 'are', 'with'],
555
- 'es': ['el', 'la', 'los', 'las', 'de', 'que', 'y', 'en'],
556
- 'fr': ['le', 'la', 'les', 'de', 'et', 'à', 'un', 'une'],
587
+ en: ["the", "and", "you", "that", "was", "for", "are", "with"],
588
+ es: ["el", "la", "los", "las", "de", "que", "y", "en"],
589
+ fr: ["le", "la", "les", "de", "et", "à", "un", "une"],
557
590
  };
558
591
  const keywords = languageKeywords[language.toLowerCase()] || [];
559
- return keywords.some(keyword => text.toLowerCase().includes(keyword));
592
+ return keywords.some((keyword) => text.toLowerCase().includes(keyword));
560
593
  }
561
594
  function hasFactualAccuracy(text, facts) {
562
595
  // This is a simplified implementation
563
- return facts.every(fact => text.includes(fact));
596
+ return facts.every((fact) => text.includes(fact));
564
597
  }
565
598
  function respondedWithinTime(startTime, maxMs) {
566
599
  return Date.now() - startTime <= maxMs;
567
600
  }
568
601
  function hasNoToxicity(text) {
569
602
  // This is a simplified implementation
570
- const toxicWords = ['hate', 'stupid', 'idiot', 'dumb'];
571
- return !toxicWords.some(word => text.toLowerCase().includes(word));
603
+ const toxicWords = ["hate", "stupid", "idiot", "dumb"];
604
+ return !toxicWords.some((word) => text.toLowerCase().includes(word));
572
605
  }
573
606
  function followsInstructions(text, instructions) {
574
- return instructions.every(instruction => {
575
- if (instruction.startsWith('!')) {
607
+ return instructions.every((instruction) => {
608
+ if (instruction.startsWith("!")) {
576
609
  return !text.includes(instruction.slice(1));
577
610
  }
578
611
  return text.includes(instruction);
579
612
  });
580
613
  }
581
614
  function containsAllRequiredFields(obj, requiredFields) {
582
- return requiredFields.every(field => field in obj);
615
+ return requiredFields.every((field) => field in obj);
583
616
  }
584
617
  function hasValidCodeSyntax(code, language) {
585
618
  // This is a simplified implementation
586
619
  // In a real app, you'd use a proper parser for each language
587
620
  try {
588
- if (language === 'json')
621
+ if (language === "json")
589
622
  JSON.parse(code);
590
623
  // Add more language validations as needed
591
624
  return true;
package/dist/batch.js CHANGED
@@ -57,7 +57,7 @@ class RequestBatcher {
57
57
  */
58
58
  async processBatch() {
59
59
  if (this.batchTimer) {
60
- if (typeof this.batchTimer === 'number') {
60
+ if (typeof this.batchTimer === "number") {
61
61
  clearTimeout(this.batchTimer);
62
62
  }
63
63
  else {
@@ -70,12 +70,12 @@ class RequestBatcher {
70
70
  }
71
71
  // Take items from queue
72
72
  const batch = this.queue.splice(0, this.maxBatchSize);
73
- const requests = batch.map(item => item.request);
73
+ const requests = batch.map((item) => item.request);
74
74
  try {
75
75
  const responses = await this.executeBatch(requests);
76
76
  // Match responses to requests and resolve/reject
77
77
  for (const response of responses) {
78
- const pendingRequest = batch.find(item => item.id === response.id);
78
+ const pendingRequest = batch.find((item) => item.id === response.id);
79
79
  if (pendingRequest) {
80
80
  if (response.status >= 200 && response.status < 300) {
81
81
  pendingRequest.resolve(response.data);
@@ -87,8 +87,8 @@ class RequestBatcher {
87
87
  }
88
88
  // Handle any requests that didn't get a response
89
89
  for (const item of batch) {
90
- if (!responses.find(r => r.id === item.id)) {
91
- item.reject(new Error('No response received for request'));
90
+ if (!responses.find((r) => r.id === item.id)) {
91
+ item.reject(new Error("No response received for request"));
92
92
  }
93
93
  }
94
94
  }
@@ -116,7 +116,7 @@ class RequestBatcher {
116
116
  */
117
117
  clear() {
118
118
  if (this.batchTimer) {
119
- if (typeof this.batchTimer === 'number') {
119
+ if (typeof this.batchTimer === "number") {
120
120
  clearTimeout(this.batchTimer);
121
121
  }
122
122
  else {
@@ -126,7 +126,7 @@ class RequestBatcher {
126
126
  }
127
127
  // Reject all pending requests
128
128
  for (const item of this.queue) {
129
- item.reject(new Error('Batch queue cleared'));
129
+ item.reject(new Error("Batch queue cleared"));
130
130
  }
131
131
  this.queue = [];
132
132
  }
@@ -146,16 +146,11 @@ exports.RequestBatcher = RequestBatcher;
146
146
  * Check if requests can be batched together
147
147
  */
148
148
  function canBatch(method, endpoint) {
149
- if (method !== 'GET') {
149
+ if (method !== "GET") {
150
150
  return false;
151
151
  }
152
- const batchableEndpoints = [
153
- '/traces',
154
- '/evaluations',
155
- '/annotations',
156
- '/results',
157
- ];
158
- return batchableEndpoints.some(pattern => endpoint.includes(pattern));
152
+ const batchableEndpoints = ["/traces", "/evaluations", "/annotations", "/results"];
153
+ return batchableEndpoints.some((pattern) => endpoint.includes(pattern));
159
154
  }
160
155
  /**
161
156
  * Batch multiple async operations with concurrency limit
@@ -164,13 +159,13 @@ async function batchProcess(items, processor, concurrency = 5) {
164
159
  const results = [];
165
160
  const executing = [];
166
161
  for (const item of items) {
167
- const promise = processor(item).then(result => {
162
+ const promise = processor(item).then((result) => {
168
163
  results.push(result);
169
164
  });
170
165
  executing.push(promise);
171
166
  if (executing.length >= concurrency) {
172
167
  await Promise.race(executing);
173
- executing.splice(executing.findIndex(p => p === promise), 1);
168
+ executing.splice(executing.indexOf(promise), 1);
174
169
  }
175
170
  }
176
171
  await Promise.all(executing);
package/dist/cache.js CHANGED
@@ -16,7 +16,7 @@ class RequestCache {
16
16
  * Generate cache key from request parameters
17
17
  */
18
18
  generateKey(method, url, params) {
19
- const paramString = params ? JSON.stringify(params) : '';
19
+ const paramString = params ? JSON.stringify(params) : "";
20
20
  return `${method}:${url}:${paramString}`;
21
21
  }
22
22
  /**
@@ -107,28 +107,24 @@ exports.CacheTTL = {
107
107
  * Determine if a request should be cached based on method and endpoint
108
108
  */
109
109
  function shouldCache(method, endpoint) {
110
- if (method !== 'GET') {
110
+ if (method !== "GET") {
111
111
  return false;
112
112
  }
113
- const noCacheEndpoints = [
114
- '/health',
115
- '/usage',
116
- '/deliveries',
117
- ];
118
- return !noCacheEndpoints.some(pattern => endpoint.includes(pattern));
113
+ const noCacheEndpoints = ["/health", "/usage", "/deliveries"];
114
+ return !noCacheEndpoints.some((pattern) => endpoint.includes(pattern));
119
115
  }
120
116
  /**
121
117
  * @internal - Internal SDK logic, not part of public API
122
118
  * Get appropriate TTL for an endpoint
123
119
  */
124
120
  function getTTL(endpoint) {
125
- if (endpoint.includes('/api-keys') || endpoint.includes('/webhooks')) {
121
+ if (endpoint.includes("/api-keys") || endpoint.includes("/webhooks")) {
126
122
  return exports.CacheTTL.LONG;
127
123
  }
128
- if (endpoint.includes('/evaluations') || endpoint.includes('/configs')) {
124
+ if (endpoint.includes("/evaluations") || endpoint.includes("/configs")) {
129
125
  return exports.CacheTTL.MEDIUM;
130
126
  }
131
- if (endpoint.includes('/traces') || endpoint.includes('/results')) {
127
+ if (endpoint.includes("/traces") || endpoint.includes("/results")) {
132
128
  return exports.CacheTTL.SHORT;
133
129
  }
134
130
  return exports.CacheTTL.MEDIUM;