@delegance/sdk 0.1.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/index.js ADDED
@@ -0,0 +1,1474 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ApiKeysModule: () => ApiKeysModule,
24
+ AuthenticationError: () => AuthenticationError,
25
+ COIModule: () => COIModule,
26
+ ChatModule: () => ChatModule,
27
+ CompaniesModule: () => CompaniesModule,
28
+ CompanySizeSchema: () => CompanySizeSchema,
29
+ CreateCompanySchema: () => CreateCompanySchema,
30
+ DeleganceClient: () => DeleganceClient,
31
+ DeleganceError: () => DeleganceError,
32
+ DocumentStatusSchema: () => DocumentStatusSchema,
33
+ DocumentTypeSchema: () => DocumentTypeSchema,
34
+ DocumentsModule: () => DocumentsModule,
35
+ KnowledgeModule: () => KnowledgeModule,
36
+ NotFoundError: () => NotFoundError,
37
+ OnboardingModule: () => OnboardingModule,
38
+ PoliciesModule: () => PoliciesModule,
39
+ QuotesModule: () => QuotesModule,
40
+ RateLimitError: () => RateLimitError,
41
+ SDK_VERSION: () => SDK_VERSION,
42
+ SOVModule: () => SOVModule,
43
+ UsageModule: () => UsageModule,
44
+ ValidationError: () => ValidationError,
45
+ createClientFromEnv: () => createClientFromEnv
46
+ });
47
+ module.exports = __toCommonJS(index_exports);
48
+
49
+ // src/types/index.ts
50
+ var import_zod = require("zod");
51
+ var CompanySizeSchema = import_zod.z.enum(["1", "2-10", "11-25", "26-50", "51-100", "100-499", "500+"]);
52
+ var CreateCompanySchema = import_zod.z.object({
53
+ name: import_zod.z.string().min(1).max(255),
54
+ legalName: import_zod.z.string().max(255).optional(),
55
+ dba: import_zod.z.string().max(255).optional(),
56
+ industry: import_zod.z.string().min(1).max(100),
57
+ companySize: CompanySizeSchema,
58
+ yearEstablished: import_zod.z.string().regex(/^\d{4}$/).optional(),
59
+ website: import_zod.z.string().url().optional(),
60
+ fein: import_zod.z.string().regex(/^\d{2}-\d{7}$/).optional(),
61
+ companyStructure: import_zod.z.string().max(100).optional(),
62
+ description: import_zod.z.string().max(2e3).optional(),
63
+ contactEmail: import_zod.z.string().email(),
64
+ contactPhone: import_zod.z.string().max(20).optional(),
65
+ address: import_zod.z.object({
66
+ street: import_zod.z.string().max(255),
67
+ suite: import_zod.z.string().max(50).optional(),
68
+ city: import_zod.z.string().max(100),
69
+ state: import_zod.z.string().length(2),
70
+ zip: import_zod.z.string().regex(/^\d{5}(-\d{4})?$/)
71
+ }).optional(),
72
+ externalId: import_zod.z.string().max(255).optional(),
73
+ metadata: import_zod.z.record(import_zod.z.unknown()).optional()
74
+ });
75
+ var DocumentTypeSchema = import_zod.z.enum([
76
+ "policy",
77
+ "loss_run",
78
+ "financial_statement",
79
+ "sov",
80
+ "application",
81
+ "certificate",
82
+ "endorsement",
83
+ "bor",
84
+ "other"
85
+ ]);
86
+ var DocumentStatusSchema = import_zod.z.enum([
87
+ "pending",
88
+ "processing",
89
+ "completed",
90
+ "processed",
91
+ "error",
92
+ "failed"
93
+ ]);
94
+ var DeleganceError = class extends Error {
95
+ constructor(message, statusCode, traceId, details) {
96
+ super(message);
97
+ this.statusCode = statusCode;
98
+ this.traceId = traceId;
99
+ this.details = details;
100
+ this.name = "DeleganceError";
101
+ }
102
+ };
103
+ var AuthenticationError = class extends DeleganceError {
104
+ constructor(message, traceId) {
105
+ super(message, 401, traceId);
106
+ this.name = "AuthenticationError";
107
+ }
108
+ };
109
+ var ValidationError = class extends DeleganceError {
110
+ constructor(message, details, traceId) {
111
+ super(message, 400, traceId, details);
112
+ this.name = "ValidationError";
113
+ }
114
+ };
115
+ var NotFoundError = class extends DeleganceError {
116
+ constructor(message, traceId) {
117
+ super(message, 404, traceId);
118
+ this.name = "NotFoundError";
119
+ }
120
+ };
121
+ var RateLimitError = class extends DeleganceError {
122
+ constructor(message, retryAfter, traceId) {
123
+ super(message, 429, traceId);
124
+ this.retryAfter = retryAfter;
125
+ this.name = "RateLimitError";
126
+ }
127
+ };
128
+
129
+ // src/utils/http.ts
130
+ var SDK_VERSION = "0.1.0";
131
+ var HttpClient = class {
132
+ constructor(config) {
133
+ this.config = {
134
+ baseUrl: (config.baseUrl || "https://app.delegance.ai").replace(/\/$/, ""),
135
+ apiKey: config.apiKey,
136
+ timeout: config.timeout || 3e4,
137
+ retries: config.retries ?? 3,
138
+ headers: config.headers || {}
139
+ };
140
+ }
141
+ async request(options) {
142
+ const { method, path, body, headers = {}, timeout, isFormData } = options;
143
+ const url = `${this.config.baseUrl}${path}`;
144
+ const requestHeaders = {
145
+ "Authorization": `Bearer ${this.config.apiKey}`,
146
+ "User-Agent": `delegance-sdk/${SDK_VERSION}`,
147
+ ...this.config.headers,
148
+ ...headers
149
+ };
150
+ if (!isFormData) {
151
+ requestHeaders["Content-Type"] = "application/json";
152
+ }
153
+ return this.executeWithRetry(
154
+ () => ({
155
+ url,
156
+ init: {
157
+ method,
158
+ headers: requestHeaders,
159
+ body: body ? isFormData ? body : JSON.stringify(body) : void 0
160
+ }
161
+ }),
162
+ timeout || this.config.timeout
163
+ );
164
+ }
165
+ /**
166
+ * Upload a file with multipart form data.
167
+ * Retries on 5xx/network errors like request().
168
+ */
169
+ async uploadFile(path, file, fileName, additionalFields = {}) {
170
+ const url = `${this.config.baseUrl}${path}`;
171
+ const formData = new FormData();
172
+ if (Buffer.isBuffer(file)) {
173
+ const arrayBuffer = file.buffer.slice(file.byteOffset, file.byteOffset + file.byteLength);
174
+ formData.append("file", new Blob([arrayBuffer]), fileName);
175
+ } else {
176
+ formData.append("file", file, fileName);
177
+ }
178
+ formData.append("fileName", fileName);
179
+ for (const [key, value] of Object.entries(additionalFields)) {
180
+ formData.append(key, value);
181
+ }
182
+ const uploadHeaders = {
183
+ "Authorization": `Bearer ${this.config.apiKey}`,
184
+ "User-Agent": `delegance-sdk/${SDK_VERSION}`,
185
+ ...this.config.headers
186
+ // Don't set Content-Type for FormData — browser sets it with boundary
187
+ };
188
+ return this.executeWithRetry(
189
+ () => ({
190
+ url,
191
+ init: {
192
+ method: "POST",
193
+ headers: uploadHeaders,
194
+ body: formData
195
+ }
196
+ }),
197
+ this.config.timeout * 2
198
+ // Double timeout for uploads
199
+ );
200
+ }
201
+ /**
202
+ * Shared retry logic for both request() and uploadFile().
203
+ * Creates a fresh AbortController per attempt, clears timeout in finally,
204
+ * and excludes non-retryable errors (401, 400, 404, 429).
205
+ */
206
+ async executeWithRetry(buildRequest, timeoutMs) {
207
+ let lastError = null;
208
+ let attempts = 0;
209
+ while (attempts <= this.config.retries) {
210
+ const controller = new AbortController();
211
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
212
+ try {
213
+ const { url, init } = buildRequest();
214
+ const response = await fetch(url, { ...init, signal: controller.signal });
215
+ const data = await response.json().catch(() => ({}));
216
+ const traceId = data.traceId;
217
+ if (!response.ok) {
218
+ throw this.handleErrorResponse(response.status, data, traceId);
219
+ }
220
+ return data;
221
+ } catch (error) {
222
+ lastError = error;
223
+ if (error instanceof AuthenticationError || error instanceof ValidationError || error instanceof NotFoundError || error instanceof RateLimitError) {
224
+ throw error;
225
+ }
226
+ if (attempts < this.config.retries) {
227
+ attempts++;
228
+ await this.delay(Math.pow(2, attempts) * 1e3);
229
+ continue;
230
+ }
231
+ throw error;
232
+ } finally {
233
+ clearTimeout(timeoutId);
234
+ }
235
+ }
236
+ throw lastError || new DeleganceError("Request failed after retries", 500);
237
+ }
238
+ handleErrorResponse(status, data, traceId) {
239
+ const message = data.message || data.error || "Unknown error";
240
+ const details = data.details;
241
+ switch (status) {
242
+ case 401:
243
+ return new AuthenticationError(message, traceId);
244
+ case 400:
245
+ return new ValidationError(message, details, traceId);
246
+ case 404:
247
+ return new NotFoundError(message, traceId);
248
+ case 429:
249
+ return new RateLimitError(
250
+ message,
251
+ data.retryAfter,
252
+ traceId
253
+ );
254
+ default:
255
+ return new DeleganceError(message, status, traceId, details);
256
+ }
257
+ }
258
+ delay(ms) {
259
+ return new Promise((resolve) => setTimeout(resolve, ms));
260
+ }
261
+ };
262
+
263
+ // src/modules/companies.ts
264
+ var CompaniesModule = class {
265
+ constructor(http) {
266
+ this.http = http;
267
+ }
268
+ /**
269
+ * Create a new company
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const company = await client.companies.create({
274
+ * name: 'ABC Construction',
275
+ * industry: 'construction',
276
+ * companySize: '11-25',
277
+ * contactEmail: 'contact@abc.com',
278
+ * fein: '12-3456789'
279
+ * });
280
+ * ```
281
+ */
282
+ async create(input) {
283
+ const parseResult = CreateCompanySchema.safeParse(input);
284
+ if (!parseResult.success) {
285
+ throw new ValidationError(
286
+ "Invalid company data",
287
+ parseResult.error.issues
288
+ );
289
+ }
290
+ const response = await this.http.request({
291
+ method: "POST",
292
+ path: "/api/v1/companies",
293
+ body: parseResult.data
294
+ });
295
+ return response.company;
296
+ }
297
+ /**
298
+ * List companies accessible to this API key
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * const companies = await client.companies.list();
303
+ *
304
+ * // Include companies created via this API key
305
+ * const allCompanies = await client.companies.list({ includeCreated: true });
306
+ * ```
307
+ */
308
+ async list(options = {}) {
309
+ const params = new URLSearchParams();
310
+ if (options.includeCreated) {
311
+ params.set("includeCreated", "true");
312
+ }
313
+ const query = params.toString();
314
+ const path = query ? `/api/v1/companies?${query}` : "/api/v1/companies";
315
+ const response = await this.http.request({
316
+ method: "GET",
317
+ path
318
+ });
319
+ return response.companies;
320
+ }
321
+ /**
322
+ * Get a company by ID
323
+ *
324
+ * @example
325
+ * ```typescript
326
+ * const company = await client.companies.get('uuid-here');
327
+ * ```
328
+ */
329
+ async get(companyId) {
330
+ const response = await this.http.request({
331
+ method: "GET",
332
+ path: `/api/v1/companies/${companyId}`
333
+ });
334
+ return response.company;
335
+ }
336
+ /**
337
+ * Create a company if it doesn't exist (using externalId for deduplication)
338
+ *
339
+ * @example
340
+ * ```typescript
341
+ * const company = await client.companies.upsert({
342
+ * name: 'ABC Construction',
343
+ * industry: 'construction',
344
+ * companySize: '11-25',
345
+ * contactEmail: 'contact@abc.com',
346
+ * externalId: 'ams-12345' // Will dedupe on this
347
+ * });
348
+ * ```
349
+ */
350
+ async upsert(input) {
351
+ const parseResult = CreateCompanySchema.safeParse(input);
352
+ if (!parseResult.success) {
353
+ throw new ValidationError(
354
+ "Invalid company data",
355
+ parseResult.error.issues
356
+ );
357
+ }
358
+ const response = await this.http.request({
359
+ method: "POST",
360
+ path: "/api/v1/companies",
361
+ body: parseResult.data
362
+ });
363
+ return {
364
+ company: response.company,
365
+ isExisting: response.isExisting
366
+ };
367
+ }
368
+ };
369
+
370
+ // src/modules/documents.ts
371
+ var DocumentsModule = class {
372
+ constructor(http) {
373
+ this.http = http;
374
+ }
375
+ /**
376
+ * Upload a document for processing
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * import fs from 'fs';
381
+ *
382
+ * const doc = await client.documents.upload({
383
+ * companyId: 'company-uuid',
384
+ * file: fs.readFileSync('./policy.pdf'),
385
+ * fileName: 'GL-2025.pdf',
386
+ * documentType: 'policy'
387
+ * });
388
+ *
389
+ * console.log(`Document ${doc.id} uploaded, status: ${doc.status}`);
390
+ * ```
391
+ */
392
+ async upload(input) {
393
+ if (!input.companyId) {
394
+ throw new ValidationError("companyId is required");
395
+ }
396
+ if (!input.file) {
397
+ throw new ValidationError("file is required");
398
+ }
399
+ if (!input.fileName) {
400
+ throw new ValidationError("fileName is required");
401
+ }
402
+ let fileData;
403
+ if (typeof input.file === "string") {
404
+ fileData = Buffer.from(input.file, "base64");
405
+ } else {
406
+ fileData = input.file;
407
+ }
408
+ const additionalFields = {
409
+ companyId: input.companyId
410
+ };
411
+ if (input.documentType) {
412
+ additionalFields.documentType = input.documentType;
413
+ }
414
+ if (input.externalId) {
415
+ additionalFields.externalId = input.externalId;
416
+ }
417
+ if (input.metadata) {
418
+ additionalFields.metadata = JSON.stringify(input.metadata);
419
+ }
420
+ const response = await this.http.uploadFile(
421
+ "/api/v1/documents",
422
+ fileData,
423
+ input.fileName,
424
+ additionalFields
425
+ );
426
+ return response.document;
427
+ }
428
+ /**
429
+ * Upload multiple documents in batch
430
+ *
431
+ * @example
432
+ * ```typescript
433
+ * const docs = await client.documents.uploadBatch([
434
+ * { companyId, file: buffer1, fileName: 'policy1.pdf' },
435
+ * { companyId, file: buffer2, fileName: 'policy2.pdf' }
436
+ * ]);
437
+ * ```
438
+ */
439
+ async uploadBatch(inputs, options = {}) {
440
+ const concurrency = options.concurrency || 3;
441
+ const documents = [];
442
+ const errors = [];
443
+ for (let i = 0; i < inputs.length; i += concurrency) {
444
+ const batch = inputs.slice(i, i + concurrency);
445
+ const results = await Promise.allSettled(
446
+ batch.map((input) => this.upload(input))
447
+ );
448
+ for (let j = 0; j < results.length; j++) {
449
+ const result = results[j];
450
+ if (result.status === "fulfilled") {
451
+ documents.push(result.value);
452
+ } else {
453
+ errors.push({ input: batch[j], error: result.reason });
454
+ }
455
+ }
456
+ }
457
+ return { documents, errors };
458
+ }
459
+ /**
460
+ * Get document details and extraction status
461
+ *
462
+ * @example
463
+ * ```typescript
464
+ * const doc = await client.documents.get('doc-uuid');
465
+ * console.log(`Status: ${doc.status}`);
466
+ * if (doc.extraction) {
467
+ * console.log(`Found ${doc.extraction.policies.length} policies`);
468
+ * }
469
+ * ```
470
+ */
471
+ async get(documentId) {
472
+ const response = await this.http.request({
473
+ method: "GET",
474
+ path: `/api/v1/documents/${documentId}`
475
+ });
476
+ return {
477
+ ...response.document,
478
+ extraction: response.extraction,
479
+ processing: response.processing,
480
+ error: response.error
481
+ };
482
+ }
483
+ /**
484
+ * List documents with optional filters
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * // List all documents
489
+ * const docs = await client.documents.list();
490
+ *
491
+ * // Filter by type and status
492
+ * const policies = await client.documents.list({
493
+ * documentType: 'policy',
494
+ * status: 'completed'
495
+ * });
496
+ *
497
+ * // Paginate
498
+ * const page2 = await client.documents.list({ offset: 50, limit: 50 });
499
+ * ```
500
+ */
501
+ async list(options = {}) {
502
+ const params = new URLSearchParams();
503
+ if (options.companyId) params.set("companyId", options.companyId);
504
+ if (options.documentType) params.set("documentType", options.documentType);
505
+ if (options.status) params.set("status", options.status);
506
+ if (options.externalId) params.set("externalId", options.externalId);
507
+ if (options.limit) params.set("limit", String(options.limit));
508
+ if (options.offset) params.set("offset", String(options.offset));
509
+ const query = params.toString();
510
+ const path = query ? `/api/v1/documents?${query}` : "/api/v1/documents";
511
+ const response = await this.http.request({
512
+ method: "GET",
513
+ path
514
+ });
515
+ return {
516
+ documents: response.documents,
517
+ pagination: response.pagination
518
+ };
519
+ }
520
+ /**
521
+ * Wait for document extraction to complete
522
+ *
523
+ * @example
524
+ * ```typescript
525
+ * const doc = await client.documents.upload({ ... });
526
+ *
527
+ * // Wait for processing to complete
528
+ * const result = await client.documents.waitForExtraction(doc.id, {
529
+ * timeoutMs: 60000,
530
+ * onStatusChange: (status) => console.log(`Status: ${status}`)
531
+ * });
532
+ *
533
+ * if (result.extraction) {
534
+ * console.log('Extraction complete:', result.extraction.policies);
535
+ * }
536
+ * ```
537
+ */
538
+ async waitForExtraction(documentId, options = {}) {
539
+ const {
540
+ timeoutMs = 12e4,
541
+ pollIntervalMs = 2e3,
542
+ onStatusChange
543
+ } = options;
544
+ const startTime = Date.now();
545
+ let lastStatus = null;
546
+ while (Date.now() - startTime < timeoutMs) {
547
+ try {
548
+ const doc = await this.get(documentId);
549
+ if (onStatusChange && doc.status !== lastStatus) {
550
+ onStatusChange(doc.status);
551
+ lastStatus = doc.status;
552
+ }
553
+ if (doc.status === "completed" || doc.status === "processed") {
554
+ return doc;
555
+ }
556
+ if (doc.status === "error" || doc.status === "failed") {
557
+ return doc;
558
+ }
559
+ } catch (error) {
560
+ if (error instanceof NotFoundError || error instanceof AuthenticationError || error instanceof RateLimitError || error instanceof ValidationError) {
561
+ throw error;
562
+ }
563
+ }
564
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
565
+ }
566
+ throw new DeleganceError(
567
+ `Document ${documentId} extraction did not complete within ${timeoutMs}ms (last status: ${lastStatus || "unknown"})`,
568
+ 408
569
+ );
570
+ }
571
+ /**
572
+ * Check if a document with the given external ID already exists
573
+ *
574
+ * @example
575
+ * ```typescript
576
+ * const existing = await client.documents.findByExternalId('ams-doc-123');
577
+ * if (existing) {
578
+ * console.log('Document already uploaded:', existing.id);
579
+ * }
580
+ * ```
581
+ */
582
+ async findByExternalId(externalId, companyId) {
583
+ const params = new URLSearchParams();
584
+ params.set("externalId", externalId);
585
+ params.set("limit", "1");
586
+ if (companyId) params.set("companyId", companyId);
587
+ const response = await this.http.request({
588
+ method: "GET",
589
+ path: `/api/v1/documents?${params.toString()}`
590
+ });
591
+ return response.documents[0] || null;
592
+ }
593
+ /**
594
+ * Archive a document (soft delete)
595
+ *
596
+ * This does NOT permanently delete the document - archived documents
597
+ * are excluded from list queries but remain for audit purposes.
598
+ *
599
+ * @example
600
+ * ```typescript
601
+ * await client.documents.archive('doc-uuid');
602
+ * console.log('Document archived');
603
+ * ```
604
+ */
605
+ async archive(documentId) {
606
+ const response = await this.http.request({
607
+ method: "PATCH",
608
+ path: `/api/v1/documents/${documentId}`,
609
+ body: { action: "archive" }
610
+ });
611
+ return { success: response.success, message: response.message };
612
+ }
613
+ /**
614
+ * Unarchive a previously archived document
615
+ *
616
+ * @example
617
+ * ```typescript
618
+ * await client.documents.unarchive('doc-uuid');
619
+ * console.log('Document restored');
620
+ * ```
621
+ */
622
+ async unarchive(documentId) {
623
+ const response = await this.http.request({
624
+ method: "PATCH",
625
+ path: `/api/v1/documents/${documentId}`,
626
+ body: { action: "unarchive" }
627
+ });
628
+ return { success: response.success, message: response.message, status: response.status };
629
+ }
630
+ /**
631
+ * Trigger re-extraction of a document
632
+ *
633
+ * Useful when:
634
+ * - Document extraction failed
635
+ * - You want to try extraction with updated extractors
636
+ * - Document was partially processed
637
+ *
638
+ * Rate limited to 3 reprocesses per document per day.
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * const result = await client.documents.reprocess('doc-uuid');
643
+ * console.log(`Reprocessing initiated. ${result.reprocessesRemaining} retries remaining today.`);
644
+ *
645
+ * // Then wait for extraction
646
+ * const doc = await client.documents.waitForExtraction('doc-uuid');
647
+ * ```
648
+ */
649
+ async reprocess(documentId) {
650
+ const response = await this.http.request({
651
+ method: "POST",
652
+ path: `/api/v1/documents/${documentId}/reprocess`
653
+ });
654
+ return {
655
+ success: response.success,
656
+ message: response.message,
657
+ status: response.status,
658
+ reprocessesRemaining: response.reprocessesRemaining
659
+ };
660
+ }
661
+ };
662
+
663
+ // src/modules/chat.ts
664
+ var ChatModule = class {
665
+ constructor(http) {
666
+ this.http = http;
667
+ }
668
+ /**
669
+ * Send a message to the Orin insurance assistant
670
+ *
671
+ * @example
672
+ * ```typescript
673
+ * const response = await client.chat.ask('What is my GL coverage limit?');
674
+ * console.log(response.response);
675
+ *
676
+ * // Continue the conversation
677
+ * const followUp = await client.chat.ask('And when does it expire?', {
678
+ * conversationId: response.conversationId
679
+ * });
680
+ * ```
681
+ */
682
+ async ask(message, options = {}) {
683
+ const response = await this.http.request({
684
+ method: "POST",
685
+ path: "/api/v1/chat",
686
+ body: {
687
+ message,
688
+ conversationId: options.conversationId,
689
+ context: options.context
690
+ }
691
+ });
692
+ return response;
693
+ }
694
+ /**
695
+ * Start a new conversation and send the first message
696
+ *
697
+ * @example
698
+ * ```typescript
699
+ * const conversation = await client.chat.startConversation('Tell me about my policies');
700
+ * console.log('Conversation ID:', conversation.conversationId);
701
+ * ```
702
+ */
703
+ async startConversation(message) {
704
+ return this.ask(message, {
705
+ conversationId: crypto.randomUUID()
706
+ });
707
+ }
708
+ };
709
+
710
+ // src/modules/quotes.ts
711
+ var QuotesModule = class {
712
+ constructor(http) {
713
+ this.http = http;
714
+ }
715
+ /**
716
+ * List available carriers for quoting
717
+ *
718
+ * @example
719
+ * ```typescript
720
+ * const { carriers } = await client.quotes.listCarriers();
721
+ * for (const carrier of carriers) {
722
+ * console.log(`${carrier.name} - avg ${carrier.averageQuoteTimeSeconds}s`);
723
+ * }
724
+ * ```
725
+ */
726
+ async listCarriers() {
727
+ return this.http.request({
728
+ method: "GET",
729
+ path: "/api/v1/quotes/carriers"
730
+ });
731
+ }
732
+ /**
733
+ * Submit a quote request to one or more carriers
734
+ *
735
+ * @example
736
+ * ```typescript
737
+ * // Get available carriers
738
+ * const { carriers } = await client.quotes.listCarriers();
739
+ *
740
+ * // Submit to first 3 carriers
741
+ * const result = await client.quotes.submit({
742
+ * carriers: carriers.slice(0, 3).map(c => c.id),
743
+ * priority: 'high'
744
+ * });
745
+ *
746
+ * console.log(`Submitted ${result.queueIds.length} quote requests`);
747
+ * ```
748
+ */
749
+ async submit(request) {
750
+ return this.http.request({
751
+ method: "POST",
752
+ path: "/api/v1/quotes",
753
+ body: request
754
+ });
755
+ }
756
+ /**
757
+ * List quote requests for the company
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * // List all quotes
762
+ * const { quotes } = await client.quotes.list();
763
+ *
764
+ * // List only pending quotes
765
+ * const { quotes: pending } = await client.quotes.list({ status: 'pending' });
766
+ * ```
767
+ */
768
+ async list(options = {}) {
769
+ const params = new URLSearchParams();
770
+ if (options.status) params.set("status", options.status);
771
+ if (options.limit) params.set("limit", String(options.limit));
772
+ const query = params.toString();
773
+ const path = query ? `/api/v1/quotes?${query}` : "/api/v1/quotes";
774
+ return this.http.request({
775
+ method: "GET",
776
+ path
777
+ });
778
+ }
779
+ /**
780
+ * Get a single quote by ID with full details
781
+ *
782
+ * @example
783
+ * ```typescript
784
+ * const { quote, actions } = await client.quotes.get('quote-uuid');
785
+ * console.log(`Status: ${quote.status}`);
786
+ * if (actions.canCancel) {
787
+ * console.log('This quote can be cancelled');
788
+ * }
789
+ * ```
790
+ */
791
+ async get(quoteId) {
792
+ const response = await this.http.request({
793
+ method: "GET",
794
+ path: `/api/v1/quotes/${quoteId}`
795
+ });
796
+ return {
797
+ quote: response.quote,
798
+ canCancel: response.actions.canCancel
799
+ };
800
+ }
801
+ /**
802
+ * Cancel a pending quote
803
+ *
804
+ * Only quotes in 'pending' status can be cancelled.
805
+ * Once a quote starts processing, it cannot be stopped.
806
+ *
807
+ * @example
808
+ * ```typescript
809
+ * try {
810
+ * await client.quotes.cancel('quote-uuid');
811
+ * console.log('Quote cancelled');
812
+ * } catch (error) {
813
+ * console.log('Cannot cancel:', error.message);
814
+ * }
815
+ * ```
816
+ */
817
+ async cancel(quoteId) {
818
+ const response = await this.http.request({
819
+ method: "DELETE",
820
+ path: `/api/v1/quotes/${quoteId}`
821
+ });
822
+ return { success: response.success, message: response.message };
823
+ }
824
+ /**
825
+ * Wait for a quote to complete
826
+ *
827
+ * @example
828
+ * ```typescript
829
+ * const result = await client.quotes.submit({ carriers: ['carrier-1'] });
830
+ * const quote = await client.quotes.waitForCompletion(result.queueIds[0]);
831
+ * console.log('Quote status:', quote.status);
832
+ * ```
833
+ */
834
+ async waitForCompletion(quoteId, options = {}) {
835
+ const { timeoutMs = 3e5, pollIntervalMs = 5e3 } = options;
836
+ const startTime = Date.now();
837
+ while (Date.now() - startTime < timeoutMs) {
838
+ try {
839
+ const { quote } = await this.get(quoteId);
840
+ if (["completed", "failed", "cancelled"].includes(quote.status)) {
841
+ return quote;
842
+ }
843
+ } catch (error) {
844
+ if (error instanceof NotFoundError || error instanceof AuthenticationError || error instanceof RateLimitError || error instanceof ValidationError) {
845
+ throw error;
846
+ }
847
+ }
848
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
849
+ }
850
+ throw new DeleganceError(`Quote ${quoteId} did not complete within ${timeoutMs}ms`, 408);
851
+ }
852
+ };
853
+
854
+ // src/modules/policies.ts
855
+ var PoliciesModule = class {
856
+ constructor(http) {
857
+ this.http = http;
858
+ }
859
+ /**
860
+ * List policies for the company
861
+ *
862
+ * @example
863
+ * ```typescript
864
+ * // List all active policies
865
+ * const { policies } = await client.policies.list({ status: 'active' });
866
+ *
867
+ * // List policies expiring in 30 days
868
+ * const { policies: expiring } = await client.policies.list({ expiringDays: 30 });
869
+ * ```
870
+ */
871
+ async list(options = {}) {
872
+ const params = new URLSearchParams();
873
+ if (options.status && options.status !== "all") params.set("status", options.status);
874
+ if (options.expiringDays) params.set("expiring", String(options.expiringDays));
875
+ if (options.policyType) params.set("type", options.policyType);
876
+ if (options.limit) params.set("limit", String(options.limit));
877
+ const query = params.toString();
878
+ const path = query ? `/api/v1/policies?${query}` : "/api/v1/policies";
879
+ return this.http.request({
880
+ method: "GET",
881
+ path
882
+ });
883
+ }
884
+ /**
885
+ * Get policies expiring soon
886
+ *
887
+ * @param days - Number of days to look ahead (default: 30)
888
+ */
889
+ async getExpiring(days = 30) {
890
+ return this.list({ expiringDays: days, status: "active" });
891
+ }
892
+ /**
893
+ * Get a single policy by ID with full details
894
+ *
895
+ * @example
896
+ * ```typescript
897
+ * const { policy, coverages } = await client.policies.get('policy-uuid');
898
+ * console.log(`${policy.carrier} - ${policy.policyType}`);
899
+ * console.log(`Coverages: ${coverages.length}`);
900
+ * ```
901
+ */
902
+ async get(policyId) {
903
+ try {
904
+ const response = await this.http.request({
905
+ method: "GET",
906
+ path: `/api/v1/policies/${policyId}`
907
+ });
908
+ return {
909
+ policy: response.policy,
910
+ coverages: response.coverages || []
911
+ };
912
+ } catch (error) {
913
+ if (error instanceof NotFoundError) {
914
+ return null;
915
+ }
916
+ throw error;
917
+ }
918
+ }
919
+ };
920
+
921
+ // src/modules/coi.ts
922
+ var COIModule = class {
923
+ constructor(http) {
924
+ this.http = http;
925
+ }
926
+ /**
927
+ * Generate a Certificate of Insurance
928
+ *
929
+ * @example
930
+ * ```typescript
931
+ * const { policies } = await client.policies.list({ status: 'active' });
932
+ *
933
+ * const result = await client.coi.generate({
934
+ * policyIds: policies.map(p => p.id),
935
+ * certificateHolder: {
936
+ * name: 'ABC Property Management',
937
+ * address: '123 Main St',
938
+ * city: 'New York',
939
+ * state: 'NY',
940
+ * zip: '10001'
941
+ * },
942
+ * certificateType: 'additional_insured'
943
+ * });
944
+ *
945
+ * console.log('Download URL:', result.downloadUrl);
946
+ * ```
947
+ */
948
+ async generate(request) {
949
+ return this.http.request({
950
+ method: "POST",
951
+ path: "/api/v1/coi",
952
+ body: request
953
+ });
954
+ }
955
+ /**
956
+ * List generated COIs
957
+ *
958
+ * @param limit - Maximum results (default: 50)
959
+ */
960
+ async list(limit = 50) {
961
+ return this.http.request({
962
+ method: "GET",
963
+ path: `/api/v1/coi?limit=${limit}`
964
+ });
965
+ }
966
+ };
967
+
968
+ // src/modules/sov.ts
969
+ var SOVModule = class {
970
+ constructor(http) {
971
+ this.http = http;
972
+ }
973
+ /**
974
+ * Upload a Schedule of Values file
975
+ *
976
+ * @example
977
+ * ```typescript
978
+ * import fs from 'fs';
979
+ *
980
+ * const result = await client.sov.upload({
981
+ * file: fs.readFileSync('./property-schedule.xlsx'),
982
+ * fileName: 'property-schedule.xlsx',
983
+ * lineOfBusiness: 'property',
984
+ * effectiveDate: '2024-01-01'
985
+ * });
986
+ *
987
+ * console.log('SOV ID:', result.sovId);
988
+ * ```
989
+ */
990
+ async upload(request) {
991
+ let fileData;
992
+ if (request.file instanceof ArrayBuffer) {
993
+ fileData = new Blob([new Uint8Array(request.file)]);
994
+ } else {
995
+ fileData = request.file;
996
+ }
997
+ const additionalFields = {};
998
+ if (request.lineOfBusiness) additionalFields.lineOfBusiness = request.lineOfBusiness;
999
+ if (request.effectiveDate) additionalFields.effectiveDate = request.effectiveDate;
1000
+ if (request.expirationDate) additionalFields.expirationDate = request.expirationDate;
1001
+ return this.http.uploadFile(
1002
+ "/api/v1/sov",
1003
+ fileData,
1004
+ request.fileName,
1005
+ additionalFields
1006
+ );
1007
+ }
1008
+ /**
1009
+ * List SOVs for the company
1010
+ */
1011
+ async list(options = {}) {
1012
+ const params = new URLSearchParams();
1013
+ if (options.status) params.set("status", options.status);
1014
+ if (options.limit) params.set("limit", String(options.limit));
1015
+ const query = params.toString();
1016
+ const path = query ? `/api/v1/sov?${query}` : "/api/v1/sov";
1017
+ return this.http.request({
1018
+ method: "GET",
1019
+ path
1020
+ });
1021
+ }
1022
+ /**
1023
+ * Get a single SOV by ID with full details and locations
1024
+ *
1025
+ * @example
1026
+ * ```typescript
1027
+ * const { sov, locations } = await client.sov.get('sov-uuid');
1028
+ * console.log(`${sov.totalLocations} locations, TIV: $${sov.totalTIV}`);
1029
+ *
1030
+ * // Access individual locations
1031
+ * for (const loc of locations.items) {
1032
+ * console.log(`${loc.address.city}, ${loc.address.state}: $${loc.values.total}`);
1033
+ * }
1034
+ * ```
1035
+ */
1036
+ async get(sovId, options = {}) {
1037
+ const params = new URLSearchParams();
1038
+ if (options.includeLocations !== void 0) {
1039
+ params.set("includeLocations", String(options.includeLocations));
1040
+ }
1041
+ if (options.locationLimit) params.set("locationLimit", String(options.locationLimit));
1042
+ if (options.locationOffset) params.set("locationOffset", String(options.locationOffset));
1043
+ const query = params.toString();
1044
+ const path = query ? `/api/v1/sov/${sovId}?${query}` : `/api/v1/sov/${sovId}`;
1045
+ return this.http.request({
1046
+ method: "GET",
1047
+ path
1048
+ });
1049
+ }
1050
+ /**
1051
+ * Wait for SOV parsing to complete
1052
+ */
1053
+ async waitForParsing(sovId, options = {}) {
1054
+ const { timeoutMs = 12e4, pollIntervalMs = 3e3 } = options;
1055
+ const startTime = Date.now();
1056
+ while (Date.now() - startTime < timeoutMs) {
1057
+ try {
1058
+ const { sov } = await this.get(sovId, { includeLocations: false });
1059
+ if (["parsed", "validated", "submitted", "error"].includes(sov.status)) {
1060
+ return sov;
1061
+ }
1062
+ } catch (error) {
1063
+ if (error instanceof NotFoundError || error instanceof AuthenticationError || error instanceof RateLimitError || error instanceof ValidationError) {
1064
+ throw error;
1065
+ }
1066
+ }
1067
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
1068
+ }
1069
+ throw new DeleganceError(`SOV ${sovId} did not complete parsing within ${timeoutMs}ms`, 408);
1070
+ }
1071
+ };
1072
+
1073
+ // src/modules/api-keys.ts
1074
+ var ApiKeysModule = class {
1075
+ constructor(http) {
1076
+ this.http = http;
1077
+ }
1078
+ /**
1079
+ * Create a new API key.
1080
+ *
1081
+ * The returned `key` value (the full secret) is shown **only once**.
1082
+ * Store it securely — it cannot be retrieved again.
1083
+ *
1084
+ * @example
1085
+ * ```typescript
1086
+ * const created = await client.apiKeys.create({
1087
+ * name: 'My Integration Key',
1088
+ * scopes: ['read', 'write'],
1089
+ * expiresInDays: 365,
1090
+ * });
1091
+ * console.log('Save this key now:', created.key);
1092
+ * ```
1093
+ */
1094
+ async create(input, options) {
1095
+ if (!input.name || !input.name.trim()) {
1096
+ throw new ValidationError("API key name is required and cannot be blank");
1097
+ }
1098
+ const body = {
1099
+ name: input.name,
1100
+ scopes: input.scopes
1101
+ };
1102
+ if (input.expiresInDays !== void 0) {
1103
+ body.expiresInDays = input.expiresInDays;
1104
+ }
1105
+ const requestOptions = {
1106
+ method: "POST",
1107
+ path: "/api/v1/api-keys",
1108
+ body
1109
+ };
1110
+ if (options?.idempotencyKey) {
1111
+ requestOptions.headers = { "Idempotency-Key": options.idempotencyKey };
1112
+ }
1113
+ const response = await this.http.request(requestOptions);
1114
+ return response.data;
1115
+ }
1116
+ /**
1117
+ * List API keys for the current workspace.
1118
+ *
1119
+ * @example
1120
+ * ```typescript
1121
+ * const { data, pagination } = await client.apiKeys.list({ limit: 20 });
1122
+ * if (pagination.hasMore) {
1123
+ * const next = await client.apiKeys.list({ cursor: pagination.nextCursor });
1124
+ * }
1125
+ * ```
1126
+ */
1127
+ async list(options = {}) {
1128
+ const params = new URLSearchParams();
1129
+ if (options.limit !== void 0) {
1130
+ params.set("limit", String(options.limit));
1131
+ }
1132
+ if (options.cursor !== void 0) {
1133
+ params.set("cursor", options.cursor);
1134
+ }
1135
+ const query = params.toString();
1136
+ const path = query ? `/api/v1/api-keys?${query}` : "/api/v1/api-keys";
1137
+ const response = await this.http.request({
1138
+ method: "GET",
1139
+ path
1140
+ });
1141
+ return {
1142
+ data: response.data,
1143
+ pagination: response.pagination
1144
+ };
1145
+ }
1146
+ /**
1147
+ * Revoke an API key immediately.
1148
+ *
1149
+ * @example
1150
+ * ```typescript
1151
+ * await client.apiKeys.revoke('key-id-here');
1152
+ * ```
1153
+ */
1154
+ async revoke(keyId) {
1155
+ await this.http.request({
1156
+ method: "DELETE",
1157
+ path: `/api/v1/api-keys/${keyId}`
1158
+ });
1159
+ }
1160
+ /**
1161
+ * Rotate an API key.
1162
+ *
1163
+ * Issues a new key while keeping the old key valid for `gracePeriodHours`
1164
+ * so you have time to update your integrations.
1165
+ *
1166
+ * @example
1167
+ * ```typescript
1168
+ * const { newKey, oldKeyValidUntil } = await client.apiKeys.rotate(
1169
+ * 'key-id-here',
1170
+ * { gracePeriodHours: 24 },
1171
+ * { idempotencyKey: 'my-rotation-id' }
1172
+ * );
1173
+ * console.log('New key (save now):', newKey.key);
1174
+ * console.log('Old key expires:', oldKeyValidUntil);
1175
+ * ```
1176
+ */
1177
+ async rotate(keyId, options, idempotency) {
1178
+ const requestOptions = {
1179
+ method: "POST",
1180
+ path: `/api/v1/api-keys/${keyId}/rotate`,
1181
+ body: { gracePeriodHours: options.gracePeriodHours }
1182
+ };
1183
+ if (idempotency?.idempotencyKey) {
1184
+ requestOptions.headers = { "Idempotency-Key": idempotency.idempotencyKey };
1185
+ }
1186
+ const response = await this.http.request(requestOptions);
1187
+ return response.data;
1188
+ }
1189
+ };
1190
+
1191
+ // src/modules/usage.ts
1192
+ var UsageModule = class {
1193
+ constructor(http) {
1194
+ this.http = http;
1195
+ }
1196
+ /**
1197
+ * Get a billing-period summary across all meters.
1198
+ *
1199
+ * @example
1200
+ * ```typescript
1201
+ * const summary = await client.usage.summary();
1202
+ * console.log(`Plan: ${summary.plan}, overage: $${summary.totalOverageCents / 100}`);
1203
+ * ```
1204
+ */
1205
+ async summary() {
1206
+ const response = await this.http.request({
1207
+ method: "GET",
1208
+ path: "/api/v1/usage/summary"
1209
+ });
1210
+ return response.data;
1211
+ }
1212
+ /**
1213
+ * Get daily usage data for a date range.
1214
+ *
1215
+ * @example
1216
+ * ```typescript
1217
+ * const { data } = await client.usage.daily({
1218
+ * from: '2026-04-01',
1219
+ * to: '2026-04-30',
1220
+ * meter: 'api_requests',
1221
+ * });
1222
+ * const total = data.reduce((sum, row) => sum + row.quantity, 0);
1223
+ * ```
1224
+ */
1225
+ async daily(options) {
1226
+ if (!options.from) {
1227
+ throw new ValidationError('daily() requires a non-empty "from" date');
1228
+ }
1229
+ if (!options.to) {
1230
+ throw new ValidationError('daily() requires a non-empty "to" date');
1231
+ }
1232
+ const params = new URLSearchParams();
1233
+ params.set("from", options.from);
1234
+ params.set("to", options.to);
1235
+ if (options.meter !== void 0) {
1236
+ params.set("meter", options.meter);
1237
+ }
1238
+ if (options.groupBy !== void 0) {
1239
+ params.set("groupBy", options.groupBy);
1240
+ }
1241
+ const response = await this.http.request({
1242
+ method: "GET",
1243
+ path: `/api/v1/usage/daily?${params.toString()}`
1244
+ });
1245
+ return { data: response.data };
1246
+ }
1247
+ /**
1248
+ * Get the current rate-limit status for this API key.
1249
+ *
1250
+ * @example
1251
+ * ```typescript
1252
+ * const limits = await client.usage.rateLimits();
1253
+ * console.log(`${limits.remaining}/${limits.requestsPerMinute} requests remaining`);
1254
+ * ```
1255
+ */
1256
+ async rateLimits() {
1257
+ const response = await this.http.request({
1258
+ method: "GET",
1259
+ path: "/api/v1/usage/rate-limits"
1260
+ });
1261
+ return response.data;
1262
+ }
1263
+ };
1264
+
1265
+ // src/modules/knowledge.ts
1266
+ var KnowledgeModule = class {
1267
+ constructor(http) {
1268
+ this.http = http;
1269
+ }
1270
+ /**
1271
+ * Search notecards and document chunks using semantic search.
1272
+ *
1273
+ * Uses POST because the query body can be complex (filters, types, etc.).
1274
+ *
1275
+ * @example
1276
+ * ```typescript
1277
+ * const { data, pagination } = await client.knowledge.search({
1278
+ * query: 'general liability occurrence limit',
1279
+ * types: ['notecard'],
1280
+ * limit: 10,
1281
+ * });
1282
+ * console.log(data[0].title, data[0].score);
1283
+ * ```
1284
+ */
1285
+ async search(input) {
1286
+ if (!input.query || !input.query.trim()) {
1287
+ throw new ValidationError("search query must be a non-empty string");
1288
+ }
1289
+ const body = { query: input.query };
1290
+ if (input.types !== void 0) body.types = input.types;
1291
+ if (input.limit !== void 0) body.limit = input.limit;
1292
+ const response = await this.http.request({
1293
+ method: "POST",
1294
+ path: "/api/v1/knowledge/search",
1295
+ body
1296
+ });
1297
+ return { data: response.data, pagination: response.pagination };
1298
+ }
1299
+ /**
1300
+ * List notecards, optionally filtered by template type.
1301
+ *
1302
+ * @example
1303
+ * ```typescript
1304
+ * const { data, pagination } = await client.knowledge.notecards({
1305
+ * type: 'policy_summary',
1306
+ * limit: 50,
1307
+ * });
1308
+ * if (pagination.hasMore) {
1309
+ * const next = await client.knowledge.notecards({ cursor: pagination.nextCursor! });
1310
+ * }
1311
+ * ```
1312
+ */
1313
+ async notecards(options = {}) {
1314
+ const params = new URLSearchParams();
1315
+ if (options.type) params.set("type", options.type);
1316
+ if (options.limit !== void 0) params.set("limit", String(options.limit));
1317
+ if (options.cursor) params.set("cursor", options.cursor);
1318
+ const query = params.toString();
1319
+ const path = query ? `/api/v1/knowledge/notecards?${query}` : "/api/v1/knowledge/notecards";
1320
+ const response = await this.http.request({
1321
+ method: "GET",
1322
+ path
1323
+ });
1324
+ return { data: response.data, pagination: response.pagination };
1325
+ }
1326
+ /**
1327
+ * Retrieve structured facts extracted from a document.
1328
+ *
1329
+ * @throws {NotFoundError} when the document does not exist
1330
+ *
1331
+ * @example
1332
+ * ```typescript
1333
+ * const facts = await client.knowledge.documentFacts('doc-uuid');
1334
+ * console.log(facts.carriers); // ['Hartford', 'Chubb']
1335
+ * console.log(facts.policies[0].policyType); // 'GL'
1336
+ * ```
1337
+ */
1338
+ async documentFacts(documentId) {
1339
+ const response = await this.http.request({
1340
+ method: "GET",
1341
+ path: `/api/v1/knowledge/documents/${documentId}/facts`
1342
+ });
1343
+ return response.data;
1344
+ }
1345
+ };
1346
+
1347
+ // src/modules/onboarding.ts
1348
+ var OnboardingModule = class {
1349
+ constructor(http) {
1350
+ this.http = http;
1351
+ }
1352
+ /**
1353
+ * Retrieve the onboarding status checklist for the authenticated company.
1354
+ *
1355
+ * Use this to determine what setup steps remain before going live.
1356
+ *
1357
+ * @example
1358
+ * ```typescript
1359
+ * const status = await client.onboarding.status();
1360
+ *
1361
+ * if (!status.quoteReady) {
1362
+ * console.log('Next step:', status.nextStep?.action);
1363
+ * }
1364
+ *
1365
+ * if (status.sandbox) {
1366
+ * console.log('Running in sandbox mode — upgrade to submit live quotes.');
1367
+ * }
1368
+ * ```
1369
+ */
1370
+ async status() {
1371
+ const response = await this.http.request({
1372
+ method: "GET",
1373
+ path: "/api/v1/onboarding/status"
1374
+ });
1375
+ return response.data;
1376
+ }
1377
+ };
1378
+
1379
+ // src/client.ts
1380
+ var API_KEY_REGEX = /^dlg_[a-zA-Z0-9]{8}_sk_[a-zA-Z0-9]{32}$/;
1381
+ var DeleganceClient = class {
1382
+ /**
1383
+ * Create a new Delegance client
1384
+ *
1385
+ * @param config - Client configuration
1386
+ * @throws Error if API key is missing or invalid format
1387
+ */
1388
+ constructor(config) {
1389
+ if (!config.apiKey) {
1390
+ throw new Error("API key is required. Get one from the Delegance dashboard.");
1391
+ }
1392
+ if (!API_KEY_REGEX.test(config.apiKey)) {
1393
+ throw new Error(
1394
+ "Invalid API key format. Expected format: dlg_xxxxxxxx_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1395
+ );
1396
+ }
1397
+ this.http = new HttpClient(config);
1398
+ this.companies = new CompaniesModule(this.http);
1399
+ this.documents = new DocumentsModule(this.http);
1400
+ this.chat = new ChatModule(this.http);
1401
+ this.quotes = new QuotesModule(this.http);
1402
+ this.policies = new PoliciesModule(this.http);
1403
+ this.coi = new COIModule(this.http);
1404
+ this.sov = new SOVModule(this.http);
1405
+ this.apiKeys = new ApiKeysModule(this.http);
1406
+ this.usage = new UsageModule(this.http);
1407
+ this.knowledge = new KnowledgeModule(this.http);
1408
+ this.onboarding = new OnboardingModule(this.http);
1409
+ }
1410
+ /**
1411
+ * Get the SDK version
1412
+ */
1413
+ static get version() {
1414
+ return SDK_VERSION;
1415
+ }
1416
+ /**
1417
+ * Verify the API key is valid by making a test request
1418
+ *
1419
+ * @example
1420
+ * ```typescript
1421
+ * const isValid = await client.verifyApiKey();
1422
+ * if (!isValid) {
1423
+ * console.error('API key is invalid or expired');
1424
+ * }
1425
+ * ```
1426
+ */
1427
+ async verifyApiKey() {
1428
+ try {
1429
+ await this.companies.list();
1430
+ return true;
1431
+ } catch {
1432
+ return false;
1433
+ }
1434
+ }
1435
+ };
1436
+ function createClientFromEnv() {
1437
+ const apiKey = process.env.DELEGANCE_API_KEY;
1438
+ const baseUrl = process.env.DELEGANCE_BASE_URL;
1439
+ if (!apiKey) {
1440
+ throw new Error(
1441
+ "DELEGANCE_API_KEY environment variable is required. Get an API key from the Delegance dashboard."
1442
+ );
1443
+ }
1444
+ return new DeleganceClient({
1445
+ apiKey,
1446
+ baseUrl
1447
+ });
1448
+ }
1449
+ // Annotate the CommonJS export names for ESM import in node:
1450
+ 0 && (module.exports = {
1451
+ ApiKeysModule,
1452
+ AuthenticationError,
1453
+ COIModule,
1454
+ ChatModule,
1455
+ CompaniesModule,
1456
+ CompanySizeSchema,
1457
+ CreateCompanySchema,
1458
+ DeleganceClient,
1459
+ DeleganceError,
1460
+ DocumentStatusSchema,
1461
+ DocumentTypeSchema,
1462
+ DocumentsModule,
1463
+ KnowledgeModule,
1464
+ NotFoundError,
1465
+ OnboardingModule,
1466
+ PoliciesModule,
1467
+ QuotesModule,
1468
+ RateLimitError,
1469
+ SDK_VERSION,
1470
+ SOVModule,
1471
+ UsageModule,
1472
+ ValidationError,
1473
+ createClientFromEnv
1474
+ });