@sembl/core 0.3.0 → 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 +438 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +181 -16
- package/dist/index.d.ts +181 -16
- package/dist/index.js +431 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
Constrain: () => Constrain,
|
|
27
27
|
Describe: () => Describe,
|
|
28
28
|
EnumResolutionError: () => EnumResolutionError,
|
|
29
|
+
FIELD_FORMATS: () => FIELD_FORMATS,
|
|
29
30
|
PROVENANCE_INSTRUCTIONS: () => PROVENANCE_INSTRUCTIONS,
|
|
30
31
|
SOURCE_INSTRUCTIONS: () => SOURCE_INSTRUCTIONS,
|
|
31
32
|
Schema: () => Schema,
|
|
@@ -38,16 +39,21 @@ __export(index_exports, {
|
|
|
38
39
|
buildRepairInput: () => buildRepairInput,
|
|
39
40
|
bundleOf: () => bundleOf,
|
|
40
41
|
coerce: () => coerce,
|
|
42
|
+
coerceDetailed: () => coerceDetailed,
|
|
41
43
|
coerceMany: () => coerceMany,
|
|
42
44
|
coerceWithProvenance: () => coerceWithProvenance,
|
|
43
45
|
collectEnumSources: () => collectEnumSources,
|
|
44
46
|
defineSchema: () => defineSchema,
|
|
47
|
+
describeFormat: () => describeFormat,
|
|
45
48
|
field: () => field,
|
|
49
|
+
formatToJsonSchema: () => formatToJsonSchema,
|
|
46
50
|
isCoerceInput: () => isCoerceInput,
|
|
47
51
|
isSource: () => isSource,
|
|
48
52
|
normalizeInstructions: () => normalizeInstructions,
|
|
49
53
|
partialCoerce: () => partialCoerce,
|
|
54
|
+
partialCoerceDetailed: () => partialCoerceDetailed,
|
|
50
55
|
partialCoerceWithProvenance: () => partialCoerceWithProvenance,
|
|
56
|
+
primeCache: () => primeCache,
|
|
51
57
|
provenanceInstructions: () => provenanceInstructions,
|
|
52
58
|
renderSources: () => renderSources,
|
|
53
59
|
resolveEnumSources: () => resolveEnumSources,
|
|
@@ -58,11 +64,164 @@ __export(index_exports, {
|
|
|
58
64
|
toOpenAIJsonSchema: () => toOpenAIJsonSchema,
|
|
59
65
|
toProvenanceSchema: () => toProvenanceSchema,
|
|
60
66
|
toSources: () => toSources,
|
|
67
|
+
validateFormat: () => validateFormat,
|
|
61
68
|
validatePartial: () => validatePartial,
|
|
62
69
|
validateStrict: () => validateStrict
|
|
63
70
|
});
|
|
64
71
|
module.exports = __toCommonJS(index_exports);
|
|
65
72
|
|
|
73
|
+
// src/schema/formats.ts
|
|
74
|
+
var FIELD_FORMATS = [
|
|
75
|
+
"url",
|
|
76
|
+
"email",
|
|
77
|
+
"date",
|
|
78
|
+
"datetime",
|
|
79
|
+
"iso-country",
|
|
80
|
+
"us-state",
|
|
81
|
+
"us-state-name",
|
|
82
|
+
"currency"
|
|
83
|
+
];
|
|
84
|
+
var ISO_COUNTRIES = new Set(
|
|
85
|
+
"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(" ")
|
|
86
|
+
);
|
|
87
|
+
var US_STATES = {
|
|
88
|
+
AL: "Alabama",
|
|
89
|
+
AK: "Alaska",
|
|
90
|
+
AZ: "Arizona",
|
|
91
|
+
AR: "Arkansas",
|
|
92
|
+
CA: "California",
|
|
93
|
+
CO: "Colorado",
|
|
94
|
+
CT: "Connecticut",
|
|
95
|
+
DE: "Delaware",
|
|
96
|
+
FL: "Florida",
|
|
97
|
+
GA: "Georgia",
|
|
98
|
+
HI: "Hawaii",
|
|
99
|
+
ID: "Idaho",
|
|
100
|
+
IL: "Illinois",
|
|
101
|
+
IN: "Indiana",
|
|
102
|
+
IA: "Iowa",
|
|
103
|
+
KS: "Kansas",
|
|
104
|
+
KY: "Kentucky",
|
|
105
|
+
LA: "Louisiana",
|
|
106
|
+
ME: "Maine",
|
|
107
|
+
MD: "Maryland",
|
|
108
|
+
MA: "Massachusetts",
|
|
109
|
+
MI: "Michigan",
|
|
110
|
+
MN: "Minnesota",
|
|
111
|
+
MS: "Mississippi",
|
|
112
|
+
MO: "Missouri",
|
|
113
|
+
MT: "Montana",
|
|
114
|
+
NE: "Nebraska",
|
|
115
|
+
NV: "Nevada",
|
|
116
|
+
NH: "New Hampshire",
|
|
117
|
+
NJ: "New Jersey",
|
|
118
|
+
NM: "New Mexico",
|
|
119
|
+
NY: "New York",
|
|
120
|
+
NC: "North Carolina",
|
|
121
|
+
ND: "North Dakota",
|
|
122
|
+
OH: "Ohio",
|
|
123
|
+
OK: "Oklahoma",
|
|
124
|
+
OR: "Oregon",
|
|
125
|
+
PA: "Pennsylvania",
|
|
126
|
+
RI: "Rhode Island",
|
|
127
|
+
SC: "South Carolina",
|
|
128
|
+
SD: "South Dakota",
|
|
129
|
+
TN: "Tennessee",
|
|
130
|
+
TX: "Texas",
|
|
131
|
+
UT: "Utah",
|
|
132
|
+
VT: "Vermont",
|
|
133
|
+
VA: "Virginia",
|
|
134
|
+
WA: "Washington",
|
|
135
|
+
WV: "West Virginia",
|
|
136
|
+
WI: "Wisconsin",
|
|
137
|
+
WY: "Wyoming",
|
|
138
|
+
DC: "District of Columbia",
|
|
139
|
+
PR: "Puerto Rico",
|
|
140
|
+
GU: "Guam",
|
|
141
|
+
VI: "U.S. Virgin Islands",
|
|
142
|
+
AS: "American Samoa",
|
|
143
|
+
MP: "Northern Mariana Islands"
|
|
144
|
+
};
|
|
145
|
+
var US_STATE_NAMES = new Set(Object.values(US_STATES));
|
|
146
|
+
var CURRENCIES = new Set(
|
|
147
|
+
"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(" ")
|
|
148
|
+
);
|
|
149
|
+
var EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
150
|
+
var DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
151
|
+
var DATETIME = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?$/;
|
|
152
|
+
function isCalendarDate(y, m, d) {
|
|
153
|
+
const date = new Date(Date.UTC(y, m - 1, d));
|
|
154
|
+
return date.getUTCFullYear() === y && date.getUTCMonth() === m - 1 && date.getUTCDate() === d;
|
|
155
|
+
}
|
|
156
|
+
function validateFormat(value, format) {
|
|
157
|
+
switch (format) {
|
|
158
|
+
case "url": {
|
|
159
|
+
try {
|
|
160
|
+
const url = new URL(value);
|
|
161
|
+
if (url.protocol === "http:" || url.protocol === "https:") return void 0;
|
|
162
|
+
} catch {
|
|
163
|
+
}
|
|
164
|
+
return `Expected an absolute http(s) URL, got ${JSON.stringify(value)}`;
|
|
165
|
+
}
|
|
166
|
+
case "email":
|
|
167
|
+
return EMAIL.test(value) ? void 0 : `Expected an email address, got ${JSON.stringify(value)}`;
|
|
168
|
+
case "date": {
|
|
169
|
+
const m = DATE.exec(value);
|
|
170
|
+
if (m && isCalendarDate(Number(m[1]), Number(m[2]), Number(m[3]))) return void 0;
|
|
171
|
+
return `Expected a calendar date as YYYY-MM-DD, got ${JSON.stringify(value)}`;
|
|
172
|
+
}
|
|
173
|
+
case "datetime":
|
|
174
|
+
return DATETIME.test(value) && !Number.isNaN(Date.parse(value)) ? void 0 : `Expected an ISO 8601 timestamp, got ${JSON.stringify(value)}`;
|
|
175
|
+
case "iso-country":
|
|
176
|
+
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)}`;
|
|
177
|
+
case "us-state":
|
|
178
|
+
return value in US_STATES ? void 0 : `Expected a two-letter USPS state code such as CA or NY, got ${JSON.stringify(value)}`;
|
|
179
|
+
case "us-state-name":
|
|
180
|
+
return US_STATE_NAMES.has(value) ? void 0 : `Expected a US state's full name such as California, got ${JSON.stringify(value)}`;
|
|
181
|
+
case "currency":
|
|
182
|
+
return CURRENCIES.has(value) ? void 0 : `Expected an ISO 4217 currency code such as USD or EUR, got ${JSON.stringify(value)}`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function describeFormat(format) {
|
|
186
|
+
switch (format) {
|
|
187
|
+
case "url":
|
|
188
|
+
return "an absolute http(s) URL";
|
|
189
|
+
case "email":
|
|
190
|
+
return "an email address";
|
|
191
|
+
case "date":
|
|
192
|
+
return "a calendar date as YYYY-MM-DD";
|
|
193
|
+
case "datetime":
|
|
194
|
+
return "an ISO 8601 timestamp (e.g. 2026-09-05T14:30:00Z)";
|
|
195
|
+
case "iso-country":
|
|
196
|
+
return "an ISO 3166-1 alpha-2 country code (e.g. US, DE, PT), never a country name";
|
|
197
|
+
case "us-state":
|
|
198
|
+
return "a two-letter USPS state code (e.g. CA, NY), never the state's name";
|
|
199
|
+
case "us-state-name":
|
|
200
|
+
return "a US state's full name (e.g. California, New York), never its abbreviation";
|
|
201
|
+
case "currency":
|
|
202
|
+
return "an ISO 4217 currency code (e.g. USD, EUR, GBP), never a symbol or a word";
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function formatToJsonSchema(format) {
|
|
206
|
+
switch (format) {
|
|
207
|
+
case "url":
|
|
208
|
+
return { format: "uri" };
|
|
209
|
+
case "email":
|
|
210
|
+
return { format: "email" };
|
|
211
|
+
case "date":
|
|
212
|
+
return { format: "date" };
|
|
213
|
+
case "datetime":
|
|
214
|
+
return { format: "date-time" };
|
|
215
|
+
case "iso-country":
|
|
216
|
+
case "us-state":
|
|
217
|
+
return { pattern: "^[A-Z]{2}$" };
|
|
218
|
+
case "currency":
|
|
219
|
+
return { pattern: "^[A-Z]{3}$" };
|
|
220
|
+
case "us-state-name":
|
|
221
|
+
return {};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
66
225
|
// src/schema/json-schema.ts
|
|
67
226
|
var CONSTRAINT_KEYWORDS = [
|
|
68
227
|
"maxLength",
|
|
@@ -79,6 +238,9 @@ function constraintsToJsonSchema(constraints, dialect) {
|
|
|
79
238
|
return {};
|
|
80
239
|
}
|
|
81
240
|
const out = {};
|
|
241
|
+
if (constraints.format !== void 0) {
|
|
242
|
+
Object.assign(out, formatToJsonSchema(constraints.format));
|
|
243
|
+
}
|
|
82
244
|
for (const keyword of CONSTRAINT_KEYWORDS) {
|
|
83
245
|
const value = constraints[keyword];
|
|
84
246
|
if (value !== void 0) {
|
|
@@ -463,7 +625,7 @@ ${summary}`);
|
|
|
463
625
|
// src/coerce/sources.ts
|
|
464
626
|
var SOURCE_TAG = "source";
|
|
465
627
|
function isSource(value) {
|
|
466
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.text === "string" && (value.label === void 0 || typeof value.label === "string");
|
|
628
|
+
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");
|
|
467
629
|
}
|
|
468
630
|
function isCoerceInput(value) {
|
|
469
631
|
return typeof value === "string" || isSource(value) || Array.isArray(value) && value.every(isSource);
|
|
@@ -483,7 +645,9 @@ function toSources(input) {
|
|
|
483
645
|
}
|
|
484
646
|
function cleanLabel(source) {
|
|
485
647
|
const label = source.label?.trim();
|
|
486
|
-
|
|
648
|
+
const cleaned = label ? { label, text: source.text } : { text: source.text };
|
|
649
|
+
if (source.maxChars !== void 0) cleaned.maxChars = source.maxChars;
|
|
650
|
+
return cleaned;
|
|
487
651
|
}
|
|
488
652
|
function escapeText(text) {
|
|
489
653
|
return text.replace(new RegExp(`</(\\s*${SOURCE_TAG}\\b)`, "gi"), "<\\/$1");
|
|
@@ -521,7 +685,10 @@ function describeConstraints(constraints) {
|
|
|
521
685
|
return [];
|
|
522
686
|
}
|
|
523
687
|
const phrases = [];
|
|
524
|
-
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern } = constraints;
|
|
688
|
+
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern, format } = constraints;
|
|
689
|
+
if (format !== void 0) {
|
|
690
|
+
phrases.push(describeFormat(format));
|
|
691
|
+
}
|
|
525
692
|
if (minLength !== void 0 && maxLength !== void 0) {
|
|
526
693
|
phrases.push(`between ${minLength} and ${maxLength} characters`);
|
|
527
694
|
} else if (maxLength !== void 0) {
|
|
@@ -634,6 +801,8 @@ function buildPrompt(schema, bundle, options = {}) {
|
|
|
634
801
|
lines.push("Instructions:");
|
|
635
802
|
lines.push("- Extract values from the sources that match the schema fields.");
|
|
636
803
|
lines.push("- Use null for optional fields that cannot be determined from the input.");
|
|
804
|
+
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.");
|
|
805
|
+
lines.push("- Never return an empty object when the input states values for any field.");
|
|
637
806
|
lines.push("- Required fields must always have a valid, non-null value.");
|
|
638
807
|
lines.push("- Interpret the user's input semantically \u2014 infer meaning, don't just pattern match.");
|
|
639
808
|
lines.push("- Respect every stated limit exactly; truncate or drop lower-priority content to stay within it.");
|
|
@@ -699,11 +868,31 @@ var PROVENANCE_INSTRUCTIONS = [
|
|
|
699
868
|
"- Judge each field on its own. A confident value next to a guessed one is",
|
|
700
869
|
" normal, and marking the guess honestly is more useful than looking sure."
|
|
701
870
|
].join("\n");
|
|
871
|
+
function provenanceFieldNames(schema, fields) {
|
|
872
|
+
if (fields === void 0) return new Set(schema.fields.map((f) => f.name));
|
|
873
|
+
const known = new Set(schema.fields.map((f) => f.name));
|
|
874
|
+
for (const name of fields) {
|
|
875
|
+
if (!known.has(name)) {
|
|
876
|
+
throw new RangeError(
|
|
877
|
+
`provenance field "${name}" is not a field of schema "${schema.id}" (fields: ${[...known].join(", ")})`
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
return new Set(fields);
|
|
882
|
+
}
|
|
702
883
|
function provenanceInstructions(options = {}) {
|
|
703
884
|
const labels = options.sourceLabels ?? [];
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
885
|
+
let text = PROVENANCE_INSTRUCTIONS;
|
|
886
|
+
if (options.fields !== void 0) {
|
|
887
|
+
text = text.replace(
|
|
888
|
+
"- Every field is wrapped as an object: put the extracted value in `value`.",
|
|
889
|
+
`- Only these fields are wrapped as objects, with the extracted value in \`value\`: ${options.fields.join(", ")}. Every other field is a plain value.`
|
|
890
|
+
);
|
|
891
|
+
}
|
|
892
|
+
if (labels.length >= 2) {
|
|
893
|
+
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`.";
|
|
894
|
+
}
|
|
895
|
+
return text;
|
|
707
896
|
}
|
|
708
897
|
function annotationSchema(parentId, field2, sourceLabels) {
|
|
709
898
|
const valueField = {
|
|
@@ -735,7 +924,7 @@ function annotationSchema(parentId, field2, sourceLabels) {
|
|
|
735
924
|
name: "source",
|
|
736
925
|
description: "The label of the source this value was read from.",
|
|
737
926
|
type: { kind: "enum", values: [...sourceLabels] },
|
|
738
|
-
required:
|
|
927
|
+
required: true
|
|
739
928
|
}
|
|
740
929
|
] : []
|
|
741
930
|
]
|
|
@@ -745,7 +934,12 @@ function toProvenanceSchema(schema, bundle, options = {}) {
|
|
|
745
934
|
const schemas = { ...bundle?.schemas ?? {} };
|
|
746
935
|
const fields = [];
|
|
747
936
|
const sourceLabels = options.sourceLabels ?? [];
|
|
937
|
+
const wrapped = provenanceFieldNames(schema, options.fields);
|
|
748
938
|
for (const field2 of schema.fields) {
|
|
939
|
+
if (!wrapped.has(field2.name)) {
|
|
940
|
+
fields.push(field2);
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
749
943
|
const annotation = annotationSchema(schema.id, field2, sourceLabels);
|
|
750
944
|
schemas[annotation.id] = annotation;
|
|
751
945
|
fields.push({
|
|
@@ -821,10 +1015,30 @@ ${tailRoom > 0 ? text.slice(text.length - tailRoom) : ""}`;
|
|
|
821
1015
|
}
|
|
822
1016
|
}
|
|
823
1017
|
function budgetSources(sources, maxChars, policy = "tail") {
|
|
824
|
-
const
|
|
825
|
-
|
|
826
|
-
|
|
1018
|
+
const records = /* @__PURE__ */ new Map();
|
|
1019
|
+
const record = (index, source, text) => {
|
|
1020
|
+
const existing = records.get(index);
|
|
1021
|
+
if (existing) {
|
|
1022
|
+
existing.keptLength = text.length;
|
|
1023
|
+
} else {
|
|
1024
|
+
records.set(index, {
|
|
1025
|
+
...source.label !== void 0 ? { label: source.label } : {},
|
|
1026
|
+
originalLength: source.text.length,
|
|
1027
|
+
keptLength: text.length
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
const capped = sources.map((source, index) => {
|
|
1032
|
+
if (source.maxChars === void 0 || source.text.length <= source.maxChars) return source;
|
|
1033
|
+
const text = truncateText(source.text, source.maxChars, policy);
|
|
1034
|
+
record(index, source, text);
|
|
1035
|
+
return { ...source, text };
|
|
1036
|
+
});
|
|
1037
|
+
const total = capped.reduce((sum, s) => sum + s.text.length, 0);
|
|
1038
|
+
if (maxChars === void 0 || total <= maxChars) {
|
|
1039
|
+
return { sources: capped, truncated: [...records.values()] };
|
|
827
1040
|
}
|
|
1041
|
+
sources = capped;
|
|
828
1042
|
const allowance = /* @__PURE__ */ new Map();
|
|
829
1043
|
const order = sources.map((s, i) => i).sort((a, b) => sources[a].text.length - sources[b].text.length);
|
|
830
1044
|
let remaining = maxChars;
|
|
@@ -834,19 +1048,14 @@ function budgetSources(sources, maxChars, policy = "tail") {
|
|
|
834
1048
|
allowance.set(index, granted);
|
|
835
1049
|
remaining -= granted;
|
|
836
1050
|
});
|
|
837
|
-
const truncated = [];
|
|
838
1051
|
const budgeted = sources.map((source, index) => {
|
|
839
1052
|
const limit = allowance.get(index) ?? 0;
|
|
840
1053
|
if (source.text.length <= limit) return source;
|
|
841
1054
|
const text = truncateText(source.text, limit, policy);
|
|
842
|
-
|
|
843
|
-
...source.label !== void 0 ? { label: source.label } : {},
|
|
844
|
-
originalLength: source.text.length,
|
|
845
|
-
keptLength: text.length
|
|
846
|
-
});
|
|
1055
|
+
record(index, source, text);
|
|
847
1056
|
return { ...source, text };
|
|
848
1057
|
});
|
|
849
|
-
return { sources: budgeted, truncated };
|
|
1058
|
+
return { sources: budgeted, truncated: [...records.values()] };
|
|
850
1059
|
}
|
|
851
1060
|
|
|
852
1061
|
// src/coerce/validator.ts
|
|
@@ -862,7 +1071,7 @@ function entries(count) {
|
|
|
862
1071
|
return `${count} ${count === 1 ? "entry" : "entries"}`;
|
|
863
1072
|
}
|
|
864
1073
|
function validateConstraints(value, constraints, path, issues) {
|
|
865
|
-
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern } = constraints;
|
|
1074
|
+
const { minLength, maxLength, minimum, maximum, minItems, maxItems, pattern, format } = constraints;
|
|
866
1075
|
if (Array.isArray(value)) {
|
|
867
1076
|
if (minItems !== void 0 && value.length < minItems) {
|
|
868
1077
|
issues.push({
|
|
@@ -906,6 +1115,10 @@ function validateConstraints(value, constraints, path, issues) {
|
|
|
906
1115
|
received: value
|
|
907
1116
|
});
|
|
908
1117
|
}
|
|
1118
|
+
if (format !== void 0) {
|
|
1119
|
+
const message = validateFormat(value, format);
|
|
1120
|
+
if (message) issues.push({ path, message, received: value });
|
|
1121
|
+
}
|
|
909
1122
|
return;
|
|
910
1123
|
}
|
|
911
1124
|
if (typeof value === "number") {
|
|
@@ -1247,8 +1460,15 @@ function generateSpanId() {
|
|
|
1247
1460
|
}
|
|
1248
1461
|
var Tracer = class {
|
|
1249
1462
|
sinks;
|
|
1250
|
-
|
|
1463
|
+
baseAttributes;
|
|
1464
|
+
/**
|
|
1465
|
+
* `baseAttributes` are merged into every span this tracer opens — how a
|
|
1466
|
+
* batch stamps `itemIndex` on the spans of each item, so a sink can tell
|
|
1467
|
+
* whose `llmCall` it is looking at under concurrency.
|
|
1468
|
+
*/
|
|
1469
|
+
constructor(sinks, baseAttributes) {
|
|
1251
1470
|
this.sinks = sinks ?? [];
|
|
1471
|
+
this.baseAttributes = baseAttributes;
|
|
1252
1472
|
}
|
|
1253
1473
|
startSpan(name, attributes, parent) {
|
|
1254
1474
|
return {
|
|
@@ -1256,7 +1476,7 @@ var Tracer = class {
|
|
|
1256
1476
|
name,
|
|
1257
1477
|
startTime: Date.now(),
|
|
1258
1478
|
events: [],
|
|
1259
|
-
attributes,
|
|
1479
|
+
attributes: this.baseAttributes ? { ...this.baseAttributes, ...attributes } : attributes,
|
|
1260
1480
|
parentId: parent?.id
|
|
1261
1481
|
};
|
|
1262
1482
|
}
|
|
@@ -1311,15 +1531,31 @@ async function resolveEnums(schema, bundle, enumResolver, tracer, parent) {
|
|
|
1311
1531
|
tracer.endSpan(span);
|
|
1312
1532
|
}
|
|
1313
1533
|
}
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1534
|
+
function emptyUsage() {
|
|
1535
|
+
return { calls: 0, promptTokens: 0, completionTokens: 0, totalTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };
|
|
1536
|
+
}
|
|
1537
|
+
function addUsage(into, usage) {
|
|
1538
|
+
into.calls += 1;
|
|
1539
|
+
if (!usage) return;
|
|
1540
|
+
into.promptTokens += usage.promptTokens;
|
|
1541
|
+
into.completionTokens += usage.completionTokens;
|
|
1542
|
+
into.totalTokens += usage.totalTokens;
|
|
1543
|
+
into.cacheReadTokens += usage.cacheReadTokens ?? 0;
|
|
1544
|
+
into.cacheWriteTokens += usage.cacheWriteTokens ?? 0;
|
|
1545
|
+
}
|
|
1546
|
+
function checkOptions(options) {
|
|
1317
1547
|
const maxRepairAttempts = options.maxRepairAttempts ?? 0;
|
|
1318
1548
|
if (!Number.isInteger(maxRepairAttempts) || maxRepairAttempts < 0) {
|
|
1319
1549
|
throw new RangeError(
|
|
1320
1550
|
`maxRepairAttempts must be a non-negative integer, got ${String(options.maxRepairAttempts)}`
|
|
1321
1551
|
);
|
|
1322
1552
|
}
|
|
1553
|
+
const retryOnEmpty = options.retryOnEmpty ?? 0;
|
|
1554
|
+
if (!Number.isInteger(retryOnEmpty) || retryOnEmpty < 0) {
|
|
1555
|
+
throw new RangeError(
|
|
1556
|
+
`retryOnEmpty must be a non-negative integer, got ${String(options.retryOnEmpty)}`
|
|
1557
|
+
);
|
|
1558
|
+
}
|
|
1323
1559
|
const instructions = normalizeInstructions(options.instructions);
|
|
1324
1560
|
const onInvalidField = options.onInvalidField ?? "throw";
|
|
1325
1561
|
if (!INVALID_FIELD_POLICIES.includes(onInvalidField)) {
|
|
@@ -1332,61 +1568,96 @@ async function runCoercion(input, options, { mode, provenance }) {
|
|
|
1332
1568
|
`maxInputChars must be a positive integer, got ${String(options.maxInputChars)}`
|
|
1333
1569
|
);
|
|
1334
1570
|
}
|
|
1571
|
+
return { maxRepairAttempts, retryOnEmpty, onInvalidField, instructions };
|
|
1572
|
+
}
|
|
1573
|
+
async function prepareRequest(options, { mode, provenance }, instructions, sourceLabels, tracer, rootSpan) {
|
|
1574
|
+
const { schema, enumResolver } = options;
|
|
1575
|
+
const bundle = options.bundle ?? bundleOf(schema);
|
|
1576
|
+
const resolvedEnums = await resolveEnums(schema, bundle, enumResolver, tracer, rootSpan);
|
|
1577
|
+
const promptSpan = tracer.startSpan("buildPrompt", {}, rootSpan);
|
|
1578
|
+
const basePrompt = buildPrompt(schema, bundle, { resolvedEnums, instructions });
|
|
1579
|
+
const provenanceOptions = { sourceLabels, fields: options.provenanceFields };
|
|
1580
|
+
const systemPrompt = provenance ? `${basePrompt}
|
|
1581
|
+
${provenanceInstructions(provenanceOptions)}` : basePrompt;
|
|
1582
|
+
tracer.addEvent(promptSpan, "promptBuilt", {
|
|
1583
|
+
promptLength: systemPrompt.length,
|
|
1584
|
+
instructionCount: instructions.length,
|
|
1585
|
+
mode
|
|
1586
|
+
});
|
|
1587
|
+
tracer.endSpan(promptSpan);
|
|
1588
|
+
const request = provenance ? toProvenanceSchema(schema, bundle, provenanceOptions) : { schema, bundle };
|
|
1589
|
+
const schemaSpan = tracer.startSpan("buildJsonSchema", {}, rootSpan);
|
|
1590
|
+
const jsonSchema = runtimeSchemaToJsonSchema(request.schema, request.bundle, {
|
|
1591
|
+
resolvedEnums
|
|
1592
|
+
});
|
|
1593
|
+
tracer.endSpan(schemaSpan);
|
|
1594
|
+
return { systemPrompt, jsonSchema, schema: request.schema, bundle: request.bundle, resolvedEnums };
|
|
1595
|
+
}
|
|
1596
|
+
function isEmptyResult(data) {
|
|
1597
|
+
return Object.values(data).every((value) => value === null || value === void 0);
|
|
1598
|
+
}
|
|
1599
|
+
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.";
|
|
1600
|
+
async function runCoercion(input, options, { mode, provenance, traceAttributes }) {
|
|
1601
|
+
const { provider, schema, traceSinks } = options;
|
|
1602
|
+
const bundle = options.bundle ?? bundleOf(schema);
|
|
1603
|
+
const { maxRepairAttempts, retryOnEmpty, onInvalidField, instructions } = checkOptions(options);
|
|
1335
1604
|
const rawSources = toSources(input);
|
|
1336
|
-
const tracer = new Tracer(traceSinks);
|
|
1605
|
+
const tracer = new Tracer(traceSinks, traceAttributes);
|
|
1337
1606
|
const rootSpan = tracer.startSpan(mode, {
|
|
1338
1607
|
schemaId: schema.id,
|
|
1339
1608
|
provenance,
|
|
1340
1609
|
onInvalidField,
|
|
1341
1610
|
sourceCount: rawSources.length
|
|
1342
1611
|
});
|
|
1612
|
+
const usage = emptyUsage();
|
|
1343
1613
|
try {
|
|
1344
1614
|
const sources = await prepareSources(rawSources, options, tracer, rootSpan);
|
|
1345
1615
|
const sourceLabels = sources.length > 1 ? sources.map((s) => s.label ?? "") : [];
|
|
1346
|
-
const
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1616
|
+
const prepared = await prepareRequest(
|
|
1617
|
+
options,
|
|
1618
|
+
{ mode, provenance },
|
|
1619
|
+
instructions,
|
|
1620
|
+
sourceLabels,
|
|
1350
1621
|
tracer,
|
|
1351
1622
|
rootSpan
|
|
1352
1623
|
);
|
|
1353
|
-
const
|
|
1354
|
-
const basePrompt = buildPrompt(schema, bundle, { resolvedEnums, instructions });
|
|
1355
|
-
const systemPrompt = provenance ? `${basePrompt}
|
|
1356
|
-
${provenanceInstructions({ sourceLabels })}` : basePrompt;
|
|
1357
|
-
tracer.addEvent(promptSpan, "promptBuilt", {
|
|
1358
|
-
promptLength: systemPrompt.length,
|
|
1359
|
-
instructionCount: instructions.length
|
|
1360
|
-
});
|
|
1361
|
-
tracer.endSpan(promptSpan);
|
|
1362
|
-
const request = provenance ? toProvenanceSchema(schema, bundle, { sourceLabels }) : { schema, bundle };
|
|
1363
|
-
const schemaSpan = tracer.startSpan("buildJsonSchema", {}, rootSpan);
|
|
1364
|
-
const jsonSchema = runtimeSchemaToJsonSchema(request.schema, request.bundle, {
|
|
1365
|
-
resolvedEnums
|
|
1366
|
-
});
|
|
1367
|
-
tracer.endSpan(schemaSpan);
|
|
1624
|
+
const { systemPrompt, jsonSchema, resolvedEnums } = prepared;
|
|
1368
1625
|
const validate = mode === "coerce" ? validateStrict : validatePartial;
|
|
1369
1626
|
const renderedInput = renderSources(sources);
|
|
1627
|
+
const hasInput = sources.some((s) => s.text.trim().length > 0);
|
|
1370
1628
|
tracer.addEvent(rootSpan, "inputRendered", {
|
|
1371
1629
|
sourceCount: sources.length,
|
|
1372
1630
|
inputLength: renderedInput.length
|
|
1373
1631
|
});
|
|
1374
1632
|
let userInput = renderedInput;
|
|
1375
1633
|
let issues = [];
|
|
1376
|
-
let run = { data: {}, provenance: {}, issues: [] };
|
|
1634
|
+
let run = { data: {}, provenance: {}, issues: [], usage };
|
|
1635
|
+
let emptyRetries = 0;
|
|
1377
1636
|
for (let attempt = 0; attempt <= maxRepairAttempts; attempt++) {
|
|
1378
1637
|
const llmSpan = tracer.startSpan("llmCall", { attempt }, rootSpan);
|
|
1379
1638
|
const response = await provider.complete({
|
|
1380
1639
|
systemPrompt,
|
|
1381
1640
|
userInput,
|
|
1382
1641
|
jsonSchema,
|
|
1383
|
-
schema:
|
|
1384
|
-
bundle:
|
|
1642
|
+
schema: prepared.schema,
|
|
1643
|
+
bundle: prepared.bundle,
|
|
1385
1644
|
resolvedEnums
|
|
1386
1645
|
});
|
|
1646
|
+
addUsage(usage, response.usage);
|
|
1387
1647
|
tracer.addEvent(llmSpan, "responseReceived", { usage: response.usage });
|
|
1388
1648
|
tracer.endSpan(llmSpan);
|
|
1389
|
-
run = provenance ? { ...splitProvenance(response.data, schema), issues: [] } : { data: response.data, provenance: {}, issues: [] };
|
|
1649
|
+
run = provenance ? { ...splitProvenance(response.data, schema), issues: [], usage } : { data: response.data, provenance: {}, issues: [], usage };
|
|
1650
|
+
if (hasInput && emptyRetries < retryOnEmpty && isEmptyResult(run.data)) {
|
|
1651
|
+
emptyRetries += 1;
|
|
1652
|
+
tracer.addEvent(rootSpan, "emptyRetry", { retry: emptyRetries });
|
|
1653
|
+
userInput = `${renderedInput}
|
|
1654
|
+
|
|
1655
|
+
---
|
|
1656
|
+
|
|
1657
|
+
${EMPTY_RETRY_NOTE}`;
|
|
1658
|
+
attempt -= 1;
|
|
1659
|
+
continue;
|
|
1660
|
+
}
|
|
1390
1661
|
const validationSpan = tracer.startSpan("validate", { attempt }, rootSpan);
|
|
1391
1662
|
issues = validate(run.data, schema, bundle, { resolvedEnums });
|
|
1392
1663
|
tracer.addEvent(validationSpan, "validated", { issueCount: issues.length });
|
|
@@ -1412,7 +1683,8 @@ ${provenanceInstructions({ sourceLabels })}` : basePrompt;
|
|
|
1412
1683
|
return {
|
|
1413
1684
|
data: outcome.data,
|
|
1414
1685
|
provenance: pruneProvenance(run.provenance, outcome.resolved),
|
|
1415
|
-
issues: outcome.resolved
|
|
1686
|
+
issues: outcome.resolved,
|
|
1687
|
+
usage
|
|
1416
1688
|
};
|
|
1417
1689
|
}
|
|
1418
1690
|
}
|
|
@@ -1433,7 +1705,8 @@ ${provenanceInstructions({ sourceLabels })}` : basePrompt;
|
|
|
1433
1705
|
}
|
|
1434
1706
|
async function prepareSources(sources, options, tracer, parent) {
|
|
1435
1707
|
const { preprocess, maxInputChars, truncate } = options;
|
|
1436
|
-
|
|
1708
|
+
const anyCapped = sources.some((s) => s.maxChars !== void 0);
|
|
1709
|
+
if (!preprocess && maxInputChars === void 0 && !anyCapped) {
|
|
1437
1710
|
return [...sources];
|
|
1438
1711
|
}
|
|
1439
1712
|
const span = tracer.startSpan("prepareInput", {}, parent);
|
|
@@ -1450,7 +1723,7 @@ async function prepareSources(sources, options, tracer, parent) {
|
|
|
1450
1723
|
lengths: prepared.map((s) => s.text.length)
|
|
1451
1724
|
});
|
|
1452
1725
|
}
|
|
1453
|
-
if (maxInputChars !== void 0) {
|
|
1726
|
+
if (maxInputChars !== void 0 || prepared.some((s) => s.maxChars !== void 0)) {
|
|
1454
1727
|
const budgeted = budgetSources(prepared, maxInputChars, truncate);
|
|
1455
1728
|
prepared = budgeted.sources;
|
|
1456
1729
|
if (budgeted.truncated.length > 0) {
|
|
@@ -1498,19 +1771,59 @@ async function partialCoerce(input, options) {
|
|
|
1498
1771
|
});
|
|
1499
1772
|
return stripNulls(data);
|
|
1500
1773
|
}
|
|
1774
|
+
async function coerceDetailed(input, options) {
|
|
1775
|
+
const { data, issues, usage } = await runCoercion(input, options, {
|
|
1776
|
+
mode: "coerce",
|
|
1777
|
+
provenance: false
|
|
1778
|
+
});
|
|
1779
|
+
return { data, issues, usage };
|
|
1780
|
+
}
|
|
1781
|
+
async function partialCoerceDetailed(input, options) {
|
|
1782
|
+
const { data, issues, usage } = await runCoercion(input, options, {
|
|
1783
|
+
mode: "partialCoerce",
|
|
1784
|
+
provenance: false
|
|
1785
|
+
});
|
|
1786
|
+
return { data: stripNulls(data), issues, usage };
|
|
1787
|
+
}
|
|
1788
|
+
var PRIME_INPUT = "Cache warm-up. There is no input to extract from; return an object with every field null.";
|
|
1789
|
+
async function primeCache(options) {
|
|
1790
|
+
const { mode = "coerce", provenance = false, ...coerceOptions } = options;
|
|
1791
|
+
const { instructions } = checkOptions(coerceOptions);
|
|
1792
|
+
const tracer = new Tracer(coerceOptions.traceSinks);
|
|
1793
|
+
const rootSpan = tracer.startSpan("primeCache", { schemaId: coerceOptions.schema.id, mode, provenance });
|
|
1794
|
+
const usage = emptyUsage();
|
|
1795
|
+
try {
|
|
1796
|
+
const prepared = await prepareRequest(coerceOptions, { mode, provenance }, instructions, [], tracer, rootSpan);
|
|
1797
|
+
const llmSpan = tracer.startSpan("llmCall", { attempt: 0, warmup: true }, rootSpan);
|
|
1798
|
+
const response = await coerceOptions.provider.complete({
|
|
1799
|
+
systemPrompt: prepared.systemPrompt,
|
|
1800
|
+
userInput: renderSources(toSources(PRIME_INPUT)),
|
|
1801
|
+
jsonSchema: prepared.jsonSchema,
|
|
1802
|
+
schema: prepared.schema,
|
|
1803
|
+
bundle: prepared.bundle,
|
|
1804
|
+
resolvedEnums: prepared.resolvedEnums
|
|
1805
|
+
});
|
|
1806
|
+
addUsage(usage, response.usage);
|
|
1807
|
+
tracer.addEvent(llmSpan, "responseReceived", { usage: response.usage });
|
|
1808
|
+
tracer.endSpan(llmSpan);
|
|
1809
|
+
return { schemaId: coerceOptions.schema.id, mode, provenance, usage, primedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
1810
|
+
} finally {
|
|
1811
|
+
tracer.endSpan(rootSpan);
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1501
1814
|
async function coerceWithProvenance(input, options) {
|
|
1502
|
-
const { data, provenance, issues } = await runCoercion(input, options, {
|
|
1815
|
+
const { data, provenance, issues, usage } = await runCoercion(input, options, {
|
|
1503
1816
|
mode: "coerce",
|
|
1504
1817
|
provenance: true
|
|
1505
1818
|
});
|
|
1506
|
-
return { data, provenance, issues };
|
|
1819
|
+
return { data, provenance, issues, usage };
|
|
1507
1820
|
}
|
|
1508
1821
|
async function partialCoerceWithProvenance(input, options) {
|
|
1509
|
-
const { data, provenance, issues } = await runCoercion(input, options, {
|
|
1822
|
+
const { data, provenance, issues, usage } = await runCoercion(input, options, {
|
|
1510
1823
|
mode: "partialCoerce",
|
|
1511
1824
|
provenance: true
|
|
1512
1825
|
});
|
|
1513
|
-
return { data: stripNulls(data), provenance, issues };
|
|
1826
|
+
return { data: stripNulls(data), provenance, issues, usage };
|
|
1514
1827
|
}
|
|
1515
1828
|
|
|
1516
1829
|
// src/coerce/coerce-many.ts
|
|
@@ -1551,60 +1864,107 @@ var BackoffGate = class {
|
|
|
1551
1864
|
this.streak = 0;
|
|
1552
1865
|
}
|
|
1553
1866
|
};
|
|
1867
|
+
var InputQueue = class {
|
|
1868
|
+
iterator;
|
|
1869
|
+
pulling = Promise.resolve();
|
|
1870
|
+
index = 0;
|
|
1871
|
+
constructor(inputs) {
|
|
1872
|
+
this.iterator = Symbol.asyncIterator in inputs ? inputs[Symbol.asyncIterator]() : inputs[Symbol.iterator]();
|
|
1873
|
+
}
|
|
1874
|
+
next() {
|
|
1875
|
+
const pull = this.pulling.then(async () => {
|
|
1876
|
+
const result = await this.iterator.next();
|
|
1877
|
+
if (result.done) return void 0;
|
|
1878
|
+
return { index: this.index++, input: result.value };
|
|
1879
|
+
});
|
|
1880
|
+
this.pulling = pull.catch(() => void 0);
|
|
1881
|
+
return pull;
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
function labelOf(input) {
|
|
1885
|
+
if (typeof input === "string") return void 0;
|
|
1886
|
+
if (isSource(input)) return input.label;
|
|
1887
|
+
return input[0]?.label;
|
|
1888
|
+
}
|
|
1554
1889
|
async function coerceMany(inputs, options) {
|
|
1555
1890
|
const {
|
|
1556
1891
|
concurrency = DEFAULT_CONCURRENCY,
|
|
1557
1892
|
mode = "coerce",
|
|
1558
|
-
provenance = false,
|
|
1559
|
-
primeCache = true,
|
|
1893
|
+
provenance: provenanceOption = false,
|
|
1894
|
+
primeCache: primeCache2 = true,
|
|
1895
|
+
primed,
|
|
1560
1896
|
onItem,
|
|
1561
1897
|
signal,
|
|
1898
|
+
retry: retryOptions,
|
|
1562
1899
|
...coerceOptions
|
|
1563
1900
|
} = options;
|
|
1564
|
-
const retry = { ...DEFAULT_RETRY, ...
|
|
1901
|
+
const retry = { ...DEFAULT_RETRY, ...retryOptions };
|
|
1902
|
+
const provenance = provenanceOption !== false;
|
|
1903
|
+
if (Array.isArray(provenanceOption)) {
|
|
1904
|
+
coerceOptions.provenanceFields = provenanceOption;
|
|
1905
|
+
}
|
|
1565
1906
|
if (!Number.isInteger(concurrency) || concurrency < 1) {
|
|
1566
1907
|
throw new RangeError(`concurrency must be a positive integer, got ${String(concurrency)}`);
|
|
1567
1908
|
}
|
|
1568
1909
|
if (!Number.isInteger(retry.attempts) || retry.attempts < 0) {
|
|
1569
1910
|
throw new RangeError(`retry.attempts must be a non-negative integer, got ${String(retry.attempts)}`);
|
|
1570
1911
|
}
|
|
1571
|
-
const results =
|
|
1912
|
+
const results = [];
|
|
1572
1913
|
const gate = new BackoffGate(retry);
|
|
1573
|
-
|
|
1914
|
+
const queue = new InputQueue(inputs);
|
|
1915
|
+
async function runOne(index, input) {
|
|
1574
1916
|
let attempts = 0;
|
|
1575
1917
|
let result;
|
|
1918
|
+
let usage = emptyUsage();
|
|
1919
|
+
const label = labelOf(input);
|
|
1920
|
+
const traceAttributes = { itemIndex: index, ...label !== void 0 ? { itemLabel: label } : {} };
|
|
1576
1921
|
for (; ; ) {
|
|
1577
1922
|
if (signal?.aborted) {
|
|
1578
|
-
result = { ok: false, index, error: signal.reason ?? new Error("Batch aborted"), attempts };
|
|
1923
|
+
result = { ok: false, index, error: signal.reason ?? new Error("Batch aborted"), usage, attempts };
|
|
1579
1924
|
break;
|
|
1580
1925
|
}
|
|
1581
1926
|
await gate.wait();
|
|
1582
1927
|
attempts += 1;
|
|
1583
1928
|
try {
|
|
1584
|
-
const run = await runCoercion(
|
|
1929
|
+
const run = await runCoercion(input, coerceOptions, { mode, provenance, traceAttributes });
|
|
1585
1930
|
const data = mode === "partialCoerce" ? stripNulls(run.data) : run.data;
|
|
1586
1931
|
gate.succeeded();
|
|
1587
|
-
result = { ok: true, index, data, provenance: run.provenance, issues: run.issues, attempts };
|
|
1932
|
+
result = { ok: true, index, data, provenance: run.provenance, issues: run.issues, usage: run.usage, attempts };
|
|
1588
1933
|
break;
|
|
1589
1934
|
} catch (error) {
|
|
1935
|
+
usage = emptyUsage();
|
|
1590
1936
|
if (isRetryable(error) && attempts <= retry.attempts) {
|
|
1591
1937
|
gate.failed();
|
|
1592
1938
|
continue;
|
|
1593
1939
|
}
|
|
1594
|
-
result = { ok: false, index, error, attempts };
|
|
1940
|
+
result = { ok: false, index, error, usage, attempts };
|
|
1595
1941
|
break;
|
|
1596
1942
|
}
|
|
1597
1943
|
}
|
|
1598
1944
|
results[index] = result;
|
|
1599
1945
|
onItem?.(result);
|
|
1600
1946
|
}
|
|
1601
|
-
let
|
|
1602
|
-
|
|
1603
|
-
|
|
1947
|
+
let pending;
|
|
1948
|
+
const warmup = primed ?? (primeCache2 === "eager" ? primeCache({ ...coerceOptions, mode, provenance }) : void 0);
|
|
1949
|
+
if (warmup) {
|
|
1950
|
+
await Promise.resolve(warmup).catch(() => void 0);
|
|
1951
|
+
} else if (primeCache2 === true) {
|
|
1952
|
+
const first = await queue.next();
|
|
1953
|
+
if (first === void 0) return results;
|
|
1954
|
+
const second = await queue.next();
|
|
1955
|
+
if (second === void 0) {
|
|
1956
|
+
await runOne(first.index, first.input);
|
|
1957
|
+
return results;
|
|
1958
|
+
}
|
|
1959
|
+
await runOne(first.index, first.input);
|
|
1960
|
+
pending = second;
|
|
1604
1961
|
}
|
|
1605
|
-
const workers = Array.from({ length:
|
|
1606
|
-
|
|
1607
|
-
await
|
|
1962
|
+
const workers = Array.from({ length: concurrency }, async () => {
|
|
1963
|
+
for (; ; ) {
|
|
1964
|
+
const item = pending ?? await queue.next();
|
|
1965
|
+
pending = void 0;
|
|
1966
|
+
if (item === void 0) return;
|
|
1967
|
+
await runOne(item.index, item.input);
|
|
1608
1968
|
}
|
|
1609
1969
|
});
|
|
1610
1970
|
await Promise.all(workers);
|
|
@@ -1643,6 +2003,7 @@ function resolveConfig(callConfig) {
|
|
|
1643
2003
|
maxRepairAttempts: callConfig?.maxRepairAttempts ?? global.maxRepairAttempts,
|
|
1644
2004
|
onInvalidField: callConfig?.onInvalidField ?? global.onInvalidField,
|
|
1645
2005
|
instructions: callConfig?.instructions ?? global.instructions,
|
|
2006
|
+
retryOnEmpty: callConfig?.retryOnEmpty ?? global.retryOnEmpty,
|
|
1646
2007
|
maxInputChars: callConfig?.maxInputChars ?? global.maxInputChars,
|
|
1647
2008
|
truncate: callConfig?.truncate ?? global.truncate,
|
|
1648
2009
|
preprocess: callConfig?.preprocess ?? global.preprocess
|
|
@@ -1677,6 +2038,7 @@ var Coercible = class _Coercible {
|
|
|
1677
2038
|
maxRepairAttempts: this._config.maxRepairAttempts,
|
|
1678
2039
|
onInvalidField: this._config.onInvalidField,
|
|
1679
2040
|
instructions: this._config.instructions,
|
|
2041
|
+
retryOnEmpty: this._config.retryOnEmpty,
|
|
1680
2042
|
maxInputChars: this._config.maxInputChars,
|
|
1681
2043
|
truncate: this._config.truncate,
|
|
1682
2044
|
preprocess: this._config.preprocess
|
|
@@ -1743,6 +2105,7 @@ var ConsoleSink = class {
|
|
|
1743
2105
|
Constrain,
|
|
1744
2106
|
Describe,
|
|
1745
2107
|
EnumResolutionError,
|
|
2108
|
+
FIELD_FORMATS,
|
|
1746
2109
|
PROVENANCE_INSTRUCTIONS,
|
|
1747
2110
|
SOURCE_INSTRUCTIONS,
|
|
1748
2111
|
Schema,
|
|
@@ -1755,16 +2118,21 @@ var ConsoleSink = class {
|
|
|
1755
2118
|
buildRepairInput,
|
|
1756
2119
|
bundleOf,
|
|
1757
2120
|
coerce,
|
|
2121
|
+
coerceDetailed,
|
|
1758
2122
|
coerceMany,
|
|
1759
2123
|
coerceWithProvenance,
|
|
1760
2124
|
collectEnumSources,
|
|
1761
2125
|
defineSchema,
|
|
2126
|
+
describeFormat,
|
|
1762
2127
|
field,
|
|
2128
|
+
formatToJsonSchema,
|
|
1763
2129
|
isCoerceInput,
|
|
1764
2130
|
isSource,
|
|
1765
2131
|
normalizeInstructions,
|
|
1766
2132
|
partialCoerce,
|
|
2133
|
+
partialCoerceDetailed,
|
|
1767
2134
|
partialCoerceWithProvenance,
|
|
2135
|
+
primeCache,
|
|
1768
2136
|
provenanceInstructions,
|
|
1769
2137
|
renderSources,
|
|
1770
2138
|
resolveEnumSources,
|
|
@@ -1775,6 +2143,7 @@ var ConsoleSink = class {
|
|
|
1775
2143
|
toOpenAIJsonSchema,
|
|
1776
2144
|
toProvenanceSchema,
|
|
1777
2145
|
toSources,
|
|
2146
|
+
validateFormat,
|
|
1778
2147
|
validatePartial,
|
|
1779
2148
|
validateStrict
|
|
1780
2149
|
});
|