@sembl/core 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +459 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +210 -16
- package/dist/index.d.ts +210 -16
- package/dist/index.js +451 -68
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,155 @@
|
|
|
1
|
+
// src/schema/formats.ts
|
|
2
|
+
var FIELD_FORMATS = [
|
|
3
|
+
"url",
|
|
4
|
+
"email",
|
|
5
|
+
"date",
|
|
6
|
+
"datetime",
|
|
7
|
+
"iso-country",
|
|
8
|
+
"us-state",
|
|
9
|
+
"us-state-name",
|
|
10
|
+
"currency"
|
|
11
|
+
];
|
|
12
|
+
var ISO_COUNTRIES = new Set(
|
|
13
|
+
"AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS YE YT ZA ZM ZW".split(" ")
|
|
14
|
+
);
|
|
15
|
+
var US_STATES = {
|
|
16
|
+
AL: "Alabama",
|
|
17
|
+
AK: "Alaska",
|
|
18
|
+
AZ: "Arizona",
|
|
19
|
+
AR: "Arkansas",
|
|
20
|
+
CA: "California",
|
|
21
|
+
CO: "Colorado",
|
|
22
|
+
CT: "Connecticut",
|
|
23
|
+
DE: "Delaware",
|
|
24
|
+
FL: "Florida",
|
|
25
|
+
GA: "Georgia",
|
|
26
|
+
HI: "Hawaii",
|
|
27
|
+
ID: "Idaho",
|
|
28
|
+
IL: "Illinois",
|
|
29
|
+
IN: "Indiana",
|
|
30
|
+
IA: "Iowa",
|
|
31
|
+
KS: "Kansas",
|
|
32
|
+
KY: "Kentucky",
|
|
33
|
+
LA: "Louisiana",
|
|
34
|
+
ME: "Maine",
|
|
35
|
+
MD: "Maryland",
|
|
36
|
+
MA: "Massachusetts",
|
|
37
|
+
MI: "Michigan",
|
|
38
|
+
MN: "Minnesota",
|
|
39
|
+
MS: "Mississippi",
|
|
40
|
+
MO: "Missouri",
|
|
41
|
+
MT: "Montana",
|
|
42
|
+
NE: "Nebraska",
|
|
43
|
+
NV: "Nevada",
|
|
44
|
+
NH: "New Hampshire",
|
|
45
|
+
NJ: "New Jersey",
|
|
46
|
+
NM: "New Mexico",
|
|
47
|
+
NY: "New York",
|
|
48
|
+
NC: "North Carolina",
|
|
49
|
+
ND: "North Dakota",
|
|
50
|
+
OH: "Ohio",
|
|
51
|
+
OK: "Oklahoma",
|
|
52
|
+
OR: "Oregon",
|
|
53
|
+
PA: "Pennsylvania",
|
|
54
|
+
RI: "Rhode Island",
|
|
55
|
+
SC: "South Carolina",
|
|
56
|
+
SD: "South Dakota",
|
|
57
|
+
TN: "Tennessee",
|
|
58
|
+
TX: "Texas",
|
|
59
|
+
UT: "Utah",
|
|
60
|
+
VT: "Vermont",
|
|
61
|
+
VA: "Virginia",
|
|
62
|
+
WA: "Washington",
|
|
63
|
+
WV: "West Virginia",
|
|
64
|
+
WI: "Wisconsin",
|
|
65
|
+
WY: "Wyoming",
|
|
66
|
+
DC: "District of Columbia",
|
|
67
|
+
PR: "Puerto Rico",
|
|
68
|
+
GU: "Guam",
|
|
69
|
+
VI: "U.S. Virgin Islands",
|
|
70
|
+
AS: "American Samoa",
|
|
71
|
+
MP: "Northern Mariana Islands"
|
|
72
|
+
};
|
|
73
|
+
var US_STATE_NAMES = new Set(Object.values(US_STATES));
|
|
74
|
+
var CURRENCIES = new Set(
|
|
75
|
+
"AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BRL BSD BTN BWP BYN BZD CAD CDF CHF CLP CNY COP CRC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HTG HUF IDR ILS INR IQD IRR ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRU MUR MVR MWK MXN MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STN SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD UYU UZS VES VND VUV WST XAF XCD XOF XPF YER ZAR ZMW ZWG".split(" ")
|
|
76
|
+
);
|
|
77
|
+
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
78
|
+
var DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
79
|
+
var DATETIME = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?$/;
|
|
80
|
+
function isCalendarDate(y, m, d) {
|
|
81
|
+
const date = new Date(Date.UTC(y, m - 1, d));
|
|
82
|
+
return date.getUTCFullYear() === y && date.getUTCMonth() === m - 1 && date.getUTCDate() === d;
|
|
83
|
+
}
|
|
84
|
+
function validateFormat(value, format) {
|
|
85
|
+
switch (format) {
|
|
86
|
+
case "url": {
|
|
87
|
+
try {
|
|
88
|
+
const url = new URL(value);
|
|
89
|
+
if (url.protocol === "http:" || url.protocol === "https:") return void 0;
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
return `Expected an absolute http(s) URL, got ${JSON.stringify(value)}`;
|
|
93
|
+
}
|
|
94
|
+
case "email":
|
|
95
|
+
return EMAIL.test(value) ? void 0 : `Expected an email address, got ${JSON.stringify(value)}`;
|
|
96
|
+
case "date": {
|
|
97
|
+
const m = DATE.exec(value);
|
|
98
|
+
if (m && isCalendarDate(Number(m[1]), Number(m[2]), Number(m[3]))) return void 0;
|
|
99
|
+
return `Expected a calendar date as YYYY-MM-DD, got ${JSON.stringify(value)}`;
|
|
100
|
+
}
|
|
101
|
+
case "datetime":
|
|
102
|
+
return DATETIME.test(value) && !Number.isNaN(Date.parse(value)) ? void 0 : `Expected an ISO 8601 timestamp, got ${JSON.stringify(value)}`;
|
|
103
|
+
case "iso-country":
|
|
104
|
+
return ISO_COUNTRIES.has(value) ? void 0 : `Expected an ISO 3166-1 alpha-2 country code such as US or DE, got ${JSON.stringify(value)}`;
|
|
105
|
+
case "us-state":
|
|
106
|
+
return value in US_STATES ? void 0 : `Expected a two-letter USPS state code such as CA or NY, got ${JSON.stringify(value)}`;
|
|
107
|
+
case "us-state-name":
|
|
108
|
+
return US_STATE_NAMES.has(value) ? void 0 : `Expected a US state's full name such as California, got ${JSON.stringify(value)}`;
|
|
109
|
+
case "currency":
|
|
110
|
+
return CURRENCIES.has(value) ? void 0 : `Expected an ISO 4217 currency code such as USD or EUR, got ${JSON.stringify(value)}`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function describeFormat(format) {
|
|
114
|
+
switch (format) {
|
|
115
|
+
case "url":
|
|
116
|
+
return "an absolute http(s) URL";
|
|
117
|
+
case "email":
|
|
118
|
+
return "an email address";
|
|
119
|
+
case "date":
|
|
120
|
+
return "a calendar date as YYYY-MM-DD";
|
|
121
|
+
case "datetime":
|
|
122
|
+
return "an ISO 8601 timestamp (e.g. 2026-09-05T14:30:00Z)";
|
|
123
|
+
case "iso-country":
|
|
124
|
+
return "an ISO 3166-1 alpha-2 country code (e.g. US, DE, PT), never a country name";
|
|
125
|
+
case "us-state":
|
|
126
|
+
return "a two-letter USPS state code (e.g. CA, NY), never the state's name";
|
|
127
|
+
case "us-state-name":
|
|
128
|
+
return "a US state's full name (e.g. California, New York), never its abbreviation";
|
|
129
|
+
case "currency":
|
|
130
|
+
return "an ISO 4217 currency code (e.g. USD, EUR, GBP), never a symbol or a word";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function formatToJsonSchema(format) {
|
|
134
|
+
switch (format) {
|
|
135
|
+
case "url":
|
|
136
|
+
return { format: "uri" };
|
|
137
|
+
case "email":
|
|
138
|
+
return { format: "email" };
|
|
139
|
+
case "date":
|
|
140
|
+
return { format: "date" };
|
|
141
|
+
case "datetime":
|
|
142
|
+
return { format: "date-time" };
|
|
143
|
+
case "iso-country":
|
|
144
|
+
case "us-state":
|
|
145
|
+
return { pattern: "^[A-Z]{2}$" };
|
|
146
|
+
case "currency":
|
|
147
|
+
return { pattern: "^[A-Z]{3}$" };
|
|
148
|
+
case "us-state-name":
|
|
149
|
+
return {};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
1
153
|
// src/schema/json-schema.ts
|
|
2
154
|
var CONSTRAINT_KEYWORDS = [
|
|
3
155
|
"maxLength",
|
|
@@ -14,6 +166,9 @@ function constraintsToJsonSchema(constraints, dialect) {
|
|
|
14
166
|
return {};
|
|
15
167
|
}
|
|
16
168
|
const out = {};
|
|
169
|
+
if (constraints.format !== void 0) {
|
|
170
|
+
Object.assign(out, formatToJsonSchema(constraints.format));
|
|
171
|
+
}
|
|
17
172
|
for (const keyword of CONSTRAINT_KEYWORDS) {
|
|
18
173
|
const value = constraints[keyword];
|
|
19
174
|
if (value !== void 0) {
|
|
@@ -398,7 +553,7 @@ ${summary}`);
|
|
|
398
553
|
// src/coerce/sources.ts
|
|
399
554
|
var SOURCE_TAG = "source";
|
|
400
555
|
function isSource(value) {
|
|
401
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.text === "string" && (value.label === void 0 || typeof value.label === "string");
|
|
556
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.text === "string" && (value.label === void 0 || typeof value.label === "string") && (value.maxChars === void 0 || typeof value.maxChars === "number");
|
|
402
557
|
}
|
|
403
558
|
function isCoerceInput(value) {
|
|
404
559
|
return typeof value === "string" || isSource(value) || Array.isArray(value) && value.every(isSource);
|
|
@@ -418,7 +573,9 @@ function toSources(input) {
|
|
|
418
573
|
}
|
|
419
574
|
function cleanLabel(source) {
|
|
420
575
|
const label = source.label?.trim();
|
|
421
|
-
|
|
576
|
+
const cleaned = label ? { label, text: source.text } : { text: source.text };
|
|
577
|
+
if (source.maxChars !== void 0) cleaned.maxChars = source.maxChars;
|
|
578
|
+
return cleaned;
|
|
422
579
|
}
|
|
423
580
|
function escapeText(text) {
|
|
424
581
|
return text.replace(new RegExp(`</(\\s*${SOURCE_TAG}\\b)`, "gi"), "<\\/$1");
|
|
@@ -443,12 +600,23 @@ var SOURCE_INSTRUCTIONS = [
|
|
|
443
600
|
].join("\n");
|
|
444
601
|
|
|
445
602
|
// src/coerce/prompt-builder.ts
|
|
603
|
+
function normalizeInstructions(instructions) {
|
|
604
|
+
if (instructions === void 0) return [];
|
|
605
|
+
const list = typeof instructions === "string" ? [instructions] : instructions;
|
|
606
|
+
if (!Array.isArray(list) || list.some((entry) => typeof entry !== "string")) {
|
|
607
|
+
throw new RangeError("instructions must be a string or an array of strings");
|
|
608
|
+
}
|
|
609
|
+
return list.map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
610
|
+
}
|
|
446
611
|
function describeConstraints(constraints) {
|
|
447
612
|
if (!constraints) {
|
|
448
613
|
return [];
|
|
449
614
|
}
|
|
450
615
|
const phrases = [];
|
|
451
|
-
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern } = constraints;
|
|
616
|
+
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern, format } = constraints;
|
|
617
|
+
if (format !== void 0) {
|
|
618
|
+
phrases.push(describeFormat(format));
|
|
619
|
+
}
|
|
452
620
|
if (minLength !== void 0 && maxLength !== void 0) {
|
|
453
621
|
phrases.push(`between ${minLength} and ${maxLength} characters`);
|
|
454
622
|
} else if (maxLength !== void 0) {
|
|
@@ -561,10 +729,20 @@ function buildPrompt(schema, bundle, options = {}) {
|
|
|
561
729
|
lines.push("Instructions:");
|
|
562
730
|
lines.push("- Extract values from the sources that match the schema fields.");
|
|
563
731
|
lines.push("- Use null for optional fields that cannot be determined from the input.");
|
|
732
|
+
lines.push("- A value the input states is never omitted because it looks like a default: return 1, 0, false or an empty list when that is what the input says.");
|
|
733
|
+
lines.push("- Never return an empty object when the input states values for any field.");
|
|
564
734
|
lines.push("- Required fields must always have a valid, non-null value.");
|
|
565
735
|
lines.push("- Interpret the user's input semantically \u2014 infer meaning, don't just pattern match.");
|
|
566
736
|
lines.push("- Respect every stated limit exactly; truncate or drop lower-priority content to stay within it.");
|
|
567
737
|
lines.push("- Return only the structured JSON output matching the schema.");
|
|
738
|
+
const instructions = normalizeInstructions(options.instructions);
|
|
739
|
+
if (instructions.length > 0) {
|
|
740
|
+
lines.push("");
|
|
741
|
+
lines.push("Additional guidance for this extraction:");
|
|
742
|
+
for (const instruction of instructions) {
|
|
743
|
+
lines.push(`- ${instruction}`);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
568
746
|
return lines.join("\n");
|
|
569
747
|
}
|
|
570
748
|
|
|
@@ -618,11 +796,31 @@ var PROVENANCE_INSTRUCTIONS = [
|
|
|
618
796
|
"- Judge each field on its own. A confident value next to a guessed one is",
|
|
619
797
|
" normal, and marking the guess honestly is more useful than looking sure."
|
|
620
798
|
].join("\n");
|
|
799
|
+
function provenanceFieldNames(schema, fields) {
|
|
800
|
+
if (fields === void 0) return new Set(schema.fields.map((f) => f.name));
|
|
801
|
+
const known = new Set(schema.fields.map((f) => f.name));
|
|
802
|
+
for (const name of fields) {
|
|
803
|
+
if (!known.has(name)) {
|
|
804
|
+
throw new RangeError(
|
|
805
|
+
`provenance field "${name}" is not a field of schema "${schema.id}" (fields: ${[...known].join(", ")})`
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
return new Set(fields);
|
|
810
|
+
}
|
|
621
811
|
function provenanceInstructions(options = {}) {
|
|
622
812
|
const labels = options.sourceLabels ?? [];
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
813
|
+
let text = PROVENANCE_INSTRUCTIONS;
|
|
814
|
+
if (options.fields !== void 0) {
|
|
815
|
+
text = text.replace(
|
|
816
|
+
"- Every field is wrapped as an object: put the extracted value in `value`.",
|
|
817
|
+
`- Only these fields are wrapped as objects, with the extracted value in \`value\`: ${options.fields.join(", ")}. Every other field is a plain value.`
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
if (labels.length >= 2) {
|
|
821
|
+
text += "\n- Always set `source` to the label of the source the value was read from. When several agree, name the one quoted in `evidence`.";
|
|
822
|
+
}
|
|
823
|
+
return text;
|
|
626
824
|
}
|
|
627
825
|
function annotationSchema(parentId, field2, sourceLabels) {
|
|
628
826
|
const valueField = {
|
|
@@ -654,7 +852,7 @@ function annotationSchema(parentId, field2, sourceLabels) {
|
|
|
654
852
|
name: "source",
|
|
655
853
|
description: "The label of the source this value was read from.",
|
|
656
854
|
type: { kind: "enum", values: [...sourceLabels] },
|
|
657
|
-
required:
|
|
855
|
+
required: true
|
|
658
856
|
}
|
|
659
857
|
] : []
|
|
660
858
|
]
|
|
@@ -664,7 +862,12 @@ function toProvenanceSchema(schema, bundle, options = {}) {
|
|
|
664
862
|
const schemas = { ...bundle?.schemas ?? {} };
|
|
665
863
|
const fields = [];
|
|
666
864
|
const sourceLabels = options.sourceLabels ?? [];
|
|
865
|
+
const wrapped = provenanceFieldNames(schema, options.fields);
|
|
667
866
|
for (const field2 of schema.fields) {
|
|
867
|
+
if (!wrapped.has(field2.name)) {
|
|
868
|
+
fields.push(field2);
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
668
871
|
const annotation = annotationSchema(schema.id, field2, sourceLabels);
|
|
669
872
|
schemas[annotation.id] = annotation;
|
|
670
873
|
fields.push({
|
|
@@ -740,10 +943,30 @@ ${tailRoom > 0 ? text.slice(text.length - tailRoom) : ""}`;
|
|
|
740
943
|
}
|
|
741
944
|
}
|
|
742
945
|
function budgetSources(sources, maxChars, policy = "tail") {
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
946
|
+
const records = /* @__PURE__ */ new Map();
|
|
947
|
+
const record = (index, source, text) => {
|
|
948
|
+
const existing = records.get(index);
|
|
949
|
+
if (existing) {
|
|
950
|
+
existing.keptLength = text.length;
|
|
951
|
+
} else {
|
|
952
|
+
records.set(index, {
|
|
953
|
+
...source.label !== void 0 ? { label: source.label } : {},
|
|
954
|
+
originalLength: source.text.length,
|
|
955
|
+
keptLength: text.length
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
const capped = sources.map((source, index) => {
|
|
960
|
+
if (source.maxChars === void 0 || source.text.length <= source.maxChars) return source;
|
|
961
|
+
const text = truncateText(source.text, source.maxChars, policy);
|
|
962
|
+
record(index, source, text);
|
|
963
|
+
return { ...source, text };
|
|
964
|
+
});
|
|
965
|
+
const total = capped.reduce((sum, s) => sum + s.text.length, 0);
|
|
966
|
+
if (maxChars === void 0 || total <= maxChars) {
|
|
967
|
+
return { sources: capped, truncated: [...records.values()] };
|
|
746
968
|
}
|
|
969
|
+
sources = capped;
|
|
747
970
|
const allowance = /* @__PURE__ */ new Map();
|
|
748
971
|
const order = sources.map((s, i) => i).sort((a, b) => sources[a].text.length - sources[b].text.length);
|
|
749
972
|
let remaining = maxChars;
|
|
@@ -753,19 +976,14 @@ function budgetSources(sources, maxChars, policy = "tail") {
|
|
|
753
976
|
allowance.set(index, granted);
|
|
754
977
|
remaining -= granted;
|
|
755
978
|
});
|
|
756
|
-
const truncated = [];
|
|
757
979
|
const budgeted = sources.map((source, index) => {
|
|
758
980
|
const limit = allowance.get(index) ?? 0;
|
|
759
981
|
if (source.text.length <= limit) return source;
|
|
760
982
|
const text = truncateText(source.text, limit, policy);
|
|
761
|
-
|
|
762
|
-
...source.label !== void 0 ? { label: source.label } : {},
|
|
763
|
-
originalLength: source.text.length,
|
|
764
|
-
keptLength: text.length
|
|
765
|
-
});
|
|
983
|
+
record(index, source, text);
|
|
766
984
|
return { ...source, text };
|
|
767
985
|
});
|
|
768
|
-
return { sources: budgeted, truncated };
|
|
986
|
+
return { sources: budgeted, truncated: [...records.values()] };
|
|
769
987
|
}
|
|
770
988
|
|
|
771
989
|
// src/coerce/validator.ts
|
|
@@ -781,7 +999,7 @@ function entries(count) {
|
|
|
781
999
|
return `${count} ${count === 1 ? "entry" : "entries"}`;
|
|
782
1000
|
}
|
|
783
1001
|
function validateConstraints(value, constraints, path, issues) {
|
|
784
|
-
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern } = constraints;
|
|
1002
|
+
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern, format } = constraints;
|
|
785
1003
|
if (Array.isArray(value)) {
|
|
786
1004
|
if (minItems !== void 0 && value.length < minItems) {
|
|
787
1005
|
issues.push({
|
|
@@ -825,6 +1043,10 @@ function validateConstraints(value, constraints, path, issues) {
|
|
|
825
1043
|
received: value
|
|
826
1044
|
});
|
|
827
1045
|
}
|
|
1046
|
+
if (format !== void 0) {
|
|
1047
|
+
const message = validateFormat(value, format);
|
|
1048
|
+
if (message) issues.push({ path, message, received: value });
|
|
1049
|
+
}
|
|
828
1050
|
return;
|
|
829
1051
|
}
|
|
830
1052
|
if (typeof value === "number") {
|
|
@@ -1166,8 +1388,15 @@ function generateSpanId() {
|
|
|
1166
1388
|
}
|
|
1167
1389
|
var Tracer = class {
|
|
1168
1390
|
sinks;
|
|
1169
|
-
|
|
1391
|
+
baseAttributes;
|
|
1392
|
+
/**
|
|
1393
|
+
* `baseAttributes` are merged into every span this tracer opens — how a
|
|
1394
|
+
* batch stamps `itemIndex` on the spans of each item, so a sink can tell
|
|
1395
|
+
* whose `llmCall` it is looking at under concurrency.
|
|
1396
|
+
*/
|
|
1397
|
+
constructor(sinks, baseAttributes) {
|
|
1170
1398
|
this.sinks = sinks ?? [];
|
|
1399
|
+
this.baseAttributes = baseAttributes;
|
|
1171
1400
|
}
|
|
1172
1401
|
startSpan(name, attributes, parent) {
|
|
1173
1402
|
return {
|
|
@@ -1175,7 +1404,7 @@ var Tracer = class {
|
|
|
1175
1404
|
name,
|
|
1176
1405
|
startTime: Date.now(),
|
|
1177
1406
|
events: [],
|
|
1178
|
-
attributes,
|
|
1407
|
+
attributes: this.baseAttributes ? { ...this.baseAttributes, ...attributes } : attributes,
|
|
1179
1408
|
parentId: parent?.id
|
|
1180
1409
|
};
|
|
1181
1410
|
}
|
|
@@ -1230,15 +1459,32 @@ async function resolveEnums(schema, bundle, enumResolver, tracer, parent) {
|
|
|
1230
1459
|
tracer.endSpan(span);
|
|
1231
1460
|
}
|
|
1232
1461
|
}
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1462
|
+
function emptyUsage() {
|
|
1463
|
+
return { calls: 0, promptTokens: 0, completionTokens: 0, totalTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };
|
|
1464
|
+
}
|
|
1465
|
+
function addUsage(into, usage) {
|
|
1466
|
+
into.calls += 1;
|
|
1467
|
+
if (!usage) return;
|
|
1468
|
+
into.promptTokens += usage.promptTokens;
|
|
1469
|
+
into.completionTokens += usage.completionTokens;
|
|
1470
|
+
into.totalTokens += usage.totalTokens;
|
|
1471
|
+
into.cacheReadTokens += usage.cacheReadTokens ?? 0;
|
|
1472
|
+
into.cacheWriteTokens += usage.cacheWriteTokens ?? 0;
|
|
1473
|
+
}
|
|
1474
|
+
function checkOptions(options) {
|
|
1236
1475
|
const maxRepairAttempts = options.maxRepairAttempts ?? 0;
|
|
1237
1476
|
if (!Number.isInteger(maxRepairAttempts) || maxRepairAttempts < 0) {
|
|
1238
1477
|
throw new RangeError(
|
|
1239
1478
|
`maxRepairAttempts must be a non-negative integer, got ${String(options.maxRepairAttempts)}`
|
|
1240
1479
|
);
|
|
1241
1480
|
}
|
|
1481
|
+
const retryOnEmpty = options.retryOnEmpty ?? 0;
|
|
1482
|
+
if (!Number.isInteger(retryOnEmpty) || retryOnEmpty < 0) {
|
|
1483
|
+
throw new RangeError(
|
|
1484
|
+
`retryOnEmpty must be a non-negative integer, got ${String(options.retryOnEmpty)}`
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
const instructions = normalizeInstructions(options.instructions);
|
|
1242
1488
|
const onInvalidField = options.onInvalidField ?? "throw";
|
|
1243
1489
|
if (!INVALID_FIELD_POLICIES.includes(onInvalidField)) {
|
|
1244
1490
|
throw new RangeError(
|
|
@@ -1250,60 +1496,96 @@ async function runCoercion(input, options, { mode, provenance }) {
|
|
|
1250
1496
|
`maxInputChars must be a positive integer, got ${String(options.maxInputChars)}`
|
|
1251
1497
|
);
|
|
1252
1498
|
}
|
|
1499
|
+
return { maxRepairAttempts, retryOnEmpty, onInvalidField, instructions };
|
|
1500
|
+
}
|
|
1501
|
+
async function prepareRequest(options, { mode, provenance }, instructions, sourceLabels, tracer, rootSpan) {
|
|
1502
|
+
const { schema, enumResolver } = options;
|
|
1503
|
+
const bundle = options.bundle ?? bundleOf(schema);
|
|
1504
|
+
const resolvedEnums = await resolveEnums(schema, bundle, enumResolver, tracer, rootSpan);
|
|
1505
|
+
const promptSpan = tracer.startSpan("buildPrompt", {}, rootSpan);
|
|
1506
|
+
const basePrompt = buildPrompt(schema, bundle, { resolvedEnums, instructions });
|
|
1507
|
+
const provenanceOptions = { sourceLabels, fields: options.provenanceFields };
|
|
1508
|
+
const systemPrompt = provenance ? `${basePrompt}
|
|
1509
|
+
${provenanceInstructions(provenanceOptions)}` : basePrompt;
|
|
1510
|
+
tracer.addEvent(promptSpan, "promptBuilt", {
|
|
1511
|
+
promptLength: systemPrompt.length,
|
|
1512
|
+
instructionCount: instructions.length,
|
|
1513
|
+
mode
|
|
1514
|
+
});
|
|
1515
|
+
tracer.endSpan(promptSpan);
|
|
1516
|
+
const request = provenance ? toProvenanceSchema(schema, bundle, provenanceOptions) : { schema, bundle };
|
|
1517
|
+
const schemaSpan = tracer.startSpan("buildJsonSchema", {}, rootSpan);
|
|
1518
|
+
const jsonSchema = runtimeSchemaToJsonSchema(request.schema, request.bundle, {
|
|
1519
|
+
resolvedEnums
|
|
1520
|
+
});
|
|
1521
|
+
tracer.endSpan(schemaSpan);
|
|
1522
|
+
return { systemPrompt, jsonSchema, schema: request.schema, bundle: request.bundle, resolvedEnums };
|
|
1523
|
+
}
|
|
1524
|
+
function isEmptyResult(data) {
|
|
1525
|
+
return Object.values(data).every((value) => value === null || value === void 0);
|
|
1526
|
+
}
|
|
1527
|
+
var EMPTY_RETRY_NOTE = "A previous attempt at this extraction returned no fields. The sources above do state values for at least some fields; read them again and return every value that is stated, leaving out only what the sources genuinely do not say.";
|
|
1528
|
+
async function runCoercion(input, options, { mode, provenance, traceAttributes }) {
|
|
1529
|
+
const { provider, schema, traceSinks } = options;
|
|
1530
|
+
const bundle = options.bundle ?? bundleOf(schema);
|
|
1531
|
+
const { maxRepairAttempts, retryOnEmpty, onInvalidField, instructions } = checkOptions(options);
|
|
1253
1532
|
const rawSources = toSources(input);
|
|
1254
|
-
const tracer = new Tracer(traceSinks);
|
|
1533
|
+
const tracer = new Tracer(traceSinks, traceAttributes);
|
|
1255
1534
|
const rootSpan = tracer.startSpan(mode, {
|
|
1256
1535
|
schemaId: schema.id,
|
|
1257
1536
|
provenance,
|
|
1258
1537
|
onInvalidField,
|
|
1259
1538
|
sourceCount: rawSources.length
|
|
1260
1539
|
});
|
|
1540
|
+
const usage = emptyUsage();
|
|
1261
1541
|
try {
|
|
1262
1542
|
const sources = await prepareSources(rawSources, options, tracer, rootSpan);
|
|
1263
1543
|
const sourceLabels = sources.length > 1 ? sources.map((s) => s.label ?? "") : [];
|
|
1264
|
-
const
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1544
|
+
const prepared = await prepareRequest(
|
|
1545
|
+
options,
|
|
1546
|
+
{ mode, provenance },
|
|
1547
|
+
instructions,
|
|
1548
|
+
sourceLabels,
|
|
1268
1549
|
tracer,
|
|
1269
1550
|
rootSpan
|
|
1270
1551
|
);
|
|
1271
|
-
const
|
|
1272
|
-
const basePrompt = buildPrompt(schema, bundle, { resolvedEnums });
|
|
1273
|
-
const systemPrompt = provenance ? `${basePrompt}
|
|
1274
|
-
${provenanceInstructions({ sourceLabels })}` : basePrompt;
|
|
1275
|
-
tracer.addEvent(promptSpan, "promptBuilt", {
|
|
1276
|
-
promptLength: systemPrompt.length
|
|
1277
|
-
});
|
|
1278
|
-
tracer.endSpan(promptSpan);
|
|
1279
|
-
const request = provenance ? toProvenanceSchema(schema, bundle, { sourceLabels }) : { schema, bundle };
|
|
1280
|
-
const schemaSpan = tracer.startSpan("buildJsonSchema", {}, rootSpan);
|
|
1281
|
-
const jsonSchema = runtimeSchemaToJsonSchema(request.schema, request.bundle, {
|
|
1282
|
-
resolvedEnums
|
|
1283
|
-
});
|
|
1284
|
-
tracer.endSpan(schemaSpan);
|
|
1552
|
+
const { systemPrompt, jsonSchema, resolvedEnums } = prepared;
|
|
1285
1553
|
const validate = mode === "coerce" ? validateStrict : validatePartial;
|
|
1286
1554
|
const renderedInput = renderSources(sources);
|
|
1555
|
+
const hasInput = sources.some((s) => s.text.trim().length > 0);
|
|
1287
1556
|
tracer.addEvent(rootSpan, "inputRendered", {
|
|
1288
1557
|
sourceCount: sources.length,
|
|
1289
1558
|
inputLength: renderedInput.length
|
|
1290
1559
|
});
|
|
1291
1560
|
let userInput = renderedInput;
|
|
1292
1561
|
let issues = [];
|
|
1293
|
-
let run = { data: {}, provenance: {}, issues: [] };
|
|
1562
|
+
let run = { data: {}, provenance: {}, issues: [], usage };
|
|
1563
|
+
let emptyRetries = 0;
|
|
1294
1564
|
for (let attempt = 0; attempt <= maxRepairAttempts; attempt++) {
|
|
1295
1565
|
const llmSpan = tracer.startSpan("llmCall", { attempt }, rootSpan);
|
|
1296
1566
|
const response = await provider.complete({
|
|
1297
1567
|
systemPrompt,
|
|
1298
1568
|
userInput,
|
|
1299
1569
|
jsonSchema,
|
|
1300
|
-
schema:
|
|
1301
|
-
bundle:
|
|
1570
|
+
schema: prepared.schema,
|
|
1571
|
+
bundle: prepared.bundle,
|
|
1302
1572
|
resolvedEnums
|
|
1303
1573
|
});
|
|
1574
|
+
addUsage(usage, response.usage);
|
|
1304
1575
|
tracer.addEvent(llmSpan, "responseReceived", { usage: response.usage });
|
|
1305
1576
|
tracer.endSpan(llmSpan);
|
|
1306
|
-
run = provenance ? { ...splitProvenance(response.data, schema), issues: [] } : { data: response.data, provenance: {}, issues: [] };
|
|
1577
|
+
run = provenance ? { ...splitProvenance(response.data, schema), issues: [], usage } : { data: response.data, provenance: {}, issues: [], usage };
|
|
1578
|
+
if (hasInput && emptyRetries < retryOnEmpty && isEmptyResult(run.data)) {
|
|
1579
|
+
emptyRetries += 1;
|
|
1580
|
+
tracer.addEvent(rootSpan, "emptyRetry", { retry: emptyRetries });
|
|
1581
|
+
userInput = `${renderedInput}
|
|
1582
|
+
|
|
1583
|
+
---
|
|
1584
|
+
|
|
1585
|
+
${EMPTY_RETRY_NOTE}`;
|
|
1586
|
+
attempt -= 1;
|
|
1587
|
+
continue;
|
|
1588
|
+
}
|
|
1307
1589
|
const validationSpan = tracer.startSpan("validate", { attempt }, rootSpan);
|
|
1308
1590
|
issues = validate(run.data, schema, bundle, { resolvedEnums });
|
|
1309
1591
|
tracer.addEvent(validationSpan, "validated", { issueCount: issues.length });
|
|
@@ -1329,7 +1611,8 @@ ${provenanceInstructions({ sourceLabels })}` : basePrompt;
|
|
|
1329
1611
|
return {
|
|
1330
1612
|
data: outcome.data,
|
|
1331
1613
|
provenance: pruneProvenance(run.provenance, outcome.resolved),
|
|
1332
|
-
issues: outcome.resolved
|
|
1614
|
+
issues: outcome.resolved,
|
|
1615
|
+
usage
|
|
1333
1616
|
};
|
|
1334
1617
|
}
|
|
1335
1618
|
}
|
|
@@ -1350,7 +1633,8 @@ ${provenanceInstructions({ sourceLabels })}` : basePrompt;
|
|
|
1350
1633
|
}
|
|
1351
1634
|
async function prepareSources(sources, options, tracer, parent) {
|
|
1352
1635
|
const { preprocess, maxInputChars, truncate } = options;
|
|
1353
|
-
|
|
1636
|
+
const anyCapped = sources.some((s) => s.maxChars !== void 0);
|
|
1637
|
+
if (!preprocess && maxInputChars === void 0 && !anyCapped) {
|
|
1354
1638
|
return [...sources];
|
|
1355
1639
|
}
|
|
1356
1640
|
const span = tracer.startSpan("prepareInput", {}, parent);
|
|
@@ -1367,7 +1651,7 @@ async function prepareSources(sources, options, tracer, parent) {
|
|
|
1367
1651
|
lengths: prepared.map((s) => s.text.length)
|
|
1368
1652
|
});
|
|
1369
1653
|
}
|
|
1370
|
-
if (maxInputChars !== void 0) {
|
|
1654
|
+
if (maxInputChars !== void 0 || prepared.some((s) => s.maxChars !== void 0)) {
|
|
1371
1655
|
const budgeted = budgetSources(prepared, maxInputChars, truncate);
|
|
1372
1656
|
prepared = budgeted.sources;
|
|
1373
1657
|
if (budgeted.truncated.length > 0) {
|
|
@@ -1415,19 +1699,59 @@ async function partialCoerce(input, options) {
|
|
|
1415
1699
|
});
|
|
1416
1700
|
return stripNulls(data);
|
|
1417
1701
|
}
|
|
1702
|
+
async function coerceDetailed(input, options) {
|
|
1703
|
+
const { data, issues, usage } = await runCoercion(input, options, {
|
|
1704
|
+
mode: "coerce",
|
|
1705
|
+
provenance: false
|
|
1706
|
+
});
|
|
1707
|
+
return { data, issues, usage };
|
|
1708
|
+
}
|
|
1709
|
+
async function partialCoerceDetailed(input, options) {
|
|
1710
|
+
const { data, issues, usage } = await runCoercion(input, options, {
|
|
1711
|
+
mode: "partialCoerce",
|
|
1712
|
+
provenance: false
|
|
1713
|
+
});
|
|
1714
|
+
return { data: stripNulls(data), issues, usage };
|
|
1715
|
+
}
|
|
1716
|
+
var PRIME_INPUT = "Cache warm-up. There is no input to extract from; return an object with every field null.";
|
|
1717
|
+
async function primeCache(options) {
|
|
1718
|
+
const { mode = "coerce", provenance = false, ...coerceOptions } = options;
|
|
1719
|
+
const { instructions } = checkOptions(coerceOptions);
|
|
1720
|
+
const tracer = new Tracer(coerceOptions.traceSinks);
|
|
1721
|
+
const rootSpan = tracer.startSpan("primeCache", { schemaId: coerceOptions.schema.id, mode, provenance });
|
|
1722
|
+
const usage = emptyUsage();
|
|
1723
|
+
try {
|
|
1724
|
+
const prepared = await prepareRequest(coerceOptions, { mode, provenance }, instructions, [], tracer, rootSpan);
|
|
1725
|
+
const llmSpan = tracer.startSpan("llmCall", { attempt: 0, warmup: true }, rootSpan);
|
|
1726
|
+
const response = await coerceOptions.provider.complete({
|
|
1727
|
+
systemPrompt: prepared.systemPrompt,
|
|
1728
|
+
userInput: renderSources(toSources(PRIME_INPUT)),
|
|
1729
|
+
jsonSchema: prepared.jsonSchema,
|
|
1730
|
+
schema: prepared.schema,
|
|
1731
|
+
bundle: prepared.bundle,
|
|
1732
|
+
resolvedEnums: prepared.resolvedEnums
|
|
1733
|
+
});
|
|
1734
|
+
addUsage(usage, response.usage);
|
|
1735
|
+
tracer.addEvent(llmSpan, "responseReceived", { usage: response.usage });
|
|
1736
|
+
tracer.endSpan(llmSpan);
|
|
1737
|
+
return { schemaId: coerceOptions.schema.id, mode, provenance, usage, primedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
1738
|
+
} finally {
|
|
1739
|
+
tracer.endSpan(rootSpan);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1418
1742
|
async function coerceWithProvenance(input, options) {
|
|
1419
|
-
const { data, provenance, issues } = await runCoercion(input, options, {
|
|
1743
|
+
const { data, provenance, issues, usage } = await runCoercion(input, options, {
|
|
1420
1744
|
mode: "coerce",
|
|
1421
1745
|
provenance: true
|
|
1422
1746
|
});
|
|
1423
|
-
return { data, provenance, issues };
|
|
1747
|
+
return { data, provenance, issues, usage };
|
|
1424
1748
|
}
|
|
1425
1749
|
async function partialCoerceWithProvenance(input, options) {
|
|
1426
|
-
const { data, provenance, issues } = await runCoercion(input, options, {
|
|
1750
|
+
const { data, provenance, issues, usage } = await runCoercion(input, options, {
|
|
1427
1751
|
mode: "partialCoerce",
|
|
1428
1752
|
provenance: true
|
|
1429
1753
|
});
|
|
1430
|
-
return { data: stripNulls(data), provenance, issues };
|
|
1754
|
+
return { data: stripNulls(data), provenance, issues, usage };
|
|
1431
1755
|
}
|
|
1432
1756
|
|
|
1433
1757
|
// src/coerce/coerce-many.ts
|
|
@@ -1468,60 +1792,107 @@ var BackoffGate = class {
|
|
|
1468
1792
|
this.streak = 0;
|
|
1469
1793
|
}
|
|
1470
1794
|
};
|
|
1795
|
+
var InputQueue = class {
|
|
1796
|
+
iterator;
|
|
1797
|
+
pulling = Promise.resolve();
|
|
1798
|
+
index = 0;
|
|
1799
|
+
constructor(inputs) {
|
|
1800
|
+
this.iterator = Symbol.asyncIterator in inputs ? inputs[Symbol.asyncIterator]() : inputs[Symbol.iterator]();
|
|
1801
|
+
}
|
|
1802
|
+
next() {
|
|
1803
|
+
const pull = this.pulling.then(async () => {
|
|
1804
|
+
const result = await this.iterator.next();
|
|
1805
|
+
if (result.done) return void 0;
|
|
1806
|
+
return { index: this.index++, input: result.value };
|
|
1807
|
+
});
|
|
1808
|
+
this.pulling = pull.catch(() => void 0);
|
|
1809
|
+
return pull;
|
|
1810
|
+
}
|
|
1811
|
+
};
|
|
1812
|
+
function labelOf(input) {
|
|
1813
|
+
if (typeof input === "string") return void 0;
|
|
1814
|
+
if (isSource(input)) return input.label;
|
|
1815
|
+
return input[0]?.label;
|
|
1816
|
+
}
|
|
1471
1817
|
async function coerceMany(inputs, options) {
|
|
1472
1818
|
const {
|
|
1473
1819
|
concurrency = DEFAULT_CONCURRENCY,
|
|
1474
1820
|
mode = "coerce",
|
|
1475
|
-
provenance = false,
|
|
1476
|
-
primeCache = true,
|
|
1821
|
+
provenance: provenanceOption = false,
|
|
1822
|
+
primeCache: primeCache2 = true,
|
|
1823
|
+
primed,
|
|
1477
1824
|
onItem,
|
|
1478
1825
|
signal,
|
|
1826
|
+
retry: retryOptions,
|
|
1479
1827
|
...coerceOptions
|
|
1480
1828
|
} = options;
|
|
1481
|
-
const retry = { ...DEFAULT_RETRY, ...
|
|
1829
|
+
const retry = { ...DEFAULT_RETRY, ...retryOptions };
|
|
1830
|
+
const provenance = provenanceOption !== false;
|
|
1831
|
+
if (Array.isArray(provenanceOption)) {
|
|
1832
|
+
coerceOptions.provenanceFields = provenanceOption;
|
|
1833
|
+
}
|
|
1482
1834
|
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
1483
1835
|
throw new RangeError(`concurrency must be a positive integer, got ${String(concurrency)}`);
|
|
1484
1836
|
}
|
|
1485
1837
|
if (!Number.isInteger(retry.attempts) || retry.attempts < 0) {
|
|
1486
1838
|
throw new RangeError(`retry.attempts must be a non-negative integer, got ${String(retry.attempts)}`);
|
|
1487
1839
|
}
|
|
1488
|
-
const results =
|
|
1840
|
+
const results = [];
|
|
1489
1841
|
const gate = new BackoffGate(retry);
|
|
1490
|
-
|
|
1842
|
+
const queue = new InputQueue(inputs);
|
|
1843
|
+
async function runOne(index, input) {
|
|
1491
1844
|
let attempts = 0;
|
|
1492
1845
|
let result;
|
|
1846
|
+
let usage = emptyUsage();
|
|
1847
|
+
const label = labelOf(input);
|
|
1848
|
+
const traceAttributes = { itemIndex: index, ...label !== void 0 ? { itemLabel: label } : {} };
|
|
1493
1849
|
for (; ; ) {
|
|
1494
1850
|
if (signal?.aborted) {
|
|
1495
|
-
result = { ok: false, index, error: signal.reason ?? new Error("Batch aborted"), attempts };
|
|
1851
|
+
result = { ok: false, index, error: signal.reason ?? new Error("Batch aborted"), usage, attempts };
|
|
1496
1852
|
break;
|
|
1497
1853
|
}
|
|
1498
1854
|
await gate.wait();
|
|
1499
1855
|
attempts += 1;
|
|
1500
1856
|
try {
|
|
1501
|
-
const run = await runCoercion(
|
|
1857
|
+
const run = await runCoercion(input, coerceOptions, { mode, provenance, traceAttributes });
|
|
1502
1858
|
const data = mode === "partialCoerce" ? stripNulls(run.data) : run.data;
|
|
1503
1859
|
gate.succeeded();
|
|
1504
|
-
result = { ok: true, index, data, provenance: run.provenance, issues: run.issues, attempts };
|
|
1860
|
+
result = { ok: true, index, data, provenance: run.provenance, issues: run.issues, usage: run.usage, attempts };
|
|
1505
1861
|
break;
|
|
1506
1862
|
} catch (error) {
|
|
1863
|
+
usage = emptyUsage();
|
|
1507
1864
|
if (isRetryable(error) && attempts <= retry.attempts) {
|
|
1508
1865
|
gate.failed();
|
|
1509
1866
|
continue;
|
|
1510
1867
|
}
|
|
1511
|
-
result = { ok: false, index, error, attempts };
|
|
1868
|
+
result = { ok: false, index, error, usage, attempts };
|
|
1512
1869
|
break;
|
|
1513
1870
|
}
|
|
1514
1871
|
}
|
|
1515
1872
|
results[index] = result;
|
|
1516
1873
|
onItem?.(result);
|
|
1517
1874
|
}
|
|
1518
|
-
let
|
|
1519
|
-
|
|
1520
|
-
|
|
1875
|
+
let pending;
|
|
1876
|
+
const warmup = primed ?? (primeCache2 === "eager" ? primeCache({ ...coerceOptions, mode, provenance }) : void 0);
|
|
1877
|
+
if (warmup) {
|
|
1878
|
+
await Promise.resolve(warmup).catch(() => void 0);
|
|
1879
|
+
} else if (primeCache2 === true) {
|
|
1880
|
+
const first = await queue.next();
|
|
1881
|
+
if (first === void 0) return results;
|
|
1882
|
+
const second = await queue.next();
|
|
1883
|
+
if (second === void 0) {
|
|
1884
|
+
await runOne(first.index, first.input);
|
|
1885
|
+
return results;
|
|
1886
|
+
}
|
|
1887
|
+
await runOne(first.index, first.input);
|
|
1888
|
+
pending = second;
|
|
1521
1889
|
}
|
|
1522
|
-
const workers = Array.from({ length:
|
|
1523
|
-
|
|
1524
|
-
await
|
|
1890
|
+
const workers = Array.from({ length: concurrency }, async () => {
|
|
1891
|
+
for (; ; ) {
|
|
1892
|
+
const item = pending ?? await queue.next();
|
|
1893
|
+
pending = void 0;
|
|
1894
|
+
if (item === void 0) return;
|
|
1895
|
+
await runOne(item.index, item.input);
|
|
1525
1896
|
}
|
|
1526
1897
|
});
|
|
1527
1898
|
await Promise.all(workers);
|
|
@@ -1559,6 +1930,8 @@ function resolveConfig(callConfig) {
|
|
|
1559
1930
|
traceSinks: callConfig?.traceSinks ?? global.traceSinks,
|
|
1560
1931
|
maxRepairAttempts: callConfig?.maxRepairAttempts ?? global.maxRepairAttempts,
|
|
1561
1932
|
onInvalidField: callConfig?.onInvalidField ?? global.onInvalidField,
|
|
1933
|
+
instructions: callConfig?.instructions ?? global.instructions,
|
|
1934
|
+
retryOnEmpty: callConfig?.retryOnEmpty ?? global.retryOnEmpty,
|
|
1562
1935
|
maxInputChars: callConfig?.maxInputChars ?? global.maxInputChars,
|
|
1563
1936
|
truncate: callConfig?.truncate ?? global.truncate,
|
|
1564
1937
|
preprocess: callConfig?.preprocess ?? global.preprocess
|
|
@@ -1592,6 +1965,8 @@ var Coercible = class _Coercible {
|
|
|
1592
1965
|
traceSinks: this._config.traceSinks,
|
|
1593
1966
|
maxRepairAttempts: this._config.maxRepairAttempts,
|
|
1594
1967
|
onInvalidField: this._config.onInvalidField,
|
|
1968
|
+
instructions: this._config.instructions,
|
|
1969
|
+
retryOnEmpty: this._config.retryOnEmpty,
|
|
1595
1970
|
maxInputChars: this._config.maxInputChars,
|
|
1596
1971
|
truncate: this._config.truncate,
|
|
1597
1972
|
preprocess: this._config.preprocess
|
|
@@ -1657,6 +2032,7 @@ export {
|
|
|
1657
2032
|
Constrain,
|
|
1658
2033
|
Describe,
|
|
1659
2034
|
EnumResolutionError,
|
|
2035
|
+
FIELD_FORMATS,
|
|
1660
2036
|
PROVENANCE_INSTRUCTIONS,
|
|
1661
2037
|
SOURCE_INSTRUCTIONS,
|
|
1662
2038
|
Schema,
|
|
@@ -1669,15 +2045,21 @@ export {
|
|
|
1669
2045
|
buildRepairInput,
|
|
1670
2046
|
bundleOf,
|
|
1671
2047
|
coerce,
|
|
2048
|
+
coerceDetailed,
|
|
1672
2049
|
coerceMany,
|
|
1673
2050
|
coerceWithProvenance,
|
|
1674
2051
|
collectEnumSources,
|
|
1675
2052
|
defineSchema,
|
|
2053
|
+
describeFormat,
|
|
1676
2054
|
field,
|
|
2055
|
+
formatToJsonSchema,
|
|
1677
2056
|
isCoerceInput,
|
|
1678
2057
|
isSource,
|
|
2058
|
+
normalizeInstructions,
|
|
1679
2059
|
partialCoerce,
|
|
2060
|
+
partialCoerceDetailed,
|
|
1680
2061
|
partialCoerceWithProvenance,
|
|
2062
|
+
primeCache,
|
|
1681
2063
|
provenanceInstructions,
|
|
1682
2064
|
renderSources,
|
|
1683
2065
|
resolveEnumSources,
|
|
@@ -1688,6 +2070,7 @@ export {
|
|
|
1688
2070
|
toOpenAIJsonSchema,
|
|
1689
2071
|
toProvenanceSchema,
|
|
1690
2072
|
toSources,
|
|
2073
|
+
validateFormat,
|
|
1691
2074
|
validatePartial,
|
|
1692
2075
|
validateStrict
|
|
1693
2076
|
};
|