@lov3kaizen/agentsea-structured 0.5.1

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,3210 @@
1
+ import { z } from 'zod';
2
+ import { zodToJsonSchema as zodToJsonSchema$1 } from 'zod-to-json-schema';
3
+ import { EventEmitter } from 'eventemitter3';
4
+
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __esm = (fn, res) => function __init() {
8
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
+ };
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ function zodToJsonSchema(schema) {
15
+ return zodToJsonSchema$1(schema, { $refStrategy: "none" });
16
+ }
17
+ function schemaToPrompt(schema, options = {}) {
18
+ const opts = { ...DEFAULT_OPTIONS, ...options };
19
+ switch (opts.format) {
20
+ case "json-schema":
21
+ return generateJsonSchemaPrompt(schema, opts);
22
+ case "typescript":
23
+ return generateTypeScriptPrompt(schema, opts);
24
+ case "natural":
25
+ return generateNaturalPrompt(schema, opts);
26
+ case "examples":
27
+ return generateExamplesPrompt(schema, opts);
28
+ default:
29
+ return generateJsonSchemaPrompt(schema, opts);
30
+ }
31
+ }
32
+ function generateJsonSchemaPrompt(schema, opts) {
33
+ const jsonSchema = zodToJsonSchema$1(schema, {
34
+ $refStrategy: "none",
35
+ errorMessages: true
36
+ });
37
+ const cleanedSchema = cleanJsonSchema(jsonSchema);
38
+ const text = [
39
+ "Respond with a JSON object that matches this schema:",
40
+ "",
41
+ "```json",
42
+ JSON.stringify(cleanedSchema, null, opts.indent),
43
+ "```"
44
+ ].join("\n");
45
+ return {
46
+ text,
47
+ format: "json-schema",
48
+ jsonSchema: cleanedSchema
49
+ };
50
+ }
51
+ function generateTypeScriptPrompt(schema, opts) {
52
+ const typeScript = zodToTypeScript(schema, opts);
53
+ const jsonSchema = zodToJsonSchema$1(schema, {
54
+ $refStrategy: "none"
55
+ });
56
+ const text = [
57
+ "Respond with a JSON object matching this TypeScript type:",
58
+ "",
59
+ "```typescript",
60
+ typeScript,
61
+ "```"
62
+ ].join("\n");
63
+ return {
64
+ text,
65
+ format: "typescript",
66
+ jsonSchema,
67
+ typeScript
68
+ };
69
+ }
70
+ function generateNaturalPrompt(schema, opts) {
71
+ const fieldInfos = analyzeSchema(schema, opts);
72
+ const jsonSchema = zodToJsonSchema$1(schema, {
73
+ $refStrategy: "none"
74
+ });
75
+ const lines = [
76
+ "Respond with a JSON object containing the following fields:",
77
+ ""
78
+ ];
79
+ for (const field of fieldInfos) {
80
+ const requiredStr = field.required ? "(required)" : "(optional)";
81
+ let line = `- ${field.name} ${requiredStr}: ${field.jsonType}`;
82
+ if (opts.includeDescriptions && field.description) {
83
+ line += ` - ${field.description}`;
84
+ }
85
+ if (opts.includeConstraints && field.constraints.length > 0) {
86
+ const constraintStrs = field.constraints.map((c) => c.description);
87
+ line += ` [${constraintStrs.join(", ")}]`;
88
+ }
89
+ lines.push(line);
90
+ if (field.children && field.children.length > 0) {
91
+ for (const child of field.children) {
92
+ lines.push(` - ${child.name}: ${child.jsonType}`);
93
+ }
94
+ }
95
+ }
96
+ return {
97
+ text: lines.join("\n"),
98
+ format: "natural",
99
+ jsonSchema
100
+ };
101
+ }
102
+ function generateExamplesPrompt(schema, opts) {
103
+ const jsonSchema = zodToJsonSchema$1(schema, {
104
+ $refStrategy: "none"
105
+ });
106
+ const example = generateExample(jsonSchema, opts.maxDepth);
107
+ const text = [
108
+ "Respond with a JSON object following this example structure:",
109
+ "",
110
+ "```json",
111
+ JSON.stringify(example, null, opts.indent),
112
+ "```"
113
+ ].join("\n");
114
+ return {
115
+ text,
116
+ format: "examples",
117
+ jsonSchema
118
+ };
119
+ }
120
+ function cleanJsonSchema(schema) {
121
+ const cleaned = {};
122
+ for (const [key, value] of Object.entries(schema)) {
123
+ if (key.startsWith("$") && key !== "$defs") continue;
124
+ if (key === "additionalProperties" && value === false) continue;
125
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
126
+ cleaned[key] = cleanJsonSchema(value);
127
+ } else if (Array.isArray(value)) {
128
+ cleaned[key] = value.map(
129
+ (item) => typeof item === "object" && item !== null ? cleanJsonSchema(item) : item
130
+ );
131
+ } else {
132
+ cleaned[key] = value;
133
+ }
134
+ }
135
+ return cleaned;
136
+ }
137
+ function zodToTypeScript(schema, opts, depth = 0) {
138
+ if (depth > opts.maxDepth) return "any";
139
+ const indent = " ".repeat(depth);
140
+ const innerIndent = " ".repeat(depth + 1);
141
+ if (schema instanceof z.ZodObject) {
142
+ const shape = schema.shape;
143
+ const lines = ["{"];
144
+ for (const [key, value] of Object.entries(shape)) {
145
+ const fieldSchema = value;
146
+ const isOptional = fieldSchema.isOptional?.() ?? false;
147
+ const typeStr = zodToTypeScript(fieldSchema, opts, depth + 1);
148
+ const optionalMarker = isOptional ? "?" : "";
149
+ const description = fieldSchema.description;
150
+ const descComment = opts.includeDescriptions && description ? ` // ${description}` : "";
151
+ lines.push(
152
+ `${innerIndent}${key}${optionalMarker}: ${typeStr};${descComment}`
153
+ );
154
+ }
155
+ lines.push(`${indent}}`);
156
+ return lines.join("\n");
157
+ }
158
+ if (schema instanceof z.ZodArray) {
159
+ const elementType = zodToTypeScript(schema.element, opts, depth);
160
+ return `${elementType}[]`;
161
+ }
162
+ if (schema instanceof z.ZodString) {
163
+ return "string";
164
+ }
165
+ if (schema instanceof z.ZodNumber) {
166
+ return "number";
167
+ }
168
+ if (schema instanceof z.ZodBoolean) {
169
+ return "boolean";
170
+ }
171
+ if (schema instanceof z.ZodNull) {
172
+ return "null";
173
+ }
174
+ if (schema instanceof z.ZodUndefined) {
175
+ return "undefined";
176
+ }
177
+ if (schema instanceof z.ZodLiteral) {
178
+ const value = schema.value;
179
+ return typeof value === "string" ? `'${value}'` : String(value);
180
+ }
181
+ if (schema instanceof z.ZodEnum) {
182
+ const values = schema.options;
183
+ return values.map((v) => `'${v}'`).join(" | ");
184
+ }
185
+ if (schema instanceof z.ZodNativeEnum) {
186
+ return "enum";
187
+ }
188
+ if (schema instanceof z.ZodUnion) {
189
+ const options = schema.options;
190
+ return options.map((o) => zodToTypeScript(o, opts, depth)).join(" | ");
191
+ }
192
+ if (schema instanceof z.ZodOptional) {
193
+ const innerType = zodToTypeScript(schema.unwrap(), opts, depth);
194
+ return `${innerType} | undefined`;
195
+ }
196
+ if (schema instanceof z.ZodNullable) {
197
+ const innerType = zodToTypeScript(schema.unwrap(), opts, depth);
198
+ return `${innerType} | null`;
199
+ }
200
+ if (schema instanceof z.ZodDefault) {
201
+ return zodToTypeScript(schema.removeDefault(), opts, depth);
202
+ }
203
+ if (schema instanceof z.ZodRecord) {
204
+ const valueType = zodToTypeScript(schema.valueSchema, opts, depth);
205
+ return `Record<string, ${valueType}>`;
206
+ }
207
+ if (schema instanceof z.ZodTuple) {
208
+ const items = schema.items;
209
+ const types = items.map((item) => zodToTypeScript(item, opts, depth));
210
+ return `[${types.join(", ")}]`;
211
+ }
212
+ if (schema instanceof z.ZodDate) {
213
+ return "Date";
214
+ }
215
+ return "unknown";
216
+ }
217
+ function analyzeSchema(schema, opts, path = "") {
218
+ const fields = [];
219
+ if (schema instanceof z.ZodObject) {
220
+ const shape = schema.shape;
221
+ for (const [key, value] of Object.entries(shape)) {
222
+ const fieldSchema = value;
223
+ const fieldPath = path ? `${path}.${key}` : key;
224
+ const info = extractFieldInfo(key, fieldSchema, fieldPath, opts);
225
+ fields.push(info);
226
+ }
227
+ }
228
+ return fields;
229
+ }
230
+ function extractFieldInfo(name, schema, path, opts) {
231
+ const constraints = extractConstraints(schema);
232
+ const { zodType, jsonType } = getTypeNames(schema);
233
+ const description = schema.description;
234
+ const isOptional = schema.isOptional?.() ?? false;
235
+ const hasDefault = schema instanceof z.ZodDefault;
236
+ const defaultValue = hasDefault ? schema._def.defaultValue() : void 0;
237
+ let children;
238
+ const unwrapped = unwrapSchema(schema);
239
+ if (unwrapped instanceof z.ZodObject) {
240
+ children = analyzeSchema(unwrapped, opts, path);
241
+ }
242
+ return {
243
+ path,
244
+ name,
245
+ zodType,
246
+ jsonType,
247
+ description,
248
+ required: !isOptional,
249
+ hasDefault,
250
+ defaultValue,
251
+ constraints,
252
+ children
253
+ };
254
+ }
255
+ function extractConstraints(schema) {
256
+ const constraints = [];
257
+ const def = schema._def;
258
+ const checks = def?.checks ?? [];
259
+ for (const check of checks) {
260
+ switch (check.kind) {
261
+ case "min":
262
+ constraints.push({
263
+ type: "min",
264
+ value: check.value,
265
+ description: `minimum: ${String(check.value)}`
266
+ });
267
+ break;
268
+ case "max":
269
+ constraints.push({
270
+ type: "max",
271
+ value: check.value,
272
+ description: `maximum: ${String(check.value)}`
273
+ });
274
+ break;
275
+ case "length":
276
+ constraints.push({
277
+ type: "length",
278
+ value: check.value,
279
+ description: `length: ${String(check.value)}`
280
+ });
281
+ break;
282
+ case "email":
283
+ constraints.push({
284
+ type: "email",
285
+ value: true,
286
+ description: "must be valid email"
287
+ });
288
+ break;
289
+ case "url":
290
+ constraints.push({
291
+ type: "url",
292
+ value: true,
293
+ description: "must be valid URL"
294
+ });
295
+ break;
296
+ case "regex":
297
+ constraints.push({
298
+ type: "regex",
299
+ value: check.value,
300
+ description: `must match pattern`
301
+ });
302
+ break;
303
+ case "int":
304
+ constraints.push({
305
+ type: "int",
306
+ value: true,
307
+ description: "must be integer"
308
+ });
309
+ break;
310
+ case "positive":
311
+ constraints.push({
312
+ type: "positive",
313
+ value: true,
314
+ description: "must be positive"
315
+ });
316
+ break;
317
+ case "negative":
318
+ constraints.push({
319
+ type: "negative",
320
+ value: true,
321
+ description: "must be negative"
322
+ });
323
+ break;
324
+ }
325
+ }
326
+ return constraints;
327
+ }
328
+ function getTypeNames(schema) {
329
+ const unwrapped = unwrapSchema(schema);
330
+ if (unwrapped instanceof z.ZodString)
331
+ return { zodType: "ZodString", jsonType: "string" };
332
+ if (unwrapped instanceof z.ZodNumber)
333
+ return { zodType: "ZodNumber", jsonType: "number" };
334
+ if (unwrapped instanceof z.ZodBoolean)
335
+ return { zodType: "ZodBoolean", jsonType: "boolean" };
336
+ if (unwrapped instanceof z.ZodNull)
337
+ return { zodType: "ZodNull", jsonType: "null" };
338
+ if (unwrapped instanceof z.ZodArray)
339
+ return { zodType: "ZodArray", jsonType: "array" };
340
+ if (unwrapped instanceof z.ZodObject)
341
+ return { zodType: "ZodObject", jsonType: "object" };
342
+ if (unwrapped instanceof z.ZodEnum)
343
+ return { zodType: "ZodEnum", jsonType: "string" };
344
+ if (unwrapped instanceof z.ZodLiteral) {
345
+ const value = unwrapped.value;
346
+ const type = typeof value;
347
+ return { zodType: "ZodLiteral", jsonType: type };
348
+ }
349
+ if (unwrapped instanceof z.ZodUnion)
350
+ return { zodType: "ZodUnion", jsonType: "union" };
351
+ if (unwrapped instanceof z.ZodRecord)
352
+ return { zodType: "ZodRecord", jsonType: "object" };
353
+ if (unwrapped instanceof z.ZodDate)
354
+ return { zodType: "ZodDate", jsonType: "string" };
355
+ return { zodType: "unknown", jsonType: "unknown" };
356
+ }
357
+ function unwrapSchema(schema) {
358
+ if (schema instanceof z.ZodOptional) return unwrapSchema(schema.unwrap());
359
+ if (schema instanceof z.ZodNullable) return unwrapSchema(schema.unwrap());
360
+ if (schema instanceof z.ZodDefault)
361
+ return unwrapSchema(schema.removeDefault());
362
+ return schema;
363
+ }
364
+ function generateExample(schema, maxDepth, depth = 0) {
365
+ if (depth > maxDepth) return null;
366
+ if (schema.examples && schema.examples.length > 0) {
367
+ return schema.examples[0];
368
+ }
369
+ if (schema.default !== void 0) {
370
+ return schema.default;
371
+ }
372
+ if (schema.const !== void 0) {
373
+ return schema.const;
374
+ }
375
+ if (schema.enum && schema.enum.length > 0) {
376
+ return schema.enum[0];
377
+ }
378
+ const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
379
+ switch (type) {
380
+ case "string":
381
+ return schema.format === "email" ? "example@email.com" : schema.format === "uri" ? "https://example.com" : "string";
382
+ case "number":
383
+ case "integer":
384
+ return schema.minimum ?? 0;
385
+ case "boolean":
386
+ return true;
387
+ case "null":
388
+ return null;
389
+ case "array":
390
+ if (schema.items) {
391
+ const itemExample = generateExample(
392
+ Array.isArray(schema.items) ? schema.items[0] : schema.items,
393
+ maxDepth,
394
+ depth + 1
395
+ );
396
+ return [itemExample];
397
+ }
398
+ return [];
399
+ case "object":
400
+ if (schema.properties) {
401
+ const obj = {};
402
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
403
+ obj[key] = generateExample(propSchema, maxDepth, depth + 1);
404
+ }
405
+ return obj;
406
+ }
407
+ return {};
408
+ default:
409
+ if (schema.anyOf && schema.anyOf.length > 0) {
410
+ return generateExample(schema.anyOf[0], maxDepth, depth);
411
+ }
412
+ if (schema.oneOf && schema.oneOf.length > 0) {
413
+ return generateExample(schema.oneOf[0], maxDepth, depth);
414
+ }
415
+ return null;
416
+ }
417
+ }
418
+ var DEFAULT_OPTIONS, SchemaPromptGenerator;
419
+ var init_SchemaToPrompt = __esm({
420
+ "src/schema/SchemaToPrompt.ts"() {
421
+ DEFAULT_OPTIONS = {
422
+ format: "json-schema",
423
+ includeDescriptions: true,
424
+ includeExamples: true,
425
+ includeConstraints: true,
426
+ maxDepth: 10,
427
+ indent: 2
428
+ };
429
+ SchemaPromptGenerator = {
430
+ toJsonSchema: (schema, options) => schemaToPrompt(schema, { ...options, format: "json-schema" }),
431
+ toTypeScript: (schema, options) => schemaToPrompt(schema, { ...options, format: "typescript" }),
432
+ toNatural: (schema, options) => schemaToPrompt(schema, { ...options, format: "natural" }),
433
+ toExamples: (schema, options) => schemaToPrompt(schema, { ...options, format: "examples" }),
434
+ generateExample
435
+ };
436
+ }
437
+ });
438
+ function validateSchema(schema, data) {
439
+ const result = schema.safeParse(data);
440
+ if (result.success) {
441
+ return {
442
+ success: true,
443
+ data: result.data
444
+ };
445
+ }
446
+ return {
447
+ success: false,
448
+ errors: formatZodErrors(result.error)
449
+ };
450
+ }
451
+ function validateSchemaOrThrow(schema, data) {
452
+ return schema.parse(data);
453
+ }
454
+ function validatePartial(schema, data, options = {}) {
455
+ const partialSchema = makePartial(schema);
456
+ const result = partialSchema.safeParse(data);
457
+ if (!result.success) {
458
+ return {
459
+ success: false,
460
+ errors: formatZodErrors(result.error)
461
+ };
462
+ }
463
+ if (options.requiredFields && options.requiredFields.length > 0) {
464
+ const missingFields = [];
465
+ for (const field of options.requiredFields) {
466
+ const value = getNestedValue(result.data, field);
467
+ if (value === void 0) {
468
+ missingFields.push({
469
+ path: field.split("."),
470
+ message: `Required field '${field}' is missing`,
471
+ expected: "value",
472
+ received: void 0,
473
+ code: "custom"
474
+ });
475
+ }
476
+ }
477
+ if (missingFields.length > 0) {
478
+ return {
479
+ success: false,
480
+ errors: missingFields
481
+ };
482
+ }
483
+ }
484
+ return {
485
+ success: true,
486
+ data: result.data
487
+ };
488
+ }
489
+ function matchesSchema(schema, data) {
490
+ return schema.safeParse(data).success;
491
+ }
492
+ function coerceToSchema(schema, data) {
493
+ const directResult = schema.safeParse(data);
494
+ if (directResult.success) {
495
+ return { success: true, data: directResult.data };
496
+ }
497
+ const coerced = coerceData(data, schema);
498
+ const coercedResult = schema.safeParse(coerced);
499
+ if (coercedResult.success) {
500
+ return { success: true, data: coercedResult.data };
501
+ }
502
+ return {
503
+ success: false,
504
+ errors: formatZodErrors(coercedResult.error)
505
+ };
506
+ }
507
+ function getValidationHints(schema, data) {
508
+ const result = schema.safeParse(data);
509
+ if (result.success) {
510
+ return [];
511
+ }
512
+ return result.error.issues.map((issue) => generateHint(issue));
513
+ }
514
+ function formatZodErrors(error) {
515
+ return error.issues.map((issue) => ({
516
+ path: issue.path.map((p) => typeof p === "number" ? p : String(p)),
517
+ message: issue.message,
518
+ expected: getExpectedFromIssue(issue),
519
+ received: getReceivedFromIssue(issue),
520
+ code: issue.code
521
+ }));
522
+ }
523
+ function makePartial(schema) {
524
+ if (schema instanceof z.ZodObject) {
525
+ return schema.partial();
526
+ }
527
+ if (schema instanceof z.ZodArray) {
528
+ return z.array(makePartial(schema.element));
529
+ }
530
+ if (schema instanceof z.ZodUnion) {
531
+ return z.union(
532
+ schema.options.map((opt) => makePartial(opt))
533
+ );
534
+ }
535
+ if (schema instanceof z.ZodIntersection) {
536
+ return z.intersection(
537
+ makePartial(schema._def.left),
538
+ makePartial(schema._def.right)
539
+ );
540
+ }
541
+ return schema.optional();
542
+ }
543
+ function getNestedValue(obj, path) {
544
+ if (typeof obj !== "object" || obj === null) {
545
+ return void 0;
546
+ }
547
+ const parts = path.split(".");
548
+ let current = obj;
549
+ for (const part of parts) {
550
+ if (typeof current !== "object" || current === null) {
551
+ return void 0;
552
+ }
553
+ const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
554
+ if (arrayMatch) {
555
+ const [, key, index] = arrayMatch;
556
+ const arr = current[key];
557
+ if (!Array.isArray(arr)) {
558
+ return void 0;
559
+ }
560
+ current = arr[parseInt(index, 10)];
561
+ } else {
562
+ current = current[part];
563
+ }
564
+ }
565
+ return current;
566
+ }
567
+ function coerceData(data, schema) {
568
+ if (schema instanceof z.ZodString && typeof data === "number") {
569
+ return String(data);
570
+ }
571
+ if (schema instanceof z.ZodNumber && typeof data === "string") {
572
+ const num = Number(data);
573
+ if (!isNaN(num)) {
574
+ return num;
575
+ }
576
+ }
577
+ if (schema instanceof z.ZodBoolean) {
578
+ if (data === "true" || data === 1) return true;
579
+ if (data === "false" || data === 0) return false;
580
+ }
581
+ if (schema instanceof z.ZodArray && typeof data === "string") {
582
+ try {
583
+ const parsed = JSON.parse(data);
584
+ if (Array.isArray(parsed)) {
585
+ return parsed;
586
+ }
587
+ } catch {
588
+ }
589
+ }
590
+ if (schema instanceof z.ZodObject && typeof data === "string") {
591
+ try {
592
+ return JSON.parse(data);
593
+ } catch {
594
+ }
595
+ }
596
+ if (schema instanceof z.ZodObject && typeof data === "object" && data !== null) {
597
+ const objSchema = schema;
598
+ const shape = objSchema.shape;
599
+ const result = {
600
+ ...data
601
+ };
602
+ for (const [key, fieldSchema] of Object.entries(shape)) {
603
+ if (key in result) {
604
+ result[key] = coerceData(result[key], fieldSchema);
605
+ }
606
+ }
607
+ return result;
608
+ }
609
+ return data;
610
+ }
611
+ function generateHint(issue, _data) {
612
+ const path = issue.path.join(".");
613
+ const pathPrefix = path ? `At '${path}': ` : "";
614
+ switch (issue.code) {
615
+ case "invalid_type":
616
+ return `${pathPrefix}Expected ${issue.expected}, but received ${issue.received}. Please provide a value of type ${issue.expected}.`;
617
+ case "invalid_literal":
618
+ return `${pathPrefix}Expected the exact value ${JSON.stringify(issue.expected)}, but received ${JSON.stringify(issue.received)}.`;
619
+ case "unrecognized_keys":
620
+ return `${pathPrefix}Unexpected keys: ${issue.keys.join(", ")}. Remove these keys or check the schema.`;
621
+ case "invalid_union":
622
+ return `${pathPrefix}Value doesn't match any of the allowed types. Check the schema for valid options.`;
623
+ case "invalid_enum_value":
624
+ return `${pathPrefix}Value must be one of: ${issue.options.join(", ")}`;
625
+ case "invalid_string":
626
+ if ("validation" in issue) {
627
+ const validation = issue.validation;
628
+ if (typeof validation === "string") {
629
+ return `${pathPrefix}String must be a valid ${validation}.`;
630
+ }
631
+ }
632
+ return `${pathPrefix}Invalid string format.`;
633
+ case "too_small": {
634
+ const smallIssue = issue;
635
+ if (smallIssue.type === "string") {
636
+ return `${pathPrefix}String must be at least ${smallIssue.minimum} characters.`;
637
+ }
638
+ if (smallIssue.type === "number") {
639
+ return `${pathPrefix}Number must be ${smallIssue.inclusive ? "at least" : "greater than"} ${smallIssue.minimum}.`;
640
+ }
641
+ if (smallIssue.type === "array") {
642
+ return `${pathPrefix}Array must have at least ${smallIssue.minimum} items.`;
643
+ }
644
+ return `${pathPrefix}Value is too small.`;
645
+ }
646
+ case "too_big": {
647
+ const bigIssue = issue;
648
+ if (bigIssue.type === "string") {
649
+ return `${pathPrefix}String must be at most ${bigIssue.maximum} characters.`;
650
+ }
651
+ if (bigIssue.type === "number") {
652
+ return `${pathPrefix}Number must be ${bigIssue.inclusive ? "at most" : "less than"} ${bigIssue.maximum}.`;
653
+ }
654
+ if (bigIssue.type === "array") {
655
+ return `${pathPrefix}Array must have at most ${bigIssue.maximum} items.`;
656
+ }
657
+ return `${pathPrefix}Value is too big.`;
658
+ }
659
+ case "custom":
660
+ return `${pathPrefix}${issue.message}`;
661
+ case "invalid_date":
662
+ return `${pathPrefix}Invalid date value. Provide a valid date string or Date object.`;
663
+ default:
664
+ return `${pathPrefix}${issue.message}`;
665
+ }
666
+ }
667
+ function getExpectedFromIssue(issue) {
668
+ if ("expected" in issue) {
669
+ return String(issue.expected);
670
+ }
671
+ return void 0;
672
+ }
673
+ function getReceivedFromIssue(issue) {
674
+ if ("received" in issue) {
675
+ return issue.received;
676
+ }
677
+ return void 0;
678
+ }
679
+ var SchemaValidator;
680
+ var init_SchemaValidator = __esm({
681
+ "src/schema/SchemaValidator.ts"() {
682
+ SchemaValidator = {
683
+ validate: validateSchema,
684
+ validateOrThrow: validateSchemaOrThrow,
685
+ validatePartial,
686
+ matches: matchesSchema,
687
+ coerce: coerceToSchema,
688
+ getHints: getValidationHints,
689
+ formatErrors: formatZodErrors
690
+ };
691
+ }
692
+ });
693
+
694
+ // src/streaming/IncrementalJsonParser.ts
695
+ function processEscapeChar(char) {
696
+ switch (char) {
697
+ case "n":
698
+ return "\n";
699
+ case "r":
700
+ return "\r";
701
+ case "t":
702
+ return " ";
703
+ case "\\":
704
+ return "\\";
705
+ case '"':
706
+ return '"';
707
+ case "/":
708
+ return "/";
709
+ case "b":
710
+ return "\b";
711
+ case "f":
712
+ return "\f";
713
+ default:
714
+ return char;
715
+ }
716
+ }
717
+ function tokenizeJson(json) {
718
+ const tokens = [];
719
+ const path = [];
720
+ let inString = false;
721
+ let inEscape = false;
722
+ let currentString = "";
723
+ let currentKey = null;
724
+ for (let i = 0; i < json.length; i++) {
725
+ const char = json[i];
726
+ if (inString) {
727
+ if (inEscape) {
728
+ currentString += processEscapeChar(char);
729
+ inEscape = false;
730
+ } else if (char === "\\") {
731
+ inEscape = true;
732
+ } else if (char === '"') {
733
+ inString = false;
734
+ tokens.push({
735
+ type: currentKey === null ? "key" : "string",
736
+ value: currentString,
737
+ path: [...path],
738
+ complete: true
739
+ });
740
+ if (currentKey === null) {
741
+ currentKey = currentString;
742
+ }
743
+ currentString = "";
744
+ } else {
745
+ currentString += char;
746
+ }
747
+ } else if (/\s/.test(char)) {
748
+ continue;
749
+ } else if (char === "{") {
750
+ tokens.push({
751
+ type: "object_start",
752
+ value: "{",
753
+ path: [...path],
754
+ complete: true
755
+ });
756
+ } else if (char === "}") {
757
+ tokens.push({
758
+ type: "object_end",
759
+ value: "}",
760
+ path: [...path],
761
+ complete: true
762
+ });
763
+ path.pop();
764
+ currentKey = null;
765
+ } else if (char === "[") {
766
+ tokens.push({
767
+ type: "array_start",
768
+ value: "[",
769
+ path: [...path],
770
+ complete: true
771
+ });
772
+ } else if (char === "]") {
773
+ tokens.push({
774
+ type: "array_end",
775
+ value: "]",
776
+ path: [...path],
777
+ complete: true
778
+ });
779
+ } else if (char === ":") {
780
+ tokens.push({
781
+ type: "colon",
782
+ value: ":",
783
+ path: [...path],
784
+ complete: true
785
+ });
786
+ if (currentKey) {
787
+ path.push(currentKey);
788
+ }
789
+ } else if (char === ",") {
790
+ tokens.push({
791
+ type: "comma",
792
+ value: ",",
793
+ path: [...path],
794
+ complete: true
795
+ });
796
+ path.pop();
797
+ currentKey = null;
798
+ } else if (char === '"') {
799
+ inString = true;
800
+ currentString = "";
801
+ }
802
+ }
803
+ return tokens;
804
+ }
805
+ var IncrementalJsonParser;
806
+ var init_IncrementalJsonParser = __esm({
807
+ "src/streaming/IncrementalJsonParser.ts"() {
808
+ IncrementalJsonParser = class {
809
+ state;
810
+ result;
811
+ pendingUpdates;
812
+ constructor() {
813
+ this.state = this.createInitialState();
814
+ this.result = {};
815
+ this.pendingUpdates = [];
816
+ }
817
+ /**
818
+ * Feed a chunk of text to the parser
819
+ */
820
+ feed(chunk) {
821
+ this.pendingUpdates = [];
822
+ this.state.buffer += chunk;
823
+ this.parse();
824
+ return this.pendingUpdates;
825
+ }
826
+ /**
827
+ * Get the current parsed result
828
+ */
829
+ getResult() {
830
+ this.finalize();
831
+ return this.result;
832
+ }
833
+ /**
834
+ * Reset the parser state
835
+ */
836
+ reset() {
837
+ this.state = this.createInitialState();
838
+ this.result = {};
839
+ this.pendingUpdates = [];
840
+ }
841
+ /**
842
+ * Create initial parser state
843
+ */
844
+ createInitialState() {
845
+ return {
846
+ currentPath: [],
847
+ depth: 0,
848
+ buffer: "",
849
+ partial: {},
850
+ inString: false,
851
+ inEscape: false,
852
+ currentString: "",
853
+ currentKey: null,
854
+ containerStack: []
855
+ };
856
+ }
857
+ /**
858
+ * Parse the current buffer
859
+ */
860
+ parse() {
861
+ let i = 0;
862
+ let lastSuccessfulIndex = -1;
863
+ while (i < this.state.buffer.length) {
864
+ const char = this.state.buffer[i];
865
+ if (this.state.inString) {
866
+ i = this.parseStringChar(i, char);
867
+ lastSuccessfulIndex = i;
868
+ } else {
869
+ if (char === "t" || char === "f" || char === "n") {
870
+ const remaining = this.state.buffer.slice(i);
871
+ const isComplete = remaining.startsWith("true") || remaining.startsWith("false") || remaining.startsWith("null");
872
+ if (!isComplete) {
873
+ break;
874
+ }
875
+ }
876
+ if (/[-\d]/.test(char)) {
877
+ const remaining = this.state.buffer.slice(i);
878
+ const match = remaining.match(/^-?\d+(\.\d+)?([eE][+-]?\d+)?/);
879
+ if (match) {
880
+ const numStr = match[0];
881
+ const afterNum = remaining.slice(numStr.length);
882
+ if (afterNum.length === 0 || afterNum.length > 0 && !/[\s,}\]]/.test(afterNum[0])) {
883
+ break;
884
+ }
885
+ }
886
+ }
887
+ i = this.parseChar(i, char);
888
+ lastSuccessfulIndex = i;
889
+ }
890
+ i++;
891
+ }
892
+ if (lastSuccessfulIndex >= 0) {
893
+ this.state.buffer = this.state.buffer.slice(lastSuccessfulIndex + 1);
894
+ }
895
+ }
896
+ /**
897
+ * Parse a character inside a string
898
+ */
899
+ parseStringChar(index, char) {
900
+ if (this.state.inEscape) {
901
+ this.state.currentString += this.processEscape(char);
902
+ this.state.inEscape = false;
903
+ return index;
904
+ }
905
+ if (char === "\\") {
906
+ this.state.inEscape = true;
907
+ return index;
908
+ }
909
+ if (char === '"') {
910
+ this.state.inString = false;
911
+ this.handleStringComplete();
912
+ return index;
913
+ }
914
+ this.state.currentString += char;
915
+ return index;
916
+ }
917
+ /**
918
+ * Parse a character outside a string
919
+ */
920
+ parseChar(index, char) {
921
+ if (/\s/.test(char)) {
922
+ return index;
923
+ }
924
+ switch (char) {
925
+ case "{":
926
+ this.handleObjectStart();
927
+ break;
928
+ case "}":
929
+ this.handleObjectEnd();
930
+ break;
931
+ case "[":
932
+ this.handleArrayStart();
933
+ break;
934
+ case "]":
935
+ this.handleArrayEnd();
936
+ break;
937
+ case '"':
938
+ this.state.inString = true;
939
+ this.state.currentString = "";
940
+ break;
941
+ case ":":
942
+ break;
943
+ case ",":
944
+ if (this.getCurrentContainer() === "object") {
945
+ this.state.currentKey = null;
946
+ } else if (this.getCurrentContainer() === "array") {
947
+ const lastPath = this.state.currentPath[this.state.currentPath.length - 1];
948
+ if (typeof lastPath === "string" && /^\d+$/.test(lastPath)) {
949
+ this.state.currentPath[this.state.currentPath.length - 1] = String(
950
+ parseInt(lastPath, 10) + 1
951
+ );
952
+ }
953
+ }
954
+ break;
955
+ case "t":
956
+ case "f":
957
+ index = this.parseBoolean(index);
958
+ break;
959
+ case "n":
960
+ index = this.parseNull(index);
961
+ break;
962
+ default:
963
+ if (/[-\d]/.test(char)) {
964
+ index = this.parseNumber(index);
965
+ }
966
+ }
967
+ return index;
968
+ }
969
+ /**
970
+ * Process an escape character
971
+ */
972
+ processEscape(char) {
973
+ switch (char) {
974
+ case "n":
975
+ return "\n";
976
+ case "r":
977
+ return "\r";
978
+ case "t":
979
+ return " ";
980
+ case "\\":
981
+ return "\\";
982
+ case '"':
983
+ return '"';
984
+ case "/":
985
+ return "/";
986
+ default:
987
+ return char;
988
+ }
989
+ }
990
+ /**
991
+ * Handle completion of a string
992
+ */
993
+ handleStringComplete() {
994
+ const value = this.state.currentString;
995
+ if (this.getCurrentContainer() === "object" && this.state.currentKey === null) {
996
+ this.state.currentKey = value;
997
+ } else {
998
+ this.setValue(value);
999
+ }
1000
+ }
1001
+ /**
1002
+ * Handle start of object
1003
+ */
1004
+ handleObjectStart() {
1005
+ this.state.depth++;
1006
+ this.state.containerStack.push("object");
1007
+ if (this.state.currentKey !== null) {
1008
+ this.state.currentPath.push(this.state.currentKey);
1009
+ this.state.currentKey = null;
1010
+ }
1011
+ this.setNestedValue(this.result, this.state.currentPath, {});
1012
+ }
1013
+ /**
1014
+ * Handle end of object
1015
+ */
1016
+ handleObjectEnd() {
1017
+ this.state.depth--;
1018
+ this.state.containerStack.pop();
1019
+ const path = [...this.state.currentPath];
1020
+ const value = this.getNestedValue(this.result, path);
1021
+ this.pendingUpdates.push({
1022
+ path,
1023
+ value,
1024
+ complete: true
1025
+ });
1026
+ const currentContainer = this.getCurrentContainer();
1027
+ if (currentContainer !== "array" && this.state.currentPath.length > 0) {
1028
+ this.state.currentPath.pop();
1029
+ }
1030
+ }
1031
+ /**
1032
+ * Handle start of array
1033
+ */
1034
+ handleArrayStart() {
1035
+ this.state.depth++;
1036
+ this.state.containerStack.push("array");
1037
+ if (this.state.currentKey !== null) {
1038
+ this.state.currentPath.push(this.state.currentKey);
1039
+ this.state.currentKey = null;
1040
+ }
1041
+ this.setNestedValue(this.result, this.state.currentPath, []);
1042
+ this.state.currentPath.push("0");
1043
+ }
1044
+ /**
1045
+ * Handle end of array
1046
+ */
1047
+ handleArrayEnd() {
1048
+ this.state.depth--;
1049
+ this.state.containerStack.pop();
1050
+ this.state.currentPath.pop();
1051
+ const path = [...this.state.currentPath];
1052
+ const value = this.getNestedValue(this.result, path);
1053
+ this.pendingUpdates.push({
1054
+ path,
1055
+ value,
1056
+ complete: true
1057
+ });
1058
+ const currentContainer = this.getCurrentContainer();
1059
+ if (currentContainer !== "array" && this.state.currentPath.length > 0) {
1060
+ this.state.currentPath.pop();
1061
+ }
1062
+ }
1063
+ /**
1064
+ * Parse a boolean value
1065
+ */
1066
+ parseBoolean(startIndex) {
1067
+ const remaining = this.state.buffer.slice(startIndex);
1068
+ if (remaining.startsWith("true")) {
1069
+ this.setValue(true);
1070
+ return startIndex + 3;
1071
+ }
1072
+ if (remaining.startsWith("false")) {
1073
+ this.setValue(false);
1074
+ return startIndex + 4;
1075
+ }
1076
+ return startIndex;
1077
+ }
1078
+ /**
1079
+ * Parse a null value
1080
+ */
1081
+ parseNull(startIndex) {
1082
+ const remaining = this.state.buffer.slice(startIndex);
1083
+ if (remaining.startsWith("null")) {
1084
+ this.setValue(null);
1085
+ return startIndex + 3;
1086
+ }
1087
+ return startIndex;
1088
+ }
1089
+ /**
1090
+ * Parse a number value
1091
+ */
1092
+ parseNumber(startIndex) {
1093
+ const remaining = this.state.buffer.slice(startIndex);
1094
+ const match = remaining.match(/^-?\d+(\.\d+)?([eE][+-]?\d+)?/);
1095
+ if (match) {
1096
+ const numStr = match[0];
1097
+ const value = numStr.includes(".") || numStr.includes("e") || numStr.includes("E") ? parseFloat(numStr) : parseInt(numStr, 10);
1098
+ this.setValue(value);
1099
+ return startIndex + numStr.length - 1;
1100
+ }
1101
+ return startIndex;
1102
+ }
1103
+ /**
1104
+ * Set a value at the current path
1105
+ */
1106
+ setValue(value) {
1107
+ let path;
1108
+ if (this.state.currentKey !== null) {
1109
+ path = [...this.state.currentPath, this.state.currentKey];
1110
+ this.state.currentKey = null;
1111
+ } else if (this.getCurrentContainer() === "array") {
1112
+ path = [...this.state.currentPath];
1113
+ } else {
1114
+ path = [...this.state.currentPath];
1115
+ }
1116
+ this.setNestedValue(this.result, path, value);
1117
+ this.pendingUpdates.push({
1118
+ path,
1119
+ value,
1120
+ complete: true
1121
+ });
1122
+ }
1123
+ /**
1124
+ * Get current container type
1125
+ */
1126
+ getCurrentContainer() {
1127
+ if (this.state.containerStack.length === 0) {
1128
+ return null;
1129
+ }
1130
+ return this.state.containerStack[this.state.containerStack.length - 1];
1131
+ }
1132
+ /**
1133
+ * Set a nested value in an object
1134
+ */
1135
+ setNestedValue(obj, path, value) {
1136
+ if (path.length === 0) {
1137
+ return;
1138
+ }
1139
+ let current = obj;
1140
+ for (let i = 0; i < path.length - 1; i++) {
1141
+ const key = path[i];
1142
+ if (typeof current !== "object" || current === null) {
1143
+ return;
1144
+ }
1145
+ const currentObj = current;
1146
+ if (!(key in currentObj)) {
1147
+ const nextKey = path[i + 1];
1148
+ currentObj[key] = /^\d+$/.test(nextKey) ? [] : {};
1149
+ }
1150
+ current = currentObj[key];
1151
+ }
1152
+ const lastKey = path[path.length - 1];
1153
+ if (typeof current === "object" && current !== null) {
1154
+ current[lastKey] = value;
1155
+ }
1156
+ }
1157
+ /**
1158
+ * Get a nested value from an object
1159
+ */
1160
+ getNestedValue(obj, path) {
1161
+ if (path.length === 0) {
1162
+ return obj;
1163
+ }
1164
+ let current = obj;
1165
+ for (const key of path) {
1166
+ if (typeof current !== "object" || current === null) {
1167
+ return void 0;
1168
+ }
1169
+ current = current[key];
1170
+ }
1171
+ return current;
1172
+ }
1173
+ /**
1174
+ * Finalize parsing - try to complete any partial values
1175
+ */
1176
+ finalize() {
1177
+ if (this.state.buffer.trim()) {
1178
+ try {
1179
+ const parsed = JSON.parse(this.state.buffer);
1180
+ this.result = parsed;
1181
+ } catch {
1182
+ }
1183
+ }
1184
+ }
1185
+ };
1186
+ }
1187
+ });
1188
+
1189
+ // src/streaming/StreamingExtractor.ts
1190
+ var StreamingExtractor_exports = {};
1191
+ __export(StreamingExtractor_exports, {
1192
+ createStreamingResult: () => createStreamingResult,
1193
+ getPartialState: () => getPartialState
1194
+ });
1195
+ function createStreamingResult(_client, provider, options, streamingOptions) {
1196
+ const emitter = new EventEmitter();
1197
+ const parser = new IncrementalJsonParser();
1198
+ let isComplete = false;
1199
+ const current = {};
1200
+ let finalResult;
1201
+ let error;
1202
+ let cancelled = false;
1203
+ const metadata = {
1204
+ totalChunks: 0,
1205
+ totalChars: 0,
1206
+ startTime: Date.now()
1207
+ };
1208
+ const streamPromise = executeStreamingExtraction();
1209
+ async function executeStreamingExtraction() {
1210
+ try {
1211
+ const jsonSchema = zodToJsonSchema(options.response_format);
1212
+ const messages = prepareMessages(
1213
+ options.messages,
1214
+ options.response_format
1215
+ );
1216
+ const stream = provider.createStreamingCompletion({
1217
+ model: options.model,
1218
+ messages,
1219
+ mode: "json",
1220
+ jsonSchema,
1221
+ stream: true
1222
+ });
1223
+ for await (const chunk of stream) {
1224
+ if (cancelled) {
1225
+ break;
1226
+ }
1227
+ metadata.totalChunks++;
1228
+ metadata.totalChars += chunk.content.length;
1229
+ const updates = parser.feed(chunk.content);
1230
+ for (const update of updates) {
1231
+ const fieldUpdate = {
1232
+ path: update.path.join("."),
1233
+ value: update.value,
1234
+ complete: update.complete,
1235
+ timestamp: Date.now()
1236
+ };
1237
+ setNestedValue(current, update.path, update.value);
1238
+ if (streamingOptions?.onFieldComplete && update.complete) {
1239
+ streamingOptions.onFieldComplete(fieldUpdate.path, update.value);
1240
+ }
1241
+ emitter.emit("field", {
1242
+ path: fieldUpdate.path,
1243
+ value: update.value
1244
+ });
1245
+ if (shouldEmitPartial(current, streamingOptions)) {
1246
+ if (streamingOptions?.onPartial) {
1247
+ streamingOptions.onPartial(current, update.path.join("."));
1248
+ }
1249
+ emitter.emit("partial", {
1250
+ data: current,
1251
+ path: update.path.join(".")
1252
+ });
1253
+ }
1254
+ }
1255
+ if (chunk.isFinal) {
1256
+ metadata.endTime = Date.now();
1257
+ metadata.usage = chunk.usage;
1258
+ break;
1259
+ }
1260
+ }
1261
+ const parsedResult = parser.getResult();
1262
+ const validation = options.response_format.safeParse(parsedResult);
1263
+ if (validation.success) {
1264
+ finalResult = validation.data;
1265
+ isComplete = true;
1266
+ emitter.emit("complete", { data: finalResult });
1267
+ } else {
1268
+ error = new Error(
1269
+ `Validation failed: ${validation.error.issues.map((i) => i.message).join(", ")}`
1270
+ );
1271
+ emitter.emit("error", { error });
1272
+ }
1273
+ } catch (err) {
1274
+ error = err instanceof Error ? err : new Error(String(err));
1275
+ emitter.emit("error", { error });
1276
+ if (streamingOptions?.onError) {
1277
+ streamingOptions.onError(error);
1278
+ }
1279
+ }
1280
+ }
1281
+ function prepareMessages(messages, schema) {
1282
+ const prompt = schemaToPrompt(schema, {
1283
+ format: "json-schema",
1284
+ includeConstraints: true
1285
+ });
1286
+ const systemIndex = messages.findIndex((m) => m.role === "system");
1287
+ if (systemIndex >= 0) {
1288
+ const newMessages = [...messages];
1289
+ newMessages[systemIndex] = {
1290
+ ...newMessages[systemIndex],
1291
+ content: `${newMessages[systemIndex].content}
1292
+
1293
+ Respond with valid JSON matching this schema:
1294
+ ${prompt.text}`
1295
+ };
1296
+ return newMessages;
1297
+ }
1298
+ return [
1299
+ {
1300
+ role: "system",
1301
+ content: `Respond with valid JSON matching this schema:
1302
+ ${prompt.text}`
1303
+ },
1304
+ ...messages
1305
+ ];
1306
+ }
1307
+ function shouldEmitPartial(partial, options2) {
1308
+ if (!options2?.yieldPartials) {
1309
+ return false;
1310
+ }
1311
+ const fieldCount = countFields(partial);
1312
+ const minFields = options2.minFieldsBeforeYield ?? 1;
1313
+ return fieldCount >= minFields;
1314
+ }
1315
+ function countFields(obj, count = 0) {
1316
+ if (typeof obj !== "object" || obj === null) {
1317
+ return count + 1;
1318
+ }
1319
+ if (Array.isArray(obj)) {
1320
+ return obj.reduce((c, item) => countFields(item, c), count);
1321
+ }
1322
+ return Object.values(obj).reduce(
1323
+ (c, value) => countFields(value, c),
1324
+ count
1325
+ );
1326
+ }
1327
+ function setNestedValue(obj, path, value) {
1328
+ let current2 = obj;
1329
+ for (let i = 0; i < path.length - 1; i++) {
1330
+ const key = path[i];
1331
+ if (!(key in current2)) {
1332
+ const nextKey = path[i + 1];
1333
+ current2[key] = /^\d+$/.test(nextKey) ? [] : {};
1334
+ }
1335
+ current2 = current2[key];
1336
+ }
1337
+ const lastKey = path[path.length - 1];
1338
+ current2[lastKey] = value;
1339
+ }
1340
+ return {
1341
+ async *partials() {
1342
+ const partialQueue = [];
1343
+ let resolveNext = null;
1344
+ let done = false;
1345
+ const onPartial = ({ data }) => {
1346
+ if (resolveNext) {
1347
+ resolveNext({ value: { ...data }, done: false });
1348
+ resolveNext = null;
1349
+ } else {
1350
+ partialQueue.push({ ...data });
1351
+ }
1352
+ };
1353
+ const onComplete = () => {
1354
+ done = true;
1355
+ if (resolveNext) {
1356
+ resolveNext({
1357
+ value: void 0,
1358
+ done: true
1359
+ });
1360
+ resolveNext = null;
1361
+ }
1362
+ };
1363
+ const onError = () => {
1364
+ done = true;
1365
+ if (resolveNext) {
1366
+ resolveNext({
1367
+ value: void 0,
1368
+ done: true
1369
+ });
1370
+ resolveNext = null;
1371
+ }
1372
+ };
1373
+ emitter.on("partial", onPartial);
1374
+ emitter.on("complete", onComplete);
1375
+ emitter.on("error", onError);
1376
+ try {
1377
+ while (!done || partialQueue.length > 0) {
1378
+ if (partialQueue.length > 0) {
1379
+ yield partialQueue.shift();
1380
+ } else if (!done) {
1381
+ const result = await new Promise((resolve) => {
1382
+ resolveNext = resolve;
1383
+ });
1384
+ if (!result.done) {
1385
+ yield result.value;
1386
+ }
1387
+ }
1388
+ }
1389
+ } finally {
1390
+ emitter.off("partial", onPartial);
1391
+ emitter.off("complete", onComplete);
1392
+ emitter.off("error", onError);
1393
+ }
1394
+ },
1395
+ async *fields() {
1396
+ const fieldQueue = [];
1397
+ let resolveNext = null;
1398
+ let done = false;
1399
+ const onField = ({ path, value }) => {
1400
+ const update = {
1401
+ path,
1402
+ value,
1403
+ complete: true,
1404
+ timestamp: Date.now()
1405
+ };
1406
+ if (resolveNext) {
1407
+ resolveNext({ value: update, done: false });
1408
+ resolveNext = null;
1409
+ } else {
1410
+ fieldQueue.push(update);
1411
+ }
1412
+ };
1413
+ const onComplete = () => {
1414
+ done = true;
1415
+ if (resolveNext) {
1416
+ resolveNext({
1417
+ value: void 0,
1418
+ done: true
1419
+ });
1420
+ resolveNext = null;
1421
+ }
1422
+ };
1423
+ const onError = () => {
1424
+ done = true;
1425
+ if (resolveNext) {
1426
+ resolveNext({
1427
+ value: void 0,
1428
+ done: true
1429
+ });
1430
+ resolveNext = null;
1431
+ }
1432
+ };
1433
+ emitter.on("field", onField);
1434
+ emitter.on("complete", onComplete);
1435
+ emitter.on("error", onError);
1436
+ try {
1437
+ while (!done || fieldQueue.length > 0) {
1438
+ if (fieldQueue.length > 0) {
1439
+ yield fieldQueue.shift();
1440
+ } else if (!done) {
1441
+ const result = await new Promise(
1442
+ (resolve) => {
1443
+ resolveNext = resolve;
1444
+ }
1445
+ );
1446
+ if (!result.done) {
1447
+ yield result.value;
1448
+ }
1449
+ }
1450
+ }
1451
+ } finally {
1452
+ emitter.off("field", onField);
1453
+ emitter.off("complete", onComplete);
1454
+ emitter.off("error", onError);
1455
+ }
1456
+ },
1457
+ async final() {
1458
+ await streamPromise;
1459
+ if (error) {
1460
+ throw error;
1461
+ }
1462
+ if (!finalResult) {
1463
+ throw new Error("Stream completed without valid result");
1464
+ }
1465
+ return finalResult;
1466
+ },
1467
+ onPartial(callback) {
1468
+ emitter.on("partial", ({ data, path }) => callback(data, path));
1469
+ },
1470
+ onField(callback) {
1471
+ emitter.on("field", ({ path, value }) => callback(path, value));
1472
+ },
1473
+ onComplete(callback) {
1474
+ emitter.on("complete", ({ data }) => callback(data));
1475
+ },
1476
+ onError(callback) {
1477
+ emitter.on("error", ({ error: error2 }) => callback(error2));
1478
+ },
1479
+ cancel() {
1480
+ cancelled = true;
1481
+ },
1482
+ get isComplete() {
1483
+ return isComplete;
1484
+ },
1485
+ get current() {
1486
+ return { ...current };
1487
+ }
1488
+ };
1489
+ }
1490
+ function getPartialState(schema, partial) {
1491
+ const fieldPaths = getAllFieldPaths(partial);
1492
+ const schemaFieldPaths = getSchemaFieldPaths(schema);
1493
+ const completedFields = fieldPaths.filter((p) => {
1494
+ const value = getNestedValue2(partial, p);
1495
+ return value !== void 0;
1496
+ });
1497
+ const inProgressFields = schemaFieldPaths.filter(
1498
+ (p) => !completedFields.includes(p)
1499
+ );
1500
+ const validation = validatePartial(schema, partial);
1501
+ return {
1502
+ data: partial,
1503
+ completedFields,
1504
+ inProgressFields,
1505
+ completionPercent: completedFields.length / schemaFieldPaths.length * 100,
1506
+ isValid: validation.success
1507
+ };
1508
+ }
1509
+ function getAllFieldPaths(obj, prefix = "", paths = []) {
1510
+ if (typeof obj !== "object" || obj === null) {
1511
+ if (prefix) {
1512
+ paths.push(prefix);
1513
+ }
1514
+ return paths;
1515
+ }
1516
+ if (Array.isArray(obj)) {
1517
+ obj.forEach((item, index) => {
1518
+ getAllFieldPaths(item, `${prefix}[${index}]`, paths);
1519
+ });
1520
+ return paths;
1521
+ }
1522
+ for (const [key, value] of Object.entries(obj)) {
1523
+ const newPrefix = prefix ? `${prefix}.${key}` : key;
1524
+ getAllFieldPaths(value, newPrefix, paths);
1525
+ }
1526
+ return paths;
1527
+ }
1528
+ function getSchemaFieldPaths(schema, prefix = "") {
1529
+ const paths = [];
1530
+ if (schema instanceof z.ZodObject) {
1531
+ const shape = schema.shape;
1532
+ for (const [key, fieldSchema] of Object.entries(shape)) {
1533
+ const newPrefix = prefix ? `${prefix}.${key}` : key;
1534
+ paths.push(...getSchemaFieldPaths(fieldSchema, newPrefix));
1535
+ }
1536
+ } else if (schema instanceof z.ZodArray) {
1537
+ if (prefix) {
1538
+ paths.push(prefix);
1539
+ }
1540
+ } else {
1541
+ if (prefix) {
1542
+ paths.push(prefix);
1543
+ }
1544
+ }
1545
+ return paths.length > 0 ? paths : [prefix].filter(Boolean);
1546
+ }
1547
+ function getNestedValue2(obj, path) {
1548
+ const parts = path.replace(/\[(\d+)\]/g, ".$1").split(".");
1549
+ let current = obj;
1550
+ for (const part of parts) {
1551
+ if (typeof current !== "object" || current === null) {
1552
+ return void 0;
1553
+ }
1554
+ current = current[part];
1555
+ }
1556
+ return current;
1557
+ }
1558
+ var init_StreamingExtractor = __esm({
1559
+ "src/streaming/StreamingExtractor.ts"() {
1560
+ init_SchemaToPrompt();
1561
+ init_SchemaValidator();
1562
+ init_IncrementalJsonParser();
1563
+ }
1564
+ });
1565
+
1566
+ // src/core/StructuredClient.ts
1567
+ init_SchemaToPrompt();
1568
+ init_SchemaValidator();
1569
+ var DEFAULT_RETRY_CONFIG = {
1570
+ maxAttempts: 3,
1571
+ backoffMultiplier: 1.5,
1572
+ initialDelay: 1e3,
1573
+ maxDelay: 1e4,
1574
+ retryOn: ["validation_error", "parse_error"]
1575
+ };
1576
+ var StructuredClient = class extends EventEmitter {
1577
+ provider;
1578
+ config;
1579
+ constructor(provider, config = {}) {
1580
+ super();
1581
+ this.provider = provider;
1582
+ this.config = {
1583
+ defaultMode: config.defaultMode ?? "json",
1584
+ defaultRetry: { ...DEFAULT_RETRY_CONFIG, ...config.defaultRetry },
1585
+ enableFixHints: config.enableFixHints ?? true,
1586
+ validatePartials: config.validatePartials ?? false,
1587
+ ...config
1588
+ };
1589
+ }
1590
+ /**
1591
+ * Extract structured data from an LLM response
1592
+ */
1593
+ async extract(options) {
1594
+ const requestId = this.generateRequestId();
1595
+ const startTime = Date.now();
1596
+ const attempts = [];
1597
+ const mode = this.resolveMode(options.mode);
1598
+ const retryConfig = {
1599
+ ...DEFAULT_RETRY_CONFIG,
1600
+ ...this.config.defaultRetry,
1601
+ ...options.retry
1602
+ };
1603
+ this.emit("extraction:start", { requestId, mode });
1604
+ let lastError;
1605
+ let currentMode = mode;
1606
+ const totalTokens = {
1607
+ promptTokens: 0,
1608
+ completionTokens: 0,
1609
+ totalTokens: 0
1610
+ };
1611
+ for (let attempt = 1; attempt <= retryConfig.maxAttempts; attempt++) {
1612
+ this.emit("extraction:attempt", {
1613
+ requestId,
1614
+ attempt,
1615
+ mode: currentMode
1616
+ });
1617
+ try {
1618
+ const result = await this.executeExtraction(
1619
+ options,
1620
+ currentMode,
1621
+ attempts,
1622
+ attempt
1623
+ );
1624
+ if (result.usage) {
1625
+ totalTokens.promptTokens += result.usage.promptTokens;
1626
+ totalTokens.completionTokens += result.usage.completionTokens;
1627
+ totalTokens.totalTokens += result.usage.totalTokens;
1628
+ }
1629
+ const validation = validateSchema(
1630
+ options.response_format,
1631
+ result.content
1632
+ );
1633
+ if (validation.success) {
1634
+ const attemptRecord = {
1635
+ attempt,
1636
+ mode: currentMode,
1637
+ success: true,
1638
+ duration: Date.now() - startTime,
1639
+ rawResponse: result.rawResponse
1640
+ };
1641
+ attempts.push(attemptRecord);
1642
+ this.emit("extraction:success", {
1643
+ requestId,
1644
+ data: validation.data,
1645
+ attempts: attempt
1646
+ });
1647
+ return {
1648
+ success: true,
1649
+ data: validation.data,
1650
+ raw: result.rawResponse,
1651
+ metadata: this.createMetadata(
1652
+ startTime,
1653
+ attempts,
1654
+ totalTokens,
1655
+ options.model
1656
+ )
1657
+ };
1658
+ }
1659
+ const validationErrors = validation.errors ?? [];
1660
+ this.emit("validation:failed", { requestId, errors: validationErrors });
1661
+ const hints = this.config.enableFixHints ? getValidationHints(options.response_format, result.content) : [];
1662
+ attempts.push({
1663
+ attempt,
1664
+ mode: currentMode,
1665
+ success: false,
1666
+ duration: Date.now() - startTime,
1667
+ rawResponse: result.rawResponse,
1668
+ error: "Validation failed",
1669
+ validationErrors
1670
+ });
1671
+ lastError = this.createStructuredError(
1672
+ "Validation failed",
1673
+ "VALIDATION_ERROR",
1674
+ attempts,
1675
+ validationErrors,
1676
+ result.content
1677
+ );
1678
+ if (attempt < retryConfig.maxAttempts && this.shouldRetry("validation_error", retryConfig, attempt)) {
1679
+ this.emit("extraction:retry", {
1680
+ requestId,
1681
+ attempt,
1682
+ reason: "validation_error",
1683
+ hints
1684
+ });
1685
+ if (hints.length > 0 && this.config.enableFixHints) {
1686
+ options = this.addFixHintsToMessages(
1687
+ options,
1688
+ hints,
1689
+ validationErrors
1690
+ );
1691
+ }
1692
+ await this.delay(this.calculateBackoff(attempt, retryConfig));
1693
+ if (this.shouldSwitchMode(currentMode, attempt, options.mode)) {
1694
+ const newMode = this.getNextMode(currentMode);
1695
+ this.emit("mode:switch", {
1696
+ requestId,
1697
+ from: currentMode,
1698
+ to: newMode
1699
+ });
1700
+ currentMode = newMode;
1701
+ }
1702
+ continue;
1703
+ }
1704
+ } catch (error) {
1705
+ const err = error instanceof Error ? error : new Error(String(error));
1706
+ this.emit("extraction:error", { requestId, error: err, attempt });
1707
+ const errorType = this.classifyError(err);
1708
+ attempts.push({
1709
+ attempt,
1710
+ mode: currentMode,
1711
+ success: false,
1712
+ duration: Date.now() - startTime,
1713
+ error: err.message
1714
+ });
1715
+ lastError = err;
1716
+ if (attempt < retryConfig.maxAttempts && this.shouldRetry(errorType, retryConfig, attempt)) {
1717
+ this.emit("extraction:retry", {
1718
+ requestId,
1719
+ attempt,
1720
+ reason: errorType,
1721
+ hints: []
1722
+ });
1723
+ await this.delay(this.calculateBackoff(attempt, retryConfig));
1724
+ continue;
1725
+ }
1726
+ }
1727
+ }
1728
+ return {
1729
+ success: false,
1730
+ error: lastError ?? new Error("All extraction attempts failed"),
1731
+ raw: attempts[attempts.length - 1]?.rawResponse,
1732
+ metadata: this.createMetadata(
1733
+ startTime,
1734
+ attempts,
1735
+ totalTokens,
1736
+ options.model
1737
+ )
1738
+ };
1739
+ }
1740
+ /**
1741
+ * Extract with streaming partial results
1742
+ */
1743
+ async extractStream(options, streamingOptions) {
1744
+ const { createStreamingResult: createStreamingResult2 } = await Promise.resolve().then(() => (init_StreamingExtractor(), StreamingExtractor_exports));
1745
+ return createStreamingResult2(
1746
+ this,
1747
+ this.provider,
1748
+ options,
1749
+ streamingOptions
1750
+ );
1751
+ }
1752
+ /**
1753
+ * Execute a single extraction attempt
1754
+ */
1755
+ async executeExtraction(options, mode, _previousAttempts, _attempt) {
1756
+ const { model, messages } = options;
1757
+ const jsonSchema = zodToJsonSchema(options.response_format);
1758
+ let response;
1759
+ switch (mode) {
1760
+ case "json":
1761
+ response = await this.extractWithJsonMode(model, messages, jsonSchema);
1762
+ break;
1763
+ case "tool":
1764
+ response = await this.extractWithToolMode(
1765
+ model,
1766
+ messages,
1767
+ jsonSchema,
1768
+ options.response_format
1769
+ );
1770
+ break;
1771
+ case "prompt":
1772
+ response = await this.extractWithPromptMode(
1773
+ model,
1774
+ messages,
1775
+ options.response_format
1776
+ );
1777
+ break;
1778
+ case "hybrid":
1779
+ response = await this.extractWithJsonMode(model, messages, jsonSchema);
1780
+ break;
1781
+ default:
1782
+ throw new Error(`Unknown extraction mode: ${mode}`);
1783
+ }
1784
+ const content = this.parseResponse(response, mode);
1785
+ return {
1786
+ content,
1787
+ rawResponse: response.content,
1788
+ usage: response.usage
1789
+ };
1790
+ }
1791
+ /**
1792
+ * Extract using JSON mode
1793
+ */
1794
+ async extractWithJsonMode(model, messages, jsonSchema) {
1795
+ return this.provider.createCompletion({
1796
+ model,
1797
+ messages,
1798
+ mode: "json",
1799
+ jsonSchema
1800
+ });
1801
+ }
1802
+ /**
1803
+ * Extract using tool/function calling mode
1804
+ */
1805
+ async extractWithToolMode(model, messages, jsonSchema, _schema) {
1806
+ const toolDefinition = {
1807
+ type: "function",
1808
+ function: {
1809
+ name: "extract_data",
1810
+ description: "Extract structured data from the response",
1811
+ parameters: jsonSchema,
1812
+ strict: true
1813
+ }
1814
+ };
1815
+ return this.provider.createCompletion({
1816
+ model,
1817
+ messages,
1818
+ mode: "tool",
1819
+ toolDefinition
1820
+ });
1821
+ }
1822
+ /**
1823
+ * Extract using prompt engineering mode
1824
+ */
1825
+ async extractWithPromptMode(model, messages, schema) {
1826
+ const prompt = schemaToPrompt(schema, {
1827
+ format: "natural",
1828
+ includeConstraints: true,
1829
+ includeExamples: true
1830
+ });
1831
+ const enhancedMessages = this.addSchemaPromptToMessages(
1832
+ messages,
1833
+ prompt.text
1834
+ );
1835
+ return this.provider.createCompletion({
1836
+ model,
1837
+ messages: enhancedMessages,
1838
+ mode: "prompt"
1839
+ });
1840
+ }
1841
+ /**
1842
+ * Parse the response based on mode
1843
+ */
1844
+ parseResponse(response, mode) {
1845
+ if (mode === "tool" && response.toolCalls && response.toolCalls.length > 0) {
1846
+ try {
1847
+ return JSON.parse(response.toolCalls[0].arguments);
1848
+ } catch {
1849
+ throw new Error("Failed to parse tool call arguments");
1850
+ }
1851
+ }
1852
+ return this.extractJsonFromContent(response.content);
1853
+ }
1854
+ /**
1855
+ * Extract JSON from text content
1856
+ */
1857
+ extractJsonFromContent(content) {
1858
+ try {
1859
+ return JSON.parse(content);
1860
+ } catch {
1861
+ }
1862
+ const codeBlockMatch = content.match(/```(?:json)?\s*([\s\S]*?)```/);
1863
+ if (codeBlockMatch) {
1864
+ try {
1865
+ return JSON.parse(codeBlockMatch[1].trim());
1866
+ } catch {
1867
+ }
1868
+ }
1869
+ const jsonMatch = content.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
1870
+ if (jsonMatch) {
1871
+ try {
1872
+ return JSON.parse(jsonMatch[1]);
1873
+ } catch {
1874
+ }
1875
+ }
1876
+ throw new Error("No valid JSON found in response");
1877
+ }
1878
+ /**
1879
+ * Add schema prompt to messages
1880
+ */
1881
+ addSchemaPromptToMessages(messages, schemaPrompt) {
1882
+ const systemIndex = messages.findIndex((m) => m.role === "system");
1883
+ if (systemIndex >= 0) {
1884
+ const newMessages = [...messages];
1885
+ newMessages[systemIndex] = {
1886
+ ...newMessages[systemIndex],
1887
+ content: `${newMessages[systemIndex].content}
1888
+
1889
+ ${schemaPrompt}
1890
+
1891
+ Respond with valid JSON only.`
1892
+ };
1893
+ return newMessages;
1894
+ }
1895
+ return [
1896
+ {
1897
+ role: "system",
1898
+ content: `${schemaPrompt}
1899
+
1900
+ Respond with valid JSON only.`
1901
+ },
1902
+ ...messages
1903
+ ];
1904
+ }
1905
+ /**
1906
+ * Add fix hints to messages for retry
1907
+ */
1908
+ addFixHintsToMessages(options, hints, errors) {
1909
+ const hintsText = hints.join("\n");
1910
+ const errorsText = errors.map((e) => `- ${e.path.join(".")}: ${e.message}`).join("\n");
1911
+ const fixPrompt = `Your previous response had validation errors:
1912
+ ${errorsText}
1913
+
1914
+ Please fix these issues:
1915
+ ${hintsText}`;
1916
+ const newMessages = [
1917
+ ...options.messages,
1918
+ {
1919
+ role: "user",
1920
+ content: fixPrompt
1921
+ }
1922
+ ];
1923
+ return {
1924
+ ...options,
1925
+ messages: newMessages
1926
+ };
1927
+ }
1928
+ /**
1929
+ * Resolve the extraction mode
1930
+ */
1931
+ resolveMode(modeConfig) {
1932
+ if (!modeConfig) {
1933
+ return this.config.defaultMode ?? "json";
1934
+ }
1935
+ if (typeof modeConfig === "string") {
1936
+ return modeConfig;
1937
+ }
1938
+ return modeConfig.mode;
1939
+ }
1940
+ /**
1941
+ * Check if we should retry
1942
+ */
1943
+ shouldRetry(errorType, config, _attempt) {
1944
+ return (config.retryOn ?? []).includes(
1945
+ errorType
1946
+ );
1947
+ }
1948
+ /**
1949
+ * Classify an error for retry logic
1950
+ */
1951
+ classifyError(error) {
1952
+ const message = error.message.toLowerCase();
1953
+ if (message.includes("rate limit") || message.includes("429")) {
1954
+ return "rate_limit";
1955
+ }
1956
+ if (message.includes("timeout")) {
1957
+ return "timeout";
1958
+ }
1959
+ if (message.includes("json") || message.includes("parse")) {
1960
+ return "parse_error";
1961
+ }
1962
+ if (message.includes("validation")) {
1963
+ return "validation_error";
1964
+ }
1965
+ return "unknown_error";
1966
+ }
1967
+ /**
1968
+ * Check if mode should be switched (for hybrid mode)
1969
+ */
1970
+ shouldSwitchMode(_currentMode, attempt, modeConfig) {
1971
+ if (!modeConfig || typeof modeConfig === "string") {
1972
+ return false;
1973
+ }
1974
+ if (!("mode" in modeConfig) || modeConfig.mode !== "hybrid") {
1975
+ return false;
1976
+ }
1977
+ const hybridConfig = modeConfig;
1978
+ return attempt > 0 && !!hybridConfig.fallbackOrder && hybridConfig.fallbackOrder.length > 0;
1979
+ }
1980
+ /**
1981
+ * Get next mode in fallback order
1982
+ */
1983
+ getNextMode(currentMode) {
1984
+ const fallbackOrder = ["json", "tool", "prompt"];
1985
+ const currentIndex = fallbackOrder.indexOf(currentMode);
1986
+ if (currentIndex < fallbackOrder.length - 1) {
1987
+ return fallbackOrder[currentIndex + 1];
1988
+ }
1989
+ return fallbackOrder[0];
1990
+ }
1991
+ /**
1992
+ * Calculate backoff delay
1993
+ */
1994
+ calculateBackoff(attempt, config) {
1995
+ const delay = (config.initialDelay ?? 1e3) * Math.pow(config.backoffMultiplier ?? 1.5, attempt - 1);
1996
+ return Math.min(delay, config.maxDelay ?? 1e4);
1997
+ }
1998
+ /**
1999
+ * Delay helper
2000
+ */
2001
+ delay(ms) {
2002
+ return new Promise((resolve) => setTimeout(resolve, ms));
2003
+ }
2004
+ /**
2005
+ * Generate a request ID
2006
+ */
2007
+ generateRequestId() {
2008
+ return `req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
2009
+ }
2010
+ /**
2011
+ * Create extraction metadata
2012
+ */
2013
+ createMetadata(startTime, attempts, usage, model) {
2014
+ return {
2015
+ totalAttempts: attempts.length,
2016
+ totalDuration: Date.now() - startTime,
2017
+ finalMode: attempts[attempts.length - 1]?.mode ?? "json",
2018
+ tokenUsage: usage,
2019
+ attempts,
2020
+ model
2021
+ };
2022
+ }
2023
+ /**
2024
+ * Create a structured error
2025
+ */
2026
+ createStructuredError(message, code, attempts, validationErrors, partial) {
2027
+ const error = new Error(message);
2028
+ error.name = "StructuredError";
2029
+ error.code = code;
2030
+ error.attempts = attempts;
2031
+ error.validationErrors = validationErrors;
2032
+ error.partial = partial;
2033
+ return error;
2034
+ }
2035
+ /**
2036
+ * Get provider capabilities
2037
+ */
2038
+ getProviderCapabilities(model) {
2039
+ return this.provider.getCapabilities(model);
2040
+ }
2041
+ /**
2042
+ * Check if a mode is supported
2043
+ */
2044
+ supportsMode(mode, model) {
2045
+ const capabilities = this.provider.getCapabilities(model);
2046
+ switch (mode) {
2047
+ case "json":
2048
+ return capabilities.jsonMode;
2049
+ case "tool":
2050
+ return capabilities.toolCalling;
2051
+ case "prompt":
2052
+ return true;
2053
+ // Always supported
2054
+ case "hybrid":
2055
+ return capabilities.jsonMode || capabilities.toolCalling;
2056
+ default:
2057
+ return false;
2058
+ }
2059
+ }
2060
+ };
2061
+ function createStructuredClient(provider, config) {
2062
+ return new StructuredClient(provider, config);
2063
+ }
2064
+
2065
+ // src/schema/index.ts
2066
+ init_SchemaToPrompt();
2067
+ init_SchemaValidator();
2068
+
2069
+ // src/streaming/index.ts
2070
+ init_StreamingExtractor();
2071
+ init_IncrementalJsonParser();
2072
+
2073
+ // src/providers/OpenAIAdapter.ts
2074
+ var MODEL_CAPABILITIES = {
2075
+ "gpt-4o": {
2076
+ jsonMode: true,
2077
+ strictJsonMode: true,
2078
+ toolCalling: true,
2079
+ streaming: true,
2080
+ systemMessages: true,
2081
+ maxContextWindow: 128e3,
2082
+ maxOutputTokens: 16384
2083
+ },
2084
+ "gpt-4o-mini": {
2085
+ jsonMode: true,
2086
+ strictJsonMode: true,
2087
+ toolCalling: true,
2088
+ streaming: true,
2089
+ systemMessages: true,
2090
+ maxContextWindow: 128e3,
2091
+ maxOutputTokens: 16384
2092
+ },
2093
+ "gpt-4-turbo": {
2094
+ jsonMode: true,
2095
+ strictJsonMode: false,
2096
+ toolCalling: true,
2097
+ streaming: true,
2098
+ systemMessages: true,
2099
+ maxContextWindow: 128e3,
2100
+ maxOutputTokens: 4096
2101
+ },
2102
+ "gpt-4": {
2103
+ jsonMode: true,
2104
+ strictJsonMode: false,
2105
+ toolCalling: true,
2106
+ streaming: true,
2107
+ systemMessages: true,
2108
+ maxContextWindow: 8192,
2109
+ maxOutputTokens: 4096
2110
+ },
2111
+ "gpt-3.5-turbo": {
2112
+ jsonMode: true,
2113
+ strictJsonMode: false,
2114
+ toolCalling: true,
2115
+ streaming: true,
2116
+ systemMessages: true,
2117
+ maxContextWindow: 16385,
2118
+ maxOutputTokens: 4096
2119
+ },
2120
+ "o1-preview": {
2121
+ jsonMode: false,
2122
+ strictJsonMode: false,
2123
+ toolCalling: false,
2124
+ streaming: false,
2125
+ systemMessages: false,
2126
+ maxContextWindow: 128e3,
2127
+ maxOutputTokens: 32768
2128
+ },
2129
+ "o1-mini": {
2130
+ jsonMode: false,
2131
+ strictJsonMode: false,
2132
+ toolCalling: false,
2133
+ streaming: false,
2134
+ systemMessages: false,
2135
+ maxContextWindow: 128e3,
2136
+ maxOutputTokens: 65536
2137
+ }
2138
+ };
2139
+ var OpenAIAdapter = class {
2140
+ name = "openai";
2141
+ client;
2142
+ constructor(client, _options = {}) {
2143
+ this.client = client;
2144
+ }
2145
+ /**
2146
+ * Get capabilities for a model
2147
+ */
2148
+ getCapabilities(model) {
2149
+ const base = MODEL_CAPABILITIES[model] ?? MODEL_CAPABILITIES["gpt-4o"];
2150
+ return {
2151
+ jsonMode: base.jsonMode ?? true,
2152
+ strictJsonMode: base.strictJsonMode ?? false,
2153
+ toolCalling: base.toolCalling ?? true,
2154
+ streaming: base.streaming ?? true,
2155
+ systemMessages: base.systemMessages ?? true,
2156
+ maxContextWindow: base.maxContextWindow,
2157
+ maxOutputTokens: base.maxOutputTokens
2158
+ };
2159
+ }
2160
+ /**
2161
+ * Check if JSON mode is available
2162
+ */
2163
+ supportsJsonMode(model) {
2164
+ return this.getCapabilities(model).jsonMode;
2165
+ }
2166
+ /**
2167
+ * Check if tool calling is available
2168
+ */
2169
+ supportsToolCalling(model) {
2170
+ return this.getCapabilities(model).toolCalling;
2171
+ }
2172
+ /**
2173
+ * Create a completion request
2174
+ */
2175
+ async createCompletion(request) {
2176
+ const params = this.buildRequestParams(request);
2177
+ const response = await this.client.chat.completions.create(params);
2178
+ return this.parseResponse(response);
2179
+ }
2180
+ /**
2181
+ * Create a streaming completion request
2182
+ */
2183
+ async *createStreamingCompletion(request) {
2184
+ const params = this.buildRequestParams(request);
2185
+ params.stream = true;
2186
+ params.stream_options = { include_usage: true };
2187
+ const stream = await this.client.chat.completions.create(params);
2188
+ const asyncStream = stream;
2189
+ const toolCalls = /* @__PURE__ */ new Map();
2190
+ for await (const chunk of asyncStream) {
2191
+ const choice = chunk.choices[0];
2192
+ if (!choice) continue;
2193
+ const delta = choice.delta;
2194
+ if (delta.tool_calls) {
2195
+ for (const tc of delta.tool_calls) {
2196
+ const existing = toolCalls.get(tc.index) ?? { arguments: "" };
2197
+ if (tc.id) existing.id = tc.id;
2198
+ if (tc.function?.name) existing.name = tc.function.name;
2199
+ if (tc.function?.arguments)
2200
+ existing.arguments += tc.function.arguments;
2201
+ toolCalls.set(tc.index, existing);
2202
+ }
2203
+ }
2204
+ const isFinal = choice.finish_reason !== null;
2205
+ yield {
2206
+ content: delta.content ?? "",
2207
+ isFinal,
2208
+ finishReason: choice.finish_reason ?? void 0,
2209
+ usage: chunk.usage ? {
2210
+ promptTokens: chunk.usage.prompt_tokens,
2211
+ completionTokens: chunk.usage.completion_tokens,
2212
+ totalTokens: chunk.usage.total_tokens
2213
+ } : void 0,
2214
+ toolCallDeltas: delta.tool_calls?.map((tc) => ({
2215
+ index: tc.index,
2216
+ id: tc.id,
2217
+ name: tc.function?.name,
2218
+ arguments: tc.function?.arguments
2219
+ }))
2220
+ };
2221
+ }
2222
+ }
2223
+ /**
2224
+ * Format messages for OpenAI
2225
+ */
2226
+ formatMessages(messages) {
2227
+ return messages.map((msg) => ({
2228
+ role: msg.role,
2229
+ content: msg.content,
2230
+ name: msg.name
2231
+ }));
2232
+ }
2233
+ /**
2234
+ * Format JSON schema for OpenAI
2235
+ */
2236
+ formatJsonSchema(schema) {
2237
+ return {
2238
+ type: "json_schema",
2239
+ json_schema: {
2240
+ name: "response",
2241
+ schema,
2242
+ strict: true
2243
+ }
2244
+ };
2245
+ }
2246
+ /**
2247
+ * Format tool definition for OpenAI
2248
+ */
2249
+ formatToolDefinition(tool) {
2250
+ return {
2251
+ type: "function",
2252
+ function: {
2253
+ name: tool.function.name,
2254
+ description: tool.function.description,
2255
+ parameters: tool.function.parameters,
2256
+ strict: tool.function.strict
2257
+ }
2258
+ };
2259
+ }
2260
+ /**
2261
+ * Build request parameters
2262
+ */
2263
+ buildRequestParams(request) {
2264
+ const params = {
2265
+ model: request.model,
2266
+ messages: this.formatMessages(request.messages),
2267
+ temperature: request.temperature,
2268
+ max_tokens: request.maxTokens
2269
+ };
2270
+ switch (request.mode) {
2271
+ case "json":
2272
+ if (request.jsonSchema) {
2273
+ const caps = this.getCapabilities(request.model);
2274
+ if (caps.strictJsonMode) {
2275
+ params.response_format = {
2276
+ type: "json_schema",
2277
+ json_schema: {
2278
+ name: "response",
2279
+ schema: request.jsonSchema,
2280
+ strict: true
2281
+ }
2282
+ };
2283
+ } else {
2284
+ params.response_format = { type: "json_object" };
2285
+ }
2286
+ }
2287
+ break;
2288
+ case "tool":
2289
+ if (request.toolDefinition) {
2290
+ params.tools = [this.formatToolDefinition(request.toolDefinition)];
2291
+ params.tool_choice = {
2292
+ type: "function",
2293
+ function: { name: request.toolDefinition.function.name }
2294
+ };
2295
+ }
2296
+ break;
2297
+ }
2298
+ if (request.options) {
2299
+ Object.assign(params, request.options);
2300
+ }
2301
+ return params;
2302
+ }
2303
+ /**
2304
+ * Parse response
2305
+ */
2306
+ parseResponse(response) {
2307
+ const choice = response.choices[0];
2308
+ const message = choice?.message;
2309
+ let toolCalls;
2310
+ if (message?.tool_calls && message.tool_calls.length > 0) {
2311
+ toolCalls = message.tool_calls.map((tc) => ({
2312
+ id: tc.id,
2313
+ name: tc.function.name,
2314
+ arguments: tc.function.arguments
2315
+ }));
2316
+ }
2317
+ return {
2318
+ content: message?.content ?? "",
2319
+ usage: response.usage ? {
2320
+ promptTokens: response.usage.prompt_tokens,
2321
+ completionTokens: response.usage.completion_tokens,
2322
+ totalTokens: response.usage.total_tokens
2323
+ } : void 0,
2324
+ finishReason: choice?.finish_reason,
2325
+ toolCalls,
2326
+ raw: response
2327
+ };
2328
+ }
2329
+ };
2330
+ function createOpenAIAdapter(client, options) {
2331
+ return new OpenAIAdapter(client, options);
2332
+ }
2333
+
2334
+ // src/providers/AnthropicAdapter.ts
2335
+ var MODEL_CAPABILITIES2 = {
2336
+ "claude-opus-4-20250514": {
2337
+ jsonMode: false,
2338
+ strictJsonMode: false,
2339
+ toolCalling: true,
2340
+ streaming: true,
2341
+ systemMessages: true,
2342
+ maxContextWindow: 2e5,
2343
+ maxOutputTokens: 32768
2344
+ },
2345
+ "claude-sonnet-4-20250514": {
2346
+ jsonMode: false,
2347
+ strictJsonMode: false,
2348
+ toolCalling: true,
2349
+ streaming: true,
2350
+ systemMessages: true,
2351
+ maxContextWindow: 2e5,
2352
+ maxOutputTokens: 64e3
2353
+ },
2354
+ "claude-3-5-sonnet-20241022": {
2355
+ jsonMode: false,
2356
+ strictJsonMode: false,
2357
+ toolCalling: true,
2358
+ streaming: true,
2359
+ systemMessages: true,
2360
+ maxContextWindow: 2e5,
2361
+ maxOutputTokens: 8192
2362
+ },
2363
+ "claude-3-5-haiku-20241022": {
2364
+ jsonMode: false,
2365
+ strictJsonMode: false,
2366
+ toolCalling: true,
2367
+ streaming: true,
2368
+ systemMessages: true,
2369
+ maxContextWindow: 2e5,
2370
+ maxOutputTokens: 8192
2371
+ },
2372
+ "claude-3-opus-20240229": {
2373
+ jsonMode: false,
2374
+ strictJsonMode: false,
2375
+ toolCalling: true,
2376
+ streaming: true,
2377
+ systemMessages: true,
2378
+ maxContextWindow: 2e5,
2379
+ maxOutputTokens: 4096
2380
+ },
2381
+ "claude-3-sonnet-20240229": {
2382
+ jsonMode: false,
2383
+ strictJsonMode: false,
2384
+ toolCalling: true,
2385
+ streaming: true,
2386
+ systemMessages: true,
2387
+ maxContextWindow: 2e5,
2388
+ maxOutputTokens: 4096
2389
+ },
2390
+ "claude-3-haiku-20240307": {
2391
+ jsonMode: false,
2392
+ strictJsonMode: false,
2393
+ toolCalling: true,
2394
+ streaming: true,
2395
+ systemMessages: true,
2396
+ maxContextWindow: 2e5,
2397
+ maxOutputTokens: 4096
2398
+ }
2399
+ };
2400
+ var AnthropicAdapter = class {
2401
+ name = "anthropic";
2402
+ client;
2403
+ options;
2404
+ constructor(client, options = {}) {
2405
+ this.client = client;
2406
+ this.options = options;
2407
+ }
2408
+ /**
2409
+ * Get capabilities for a model
2410
+ */
2411
+ getCapabilities(model) {
2412
+ const modelKey = Object.keys(MODEL_CAPABILITIES2).find(
2413
+ (key) => model.includes(key) || key.includes(model)
2414
+ );
2415
+ const base = modelKey ? MODEL_CAPABILITIES2[modelKey] : MODEL_CAPABILITIES2["claude-3-5-sonnet-20241022"];
2416
+ return {
2417
+ jsonMode: base.jsonMode ?? false,
2418
+ strictJsonMode: base.strictJsonMode ?? false,
2419
+ toolCalling: base.toolCalling ?? true,
2420
+ streaming: base.streaming ?? true,
2421
+ systemMessages: base.systemMessages ?? true,
2422
+ maxContextWindow: base.maxContextWindow,
2423
+ maxOutputTokens: base.maxOutputTokens
2424
+ };
2425
+ }
2426
+ /**
2427
+ * Check if JSON mode is available
2428
+ */
2429
+ supportsJsonMode(_model) {
2430
+ return false;
2431
+ }
2432
+ /**
2433
+ * Check if tool calling is available
2434
+ */
2435
+ supportsToolCalling(model) {
2436
+ return this.getCapabilities(model).toolCalling;
2437
+ }
2438
+ /**
2439
+ * Create a completion request
2440
+ */
2441
+ async createCompletion(request) {
2442
+ const params = this.buildRequestParams(request);
2443
+ const response = await this.client.messages.create(params);
2444
+ return this.parseResponse(response);
2445
+ }
2446
+ /**
2447
+ * Create a streaming completion request
2448
+ */
2449
+ async *createStreamingCompletion(request) {
2450
+ const params = this.buildRequestParams(request);
2451
+ params.stream = true;
2452
+ const stream = await this.client.messages.create(params);
2453
+ const asyncStream = stream;
2454
+ let toolCallBuffer = null;
2455
+ let inputTokens = 0;
2456
+ let outputTokens = 0;
2457
+ for await (const event of asyncStream) {
2458
+ switch (event.type) {
2459
+ case "message_start":
2460
+ if (event.message?.usage) {
2461
+ inputTokens = event.message.usage.input_tokens;
2462
+ }
2463
+ break;
2464
+ case "content_block_start":
2465
+ if (event.content_block?.type === "tool_use") {
2466
+ toolCallBuffer = {
2467
+ id: event.content_block.id,
2468
+ name: event.content_block.name,
2469
+ arguments: ""
2470
+ };
2471
+ }
2472
+ break;
2473
+ case "content_block_delta":
2474
+ if (event.delta?.type === "text_delta" && event.delta.text) {
2475
+ yield {
2476
+ content: event.delta.text,
2477
+ isFinal: false
2478
+ };
2479
+ } else if (event.delta?.type === "input_json_delta" && event.delta.partial_json) {
2480
+ if (toolCallBuffer) {
2481
+ toolCallBuffer.arguments += event.delta.partial_json;
2482
+ }
2483
+ yield {
2484
+ content: "",
2485
+ isFinal: false,
2486
+ toolCallDeltas: toolCallBuffer ? [
2487
+ {
2488
+ index: 0,
2489
+ id: toolCallBuffer.id,
2490
+ name: toolCallBuffer.name,
2491
+ arguments: event.delta.partial_json
2492
+ }
2493
+ ] : void 0
2494
+ };
2495
+ }
2496
+ break;
2497
+ case "message_delta":
2498
+ if (event.usage) {
2499
+ outputTokens = event.usage.output_tokens;
2500
+ }
2501
+ break;
2502
+ case "message_stop":
2503
+ yield {
2504
+ content: "",
2505
+ isFinal: true,
2506
+ usage: {
2507
+ promptTokens: inputTokens,
2508
+ completionTokens: outputTokens,
2509
+ totalTokens: inputTokens + outputTokens
2510
+ }
2511
+ };
2512
+ break;
2513
+ }
2514
+ }
2515
+ }
2516
+ /**
2517
+ * Format messages for Anthropic
2518
+ */
2519
+ formatMessages(messages) {
2520
+ const systemMessage = messages.find((m) => m.role === "system");
2521
+ const otherMessages = messages.filter((m) => m.role !== "system");
2522
+ return {
2523
+ system: systemMessage?.content,
2524
+ messages: otherMessages.map((msg) => ({
2525
+ role: msg.role === "assistant" ? "assistant" : "user",
2526
+ content: msg.content
2527
+ }))
2528
+ };
2529
+ }
2530
+ /**
2531
+ * Format JSON schema for Anthropic (via tool calling)
2532
+ */
2533
+ formatJsonSchema(schema) {
2534
+ return {
2535
+ name: "extract_structured_data",
2536
+ description: "Extract structured data from the conversation",
2537
+ input_schema: schema
2538
+ };
2539
+ }
2540
+ /**
2541
+ * Format tool definition for Anthropic
2542
+ */
2543
+ formatToolDefinition(tool) {
2544
+ return {
2545
+ name: tool.function.name,
2546
+ description: tool.function.description,
2547
+ input_schema: tool.function.parameters
2548
+ };
2549
+ }
2550
+ /**
2551
+ * Build request parameters
2552
+ */
2553
+ buildRequestParams(request) {
2554
+ const formatted = this.formatMessages(request.messages);
2555
+ const params = {
2556
+ model: request.model,
2557
+ messages: formatted.messages,
2558
+ max_tokens: request.maxTokens ?? 4096
2559
+ };
2560
+ if (formatted.system) {
2561
+ params.system = formatted.system;
2562
+ }
2563
+ if (request.temperature !== void 0) {
2564
+ params.temperature = request.temperature;
2565
+ }
2566
+ switch (request.mode) {
2567
+ case "json":
2568
+ if (request.jsonSchema) {
2569
+ params.tools = [this.formatJsonSchema(request.jsonSchema)];
2570
+ params.tool_choice = {
2571
+ type: "tool",
2572
+ name: "extract_structured_data"
2573
+ };
2574
+ }
2575
+ break;
2576
+ case "tool":
2577
+ if (request.toolDefinition) {
2578
+ params.tools = [this.formatToolDefinition(request.toolDefinition)];
2579
+ params.tool_choice = {
2580
+ type: "tool",
2581
+ name: request.toolDefinition.function.name
2582
+ };
2583
+ }
2584
+ break;
2585
+ case "prompt":
2586
+ if (params.system) {
2587
+ params.system = `${params.system}
2588
+
2589
+ Respond with valid JSON only.`;
2590
+ } else {
2591
+ params.system = "Respond with valid JSON only.";
2592
+ }
2593
+ break;
2594
+ }
2595
+ if (this.options.metadata) {
2596
+ params.metadata = this.options.metadata;
2597
+ }
2598
+ if (request.options) {
2599
+ Object.assign(params, request.options);
2600
+ }
2601
+ return params;
2602
+ }
2603
+ /**
2604
+ * Parse response
2605
+ */
2606
+ parseResponse(response) {
2607
+ let content = "";
2608
+ let toolCalls;
2609
+ for (const block of response.content) {
2610
+ if (block.type === "text" && block.text) {
2611
+ content += block.text;
2612
+ } else if (block.type === "tool_use") {
2613
+ if (!toolCalls) {
2614
+ toolCalls = [];
2615
+ }
2616
+ toolCalls.push({
2617
+ id: block.id ?? "",
2618
+ name: block.name ?? "",
2619
+ arguments: JSON.stringify(block.input)
2620
+ });
2621
+ }
2622
+ }
2623
+ return {
2624
+ content,
2625
+ usage: {
2626
+ promptTokens: response.usage.input_tokens,
2627
+ completionTokens: response.usage.output_tokens,
2628
+ totalTokens: response.usage.input_tokens + response.usage.output_tokens
2629
+ },
2630
+ finishReason: response.stop_reason ?? void 0,
2631
+ toolCalls,
2632
+ raw: response
2633
+ };
2634
+ }
2635
+ };
2636
+ function createAnthropicAdapter(client, options) {
2637
+ return new AnthropicAdapter(client, options);
2638
+ }
2639
+
2640
+ // src/providers/GoogleAdapter.ts
2641
+ var MODEL_CAPABILITIES3 = {
2642
+ "gemini-2.0-flash": {
2643
+ jsonMode: true,
2644
+ strictJsonMode: true,
2645
+ toolCalling: true,
2646
+ streaming: true,
2647
+ systemMessages: true,
2648
+ maxContextWindow: 1e6,
2649
+ maxOutputTokens: 8192
2650
+ },
2651
+ "gemini-2.0-flash-lite": {
2652
+ jsonMode: true,
2653
+ strictJsonMode: true,
2654
+ toolCalling: true,
2655
+ streaming: true,
2656
+ systemMessages: true,
2657
+ maxContextWindow: 1e6,
2658
+ maxOutputTokens: 8192
2659
+ },
2660
+ "gemini-1.5-pro": {
2661
+ jsonMode: true,
2662
+ strictJsonMode: true,
2663
+ toolCalling: true,
2664
+ streaming: true,
2665
+ systemMessages: true,
2666
+ maxContextWindow: 2e6,
2667
+ maxOutputTokens: 8192
2668
+ },
2669
+ "gemini-1.5-flash": {
2670
+ jsonMode: true,
2671
+ strictJsonMode: true,
2672
+ toolCalling: true,
2673
+ streaming: true,
2674
+ systemMessages: true,
2675
+ maxContextWindow: 1e6,
2676
+ maxOutputTokens: 8192
2677
+ },
2678
+ "gemini-1.0-pro": {
2679
+ jsonMode: true,
2680
+ strictJsonMode: false,
2681
+ toolCalling: true,
2682
+ streaming: true,
2683
+ systemMessages: true,
2684
+ maxContextWindow: 32e3,
2685
+ maxOutputTokens: 8192
2686
+ }
2687
+ };
2688
+ var GoogleAdapter = class {
2689
+ name = "google";
2690
+ client;
2691
+ options;
2692
+ constructor(client, options = {}) {
2693
+ this.client = client;
2694
+ this.options = options;
2695
+ }
2696
+ /**
2697
+ * Get capabilities for a model
2698
+ */
2699
+ getCapabilities(model) {
2700
+ const modelKey = Object.keys(MODEL_CAPABILITIES3).find(
2701
+ (key) => model.includes(key) || key.includes(model)
2702
+ );
2703
+ const base = modelKey ? MODEL_CAPABILITIES3[modelKey] : MODEL_CAPABILITIES3["gemini-2.0-flash"];
2704
+ return {
2705
+ jsonMode: base.jsonMode ?? true,
2706
+ strictJsonMode: base.strictJsonMode ?? true,
2707
+ toolCalling: base.toolCalling ?? true,
2708
+ streaming: base.streaming ?? true,
2709
+ systemMessages: base.systemMessages ?? true,
2710
+ maxContextWindow: base.maxContextWindow,
2711
+ maxOutputTokens: base.maxOutputTokens
2712
+ };
2713
+ }
2714
+ /**
2715
+ * Check if JSON mode is available
2716
+ */
2717
+ supportsJsonMode(model) {
2718
+ return this.getCapabilities(model).jsonMode;
2719
+ }
2720
+ /**
2721
+ * Check if tool calling is available
2722
+ */
2723
+ supportsToolCalling(model) {
2724
+ return this.getCapabilities(model).toolCalling;
2725
+ }
2726
+ /**
2727
+ * Create a completion request
2728
+ */
2729
+ async createCompletion(request) {
2730
+ const model = this.getModel(request);
2731
+ const contents = this.formatContents(request.messages);
2732
+ const result = await model.generateContent({ contents });
2733
+ return this.parseResponse(result.response);
2734
+ }
2735
+ /**
2736
+ * Create a streaming completion request
2737
+ */
2738
+ async *createStreamingCompletion(request) {
2739
+ const model = this.getModel(request);
2740
+ const contents = this.formatContents(request.messages);
2741
+ const streamResult = await model.generateContentStream({ contents });
2742
+ for await (const chunk of streamResult.stream) {
2743
+ const text = chunk.text();
2744
+ const candidate = chunk.candidates?.[0];
2745
+ const isFinal = candidate?.finishReason !== void 0;
2746
+ yield {
2747
+ content: text,
2748
+ isFinal,
2749
+ finishReason: candidate?.finishReason,
2750
+ usage: chunk.usageMetadata ? {
2751
+ promptTokens: chunk.usageMetadata.promptTokenCount,
2752
+ completionTokens: chunk.usageMetadata.candidatesTokenCount,
2753
+ totalTokens: chunk.usageMetadata.totalTokenCount
2754
+ } : void 0
2755
+ };
2756
+ }
2757
+ }
2758
+ /**
2759
+ * Format messages for Google
2760
+ */
2761
+ formatMessages(messages) {
2762
+ return this.formatContents(messages);
2763
+ }
2764
+ /**
2765
+ * Format JSON schema for Google
2766
+ */
2767
+ formatJsonSchema(schema) {
2768
+ return {
2769
+ responseMimeType: "application/json",
2770
+ responseSchema: this.convertToGoogleSchema(schema)
2771
+ };
2772
+ }
2773
+ /**
2774
+ * Format tool definition for Google
2775
+ */
2776
+ formatToolDefinition(tool) {
2777
+ return {
2778
+ functionDeclarations: [
2779
+ {
2780
+ name: tool.function.name,
2781
+ description: tool.function.description,
2782
+ parameters: this.convertToGoogleSchema(tool.function.parameters)
2783
+ }
2784
+ ]
2785
+ };
2786
+ }
2787
+ /**
2788
+ * Get the generative model with configuration
2789
+ */
2790
+ getModel(request) {
2791
+ const generationConfig = {};
2792
+ if (request.temperature !== void 0) {
2793
+ generationConfig.temperature = request.temperature;
2794
+ }
2795
+ if (request.maxTokens !== void 0) {
2796
+ generationConfig.maxOutputTokens = request.maxTokens;
2797
+ }
2798
+ let tools;
2799
+ let toolConfig;
2800
+ switch (request.mode) {
2801
+ case "json":
2802
+ if (request.jsonSchema) {
2803
+ generationConfig.responseMimeType = "application/json";
2804
+ generationConfig.responseSchema = this.convertToGoogleSchema(
2805
+ request.jsonSchema
2806
+ );
2807
+ }
2808
+ break;
2809
+ case "tool":
2810
+ if (request.toolDefinition) {
2811
+ tools = [
2812
+ {
2813
+ functionDeclarations: [
2814
+ {
2815
+ name: request.toolDefinition.function.name,
2816
+ description: request.toolDefinition.function.description,
2817
+ parameters: this.convertToGoogleSchema(
2818
+ request.toolDefinition.function.parameters
2819
+ )
2820
+ }
2821
+ ]
2822
+ }
2823
+ ];
2824
+ toolConfig = {
2825
+ functionCallingConfig: {
2826
+ mode: "ANY",
2827
+ allowedFunctionNames: [request.toolDefinition.function.name]
2828
+ }
2829
+ };
2830
+ }
2831
+ break;
2832
+ }
2833
+ if (this.options.generationConfig) {
2834
+ Object.assign(generationConfig, this.options.generationConfig);
2835
+ }
2836
+ return this.client.getGenerativeModel({
2837
+ model: request.model,
2838
+ generationConfig,
2839
+ tools,
2840
+ toolConfig
2841
+ });
2842
+ }
2843
+ /**
2844
+ * Format contents for Google API
2845
+ */
2846
+ formatContents(messages) {
2847
+ const contents = [];
2848
+ const systemMessage = messages.find((m) => m.role === "system");
2849
+ const otherMessages = messages.filter((m) => m.role !== "system");
2850
+ if (systemMessage) {
2851
+ if (otherMessages.length > 0 && otherMessages[0].role === "user") {
2852
+ otherMessages[0] = {
2853
+ ...otherMessages[0],
2854
+ content: `${systemMessage.content}
2855
+
2856
+ ${otherMessages[0].content}`
2857
+ };
2858
+ } else {
2859
+ contents.push({
2860
+ role: "user",
2861
+ parts: [{ text: systemMessage.content }]
2862
+ });
2863
+ }
2864
+ }
2865
+ for (const msg of otherMessages) {
2866
+ contents.push({
2867
+ role: msg.role === "assistant" ? "model" : "user",
2868
+ parts: [{ text: msg.content }]
2869
+ });
2870
+ }
2871
+ return contents;
2872
+ }
2873
+ /**
2874
+ * Convert JSON Schema to Google's schema format
2875
+ */
2876
+ convertToGoogleSchema(schema) {
2877
+ const converted = {};
2878
+ if (schema.type) {
2879
+ converted.type = Array.isArray(schema.type) ? schema.type[0].toUpperCase() : schema.type.toUpperCase();
2880
+ }
2881
+ if (schema.description) {
2882
+ converted.description = schema.description;
2883
+ }
2884
+ if (schema.enum) {
2885
+ converted.enum = schema.enum;
2886
+ }
2887
+ if (schema.properties) {
2888
+ converted.properties = Object.fromEntries(
2889
+ Object.entries(schema.properties).map(([key, prop]) => [
2890
+ key,
2891
+ this.convertToGoogleSchema(prop)
2892
+ ])
2893
+ );
2894
+ }
2895
+ if (schema.required) {
2896
+ converted.required = schema.required;
2897
+ }
2898
+ if (schema.items) {
2899
+ converted.items = this.convertToGoogleSchema(schema.items);
2900
+ }
2901
+ if (schema.minimum !== void 0) {
2902
+ converted.minimum = schema.minimum;
2903
+ }
2904
+ if (schema.maximum !== void 0) {
2905
+ converted.maximum = schema.maximum;
2906
+ }
2907
+ if (schema.minLength !== void 0) {
2908
+ converted.minLength = schema.minLength;
2909
+ }
2910
+ if (schema.maxLength !== void 0) {
2911
+ converted.maxLength = schema.maxLength;
2912
+ }
2913
+ if (schema.pattern !== void 0) {
2914
+ converted.pattern = schema.pattern;
2915
+ }
2916
+ return converted;
2917
+ }
2918
+ /**
2919
+ * Parse response
2920
+ */
2921
+ parseResponse(response) {
2922
+ let content = "";
2923
+ let toolCalls;
2924
+ try {
2925
+ content = response.text();
2926
+ } catch {
2927
+ }
2928
+ const functionCalls = response.functionCalls?.();
2929
+ if (functionCalls && functionCalls.length > 0) {
2930
+ toolCalls = functionCalls.map((fc, index) => ({
2931
+ id: `call_${index}`,
2932
+ name: fc.name,
2933
+ arguments: JSON.stringify(fc.args)
2934
+ }));
2935
+ }
2936
+ if (!toolCalls && response.candidates) {
2937
+ for (const candidate of response.candidates) {
2938
+ for (const part of candidate.content.parts) {
2939
+ if (part.functionCall) {
2940
+ if (!toolCalls) {
2941
+ toolCalls = [];
2942
+ }
2943
+ toolCalls.push({
2944
+ id: `call_${toolCalls.length}`,
2945
+ name: part.functionCall.name,
2946
+ arguments: JSON.stringify(part.functionCall.args)
2947
+ });
2948
+ }
2949
+ }
2950
+ }
2951
+ }
2952
+ return {
2953
+ content,
2954
+ usage: response.usageMetadata ? {
2955
+ promptTokens: response.usageMetadata.promptTokenCount,
2956
+ completionTokens: response.usageMetadata.candidatesTokenCount,
2957
+ totalTokens: response.usageMetadata.totalTokenCount
2958
+ } : void 0,
2959
+ finishReason: response.candidates?.[0]?.finishReason,
2960
+ toolCalls,
2961
+ raw: response
2962
+ };
2963
+ }
2964
+ };
2965
+ function createGoogleAdapter(client, options) {
2966
+ return new GoogleAdapter(client, options);
2967
+ }
2968
+ var StructuredProvider = class {
2969
+ clients;
2970
+ adapters;
2971
+ options;
2972
+ defaultProviderName = null;
2973
+ constructor(options = {}) {
2974
+ this.clients = /* @__PURE__ */ new Map();
2975
+ this.adapters = /* @__PURE__ */ new Map();
2976
+ this.options = {
2977
+ enableFixHints: true,
2978
+ validatePartials: false,
2979
+ maxRetries: 3,
2980
+ ...options
2981
+ };
2982
+ }
2983
+ /**
2984
+ * Register a provider client
2985
+ */
2986
+ registerProvider(name, agentSeaClient, setAsDefault = false) {
2987
+ const adapter = this.createAdapter(agentSeaClient);
2988
+ this.adapters.set(name, adapter);
2989
+ const client = new StructuredClient(adapter, {
2990
+ defaultMode: this.options.defaultMode,
2991
+ enableFixHints: this.options.enableFixHints,
2992
+ validatePartials: this.options.validatePartials,
2993
+ defaultRetry: {
2994
+ maxAttempts: this.options.maxRetries ?? 3,
2995
+ retryOn: ["validation_error", "parse_error"]
2996
+ }
2997
+ });
2998
+ this.clients.set(name, client);
2999
+ if (setAsDefault || !this.defaultProviderName) {
3000
+ this.defaultProviderName = name;
3001
+ }
3002
+ return this;
3003
+ }
3004
+ /**
3005
+ * Get a structured client
3006
+ */
3007
+ getClient(name) {
3008
+ const providerName = name ?? this.defaultProviderName;
3009
+ if (!providerName) {
3010
+ throw new Error("No provider registered");
3011
+ }
3012
+ const client = this.clients.get(providerName);
3013
+ if (!client) {
3014
+ throw new Error(`Provider '${providerName}' not found`);
3015
+ }
3016
+ return client;
3017
+ }
3018
+ /**
3019
+ * Extract structured data
3020
+ */
3021
+ async extract(schema, prompt, options) {
3022
+ const client = this.getClient(options?.provider);
3023
+ const messages = Array.isArray(prompt) ? prompt : [{ role: "user", content: prompt }];
3024
+ return client.extract({
3025
+ model: options?.model ?? this.options.defaultModel ?? "gpt-4o",
3026
+ messages,
3027
+ response_format: schema,
3028
+ mode: options?.mode ?? this.options.defaultMode
3029
+ });
3030
+ }
3031
+ /**
3032
+ * Extract structured data with streaming
3033
+ */
3034
+ extractStream(schema, prompt, options) {
3035
+ const client = this.getClient(options?.provider);
3036
+ const messages = Array.isArray(prompt) ? prompt : [{ role: "user", content: prompt }];
3037
+ return client.extractStream(
3038
+ {
3039
+ model: options?.model ?? this.options.defaultModel ?? "gpt-4o",
3040
+ messages,
3041
+ response_format: schema,
3042
+ mode: options?.mode ?? this.options.defaultMode
3043
+ },
3044
+ options?.streaming
3045
+ );
3046
+ }
3047
+ /**
3048
+ * Create a typed extractor for reuse
3049
+ */
3050
+ createExtractor(schema, options) {
3051
+ return new TypedExtractor(this, schema, options);
3052
+ }
3053
+ /**
3054
+ * Create adapter from AgentSea client
3055
+ */
3056
+ createAdapter(agentSeaClient) {
3057
+ switch (agentSeaClient.provider) {
3058
+ case "openai":
3059
+ return new OpenAIAdapter(
3060
+ agentSeaClient.client
3061
+ );
3062
+ case "anthropic":
3063
+ return new AnthropicAdapter(
3064
+ agentSeaClient.client
3065
+ );
3066
+ case "google":
3067
+ return new GoogleAdapter(
3068
+ agentSeaClient.client
3069
+ );
3070
+ default:
3071
+ throw new Error(
3072
+ `Unsupported provider: ${agentSeaClient.provider}`
3073
+ );
3074
+ }
3075
+ }
3076
+ };
3077
+ var TypedExtractor = class {
3078
+ constructor(provider, schema, options) {
3079
+ this.provider = provider;
3080
+ this.schema = schema;
3081
+ this.options = options;
3082
+ }
3083
+ /**
3084
+ * Extract structured data
3085
+ */
3086
+ async extract(prompt, overrideOptions) {
3087
+ return this.provider.extract(this.schema, prompt, {
3088
+ ...this.options,
3089
+ ...overrideOptions
3090
+ });
3091
+ }
3092
+ /**
3093
+ * Extract with streaming
3094
+ */
3095
+ extractStream(prompt, streamingOptions) {
3096
+ return this.provider.extractStream(this.schema, prompt, {
3097
+ ...this.options,
3098
+ streaming: streamingOptions
3099
+ });
3100
+ }
3101
+ /**
3102
+ * Get the schema
3103
+ */
3104
+ getSchema() {
3105
+ return this.schema;
3106
+ }
3107
+ };
3108
+ function createStructuredProvider(options) {
3109
+ return new StructuredProvider(options);
3110
+ }
3111
+ var Extractors = {
3112
+ /**
3113
+ * Create a list extractor
3114
+ */
3115
+ list(itemSchema, options) {
3116
+ let schema = z.array(itemSchema);
3117
+ if (options?.minItems !== void 0) {
3118
+ schema = schema.min(options.minItems);
3119
+ }
3120
+ if (options?.maxItems !== void 0) {
3121
+ schema = schema.max(options.maxItems);
3122
+ }
3123
+ return schema;
3124
+ },
3125
+ /**
3126
+ * Create an entity extractor
3127
+ */
3128
+ entity(shape) {
3129
+ return z.object(shape);
3130
+ },
3131
+ /**
3132
+ * Create a classification extractor
3133
+ */
3134
+ classification(categories, options) {
3135
+ if (options?.confidence) {
3136
+ return z.object({
3137
+ category: z.enum(categories),
3138
+ confidence: z.number().min(0).max(1),
3139
+ reasoning: z.string().optional()
3140
+ });
3141
+ }
3142
+ return z.object({
3143
+ category: z.enum(categories)
3144
+ });
3145
+ },
3146
+ /**
3147
+ * Create a sentiment analyzer
3148
+ */
3149
+ sentiment() {
3150
+ return z.object({
3151
+ sentiment: z.enum(["positive", "negative", "neutral", "mixed"]),
3152
+ score: z.number().min(-1).max(1),
3153
+ aspects: z.array(
3154
+ z.object({
3155
+ aspect: z.string(),
3156
+ sentiment: z.enum(["positive", "negative", "neutral"])
3157
+ })
3158
+ ).optional()
3159
+ });
3160
+ },
3161
+ /**
3162
+ * Create a key-value extractor
3163
+ */
3164
+ keyValue() {
3165
+ return z.record(z.string(), z.unknown());
3166
+ },
3167
+ /**
3168
+ * Create a summary extractor
3169
+ */
3170
+ summary(options) {
3171
+ let summarySchema = z.string();
3172
+ if (options?.maxLength) {
3173
+ summarySchema = summarySchema.max(options.maxLength);
3174
+ }
3175
+ return z.object({
3176
+ summary: summarySchema,
3177
+ keyPoints: z.array(z.string()),
3178
+ entities: z.array(
3179
+ z.object({
3180
+ name: z.string(),
3181
+ type: z.string()
3182
+ })
3183
+ ).optional()
3184
+ });
3185
+ }
3186
+ };
3187
+
3188
+ // src/types/core.types.ts
3189
+ var StructuredError = class extends Error {
3190
+ /** Error code */
3191
+ code;
3192
+ /** Extraction attempts */
3193
+ attempts;
3194
+ /** Last validation errors */
3195
+ validationErrors;
3196
+ /** Partial result if available */
3197
+ partial;
3198
+ constructor(message, code, attempts, validationErrors, partial) {
3199
+ super(message);
3200
+ this.name = "StructuredError";
3201
+ this.code = code;
3202
+ this.attempts = attempts;
3203
+ this.validationErrors = validationErrors;
3204
+ this.partial = partial;
3205
+ }
3206
+ };
3207
+
3208
+ export { AnthropicAdapter, Extractors, GoogleAdapter, IncrementalJsonParser, OpenAIAdapter, SchemaPromptGenerator, SchemaValidator, StructuredClient, StructuredError, StructuredProvider, TypedExtractor, analyzeSchema, coerceToSchema, createAnthropicAdapter, createGoogleAdapter, createOpenAIAdapter, createStreamingResult, createStructuredClient, createStructuredProvider, extractFieldInfo, formatZodErrors, generateExample, getPartialState, getValidationHints, matchesSchema, schemaToPrompt, tokenizeJson, validatePartial, validateSchema, validateSchemaOrThrow, zodToJsonSchema };
3209
+ //# sourceMappingURL=index.js.map
3210
+ //# sourceMappingURL=index.js.map