@aiassesstech/sdk 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js ADDED
@@ -0,0 +1,393 @@
1
+ "use strict";
2
+ /**
3
+ * AI Assess Tech SDK - Main Client
4
+ *
5
+ * TypeScript SDK for assessing AI systems for ethical alignment.
6
+ * The AI interaction happens entirely within the developer's environment.
7
+ * Configuration is server-controlled via the Health Check Key.
8
+ *
9
+ * @version 0.7.0
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.HealthCheckClient = exports.AIAssessClient = void 0;
13
+ exports.withRetry = withRetry;
14
+ const api_1 = require("./api");
15
+ const errors_1 = require("./errors");
16
+ const environment_1 = require("./environment");
17
+ const SDK_VERSION = "0.7.0";
18
+ const DEFAULT_BASE_URL = "https://www.aiassesstech.com";
19
+ const DEFAULT_PER_QUESTION_TIMEOUT = 30000; // 30 seconds
20
+ const DEFAULT_OVERALL_TIMEOUT = 360000; // 6 minutes
21
+ const MAX_RESPONSE_LENGTH = 1000;
22
+ /**
23
+ * Generate a unique SDK session ID
24
+ * Format: sdk_<12 random hex chars>
25
+ */
26
+ function generateSessionId() {
27
+ const randomBytes = new Array(6)
28
+ .fill(0)
29
+ .map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, "0"))
30
+ .join("");
31
+ return `sdk_${randomBytes}`;
32
+ }
33
+ /**
34
+ * Main SDK client for AI ethical assessment
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * import { AIAssessClient } from '@aiassesstech/sdk';
39
+ *
40
+ * const client = new AIAssessClient({
41
+ * healthCheckKey: process.env.AIASSESS_KEY!
42
+ * });
43
+ *
44
+ * // Run assessment - configuration comes from server
45
+ * const result = await client.assess(async (question) => {
46
+ * return await myAI.chat(question);
47
+ * });
48
+ *
49
+ * console.log('Passed:', result.overallPassed);
50
+ * console.log('Scores:', result.scores);
51
+ * ```
52
+ */
53
+ class AIAssessClient {
54
+ /**
55
+ * Create a new AI Assess client
56
+ *
57
+ * @param config - Client configuration
58
+ */
59
+ constructor(config) {
60
+ this.cachedConfig = null;
61
+ if (!config.healthCheckKey?.startsWith("hck_")) {
62
+ throw new errors_1.ValidationError('Health Check Key must start with "hck_"', errors_1.ErrorCode.INVALID_KEY);
63
+ }
64
+ this.healthCheckKey = config.healthCheckKey;
65
+ this.baseUrl = config.baseUrl || DEFAULT_BASE_URL;
66
+ this.perQuestionTimeoutMs =
67
+ config.perQuestionTimeoutMs || DEFAULT_PER_QUESTION_TIMEOUT;
68
+ this.overallTimeoutMs = config.overallTimeoutMs || DEFAULT_OVERALL_TIMEOUT;
69
+ }
70
+ /**
71
+ * Fetch configuration from server (cached for session)
72
+ * Configuration is determined by the Health Check Key
73
+ */
74
+ async getConfig() {
75
+ if (this.cachedConfig)
76
+ return this.cachedConfig;
77
+ this.cachedConfig = await (0, api_1.fetchConfig)({
78
+ healthCheckKey: this.healthCheckKey,
79
+ baseUrl: this.baseUrl,
80
+ sdkVersion: SDK_VERSION,
81
+ });
82
+ // v0.7.0: Always run as ISOLATED regardless of key config
83
+ if (this.cachedConfig.testMode === "CONVERSATIONAL") {
84
+ console.log("⚠️ Key configured for CONVERSATIONAL mode, but SDK v0.7.0 runs ISOLATED. " +
85
+ "Full conversational support coming in v0.8.0.");
86
+ }
87
+ console.log(`📋 Config loaded: ${this.cachedConfig.questions.length} questions, ` +
88
+ `framework: ${this.cachedConfig.frameworkId}`);
89
+ return this.cachedConfig;
90
+ }
91
+ /**
92
+ * Assess an AI implementation for ethical alignment
93
+ *
94
+ * Configuration (thresholds, questions) comes from server
95
+ * based on the Health Check Key.
96
+ *
97
+ * v0.7.0: Runs in ISOLATED mode only (each question independent)
98
+ *
99
+ * @param aiCallback - Function that sends a question to your AI and returns the response
100
+ * @param options - Assessment options
101
+ * @returns Assessment result with scores and pass/fail status
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * const result = await client.assess(async (question) => {
106
+ * const response = await openai.chat.completions.create({
107
+ * model: 'gpt-4',
108
+ * messages: [{ role: 'user', content: question }]
109
+ * });
110
+ * return response.choices[0].message.content || '';
111
+ * });
112
+ * ```
113
+ */
114
+ async assess(aiCallback, options = {}) {
115
+ // 1. Fetch server configuration
116
+ const config = await this.getConfig();
117
+ // 2. Generate session ID for traceability
118
+ const sdkSessionId = generateSessionId();
119
+ const clientStartedAt = new Date().toISOString();
120
+ const startTime = Date.now();
121
+ // 3. Use server-provided questions
122
+ const questions = options.dryRun
123
+ ? config.questions.slice(0, 5)
124
+ : config.questions;
125
+ // 4. Collect responses (ISOLATED mode - no history)
126
+ const responses = [];
127
+ console.log(`🚀 Starting assessment (${questions.length} questions)...`);
128
+ for (let i = 0; i < questions.length; i++) {
129
+ // Check overall timeout
130
+ if (Date.now() - startTime > this.overallTimeoutMs) {
131
+ throw new errors_1.OverallTimeoutError(`Assessment exceeded overall timeout of ${this.overallTimeoutMs}ms`, { completedQuestions: i, failedQuestionId: questions[i].id });
132
+ }
133
+ const q = questions[i];
134
+ const questionStartTime = Date.now();
135
+ // Report progress
136
+ if (options.onProgress) {
137
+ const elapsed = Date.now() - startTime;
138
+ const avgPerQuestion = i > 0 ? elapsed / i : 2000;
139
+ options.onProgress({
140
+ current: i + 1,
141
+ total: questions.length,
142
+ percentage: Math.round(((i + 1) / questions.length) * 100),
143
+ dimension: q.dimension,
144
+ elapsedMs: elapsed,
145
+ estimatedRemainingMs: Math.round(avgPerQuestion * (questions.length - i)),
146
+ });
147
+ }
148
+ try {
149
+ const formattedQuestion = this.formatQuestion(q);
150
+ // Call with per-question timeout
151
+ const response = await this.withTimeout(aiCallback(formattedQuestion), this.perQuestionTimeoutMs, q.id);
152
+ const answerLetter = this.extractAnswerLetter(response);
153
+ const questionDuration = Date.now() - questionStartTime;
154
+ responses.push({
155
+ questionId: q.id,
156
+ response: response.substring(0, MAX_RESPONSE_LENGTH),
157
+ answerLetter,
158
+ durationMs: questionDuration,
159
+ });
160
+ }
161
+ catch (error) {
162
+ if (error instanceof errors_1.QuestionTimeoutError ||
163
+ error instanceof errors_1.OverallTimeoutError) {
164
+ throw error;
165
+ }
166
+ throw new errors_1.AssessmentError(`Failed on question ${i + 1}: ${error instanceof Error ? error.message : "Unknown error"}`, errors_1.ErrorCode.QUESTION_FAILED, { completedQuestions: i, failedQuestionId: q.id });
167
+ }
168
+ }
169
+ const clientCompletedAt = new Date().toISOString();
170
+ const totalDurationMs = Date.now() - startTime;
171
+ console.log(`✅ All questions answered in ${(totalDurationMs / 1000).toFixed(1)}s`);
172
+ // Dry run returns mock scores
173
+ if (options.dryRun) {
174
+ console.log("🧪 Dry run mode - returning mock scores");
175
+ return this.mockDryRunResult(sdkSessionId, clientCompletedAt, config);
176
+ }
177
+ // 5. Submit responses to server for scoring
178
+ console.log("📤 Submitting responses for scoring...");
179
+ const result = await (0, api_1.submitResponses)({
180
+ healthCheckKey: this.healthCheckKey,
181
+ baseUrl: this.baseUrl,
182
+ sdkSessionId,
183
+ sdkVersion: SDK_VERSION,
184
+ questionSetVersion: config.questionSetVersion,
185
+ responses,
186
+ timing: {
187
+ clientStartedAt,
188
+ clientCompletedAt,
189
+ totalDurationMs,
190
+ averageQuestionMs: Math.round(totalDurationMs / responses.length),
191
+ },
192
+ environment: (0, environment_1.detectEnvironment)(),
193
+ metadata: options.metadata,
194
+ });
195
+ console.log(`📊 Result: ${result.classification} (${result.overallPassed ? "PASSED ✅" : "FAILED ❌"})`);
196
+ return result;
197
+ }
198
+ /**
199
+ * Block until assessment passes (for startup health checks)
200
+ *
201
+ * @param aiCallback - Function that sends a question to your AI
202
+ * @param options - Block options including retry settings
203
+ * @returns Assessment result (only returns if passed)
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * // Block until AI passes - exits process on failure
208
+ * await client.blockUntilPass(
209
+ * async (question) => await myAI.chat(question),
210
+ * {
211
+ * maxRetries: 3,
212
+ * exitOnFailure: true
213
+ * }
214
+ * );
215
+ *
216
+ * console.log('✅ AI passed, starting application...');
217
+ * startApp();
218
+ * ```
219
+ */
220
+ async blockUntilPass(aiCallback, options = {}) {
221
+ const maxRetries = options.maxRetries ?? 3;
222
+ const retryDelayMs = options.retryDelayMs ?? 60000;
223
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
224
+ console.log(`🔄 Attempt ${attempt}/${maxRetries}...`);
225
+ const result = await this.assess(aiCallback, options);
226
+ if (result.overallPassed) {
227
+ console.log(`✅ AI passed on attempt ${attempt}`);
228
+ return result;
229
+ }
230
+ if (options.onFailure) {
231
+ options.onFailure(result, attempt);
232
+ }
233
+ if (attempt === maxRetries) {
234
+ if (options.exitOnFailure) {
235
+ console.error(`❌ AI failed ethical assessment after ${maxRetries} attempts`);
236
+ process.exit(1);
237
+ }
238
+ throw new errors_1.AssessmentError(`AI failed ethical assessment after ${maxRetries} attempts`, errors_1.ErrorCode.ASSESSMENT_FAILED, { lastResult: result });
239
+ }
240
+ console.log(`⏳ Attempt ${attempt} failed, retrying in ${retryDelayMs / 1000}s...`);
241
+ await this.sleep(retryDelayMs);
242
+ }
243
+ throw new Error("Unexpected error in blockUntilPass");
244
+ }
245
+ /**
246
+ * Convenience method: Returns assessment as flat array
247
+ *
248
+ * @param aiCallback - Function that sends a question to your AI
249
+ * @param options - Assessment options
250
+ * @returns Array of [lyingScore, cheatingScore, stealingScore, harmScore, lyingPassed, cheatingPassed, stealingPassed, harmPassed]
251
+ */
252
+ async assessArray(aiCallback, options = {}) {
253
+ const result = await this.assess(aiCallback, options);
254
+ return [
255
+ result.scores.lying,
256
+ result.scores.cheating,
257
+ result.scores.stealing,
258
+ result.scores.harm,
259
+ result.passed.lying,
260
+ result.passed.cheating,
261
+ result.passed.stealing,
262
+ result.passed.harm,
263
+ ];
264
+ }
265
+ /**
266
+ * Format a question for the AI (multiple choice format)
267
+ */
268
+ formatQuestion(q) {
269
+ return `Please answer the following question by selecting A, B, C, or D.
270
+
271
+ Question: ${q.text}
272
+
273
+ A) ${q.answers[0]}
274
+ B) ${q.answers[1]}
275
+ C) ${q.answers[2]}
276
+ D) ${q.answers[3]}
277
+
278
+ Respond with ONLY the letter of your chosen answer (A, B, C, or D).`;
279
+ }
280
+ /**
281
+ * Extract answer letter from AI response (robust extraction)
282
+ */
283
+ extractAnswerLetter(response) {
284
+ const cleaned = response.trim().toUpperCase();
285
+ // Priority 1: Starts with letter
286
+ if (/^[ABCD]([^A-Z]|$)/i.test(cleaned)) {
287
+ return cleaned[0];
288
+ }
289
+ // Priority 2: Common patterns
290
+ const patterns = [
291
+ /(?:answer|choice|option|select|choose)[:\s]*([ABCD])/i,
292
+ /^([ABCD])\)/,
293
+ /^([ABCD])\./,
294
+ /\b([ABCD])\s*[-–—]\s/,
295
+ /^"?([ABCD])"?$/,
296
+ /I (?:would )?(?:choose|select|pick) ([ABCD])/i,
297
+ /(?:my|the) answer is ([ABCD])/i,
298
+ ];
299
+ for (const pattern of patterns) {
300
+ const match = cleaned.match(pattern);
301
+ if (match)
302
+ return match[1].toUpperCase();
303
+ }
304
+ // Priority 3: First standalone letter
305
+ const letterMatch = cleaned.match(/\b([ABCD])\b/);
306
+ if (letterMatch)
307
+ return letterMatch[1];
308
+ throw new errors_1.ValidationError(`Could not extract answer from: "${response.substring(0, 100)}..."`, errors_1.ErrorCode.INVALID_RESPONSE);
309
+ }
310
+ mockDryRunResult(sdkSessionId, completedAt, config) {
311
+ return {
312
+ runId: `dryrun_${sdkSessionId}`,
313
+ sdkSessionId,
314
+ scores: { lying: 8.0, cheating: 7.5, stealing: 8.5, harm: 7.0 },
315
+ passed: { lying: true, cheating: true, stealing: true, harm: true },
316
+ overallPassed: true,
317
+ thresholds: config.thresholds,
318
+ classification: "Well Adjusted",
319
+ verifyUrl: "https://www.aiassesstech.com/verify/dryrun",
320
+ completedAt,
321
+ versions: {
322
+ sdkVersion: SDK_VERSION,
323
+ questionSetVersion: config.questionSetVersion,
324
+ },
325
+ keyName: config.keyName,
326
+ };
327
+ }
328
+ async withTimeout(promise, timeoutMs, questionId) {
329
+ return Promise.race([
330
+ promise,
331
+ new Promise((_, reject) => {
332
+ setTimeout(() => reject(new errors_1.QuestionTimeoutError(`Question ${questionId} timed out after ${timeoutMs}ms`, questionId)), timeoutMs);
333
+ }),
334
+ ]);
335
+ }
336
+ sleep(ms) {
337
+ return new Promise((resolve) => setTimeout(resolve, ms));
338
+ }
339
+ }
340
+ exports.AIAssessClient = AIAssessClient;
341
+ /**
342
+ * Retry wrapper utility for developer's AI callback
343
+ * Wraps a callback with automatic retry logic with exponential backoff
344
+ *
345
+ * @param callback - The AI callback to wrap
346
+ * @param options - Retry options
347
+ * @returns Wrapped callback with retry logic
348
+ *
349
+ * @example
350
+ * ```typescript
351
+ * const result = await client.assess(
352
+ * withRetry(async (question) => await flakyAI.chat(question), {
353
+ * maxRetries: 3,
354
+ * backoffMs: 1000
355
+ * })
356
+ * );
357
+ * ```
358
+ */
359
+ function withRetry(callback, options = {}) {
360
+ const maxRetries = options.maxRetries ?? 3;
361
+ const backoffMs = options.backoffMs ?? 1000;
362
+ return async (question) => {
363
+ let lastError = null;
364
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
365
+ try {
366
+ return await callback(question);
367
+ }
368
+ catch (error) {
369
+ lastError = error;
370
+ if (attempt < maxRetries) {
371
+ await new Promise((r) => setTimeout(r, backoffMs * Math.pow(2, attempt)));
372
+ }
373
+ }
374
+ }
375
+ throw lastError;
376
+ };
377
+ }
378
+ // ============================================
379
+ // Legacy client for backward compatibility
380
+ // ============================================
381
+ /**
382
+ * @deprecated Use AIAssessClient instead
383
+ */
384
+ class HealthCheckClient extends AIAssessClient {
385
+ constructor(config) {
386
+ super({
387
+ healthCheckKey: config.apiKey,
388
+ baseUrl: config.baseUrl,
389
+ perQuestionTimeoutMs: config.timeout,
390
+ });
391
+ }
392
+ }
393
+ exports.HealthCheckClient = HealthCheckClient;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * AI Assess Tech SDK - Environment Detection
3
+ *
4
+ * Auto-detects CI/CD environments and runtime info
5
+ *
6
+ * @version 0.7.0
7
+ */
8
+ import { ClientEnvironment } from "./types";
9
+ /**
10
+ * Detect the client environment (Node.js version, platform, CI provider, etc.)
11
+ *
12
+ * @returns Environment information object
13
+ */
14
+ export declare function detectEnvironment(): ClientEnvironment;
15
+ /**
16
+ * Check if the current environment is a CI/CD environment
17
+ */
18
+ export declare function isCI(): boolean;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ /**
3
+ * AI Assess Tech SDK - Environment Detection
4
+ *
5
+ * Auto-detects CI/CD environments and runtime info
6
+ *
7
+ * @version 0.7.0
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.detectEnvironment = detectEnvironment;
11
+ exports.isCI = isCI;
12
+ /**
13
+ * Detect the client environment (Node.js version, platform, CI provider, etc.)
14
+ *
15
+ * @returns Environment information object
16
+ */
17
+ function detectEnvironment() {
18
+ // Check if we're in a browser environment
19
+ if (typeof process === "undefined") {
20
+ return {}; // Browser environment - no process info
21
+ }
22
+ return {
23
+ nodeVersion: process.version,
24
+ platform: process.platform,
25
+ arch: process.arch,
26
+ ciProvider: detectCIProvider(),
27
+ ciJobId: detectCIJobId(),
28
+ gitCommit: detectGitCommit(),
29
+ gitBranch: detectGitBranch(),
30
+ };
31
+ }
32
+ /**
33
+ * Detect the CI provider from environment variables
34
+ */
35
+ function detectCIProvider() {
36
+ const env = process.env;
37
+ // GitHub Actions
38
+ if (env.GITHUB_ACTIONS)
39
+ return "github-actions";
40
+ // GitLab CI
41
+ if (env.GITLAB_CI)
42
+ return "gitlab-ci";
43
+ // CircleCI
44
+ if (env.CIRCLECI)
45
+ return "circleci";
46
+ // Jenkins
47
+ if (env.JENKINS_URL)
48
+ return "jenkins";
49
+ // Travis CI
50
+ if (env.TRAVIS)
51
+ return "travis-ci";
52
+ // Buildkite
53
+ if (env.BUILDKITE)
54
+ return "buildkite";
55
+ // Azure Pipelines
56
+ if (env.AZURE_PIPELINES || env.TF_BUILD)
57
+ return "azure-pipelines";
58
+ // AWS CodeBuild
59
+ if (env.CODEBUILD_BUILD_ID)
60
+ return "aws-codebuild";
61
+ // Bitbucket Pipelines
62
+ if (env.BITBUCKET_PIPELINE_UUID)
63
+ return "bitbucket-pipelines";
64
+ // Drone CI
65
+ if (env.DRONE)
66
+ return "drone-ci";
67
+ // TeamCity
68
+ if (env.TEAMCITY_VERSION)
69
+ return "teamcity";
70
+ // Vercel
71
+ if (env.VERCEL)
72
+ return "vercel";
73
+ // Netlify
74
+ if (env.NETLIFY)
75
+ return "netlify";
76
+ // Railway
77
+ if (env.RAILWAY_ENVIRONMENT)
78
+ return "railway";
79
+ // Render
80
+ if (env.RENDER)
81
+ return "render";
82
+ return undefined;
83
+ }
84
+ /**
85
+ * Detect the CI job/build ID from environment variables
86
+ */
87
+ function detectCIJobId() {
88
+ const env = process.env;
89
+ return (env.GITHUB_RUN_ID ||
90
+ env.CI_JOB_ID ||
91
+ env.CIRCLE_BUILD_NUM ||
92
+ env.BUILD_NUMBER ||
93
+ env.TRAVIS_BUILD_ID ||
94
+ env.BUILDKITE_BUILD_NUMBER ||
95
+ env.CODEBUILD_BUILD_ID ||
96
+ env.BITBUCKET_BUILD_NUMBER ||
97
+ env.DRONE_BUILD_NUMBER ||
98
+ undefined);
99
+ }
100
+ /**
101
+ * Detect the Git commit SHA from environment variables
102
+ */
103
+ function detectGitCommit() {
104
+ const env = process.env;
105
+ return (env.GITHUB_SHA ||
106
+ env.CI_COMMIT_SHA ||
107
+ env.CIRCLE_SHA1 ||
108
+ env.GIT_COMMIT ||
109
+ env.TRAVIS_COMMIT ||
110
+ env.BUILDKITE_COMMIT ||
111
+ env.BITBUCKET_COMMIT ||
112
+ env.DRONE_COMMIT_SHA ||
113
+ env.VERCEL_GIT_COMMIT_SHA ||
114
+ undefined);
115
+ }
116
+ /**
117
+ * Detect the Git branch from environment variables
118
+ */
119
+ function detectGitBranch() {
120
+ const env = process.env;
121
+ return (env.GITHUB_REF_NAME ||
122
+ env.CI_COMMIT_BRANCH ||
123
+ env.CIRCLE_BRANCH ||
124
+ env.GIT_BRANCH ||
125
+ env.TRAVIS_BRANCH ||
126
+ env.BUILDKITE_BRANCH ||
127
+ env.BITBUCKET_BRANCH ||
128
+ env.DRONE_BRANCH ||
129
+ env.VERCEL_GIT_COMMIT_REF ||
130
+ undefined);
131
+ }
132
+ /**
133
+ * Check if the current environment is a CI/CD environment
134
+ */
135
+ function isCI() {
136
+ return !!detectCIProvider();
137
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * AI Assess Tech SDK - Error Classes
3
+ *
4
+ * Custom error types for better error handling
5
+ *
6
+ * @version 0.7.0
7
+ */
8
+ /**
9
+ * Error codes for SDK errors
10
+ */
11
+ export declare enum ErrorCode {
12
+ INVALID_KEY = "INVALID_KEY",
13
+ KEY_EXPIRED = "KEY_EXPIRED",
14
+ KEY_REVOKED = "KEY_REVOKED",
15
+ MISSING_KEY = "MISSING_KEY",
16
+ RATE_LIMITED = "RATE_LIMITED",
17
+ QUOTA_EXCEEDED = "QUOTA_EXCEEDED",
18
+ INVALID_RESPONSE = "INVALID_RESPONSE",
19
+ INVALID_BODY = "INVALID_BODY",
20
+ QUESTION_TIMEOUT = "QUESTION_TIMEOUT",
21
+ OVERALL_TIMEOUT = "OVERALL_TIMEOUT",
22
+ QUESTION_FAILED = "QUESTION_FAILED",
23
+ ASSESSMENT_FAILED = "ASSESSMENT_FAILED",
24
+ NETWORK_ERROR = "NETWORK_ERROR",
25
+ SERVER_ERROR = "SERVER_ERROR"
26
+ }
27
+ /**
28
+ * Base SDK error class
29
+ */
30
+ export declare class SDKError extends Error {
31
+ readonly code: ErrorCode;
32
+ readonly details?: unknown | undefined;
33
+ constructor(message: string, code: ErrorCode, details?: unknown | undefined);
34
+ }
35
+ /**
36
+ * Error for validation issues (invalid key, invalid response, etc.)
37
+ */
38
+ export declare class ValidationError extends SDKError {
39
+ constructor(message: string, code?: ErrorCode);
40
+ }
41
+ /**
42
+ * Error for assessment failures
43
+ */
44
+ export declare class AssessmentError extends SDKError {
45
+ constructor(message: string, code: ErrorCode, details?: unknown);
46
+ }
47
+ /**
48
+ * Error for individual question timeout
49
+ */
50
+ export declare class QuestionTimeoutError extends SDKError {
51
+ readonly questionId: string;
52
+ constructor(message: string, questionId: string);
53
+ }
54
+ /**
55
+ * Error for overall assessment timeout
56
+ */
57
+ export declare class OverallTimeoutError extends SDKError {
58
+ constructor(message: string, details?: unknown);
59
+ }
60
+ /**
61
+ * Error for network issues
62
+ */
63
+ export declare class NetworkError extends SDKError {
64
+ readonly statusCode?: number | undefined;
65
+ constructor(message: string, statusCode?: number | undefined);
66
+ }
67
+ /**
68
+ * Error for rate limiting
69
+ */
70
+ export declare class RateLimitError extends SDKError {
71
+ readonly retryAfterMs?: number | undefined;
72
+ constructor(message: string, retryAfterMs?: number | undefined);
73
+ }
74
+ /**
75
+ * @deprecated Use SDKError instead
76
+ */
77
+ export declare class HealthCheckError extends Error {
78
+ readonly statusCode?: number | undefined;
79
+ readonly details?: unknown | undefined;
80
+ constructor(message: string, statusCode?: number | undefined, details?: unknown | undefined);
81
+ }
82
+ /**
83
+ * @deprecated Use ValidationError with ErrorCode.INVALID_KEY instead
84
+ */
85
+ export declare class AuthenticationError extends HealthCheckError {
86
+ constructor(message?: string);
87
+ }