@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
package/dist/context.d.ts CHANGED
@@ -131,4 +131,4 @@ export declare function withContextSync<T>(metadata: ContextMetadata, fn: () =>
131
131
  * }
132
132
  * ```
133
133
  */
134
- export declare function WithContext(metadata: ContextMetadata): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
134
+ export declare function WithContext(metadata: ContextMetadata): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
package/dist/context.js CHANGED
@@ -28,9 +28,7 @@ exports.withContext = withContext;
28
28
  exports.withContextSync = withContextSync;
29
29
  exports.WithContext = WithContext;
30
30
  // Detect environment
31
- const isNode = typeof process !== 'undefined' &&
32
- process.versions?.node &&
33
- typeof require !== 'undefined';
31
+ const isNode = typeof process !== "undefined" && process.versions?.node && typeof require !== "undefined";
34
32
  // Browser fallback: simple context stack
35
33
  class BrowserContextStorage {
36
34
  constructor() {
@@ -57,11 +55,11 @@ let contextStorage;
57
55
  if (isNode) {
58
56
  try {
59
57
  // Dynamic import for Node.js only
60
- const { AsyncLocalStorage } = require('async_hooks');
58
+ const { AsyncLocalStorage } = require("node:async_hooks");
61
59
  // Create without type argument due to require() being untyped
62
60
  contextStorage = new AsyncLocalStorage();
63
61
  }
64
- catch (error) {
62
+ catch (_error) {
65
63
  // Fallback if async_hooks is not available
66
64
  contextStorage = new BrowserContextStorage();
67
65
  }
@@ -205,7 +203,7 @@ function withContextSync(metadata, fn) {
205
203
  * ```
206
204
  */
207
205
  function WithContext(metadata) {
208
- return function (target, propertyKey, descriptor) {
206
+ return (_target, _propertyKey, descriptor) => {
209
207
  const originalMethod = descriptor.value;
210
208
  descriptor.value = async function (...args) {
211
209
  return withContext(metadata, () => originalMethod.apply(this, args));
package/dist/errors.d.ts CHANGED
@@ -47,6 +47,8 @@ export declare class EvalAIError extends Error {
47
47
  retryAfter?: number;
48
48
  /** When the limit resets (for feature limit errors) */
49
49
  resetAt?: Date;
50
+ /** Request ID from API (for correlation/debugging) */
51
+ requestId?: string;
50
52
  constructor(message: string, code: string, statusCode: number, details?: any);
51
53
  /**
52
54
  * Get formatted error message with solutions
package/dist/errors.js CHANGED
@@ -11,126 +11,126 @@ exports.createErrorFromResponse = createErrorFromResponse;
11
11
  */
12
12
  const ERROR_DOCS = {
13
13
  MISSING_API_KEY: {
14
- code: 'MISSING_API_KEY',
15
- message: 'API key is required to initialize the SDK',
16
- documentation: 'https://docs.ai-eval-platform.com/errors/missing-api-key',
14
+ code: "MISSING_API_KEY",
15
+ message: "API key is required to initialize the SDK",
16
+ documentation: "https://docs.ai-eval-platform.com/errors/missing-api-key",
17
17
  solutions: [
18
- 'Set EVALAI_API_KEY environment variable',
18
+ "Set EVALAI_API_KEY environment variable",
19
19
  'Pass apiKey in config: new AIEvalClient({ apiKey: "..." })',
20
- 'Get your API key from https://platform.ai-eval-platform.com/settings/api-keys'
20
+ "Get your API key from https://platform.ai-eval-platform.com/settings/api-keys",
21
21
  ],
22
- retryable: false
22
+ retryable: false,
23
23
  },
24
24
  MISSING_ORGANIZATION_ID: {
25
- code: 'MISSING_ORGANIZATION_ID',
26
- message: 'Organization ID is required for this operation',
27
- documentation: 'https://docs.ai-eval-platform.com/errors/missing-org-id',
25
+ code: "MISSING_ORGANIZATION_ID",
26
+ message: "Organization ID is required for this operation",
27
+ documentation: "https://docs.ai-eval-platform.com/errors/missing-org-id",
28
28
  solutions: [
29
- 'Set EVALAI_ORGANIZATION_ID environment variable',
30
- 'Pass organizationId in config: new AIEvalClient({ organizationId: 123 })',
31
- 'Pass organizationId in method params'
29
+ "Set EVALAI_ORGANIZATION_ID environment variable",
30
+ "Pass organizationId in config: new AIEvalClient({ organizationId: 123 })",
31
+ "Pass organizationId in method params",
32
32
  ],
33
- retryable: false
33
+ retryable: false,
34
34
  },
35
35
  RATE_LIMIT_EXCEEDED: {
36
- code: 'RATE_LIMIT_EXCEEDED',
37
- message: 'Rate limit exceeded',
38
- documentation: 'https://docs.ai-eval-platform.com/errors/rate-limit',
36
+ code: "RATE_LIMIT_EXCEEDED",
37
+ message: "Rate limit exceeded",
38
+ documentation: "https://docs.ai-eval-platform.com/errors/rate-limit",
39
39
  solutions: [
40
- 'Wait before retrying (check retryAfter property)',
41
- 'Upgrade your plan for higher rate limits',
42
- 'Implement exponential backoff in your application'
40
+ "Wait before retrying (check retryAfter property)",
41
+ "Upgrade your plan for higher rate limits",
42
+ "Implement exponential backoff in your application",
43
43
  ],
44
- retryable: true
44
+ retryable: true,
45
45
  },
46
46
  TIMEOUT: {
47
- code: 'TIMEOUT',
48
- message: 'Request timed out',
49
- documentation: 'https://docs.ai-eval-platform.com/errors/timeout',
47
+ code: "TIMEOUT",
48
+ message: "Request timed out",
49
+ documentation: "https://docs.ai-eval-platform.com/errors/timeout",
50
50
  solutions: [
51
- 'Increase timeout: new AIEvalClient({ timeout: 60000 })',
52
- 'Check your network connection',
53
- 'The service may be experiencing high load'
51
+ "Increase timeout: new AIEvalClient({ timeout: 60000 })",
52
+ "Check your network connection",
53
+ "The service may be experiencing high load",
54
54
  ],
55
- retryable: true
55
+ retryable: true,
56
56
  },
57
57
  NETWORK_ERROR: {
58
- code: 'NETWORK_ERROR',
59
- message: 'Network connectivity issue',
60
- documentation: 'https://docs.ai-eval-platform.com/errors/network',
58
+ code: "NETWORK_ERROR",
59
+ message: "Network connectivity issue",
60
+ documentation: "https://docs.ai-eval-platform.com/errors/network",
61
61
  solutions: [
62
- 'Check your internet connection',
63
- 'Verify the baseUrl is correct',
64
- 'Check if you can reach the API endpoint'
62
+ "Check your internet connection",
63
+ "Verify the baseUrl is correct",
64
+ "Check if you can reach the API endpoint",
65
65
  ],
66
- retryable: true
66
+ retryable: true,
67
67
  },
68
68
  UNAUTHORIZED: {
69
- code: 'UNAUTHORIZED',
70
- message: 'Authentication failed',
71
- documentation: 'https://docs.ai-eval-platform.com/errors/unauthorized',
69
+ code: "UNAUTHORIZED",
70
+ message: "Authentication failed",
71
+ documentation: "https://docs.ai-eval-platform.com/errors/unauthorized",
72
72
  solutions: [
73
- 'Verify your API key is correct',
74
- 'Check if your API key has expired',
75
- 'Ensure your API key has the required permissions'
73
+ "Verify your API key is correct",
74
+ "Check if your API key has expired",
75
+ "Ensure your API key has the required permissions",
76
76
  ],
77
- retryable: false
77
+ retryable: false,
78
78
  },
79
79
  FORBIDDEN: {
80
- code: 'FORBIDDEN',
81
- message: 'Access forbidden',
82
- documentation: 'https://docs.ai-eval-platform.com/errors/forbidden',
80
+ code: "FORBIDDEN",
81
+ message: "Access forbidden",
82
+ documentation: "https://docs.ai-eval-platform.com/errors/forbidden",
83
83
  solutions: [
84
- 'Check if you have permission for this resource',
85
- 'Verify you\'re using the correct organization ID',
86
- 'Contact support if you believe this is an error'
84
+ "Check if you have permission for this resource",
85
+ "Verify you're using the correct organization ID",
86
+ "Contact support if you believe this is an error",
87
87
  ],
88
- retryable: false
88
+ retryable: false,
89
89
  },
90
90
  NOT_FOUND: {
91
- code: 'NOT_FOUND',
92
- message: 'Resource not found',
93
- documentation: 'https://docs.ai-eval-platform.com/errors/not-found',
91
+ code: "NOT_FOUND",
92
+ message: "Resource not found",
93
+ documentation: "https://docs.ai-eval-platform.com/errors/not-found",
94
94
  solutions: [
95
- 'Verify the resource ID is correct',
96
- 'Check if the resource was deleted',
97
- 'Ensure you\'re querying the correct organization'
95
+ "Verify the resource ID is correct",
96
+ "Check if the resource was deleted",
97
+ "Ensure you're querying the correct organization",
98
98
  ],
99
- retryable: false
99
+ retryable: false,
100
100
  },
101
101
  VALIDATION_ERROR: {
102
- code: 'VALIDATION_ERROR',
103
- message: 'Request validation failed',
104
- documentation: 'https://docs.ai-eval-platform.com/errors/validation',
102
+ code: "VALIDATION_ERROR",
103
+ message: "Request validation failed",
104
+ documentation: "https://docs.ai-eval-platform.com/errors/validation",
105
105
  solutions: [
106
- 'Check the error details for specific validation failures',
107
- 'Verify all required fields are provided',
108
- 'Ensure field types match the expected format'
106
+ "Check the error details for specific validation failures",
107
+ "Verify all required fields are provided",
108
+ "Ensure field types match the expected format",
109
109
  ],
110
- retryable: false
110
+ retryable: false,
111
111
  },
112
112
  INTERNAL_SERVER_ERROR: {
113
- code: 'INTERNAL_SERVER_ERROR',
114
- message: 'Internal server error',
115
- documentation: 'https://docs.ai-eval-platform.com/errors/server-error',
113
+ code: "INTERNAL_SERVER_ERROR",
114
+ message: "Internal server error",
115
+ documentation: "https://docs.ai-eval-platform.com/errors/server-error",
116
116
  solutions: [
117
- 'Retry the request after a brief delay',
118
- 'Check status page: https://status.ai-eval-platform.com',
119
- 'Contact support if the issue persists'
117
+ "Retry the request after a brief delay",
118
+ "Check status page: https://status.ai-eval-platform.com",
119
+ "Contact support if the issue persists",
120
120
  ],
121
- retryable: true
121
+ retryable: true,
122
122
  },
123
123
  FEATURE_LIMIT_REACHED: {
124
- code: 'FEATURE_LIMIT_REACHED',
125
- message: 'Feature usage limit reached',
126
- documentation: 'https://docs.ai-eval-platform.com/errors/feature-limit',
124
+ code: "FEATURE_LIMIT_REACHED",
125
+ message: "Feature usage limit reached",
126
+ documentation: "https://docs.ai-eval-platform.com/errors/feature-limit",
127
127
  solutions: [
128
- 'Upgrade your plan for higher limits',
129
- 'Wait for your usage to reset (check resetAt property)',
130
- 'Optimize your usage patterns'
128
+ "Upgrade your plan for higher limits",
129
+ "Wait for your usage to reset (check resetAt property)",
130
+ "Optimize your usage patterns",
131
131
  ],
132
- retryable: false
133
- }
132
+ retryable: false,
133
+ },
134
134
  };
135
135
  /**
136
136
  * Enhanced SDK Error class with rich error information and documentation
@@ -156,7 +156,7 @@ const ERROR_DOCS = {
156
156
  class EvalAIError extends Error {
157
157
  constructor(message, code, statusCode, details) {
158
158
  super(message);
159
- this.name = 'EvalAIError';
159
+ this.name = "EvalAIError";
160
160
  this.code = code;
161
161
  this.statusCode = statusCode;
162
162
  this.details = details;
@@ -168,18 +168,19 @@ class EvalAIError extends Error {
168
168
  this.retryable = errorDoc.retryable;
169
169
  }
170
170
  else {
171
- this.documentation = 'https://docs.ai-eval-platform.com/errors';
172
- this.solutions = ['Check the API documentation for more information'];
171
+ this.documentation = "https://docs.ai-eval-platform.com/errors";
172
+ this.solutions = ["Check the API documentation for more information"];
173
173
  this.retryable = false;
174
174
  }
175
175
  // Extract retry-after for rate limits
176
- if (code === 'RATE_LIMIT_EXCEEDED' && details?.retryAfter) {
176
+ if (code === "RATE_LIMIT_EXCEEDED" && details?.retryAfter) {
177
177
  this.retryAfter = details.retryAfter;
178
178
  }
179
179
  // Extract reset time for feature limits
180
- if (code === 'FEATURE_LIMIT_REACHED' && details?.resetAt) {
180
+ if (code === "FEATURE_LIMIT_REACHED" && details?.resetAt) {
181
181
  this.resetAt = new Date(details.resetAt);
182
182
  }
183
+ this.requestId = details?.error?.requestId ?? details?.requestId;
183
184
  // Ensure proper prototype chain
184
185
  Object.setPrototypeOf(this, EvalAIError.prototype);
185
186
  }
@@ -189,7 +190,7 @@ class EvalAIError extends Error {
189
190
  getDetailedMessage() {
190
191
  let msg = `${this.code}: ${this.message}\n\n`;
191
192
  msg += `Documentation: ${this.documentation}\n\n`;
192
- msg += 'Suggested solutions:\n';
193
+ msg += "Suggested solutions:\n";
193
194
  this.solutions.forEach((solution, i) => {
194
195
  msg += ` ${i + 1}. ${solution}\n`;
195
196
  });
@@ -221,7 +222,8 @@ class EvalAIError extends Error {
221
222
  retryable: this.retryable,
222
223
  retryAfter: this.retryAfter,
223
224
  resetAt: this.resetAt,
224
- details: this.details
225
+ requestId: this.requestId,
226
+ details: this.details,
225
227
  };
226
228
  }
227
229
  }
@@ -232,53 +234,60 @@ exports.SDKError = EvalAIError;
232
234
  */
233
235
  function createErrorFromResponse(response, data) {
234
236
  const status = response.status;
235
- let code = data?.code || 'UNKNOWN_ERROR';
236
- let message = data?.error || data?.message || response.statusText;
237
- // Map HTTP status to error codes
238
- if (!data?.code) {
237
+ const errObj = data?.error && typeof data.error === "object" ? data.error : data;
238
+ let code = errObj?.code ?? data?.code ?? "UNKNOWN_ERROR";
239
+ const message = typeof data?.error === "string"
240
+ ? data.error
241
+ : (errObj?.message ?? data?.message ?? response.statusText);
242
+ const requestId = errObj?.requestId ?? data?.requestId ?? response.headers.get("x-request-id") ?? undefined;
243
+ // Map HTTP status to error codes when code not in response
244
+ if (!errObj?.code && !data?.code) {
239
245
  if (status === 401)
240
- code = 'UNAUTHORIZED';
246
+ code = "UNAUTHORIZED";
241
247
  else if (status === 403)
242
- code = 'FORBIDDEN';
248
+ code = "FORBIDDEN";
243
249
  else if (status === 404)
244
- code = 'NOT_FOUND';
250
+ code = "NOT_FOUND";
245
251
  else if (status === 408)
246
- code = 'TIMEOUT';
252
+ code = "TIMEOUT";
247
253
  else if (status === 422)
248
- code = 'VALIDATION_ERROR';
254
+ code = "VALIDATION_ERROR";
249
255
  else if (status === 429)
250
- code = 'RATE_LIMIT_EXCEEDED';
256
+ code = "RATE_LIMIT_EXCEEDED";
251
257
  else if (status >= 500)
252
- code = 'INTERNAL_SERVER_ERROR';
258
+ code = "INTERNAL_SERVER_ERROR";
253
259
  }
254
- return new EvalAIError(message, code, status, data);
260
+ const err = new EvalAIError(message, code, status, data);
261
+ if (requestId)
262
+ err.requestId = requestId;
263
+ return err;
255
264
  }
256
265
  // Specific error types
257
266
  class RateLimitError extends EvalAIError {
258
267
  constructor(message, retryAfter) {
259
- super(message, 'RATE_LIMIT_EXCEEDED', 429, { retryAfter });
260
- this.name = 'RateLimitError';
268
+ super(message, "RATE_LIMIT_EXCEEDED", 429, { retryAfter });
269
+ this.name = "RateLimitError";
261
270
  }
262
271
  }
263
272
  exports.RateLimitError = RateLimitError;
264
273
  class AuthenticationError extends EvalAIError {
265
- constructor(message = 'Authentication failed') {
266
- super(message, 'AUTHENTICATION_ERROR', 401);
267
- this.name = 'AuthenticationError';
274
+ constructor(message = "Authentication failed") {
275
+ super(message, "AUTHENTICATION_ERROR", 401);
276
+ this.name = "AuthenticationError";
268
277
  }
269
278
  }
270
279
  exports.AuthenticationError = AuthenticationError;
271
280
  class ValidationError extends EvalAIError {
272
- constructor(message = 'Validation failed', details) {
273
- super(message, 'VALIDATION_ERROR', 400, details);
274
- this.name = 'ValidationError';
281
+ constructor(message = "Validation failed", details) {
282
+ super(message, "VALIDATION_ERROR", 400, details);
283
+ this.name = "ValidationError";
275
284
  }
276
285
  }
277
286
  exports.ValidationError = ValidationError;
278
287
  class NetworkError extends EvalAIError {
279
- constructor(message = 'Network request failed') {
280
- super(message, 'NETWORK_ERROR', 0);
281
- this.name = 'NetworkError';
288
+ constructor(message = "Network request failed") {
289
+ super(message, "NETWORK_ERROR", 0);
290
+ this.name = "NetworkError";
282
291
  this.retryable = true;
283
292
  }
284
293
  }
package/dist/export.d.ts CHANGED
@@ -20,13 +20,13 @@
20
20
  * await importFromLangSmith(client, langsmithData);
21
21
  * ```
22
22
  */
23
- import type { AIEvalClient } from './client';
24
- import type { Trace, Evaluation, TestCase, EvaluationRun } from './types';
25
- export type ExportFormat = 'json' | 'csv' | 'jsonl';
23
+ import type { AIEvalClient } from "./client";
24
+ import type { Evaluation, EvaluationRun, TestCase, Trace } from "./types";
25
+ export type ExportFormat = "json" | "csv" | "jsonl";
26
26
  export type { ExportFormat as ExportType };
27
27
  export interface ExportOptions {
28
28
  /** Export format */
29
- format: 'json' | 'csv' | 'jsonl';
29
+ format: "json" | "csv" | "jsonl";
30
30
  /** Include traces */
31
31
  includeTraces?: boolean;
32
32
  /** Include evaluations */
@@ -152,7 +152,7 @@ export declare function importData(client: AIEvalClient, data: ExportData, optio
152
152
  * });
153
153
  * ```
154
154
  */
155
- export declare function exportToFile(client: AIEvalClient, filePath: string, options: Omit<ExportOptions, 'format'>): Promise<void>;
155
+ export declare function exportToFile(client: AIEvalClient, filePath: string, options: Omit<ExportOptions, "format">): Promise<void>;
156
156
  /**
157
157
  * Import data from JSON file
158
158
  *
@@ -192,4 +192,4 @@ export declare function importFromLangSmith(client: AIEvalClient, langsmithData:
192
192
  * fs.writeFileSync('traces.csv', csv);
193
193
  * ```
194
194
  */
195
- export declare function convertToCSV(data: ExportData, type: 'traces' | 'evaluations'): string;
195
+ export declare function convertToCSV(data: ExportData, type: "traces" | "evaluations"): string;
package/dist/export.js CHANGED
@@ -81,16 +81,16 @@ async function exportData(client, options) {
81
81
  const exportData = {
82
82
  metadata: {
83
83
  exportedAt: new Date().toISOString(),
84
- version: '1.0.0',
84
+ version: "1.0.0",
85
85
  format: options.format,
86
- organizationId: options.organizationId
87
- }
86
+ organizationId: options.organizationId,
87
+ },
88
88
  };
89
89
  // Export traces
90
90
  if (options.includeTraces) {
91
91
  const traces = await client.traces.list({
92
92
  organizationId: options.organizationId,
93
- limit: options.limit
93
+ limit: options.limit,
94
94
  });
95
95
  exportData.traces = traces;
96
96
  }
@@ -98,7 +98,7 @@ async function exportData(client, options) {
98
98
  if (options.includeEvaluations) {
99
99
  const evaluations = await client.evaluations.list({
100
100
  organizationId: options.organizationId,
101
- limit: options.limit
101
+ limit: options.limit,
102
102
  });
103
103
  exportData.evaluations = evaluations;
104
104
  // Export test cases for each evaluation
@@ -140,7 +140,7 @@ async function importData(client, data, options) {
140
140
  const result = {
141
141
  summary: { total: 0, imported: 0, skipped: 0, failed: 0 },
142
142
  details: {},
143
- errors: []
143
+ errors: [],
144
144
  };
145
145
  if (options.dryRun) {
146
146
  // Count what would be imported
@@ -165,13 +165,15 @@ async function importData(client, data, options) {
165
165
  organizationId: options.organizationId || trace.organizationId,
166
166
  status: trace.status,
167
167
  durationMs: trace.durationMs || undefined,
168
- metadata: trace.metadata || undefined
168
+ metadata: trace.metadata || undefined,
169
169
  });
170
170
  traceResults.imported++;
171
171
  result.summary.imported++;
172
172
  }
173
173
  catch (error) {
174
- if (options.skipDuplicates && error instanceof Error && error.message.includes('already exists')) {
174
+ if (options.skipDuplicates &&
175
+ error instanceof Error &&
176
+ error.message.includes("already exists")) {
175
177
  traceResults.skipped++;
176
178
  result.summary.skipped++;
177
179
  }
@@ -180,7 +182,7 @@ async function importData(client, data, options) {
180
182
  result.summary.failed++;
181
183
  result.errors?.push({
182
184
  item: `trace:${trace.traceId}`,
183
- error: error instanceof Error ? error.message : String(error)
185
+ error: error instanceof Error ? error.message : String(error),
184
186
  });
185
187
  }
186
188
  }
@@ -194,7 +196,7 @@ async function importData(client, data, options) {
194
196
  for (const evaluation of data.evaluations) {
195
197
  try {
196
198
  if (!options.createdBy) {
197
- throw new Error('createdBy is required for importing evaluations');
199
+ throw new Error("createdBy is required for importing evaluations");
198
200
  }
199
201
  await client.evaluations.create({
200
202
  name: evaluation.name,
@@ -202,13 +204,15 @@ async function importData(client, data, options) {
202
204
  type: evaluation.type,
203
205
  organizationId: options.organizationId || evaluation.organizationId,
204
206
  createdBy: options.createdBy,
205
- status: evaluation.status
207
+ status: evaluation.status,
206
208
  });
207
209
  evalResults.imported++;
208
210
  result.summary.imported++;
209
211
  }
210
212
  catch (error) {
211
- if (options.skipDuplicates && error instanceof Error && error.message.includes('already exists')) {
213
+ if (options.skipDuplicates &&
214
+ error instanceof Error &&
215
+ error.message.includes("already exists")) {
212
216
  evalResults.skipped++;
213
217
  result.summary.skipped++;
214
218
  }
@@ -217,7 +221,7 @@ async function importData(client, data, options) {
217
221
  result.summary.failed++;
218
222
  result.errors?.push({
219
223
  item: `evaluation:${evaluation.name}`,
220
- error: error instanceof Error ? error.message : String(error)
224
+ error: error instanceof Error ? error.message : String(error),
221
225
  });
222
226
  }
223
227
  }
@@ -239,8 +243,8 @@ async function importData(client, data, options) {
239
243
  * ```
240
244
  */
241
245
  async function exportToFile(client, filePath, options) {
242
- const data = await exportData(client, { ...options, format: 'json' });
243
- const fs = await Promise.resolve().then(() => __importStar(require('fs')));
246
+ const data = await exportData(client, { ...options, format: "json" });
247
+ const fs = await Promise.resolve().then(() => __importStar(require("node:fs")));
244
248
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
245
249
  }
246
250
  /**
@@ -255,8 +259,8 @@ async function exportToFile(client, filePath, options) {
255
259
  * ```
256
260
  */
257
261
  async function importFromFile(client, filePath, options) {
258
- const fs = await Promise.resolve().then(() => __importStar(require('fs')));
259
- const content = fs.readFileSync(filePath, 'utf-8');
262
+ const fs = await Promise.resolve().then(() => __importStar(require("node:fs")));
263
+ const content = fs.readFileSync(filePath, "utf-8");
260
264
  const data = JSON.parse(content);
261
265
  return importData(client, data, options);
262
266
  }
@@ -281,27 +285,27 @@ async function importFromLangSmith(client, langsmithData, options) {
281
285
  const transformedData = {
282
286
  metadata: {
283
287
  exportedAt: new Date().toISOString(),
284
- version: '1.0.0',
285
- format: 'json',
286
- organizationId: options.organizationId
288
+ version: "1.0.0",
289
+ format: "json",
290
+ organizationId: options.organizationId,
287
291
  },
288
- traces: []
292
+ traces: [],
289
293
  };
290
294
  // Transform runs to traces
291
295
  if (langsmithData.runs && Array.isArray(langsmithData.runs)) {
292
296
  transformedData.traces = langsmithData.runs.map((run) => ({
293
- name: run.name || 'Imported Trace',
297
+ name: run.name || "Imported Trace",
294
298
  traceId: run.id || `langsmith-${Date.now()}-${Math.random()}`,
295
299
  organizationId: options.organizationId,
296
- status: run.error ? 'error' : 'success',
300
+ status: run.error ? "error" : "success",
297
301
  durationMs: run.execution_time ? Math.round(run.execution_time * 1000) : null,
298
302
  metadata: {
299
- source: 'langsmith',
303
+ source: "langsmith",
300
304
  original_id: run.id,
301
305
  inputs: run.inputs,
302
- outputs: run.outputs
306
+ outputs: run.outputs,
303
307
  },
304
- createdAt: run.start_time || new Date().toISOString()
308
+ createdAt: run.start_time || new Date().toISOString(),
305
309
  }));
306
310
  }
307
311
  return importData(client, transformedData, options);
@@ -317,18 +321,20 @@ async function importFromLangSmith(client, langsmithData, options) {
317
321
  * ```
318
322
  */
319
323
  function convertToCSV(data, type) {
320
- const items = type === 'traces' ? data.traces : data.evaluations;
324
+ const items = type === "traces" ? data.traces : data.evaluations;
321
325
  if (!items || items.length === 0)
322
- return '';
326
+ return "";
323
327
  // Get headers from first item
324
328
  const headers = Object.keys(items[0]);
325
- const rows = items.map(item => headers.map(h => {
329
+ const rows = items.map((item) => headers
330
+ .map((h) => {
326
331
  const value = item[h];
327
332
  if (value === null || value === undefined)
328
- return '';
329
- if (typeof value === 'object')
333
+ return "";
334
+ if (typeof value === "object")
330
335
  return JSON.stringify(value);
331
336
  return String(value);
332
- }).join(','));
333
- return [headers.join(','), ...rows].join('\n');
337
+ })
338
+ .join(","));
339
+ return [headers.join(","), ...rows].join("\n");
334
340
  }