@claritylabs/cl-sdk 1.3.3 → 1.3.5

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.mjs CHANGED
@@ -572,6 +572,7 @@ var FormReferenceSchema = z3.object({
572
572
  var TaxFeeItemSchema = z3.object({
573
573
  name: z3.string(),
574
574
  amount: z3.string(),
575
+ amountValue: z3.number().optional(),
575
576
  type: z3.enum(["tax", "fee", "surcharge", "assessment"]).optional(),
576
577
  description: z3.string().optional()
577
578
  });
@@ -616,9 +617,11 @@ var CoverageValueTypeSchema = z4.enum([
616
617
  var CoverageSchema = z4.object({
617
618
  name: z4.string(),
618
619
  limit: z4.string(),
620
+ limitAmount: z4.number().optional(),
619
621
  limitType: LimitTypeSchema.optional(),
620
622
  limitValueType: CoverageValueTypeSchema.optional(),
621
623
  deductible: z4.string().optional(),
624
+ deductibleAmount: z4.number().optional(),
622
625
  deductibleValueType: CoverageValueTypeSchema.optional(),
623
626
  formNumber: z4.string().optional(),
624
627
  pageNumber: z4.number().optional(),
@@ -634,9 +637,11 @@ var EnrichedCoverageSchema = z4.object({
634
637
  formNumber: z4.string().optional(),
635
638
  formEditionDate: z4.string().optional(),
636
639
  limit: z4.string(),
640
+ limitAmount: z4.number().optional(),
637
641
  limitType: LimitTypeSchema.optional(),
638
642
  limitValueType: CoverageValueTypeSchema.optional(),
639
643
  deductible: z4.string().optional(),
644
+ deductibleAmount: z4.number().optional(),
640
645
  deductibleType: DeductibleTypeSchema.optional(),
641
646
  deductibleValueType: CoverageValueTypeSchema.optional(),
642
647
  sir: z4.string().optional(),
@@ -1317,7 +1322,8 @@ var UnderwritingConditionSchema = z16.object({
1317
1322
  });
1318
1323
  var PremiumLineSchema = z16.object({
1319
1324
  line: z16.string(),
1320
- amount: z16.string()
1325
+ amount: z16.string(),
1326
+ amountValue: z16.number().optional()
1321
1327
  });
1322
1328
  var AuxiliaryFactSchema = z16.object({
1323
1329
  key: z16.string(),
@@ -1360,6 +1366,7 @@ var BaseDocumentFields = {
1360
1366
  security: z16.string().optional(),
1361
1367
  insuredName: z16.string(),
1362
1368
  premium: z16.string().optional(),
1369
+ premiumAmount: z16.number().optional(),
1363
1370
  summary: z16.string().optional(),
1364
1371
  policyTypes: z16.array(z16.string()).optional(),
1365
1372
  coverages: z16.array(CoverageSchema),
@@ -1411,8 +1418,11 @@ var BaseDocumentFields = {
1411
1418
  mortgageHolders: z16.array(EndorsementPartySchema).optional(),
1412
1419
  taxesAndFees: z16.array(TaxFeeItemSchema).optional(),
1413
1420
  totalCost: z16.string().optional(),
1421
+ totalCostAmount: z16.number().optional(),
1414
1422
  minimumPremium: z16.string().optional(),
1423
+ minimumPremiumAmount: z16.number().optional(),
1415
1424
  depositPremium: z16.string().optional(),
1425
+ depositPremiumAmount: z16.number().optional(),
1416
1426
  paymentPlan: PaymentPlanSchema.optional(),
1417
1427
  auditType: AuditTypeSchema.optional(),
1418
1428
  ratingBasis: z16.array(RatingBasisSchema).optional(),
@@ -2886,21 +2896,6 @@ function getCoveredReasons(memory) {
2886
2896
  }
2887
2897
 
2888
2898
  // src/extraction/promote.ts
2889
- function getDeclarationFields(doc) {
2890
- const decl = doc.declarations;
2891
- return Array.isArray(decl?.fields) ? decl.fields : [];
2892
- }
2893
- function fieldMatches(fieldName, patterns) {
2894
- const lower = normalizeFieldName(fieldName);
2895
- return patterns.some((p) => lower === normalizeFieldName(p));
2896
- }
2897
- function normalizeFieldName(fieldName) {
2898
- return fieldName.toLowerCase().replace(/[^a-z0-9]/g, "");
2899
- }
2900
- function findFieldValue(fields, patterns, reject) {
2901
- const match = fields.find((f) => fieldMatches(f.field, patterns) && !reject?.(f));
2902
- return match?.value;
2903
- }
2904
2899
  function stringValue(value) {
2905
2900
  return typeof value === "string" && value.trim() ? value : void 0;
2906
2901
  }
@@ -2919,14 +2914,6 @@ function promoteRawFields(raw, mappings) {
2919
2914
  delete raw[from];
2920
2915
  }
2921
2916
  }
2922
- function findRawOrDeclarationValue(raw, fields, lookup) {
2923
- return (lookup.rawKey ? raw[lookup.rawKey] : void 0) || findFieldValue(fields, lookup.patterns, lookup.reject);
2924
- }
2925
- function promoteRawOrDeclarationString(raw, fields, targetKey, rawKeys, lookup) {
2926
- if (raw[targetKey]) return;
2927
- const value = findRawString(raw, rawKeys) ?? findFieldValue(fields, lookup.patterns, lookup.reject);
2928
- if (value) raw[targetKey] = value;
2929
- }
2930
2917
  function promoteCarrierFields(doc) {
2931
2918
  const raw = doc;
2932
2919
  promoteRawFields(raw, [
@@ -2943,55 +2930,14 @@ function promoteCarrierFields(doc) {
2943
2930
  };
2944
2931
  }
2945
2932
  }
2946
- var BROKER_NAME_PATTERNS = [
2947
- "brokerName",
2948
- "broker",
2949
- "agentName",
2950
- "agent",
2951
- "producerName",
2952
- "producerAgency",
2953
- "agencyName",
2954
- "brokerAgency"
2955
- ];
2956
- var BROKER_CONTACT_PATTERNS = [
2957
- "brokerContactName",
2958
- "brokerContact",
2959
- "agentContactName",
2960
- "producerContactName",
2961
- "producerContact"
2962
- ];
2963
- var BROKER_LICENSE_PATTERNS = [
2964
- "brokerLicenseNumber",
2965
- "brokerNumber",
2966
- "agentLicenseNumber",
2967
- "producerLicenseNumber",
2968
- "producerNumber",
2969
- "agentNumber"
2970
- ];
2971
- var BROKER_PHONE_PATTERNS = ["brokerPhone", "agentPhone", "producerPhone"];
2972
- var BROKER_EMAIL_PATTERNS = ["brokerEmail", "agentEmail", "producerEmail"];
2973
- var BROKER_ADDRESS_PATTERNS = ["brokerAddress", "agentAddress", "producerAddress"];
2974
2933
  function promoteBroker(doc) {
2975
2934
  const raw = doc;
2976
- const fields = getDeclarationFields(doc);
2977
- const brokerAgency = findRawOrDeclarationValue(raw, fields, {
2978
- rawKey: "brokerAgency",
2979
- patterns: BROKER_NAME_PATTERNS
2980
- });
2981
- const brokerContact = findRawOrDeclarationValue(raw, fields, {
2982
- rawKey: "brokerContactName",
2983
- patterns: BROKER_CONTACT_PATTERNS
2984
- });
2985
- const brokerLicense = findRawOrDeclarationValue(raw, fields, {
2986
- rawKey: "brokerLicenseNumber",
2987
- patterns: BROKER_LICENSE_PATTERNS
2988
- });
2989
- const brokerPhone = findRawOrDeclarationValue(raw, fields, { patterns: BROKER_PHONE_PATTERNS });
2990
- const brokerEmail = findRawOrDeclarationValue(raw, fields, { patterns: BROKER_EMAIL_PATTERNS });
2991
- const brokerAddress = findRawOrDeclarationValue(raw, fields, { patterns: BROKER_ADDRESS_PATTERNS });
2992
- if (brokerAgency) raw.brokerAgency = brokerAgency;
2993
- if (brokerContact) raw.brokerContactName = brokerContact;
2994
- if (brokerLicense) raw.brokerLicenseNumber = brokerLicense;
2935
+ const brokerAgency = findRawString(raw, ["brokerAgency"]);
2936
+ const brokerContact = findRawString(raw, ["brokerContactName"]);
2937
+ const brokerLicense = findRawString(raw, ["brokerLicenseNumber"]);
2938
+ const brokerPhone = findRawString(raw, ["brokerPhone"]);
2939
+ const brokerEmail = findRawString(raw, ["brokerEmail"]);
2940
+ const brokerAddress = findRawString(raw, ["brokerAddress"]);
2995
2941
  if (!raw.producer && brokerAgency) {
2996
2942
  raw.producer = {
2997
2943
  agencyName: brokerAgency,
@@ -3003,421 +2949,9 @@ function promoteBroker(doc) {
3003
2949
  };
3004
2950
  }
3005
2951
  }
3006
- var LOSS_PAYEE_NAME_PATTERNS = [
3007
- "lossPayeeName",
3008
- "lossPayee",
3009
- "lossPayeeHolder"
3010
- ];
3011
- var LOSS_PAYEE_ADDRESS_PATTERNS = ["lossPayeeAddress"];
3012
- var MORTGAGE_HOLDER_NAME_PATTERNS = [
3013
- "mortgagee",
3014
- "mortgageHolder",
3015
- "mortgageHolderName",
3016
- "mortgageeName",
3017
- "lienholder",
3018
- "lienholderName"
3019
- ];
3020
- var MORTGAGE_HOLDER_ADDRESS_PATTERNS = [
3021
- "mortgageeAddress",
3022
- "mortgageHolderAddress",
3023
- "lienholderAddress"
3024
- ];
3025
- function promoteLossPayees(doc) {
3026
- const raw = doc;
3027
- const fields = getDeclarationFields(doc);
3028
- if (!raw.lossPayees || Array.isArray(raw.lossPayees) && raw.lossPayees.length === 0) {
3029
- const name = findFieldValue(fields, LOSS_PAYEE_NAME_PATTERNS);
3030
- if (name) {
3031
- const address = findFieldValue(fields, LOSS_PAYEE_ADDRESS_PATTERNS);
3032
- raw.lossPayees = [{
3033
- name,
3034
- role: "loss_payee",
3035
- ...address ? { address: { street1: address } } : {}
3036
- }];
3037
- }
3038
- }
3039
- if (!raw.mortgageHolders || Array.isArray(raw.mortgageHolders) && raw.mortgageHolders.length === 0) {
3040
- const name = findFieldValue(fields, MORTGAGE_HOLDER_NAME_PATTERNS);
3041
- if (name) {
3042
- const address = findFieldValue(fields, MORTGAGE_HOLDER_ADDRESS_PATTERNS);
3043
- raw.mortgageHolders = [{
3044
- name,
3045
- role: "mortgage_holder",
3046
- ...address ? { address: { street1: address } } : {}
3047
- }];
3048
- }
3049
- }
3050
- }
3051
- function promoteLocations(doc) {
3052
- const raw = doc;
3053
- if (Array.isArray(raw.locations) && raw.locations.length > 0) return;
3054
- const fields = getDeclarationFields(doc);
3055
- if (fields.length === 0) return;
3056
- const locationGroups = /* @__PURE__ */ new Map();
3057
- for (const f of fields) {
3058
- const lower = f.field.toLowerCase().replace(/[\s_-]/g, "");
3059
- if (lower.includes("locationnumber") || lower.includes("locnumber") || lower.includes("locno")) {
3060
- const key = f.value;
3061
- if (!locationGroups.has(key)) locationGroups.set(key, /* @__PURE__ */ new Map());
3062
- locationGroups.get(key).set("number", f.value);
3063
- continue;
3064
- }
3065
- if (lower.includes("buildingnumber") || lower.includes("bldgnumber") || lower.includes("bldgno")) {
3066
- const lastKey2 = [...locationGroups.keys()].pop();
3067
- if (lastKey2) locationGroups.get(lastKey2).set("buildingNumber", f.value);
3068
- continue;
3069
- }
3070
- const section = (f.section ?? "").toLowerCase();
3071
- const isLocationField = section.includes("location") || section.includes("building") || section.includes("premises") || section.includes("schedule of locations");
3072
- if (!isLocationField) continue;
3073
- if (locationGroups.size === 0) {
3074
- locationGroups.set("1", /* @__PURE__ */ new Map([["number", "1"]]));
3075
- }
3076
- const lastKey = [...locationGroups.keys()].pop();
3077
- const group = locationGroups.get(lastKey);
3078
- if (lower.includes("construction") || lower.includes("constructiontype")) {
3079
- group.set("constructionType", f.value);
3080
- } else if (lower.includes("occupancy") || lower.includes("occupancytype")) {
3081
- group.set("occupancy", f.value);
3082
- } else if (lower.includes("yearbuilt")) {
3083
- group.set("yearBuilt", f.value);
3084
- } else if (lower.includes("squarefootage") || lower.includes("sqft") || lower.includes("area")) {
3085
- group.set("squareFootage", f.value);
3086
- } else if (lower.includes("protectionclass") || lower.includes("fireprotection")) {
3087
- group.set("protectionClass", f.value);
3088
- } else if (lower.includes("sprinkler")) {
3089
- group.set("sprinklered", f.value);
3090
- } else if (lower.includes("buildingvalue") || lower.includes("buildingamt") || lower.includes("buildingcoverage")) {
3091
- group.set("buildingValue", f.value);
3092
- } else if (lower.includes("contentsvalue") || lower.includes("contentsamt") || lower.includes("contentscoverage")) {
3093
- group.set("contentsValue", f.value);
3094
- } else if (lower.includes("businessincome") || lower.includes("bivalue") || lower.includes("businessincomevalue")) {
3095
- group.set("businessIncomeValue", f.value);
3096
- } else if (lower.includes("description") || lower.includes("buildingdescription") || lower.includes("locationdescription")) {
3097
- group.set("description", f.value);
3098
- } else if (lower.includes("address") || lower.includes("industryaddress") || lower.includes("locationaddress") || lower.includes("premisesaddress")) {
3099
- group.set("address", f.value);
3100
- } else if (lower.includes("alarm") || lower.includes("alarmtype")) {
3101
- group.set("alarmType", f.value);
3102
- }
3103
- }
3104
- if (locationGroups.size === 0) return;
3105
- const locations = [];
3106
- for (const [, group] of locationGroups) {
3107
- const num = parseInt(group.get("number") ?? "0", 10) || locations.length + 1;
3108
- const addressStr = group.get("address");
3109
- locations.push({
3110
- number: num,
3111
- address: addressStr ? { street1: addressStr } : { street1: "See declarations" },
3112
- ...group.get("description") ? { description: group.get("description") } : {},
3113
- ...group.get("constructionType") ? { constructionType: group.get("constructionType") } : {},
3114
- ...group.get("occupancy") ? { occupancy: group.get("occupancy") } : {},
3115
- ...group.get("yearBuilt") ? { yearBuilt: parseInt(group.get("yearBuilt"), 10) || void 0 } : {},
3116
- ...group.get("squareFootage") ? { squareFootage: parseInt(group.get("squareFootage").replace(/[^0-9]/g, ""), 10) || void 0 } : {},
3117
- ...group.get("protectionClass") ? { protectionClass: group.get("protectionClass") } : {},
3118
- ...group.get("sprinklered") ? { sprinklered: /yes|true/i.test(group.get("sprinklered")) } : {},
3119
- ...group.get("buildingValue") ? { buildingValue: group.get("buildingValue") } : {},
3120
- ...group.get("contentsValue") ? { contentsValue: group.get("contentsValue") } : {},
3121
- ...group.get("businessIncomeValue") ? { businessIncomeValue: group.get("businessIncomeValue") } : {},
3122
- ...group.get("alarmType") ? { alarmType: group.get("alarmType") } : {}
3123
- });
3124
- }
3125
- if (locations.length > 0) {
3126
- raw.locations = locations;
3127
- }
3128
- }
3129
- function normalizeName(name) {
3130
- return name.toLowerCase().replace(/[^a-z0-9]/g, "");
3131
- }
3132
- var LIMIT_COVERAGE_MAP = [
3133
- // GL standard
3134
- [["eachoccurrence", "peroccurrence", "occurrencecombined"], "perOccurrence"],
3135
- [["generalaggregate"], "generalAggregate"],
3136
- [["productscompletedoperationsaggregate", "productscompletedopsaggregate", "prodcompopsagg"], "productsCompletedOpsAggregate"],
3137
- [["personaladvertisinginjury", "personaladvinjury", "pai"], "personalAdvertisingInjury"],
3138
- [["firedamage", "firedamagelegalliability", "damagetorentedpremises", "damagetopremisesrentedtoyou"], "fireDamage"],
3139
- [["medicalexpense", "medexp", "medicalexpenseanypersonanyperson", "medicalexpenseanyone"], "medicalExpense"],
3140
- // Auto
3141
- [["combinedsingle", "combinedsinglelimit", "csl"], "combinedSingleLimit"],
3142
- [["bodilyinjuryperperson", "biperperson"], "bodilyInjuryPerPerson"],
3143
- [["bodilyinjuryperaccident", "biperaccident"], "bodilyInjuryPerAccident"],
3144
- [["propertydamage", "pdperaccident"], "propertyDamage"],
3145
- // Umbrella/Excess
3146
- [["umbrellaoccurrence", "eachoccurrenceumbrella", "excessoccurrence", "excesseachoccurrence"], "eachOccurrenceUmbrella"],
3147
- [["umbrellaaggregate", "excessaggregate"], "umbrellaAggregate"],
3148
- [["umbrella retention", "selfinsuredretention", "sir", "excessretention"], "umbrellaRetention"]
3149
- ];
3150
- function synthesizeLimits(doc) {
3151
- const raw = doc;
3152
- if (raw.limits && typeof raw.limits === "object" && Object.keys(raw.limits).length > 0) return;
3153
- const coverages = doc.coverages;
3154
- if (!coverages || coverages.length === 0) return;
3155
- const limits = {};
3156
- for (const cov of coverages) {
3157
- if (!cov.name || !cov.limit) continue;
3158
- const normalized = normalizeName(cov.name);
3159
- for (const [patterns, fieldName] of LIMIT_COVERAGE_MAP) {
3160
- if (patterns.some((p) => normalized.includes(p) || p.includes(normalized))) {
3161
- if (fieldName.includes("Aggregate") || fieldName.includes("aggregate")) {
3162
- if (!cov.limitType || cov.limitType === "aggregate") {
3163
- limits[fieldName] = cov.limit;
3164
- }
3165
- } else {
3166
- if (!limits[fieldName]) {
3167
- limits[fieldName] = cov.limit;
3168
- }
3169
- }
3170
- break;
3171
- }
3172
- }
3173
- }
3174
- const hasStatutory = coverages.some(
3175
- (c) => c.limitType === "statutory" || normalizeName(c.name ?? "").includes("statutory")
3176
- );
3177
- if (hasStatutory) {
3178
- limits.statutory = "true";
3179
- }
3180
- const elCoverages = coverages.filter(
3181
- (c) => normalizeName(c.name ?? "").includes("employersliability")
3182
- );
3183
- if (elCoverages.length > 0) {
3184
- const el = {};
3185
- for (const c of elCoverages) {
3186
- if (!c.limit) continue;
3187
- const n = normalizeName(c.name ?? "");
3188
- if (n.includes("accident") || n.includes("eachaccident")) el.eachAccident = c.limit;
3189
- else if (n.includes("diseasepolicy") || n.includes("diseasepolicylimit")) el.diseasePolicyLimit = c.limit;
3190
- else if (n.includes("diseaseemployee") || n.includes("diseaseeachemployee")) el.diseaseEachEmployee = c.limit;
3191
- else if (!el.eachAccident) el.eachAccident = c.limit;
3192
- }
3193
- if (Object.keys(el).length > 0) {
3194
- limits.employersLiability = el;
3195
- }
3196
- }
3197
- if (Object.keys(limits).length > 0) {
3198
- const result = { ...limits };
3199
- if (result.statutory === "true") result.statutory = true;
3200
- raw.limits = result;
3201
- }
3202
- }
3203
- function synthesizeDeductibles(doc) {
3204
- const raw = doc;
3205
- if (raw.deductibles && typeof raw.deductibles === "object" && Object.keys(raw.deductibles).length > 0) return;
3206
- const coverages = doc.coverages;
3207
- if (!coverages || coverages.length === 0) return;
3208
- const deductibleValues = coverages.filter((c) => c.deductible && c.deductible.trim() !== "" && c.deductible !== "N/A" && c.deductible !== "None").map((c) => c.deductible);
3209
- if (deductibleValues.length === 0) return;
3210
- const freq = /* @__PURE__ */ new Map();
3211
- for (const d of deductibleValues) {
3212
- freq.set(d, (freq.get(d) ?? 0) + 1);
3213
- }
3214
- let mostCommon = deductibleValues[0];
3215
- let maxFreq = 0;
3216
- for (const [val, count] of freq) {
3217
- if (count > maxFreq) {
3218
- mostCommon = val;
3219
- maxFreq = count;
3220
- }
3221
- }
3222
- const deductibles = {};
3223
- const hasPerClaim = coverages.some(
3224
- (c) => c.deductible && normalizeName(c.name ?? "").includes("perclaim")
3225
- );
3226
- if (hasPerClaim) {
3227
- deductibles.perClaim = mostCommon;
3228
- } else {
3229
- deductibles.perOccurrence = mostCommon;
3230
- }
3231
- const sirCoverage = coverages.find(
3232
- (c) => c.deductible && (normalizeName(c.name ?? "").includes("selfinsuredretention") || normalizeName(c.name ?? "").includes("sir"))
3233
- );
3234
- if (sirCoverage?.deductible) {
3235
- deductibles.selfInsuredRetention = sirCoverage.deductible;
3236
- }
3237
- const aggDed = coverages.find(
3238
- (c) => c.deductible && normalizeName(c.name ?? "").includes("aggregatedeductible")
3239
- );
3240
- if (aggDed?.deductible) {
3241
- deductibles.aggregateDeductible = aggDed.deductible;
3242
- }
3243
- if (Object.keys(deductibles).length > 0) {
3244
- raw.deductibles = deductibles;
3245
- }
3246
- }
3247
- var PREMIUM_PATTERNS = [
3248
- "premium",
3249
- "premiumAmount",
3250
- "premium amount",
3251
- "totalPremium",
3252
- "total premium",
3253
- "totalPolicyPremium",
3254
- "total policy premium",
3255
- "annualPremium",
3256
- "annual premium",
3257
- "estimatedAnnualPremium",
3258
- "estimated annual premium",
3259
- "policyPremium",
3260
- "policy premium",
3261
- "basePremium",
3262
- "base premium",
3263
- "planCost",
3264
- "plan cost",
3265
- "policyCost",
3266
- "policy cost",
3267
- "premiumSubtotal",
3268
- "premium subtotal",
3269
- "subtotalPremium",
3270
- "subtotal premium",
3271
- "quotedPremium",
3272
- "quoted premium"
3273
- ];
3274
- var TOTAL_COST_PATTERNS = [
3275
- "totalCost",
3276
- "total cost",
3277
- "total",
3278
- "totalDue",
3279
- "total due",
3280
- "amountPaid",
3281
- "amount paid",
3282
- "totalPaid",
3283
- "total paid",
3284
- "totalPrice",
3285
- "total price",
3286
- "totalTripCost",
3287
- "total trip cost",
3288
- "amountCharged",
3289
- "amount charged",
3290
- "amountDue",
3291
- "amount due",
3292
- "totalAmountDue",
3293
- "total amount due",
3294
- "totalAmount",
3295
- "total amount",
3296
- "grandTotal",
3297
- "grand total",
3298
- "totalPayable",
3299
- "total payable",
3300
- "totalCharges",
3301
- "total charges",
3302
- "totalPolicyCost",
3303
- "total policy cost"
3304
- ];
3305
- var PREMIUM_RAW_KEYS = [
3306
- "premium",
3307
- "premiumAmount",
3308
- "premium_amount",
3309
- "totalPremium",
3310
- "totalPolicyPremium",
3311
- "annualPremium",
3312
- "estimatedAnnualPremium",
3313
- "policyPremium",
3314
- "basePremium",
3315
- "planCost",
3316
- "policyCost",
3317
- "premiumSubtotal",
3318
- "subtotalPremium",
3319
- "quotedPremium"
3320
- ];
3321
- var TOTAL_COST_RAW_KEYS = [
3322
- "totalCost",
3323
- "total_cost",
3324
- "total",
3325
- "totalDue",
3326
- "amountPaid",
3327
- "amount_paid",
3328
- "totalPaid",
3329
- "total_paid",
3330
- "totalPrice",
3331
- "totalTripCost",
3332
- "amountCharged",
3333
- "amountDue",
3334
- "totalAmountDue",
3335
- "totalAmount",
3336
- "grandTotal",
3337
- "totalPayable",
3338
- "totalCharges",
3339
- "totalPolicyCost"
3340
- ];
3341
- function isTaxOrFeeField(fieldName) {
3342
- const normalized = normalizeFieldName(fieldName);
3343
- return /tax|gst|hst|pst|qst|fee|surcharge|assessment|stamp|filing|inspection/.test(normalized);
3344
- }
3345
- function isTotalCostField(fieldName) {
3346
- return fieldMatches(fieldName, TOTAL_COST_PATTERNS);
3347
- }
3348
- function taxFeeType(fieldName) {
3349
- const normalized = normalizeFieldName(fieldName);
3350
- if (normalized.includes("tax") || ["gst", "hst", "pst", "qst"].some((token) => normalized.includes(token))) return "tax";
3351
- if (normalized.includes("surcharge")) return "surcharge";
3352
- if (normalized.includes("assessment")) return "assessment";
3353
- if (normalized.includes("fee") || normalized.includes("stamp") || normalized.includes("filing")) return "fee";
3354
- return void 0;
3355
- }
3356
- function titleizeFieldName(fieldName) {
3357
- const spaced = fieldName.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
3358
- return spaced.replace(/\b\w/g, (letter) => letter.toUpperCase());
3359
- }
3360
- function taxFeeKey(item) {
3361
- return [
3362
- normalizeFieldName(item.name),
3363
- normalizeFieldName(item.amount),
3364
- item.type ?? ""
3365
- ].join("|");
3366
- }
3367
- function taxFeeItemFromField(field) {
3368
- const type = taxFeeType(field.field);
3369
- return {
3370
- name: titleizeFieldName(field.field),
3371
- amount: absorbNegative(field.value),
3372
- ...type ? { type } : {}
3373
- };
3374
- }
3375
- function absorbNegative(value) {
3376
- return value.replace(/^-\s*/, "").replace(/^\(\s*(.*?)\s*\)$/, "$1");
3377
- }
3378
- function promotePremium(doc) {
3379
- const raw = doc;
3380
- const fields = getDeclarationFields(doc);
3381
- promoteRawOrDeclarationString(raw, fields, "premium", PREMIUM_RAW_KEYS, {
3382
- patterns: PREMIUM_PATTERNS,
3383
- reject: (field) => isTaxOrFeeField(field.field)
3384
- });
3385
- promoteRawOrDeclarationString(raw, fields, "totalCost", TOTAL_COST_RAW_KEYS, {
3386
- patterns: TOTAL_COST_PATTERNS
3387
- });
3388
- if (typeof raw.premium === "string") raw.premium = absorbNegative(raw.premium);
3389
- if (typeof raw.totalCost === "string") raw.totalCost = absorbNegative(raw.totalCost);
3390
- }
3391
- function synthesizeTaxesAndFees(doc) {
3392
- const raw = doc;
3393
- const fields = getDeclarationFields(doc);
3394
- if (fields.length === 0) return;
3395
- const existing = Array.isArray(raw.taxesAndFees) ? raw.taxesAndFees : [];
3396
- const byKey = /* @__PURE__ */ new Map();
3397
- for (const item of existing) {
3398
- if (!item?.name || !item?.amount) continue;
3399
- byKey.set(taxFeeKey(item), item);
3400
- }
3401
- for (const field of fields) {
3402
- if (!field.value?.trim()) continue;
3403
- if (!isTaxOrFeeField(field.field)) continue;
3404
- if (isTotalCostField(field.field)) continue;
3405
- const item = taxFeeItemFromField(field);
3406
- byKey.set(taxFeeKey(item), item);
3407
- }
3408
- if (byKey.size > 0) {
3409
- raw.taxesAndFees = [...byKey.values()];
3410
- }
3411
- }
3412
2952
  function promoteExtractedFields(doc) {
3413
2953
  promoteCarrierFields(doc);
3414
2954
  promoteBroker(doc);
3415
- promoteLossPayees(doc);
3416
- promoteLocations(doc);
3417
- synthesizeLimits(doc);
3418
- synthesizeDeductibles(doc);
3419
- synthesizeTaxesAndFees(doc);
3420
- promotePremium(doc);
3421
2955
  }
3422
2956
 
3423
2957
  // src/extraction/alignment.ts
@@ -6140,6 +5674,12 @@ Focus on:
6140
5674
 
6141
5675
  Look on the declarations page, named insured schedule, loss payee schedule, mortgagee schedule, and any endorsements that add or modify named insureds, loss payees, or mortgage holders.
6142
5676
 
5677
+ Critical rules:
5678
+ - Prefer declaration-table labels such as "Named Insured", "Named Insured and Address", "Applicant", or "Insured" over contact blocks, notice contacts, authorized officers, licensing statements, signatures, and corporate-authority wording.
5679
+ - Do not use an authorized officer, broker, producer, contact person, officer title, email address owner, or licensing/entity-status statement as the primary insured unless that exact person/entity is explicitly labeled as the named insured.
5680
+ - If a row combines the insured name with a mailing address, put the legal name in insuredName and the mailing address in insuredAddress.
5681
+ - Entity type must come from the insured's own legal suffix or an explicit declaration field, not from generic incorporation/licensing notices elsewhere in the policy.
5682
+
6143
5683
  Return JSON only.`;
6144
5684
  }
6145
5685
 
@@ -6173,7 +5713,9 @@ For EACH coverage, also extract:
6173
5713
  - sectionRef: the declarations/schedule/endorsement section heading where it appears
6174
5714
  - originalContent: the verbatim row or short source snippet used for this coverage
6175
5715
  - limitType: when applicable, classify the limit as per_occurrence, per_claim, aggregate, per_person, per_accident, statutory, blanket, or scheduled
5716
+ - limitAmount: the limit as a plain number with no currency symbols or commas when the source states a fixed numeric currency amount
6176
5717
  - limitValueType: classify the limit as numeric, included, not_included, as_stated, waiting_period, referential, or other
5718
+ - deductibleAmount: the deductible or retention as a plain number with no currency symbols or commas when the source states a fixed numeric currency amount
6177
5719
  - deductibleValueType: classify the deductible/value term similarly when deductible is present
6178
5720
 
6179
5721
  Critical rules:
@@ -6182,6 +5724,7 @@ Critical rules:
6182
5724
  - Do not treat a generic waiting period, deductible explanation, limits clause, coinsurance clause, or definitions text as a standalone coverage unless the page contains an actual policy-specific schedule row or declaration entry.
6183
5725
  - Values like "Included" or "Not Included" are valid only when they appear as an explicit declarations/schedule/endorsement entry for a named coverage. Do not infer them from narrative form language.
6184
5726
  - If a waiting period or hour deductible is shown as part of a specific declarations/schedule row, it may be captured in deductible. Otherwise omit it.
5727
+ - Only populate limitAmount and deductibleAmount from actual policy-specific declaration, schedule, or endorsement values. Do not calculate them from examples, definitions, rating narratives, or generic form language.
6185
5728
  - Use limitValueType or deductibleValueType to preserve non-numeric terms precisely instead of forcing them into numeric semantics.
6186
5729
  - Preserve one row per real coverage entry. Do not merge adjacent schedule rows into malformed names.
6187
5730
  - Keep individual/per-occurrence limits separate from aggregate limits even when they have the same coverage name, limit amount, deductible, and form number. Use limitType to distinguish them.
@@ -6401,22 +5944,28 @@ Return JSON only.`;
6401
5944
  import { z as z32 } from "zod";
6402
5945
  var PremiumBreakdownSchema = z32.object({
6403
5946
  premium: z32.string().optional().describe("Total premium amount, e.g. '$5,000'"),
5947
+ premiumAmount: z32.number().optional().describe("Total premium as a plain number with no currency symbols or commas"),
6404
5948
  totalCost: z32.string().optional().describe("Total cost including taxes and fees, e.g. '$5,250'"),
5949
+ totalCostAmount: z32.number().optional().describe("Total cost as a plain number with no currency symbols or commas"),
6405
5950
  premiumBreakdown: z32.array(
6406
5951
  z32.object({
6407
5952
  line: z32.string().describe("Coverage line name"),
6408
- amount: z32.string().describe("Premium amount for this line")
5953
+ amount: z32.string().describe("Premium amount for this line"),
5954
+ amountValue: z32.number().optional().describe("Premium amount as a plain number with no currency symbols or commas")
6409
5955
  })
6410
5956
  ).optional().describe("Per-coverage-line premium breakdown"),
6411
5957
  taxesAndFees: z32.array(
6412
5958
  z32.object({
6413
5959
  name: z32.string().describe("Fee or tax name"),
6414
5960
  amount: z32.string().describe("Dollar amount"),
5961
+ amountValue: z32.number().optional().describe("Fee or tax amount as a plain number with no currency symbols or commas"),
6415
5962
  type: z32.enum(["tax", "fee", "surcharge", "assessment"]).optional().describe("Fee category")
6416
5963
  })
6417
5964
  ).optional().describe("Taxes, fees, surcharges, and assessments"),
6418
5965
  minimumPremium: z32.string().optional().describe("Minimum premium if stated"),
5966
+ minimumPremiumAmount: z32.number().optional().describe("Minimum premium as a plain number when the source states a fixed amount"),
6419
5967
  depositPremium: z32.string().optional().describe("Deposit premium if stated"),
5968
+ depositPremiumAmount: z32.number().optional().describe("Deposit premium as a plain number when the source states a fixed amount"),
6420
5969
  paymentPlan: z32.string().optional().describe("Payment plan description"),
6421
5970
  auditType: z32.enum(["annual", "semi_annual", "quarterly", "monthly", "final", "self"]).optional().describe("Premium audit type"),
6422
5971
  ratingBasis: z32.string().optional().describe("Rating basis, e.g. payroll, revenue, area, units")
@@ -6426,6 +5975,7 @@ function buildPremiumBreakdownPrompt() {
6426
5975
 
6427
5976
  Focus on:
6428
5977
  - Total premium and total cost (including taxes/fees)
5978
+ - Plain numeric amount fields for stated money values, without currency symbols or commas
6429
5979
  - Per-coverage-line premium breakdown if available
6430
5980
  - Taxes, fees, surcharges, and assessments with their amounts and types
6431
5981
  - Minimum premium and deposit premium if stated
@@ -6434,6 +5984,7 @@ Focus on:
6434
5984
  - Rating basis: payroll, revenue, area, units, or other
6435
5985
 
6436
5986
  Look on the declarations page, premium summary, and any premium/cost schedules.
5987
+ Prefer premium tables and schedules over definitions, exclusions, rating-basis narratives, licensing statements, or descriptions of premium trust funds. Do not use unrelated business volume, controlled written premium, deductible, limit, tax-only, fee-only, or percentage-only values as the policy premium.
6437
5988
 
6438
5989
  Return JSON only.`;
6439
5990
  }
@@ -7841,41 +7392,11 @@ function toReviewRoundRecord(round, review) {
7841
7392
  }
7842
7393
 
7843
7394
  // src/extraction/planning.ts
7844
- function normalizePageAssignments(pageAssignments, formInventory) {
7845
- const pageFormTypes = /* @__PURE__ */ new Map();
7846
- if (formInventory) {
7847
- for (const form of formInventory.forms) {
7848
- if (form.pageStart != null) {
7849
- const end = form.pageEnd ?? form.pageStart;
7850
- for (let p = form.pageStart; p <= end; p += 1) {
7851
- const types = pageFormTypes.get(p) ?? /* @__PURE__ */ new Set();
7852
- types.add(form.formType);
7853
- pageFormTypes.set(p, types);
7854
- }
7855
- }
7856
- }
7857
- }
7395
+ function normalizePageAssignments(pageAssignments, _formInventory) {
7858
7396
  return pageAssignments.map((assignment) => {
7859
- let extractorNames = [...new Set(
7397
+ const extractorNames = [...new Set(
7860
7398
  assignment.extractorNames.filter(Boolean)
7861
7399
  )];
7862
- const hasDeclarations = extractorNames.includes("declarations");
7863
- const hasConditions = extractorNames.includes("conditions");
7864
- const hasExclusions = extractorNames.includes("exclusions");
7865
- const hasEndorsements = extractorNames.includes("endorsements");
7866
- const looksLikeScheduleValues = assignment.hasScheduleValues === true;
7867
- const roleBlocksCoverageLimits = assignment.pageRole === "policy_form" || assignment.pageRole === "condition_exclusion_form" || assignment.pageRole === "endorsement_form";
7868
- const inventoryTypes = pageFormTypes.get(assignment.localPageNumber);
7869
- const inventoryBlocksCoverageLimits = inventoryTypes != null && !looksLikeScheduleValues && !hasDeclarations && (inventoryTypes.has("endorsement") || inventoryTypes.has("notice") || inventoryTypes.has("application"));
7870
- if (extractorNames.includes("coverage_limits")) {
7871
- const shouldDropCoverageLimits = inventoryBlocksCoverageLimits || !looksLikeScheduleValues && roleBlocksCoverageLimits || !hasDeclarations && !looksLikeScheduleValues && (hasConditions || hasExclusions) || !hasDeclarations && !looksLikeScheduleValues && hasEndorsements;
7872
- if (shouldDropCoverageLimits) {
7873
- extractorNames = extractorNames.filter((name) => name !== "coverage_limits");
7874
- }
7875
- }
7876
- if (inventoryTypes?.has("endorsement") && !extractorNames.includes("endorsements")) {
7877
- extractorNames = [...extractorNames, "endorsements"];
7878
- }
7879
7400
  return {
7880
7401
  ...assignment,
7881
7402
  extractorNames
@@ -8214,6 +7735,18 @@ function createExtractor(config) {
8214
7735
  return typeof start === "number" && typeof end === "number" && start <= endPage && end >= startPage;
8215
7736
  });
8216
7737
  }
7738
+ function formatSourceSpanText(spans) {
7739
+ return spans.filter((span) => span.text.trim().length > 0).map((span) => {
7740
+ const page = pageNumberForSpan(span);
7741
+ const label = [
7742
+ page ? `Page ${page}` : void 0,
7743
+ span.sectionId,
7744
+ span.formNumber
7745
+ ].filter(Boolean).join(" | ");
7746
+ return label ? `${label}
7747
+ ${span.text}` : span.text;
7748
+ }).join("\n\n---\n\n");
7749
+ }
8217
7750
  function inferSectionType(title, text) {
8218
7751
  const value = `${title} ${text.slice(0, 500)}`.toLowerCase();
8219
7752
  if (/\bdefinition|defined terms?\b/.test(value)) return "definition";
@@ -8250,93 +7783,6 @@ function createExtractor(config) {
8250
7783
  if (!line) return void 0;
8251
7784
  return line.slice(0, 100);
8252
7785
  }
8253
- function buildDeterministicFormInventory(spans, pageCount) {
8254
- if (spans.length === 0) return void 0;
8255
- const formPattern = /\b([A-Z]{1,4}\s?\d{2,5}(?:\s?\d{2,4})?|[A-Z]{2,8}-\d{2,8})\b/g;
8256
- const seen = /* @__PURE__ */ new Map();
8257
- for (const span of spans) {
8258
- const page = pageNumberForSpan(span);
8259
- if (!page) continue;
8260
- const title = firstHeadingLine(span.text) ?? span.sectionId;
8261
- const matches = /* @__PURE__ */ new Set([
8262
- ...span.formNumber ? [span.formNumber] : [],
8263
- ...Array.from(span.text.slice(0, 1200).matchAll(formPattern), (match) => match[1].trim())
8264
- ]);
8265
- for (const formNumber of matches) {
8266
- const key = `${formNumber}:${title ?? ""}`;
8267
- const existing = seen.get(key);
8268
- const formType = inferFormType(title ?? "", span.text);
8269
- if (existing) {
8270
- existing.pageStart = Math.min(existing.pageStart ?? page, page);
8271
- existing.pageEnd = Math.max(existing.pageEnd ?? page, page);
8272
- continue;
8273
- }
8274
- seen.set(key, {
8275
- formNumber,
8276
- title,
8277
- formType,
8278
- pageStart: Math.min(page, pageCount),
8279
- pageEnd: Math.min(page, pageCount)
8280
- });
8281
- }
8282
- }
8283
- const forms = [...seen.values()].sort((a, b) => (a.pageStart ?? 0) - (b.pageStart ?? 0));
8284
- return forms.length > 0 ? { forms } : void 0;
8285
- }
8286
- function inferFormType(title, text) {
8287
- const value = `${title} ${text.slice(0, 700)}`.toLowerCase();
8288
- if (/\bdeclarations?|schedule\b/.test(value)) return "declarations";
8289
- if (/\bendorsement|amendatory|additional insured\b/.test(value)) return "endorsement";
8290
- if (/\bnotice|department of insurance|complaint|privacy\b/.test(value)) return "notice";
8291
- if (/\bapplication|questionnaire\b/.test(value)) return "application";
8292
- if (/\bcoverage|policy form|conditions|exclusions|definitions|causes of loss\b/.test(value)) return "coverage";
8293
- return "other";
8294
- }
8295
- function buildDeterministicPageAssignments(spans, pageCount) {
8296
- if (spans.length === 0) return [];
8297
- const pageTexts = /* @__PURE__ */ new Map();
8298
- for (const span of spans) {
8299
- const page = pageNumberForSpan(span);
8300
- if (!page) continue;
8301
- pageTexts.set(page, [pageTexts.get(page), span.sectionId, span.text].filter(Boolean).join("\n"));
8302
- }
8303
- return Array.from({ length: pageCount }, (_, index) => {
8304
- const page = index + 1;
8305
- const text = pageTexts.get(page) ?? "";
8306
- const lower = text.toLowerCase();
8307
- const extractorNames = [];
8308
- if (/\bdeclarations?|policy period|named insured|producer|schedule\b/.test(lower)) {
8309
- extractorNames.push("carrier_info", "named_insured", "declarations");
8310
- }
8311
- if (/\blimit|deductible|premium|coinsurance|scheduled amount|blanket\b/.test(lower) && /\$|\b\d{2,}(?:,\d{3})*\b/.test(lower)) {
8312
- extractorNames.push("coverage_limits");
8313
- }
8314
- if (/\bpremium|tax|fee|surcharge\b/.test(lower) && /\$/.test(lower)) extractorNames.push("premium_breakdown");
8315
- if (/\bendorsement|additional insured|amendatory\b/.test(lower)) extractorNames.push("endorsements");
8316
- if (/\bexclusion|not covered|does not apply\b/.test(lower)) extractorNames.push("exclusions");
8317
- if (/\bcondition|duties in the event|loss condition|general condition\b/.test(lower)) extractorNames.push("conditions");
8318
- if (/\bdefinition|defined terms?\b/.test(lower)) extractorNames.push("definitions");
8319
- if (/\bcovered cause|covered peril|cause of loss|perils insured\b/.test(lower)) extractorNames.push("covered_reasons");
8320
- if (textIncludesSupplementarySignal(text)) extractorNames.push("supplementary");
8321
- if (extractorNames.length === 0 && text.trim().length > 180) extractorNames.push("sections");
8322
- return {
8323
- localPageNumber: page,
8324
- extractorNames: [...new Set(extractorNames)],
8325
- pageRole: inferPageRole(lower),
8326
- hasScheduleValues: /\$|\b\d{2,}(?:,\d{3})*\b/.test(lower) && /\blimit|deductible|premium|schedule|class|location\b/.test(lower),
8327
- confidence: text.trim().length > 0 ? 0.8 : 0,
8328
- notes: "Deterministic source-span page assignment"
8329
- };
8330
- });
8331
- }
8332
- function inferPageRole(lowerText) {
8333
- if (/\bdeclarations?|schedule\b/.test(lowerText)) return "declarations_schedule";
8334
- if (/\bendorsement\b/.test(lowerText)) return "endorsement_form";
8335
- if (/\bexclusion|condition\b/.test(lowerText)) return "condition_exclusion_form";
8336
- if (/\bnotice|department of insurance|complaint\b/.test(lowerText)) return "supplementary";
8337
- if (lowerText.trim()) return "policy_form";
8338
- return "other";
8339
- }
8340
7786
  function shouldRunLlmReview(mode, report, sourceSpansAvailable) {
8341
7787
  if (mode === "skip" || maxReviewRounds <= 0) return false;
8342
7788
  if (mode === "always") return true;
@@ -8557,21 +8003,28 @@ function createExtractor(config) {
8557
8003
  return promise;
8558
8004
  }
8559
8005
  async function getPageRangeText(startPage, endPage) {
8560
- return doclingDocument ? getDoclingPageRangeText(doclingDocument, startPage, endPage) : "";
8006
+ if (doclingDocument) return getDoclingPageRangeText(doclingDocument, startPage, endPage);
8007
+ return formatSourceSpanText(spansForPageRange(sourceSpans, startPage, endPage));
8561
8008
  }
8562
8009
  function withFullDocumentTextContext(prompt) {
8563
- if (!doclingDocument) return prompt;
8564
- return `${prompt}
8010
+ if (doclingDocument) return `${prompt}
8565
8011
 
8566
8012
  DOCLING DOCUMENT TEXT:
8567
8013
  ${doclingDocument.fullText}`;
8014
+ const sourceText = formatSourceSpanText(sourceSpans);
8015
+ if (!sourceText) return prompt;
8016
+ return `${prompt}
8017
+
8018
+ SOURCE SPAN DOCUMENT TEXT:
8019
+ ${sourceText}`;
8568
8020
  }
8569
8021
  function withPageRangeTextContext(prompt, startPage, endPage, pageText) {
8570
- if (!doclingDocument) return prompt;
8022
+ if (!pageText) return prompt;
8023
+ const label = doclingDocument ? "DOCLING DOCUMENT" : "SOURCE SPAN DOCUMENT";
8571
8024
  return `${prompt}
8572
8025
 
8573
- DOCLING DOCUMENT PAGES ${startPage}-${endPage}:
8574
- ${pageText || "(No Docling text was available for this page range.)"}`;
8026
+ ${label} PAGES ${startPage}-${endPage}:
8027
+ ${pageText}`;
8575
8028
  }
8576
8029
  let classifyResult;
8577
8030
  if (resumed?.classifyResult && pipelineCtx.isPhaseComplete("classify")) {
@@ -8628,17 +8081,6 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
8628
8081
  formInventory = resumed.formInventory;
8629
8082
  memory.set("form_inventory", formInventory);
8630
8083
  onProgress?.("Resuming from checkpoint (form inventory complete)...");
8631
- } else if (sourceSpans.length > 0) {
8632
- formInventory = buildDeterministicFormInventory(sourceSpans, pageCount) ?? { forms: [] };
8633
- onProgress?.(`Built deterministic form inventory for ${primaryType} ${documentType}.`);
8634
- memory.set("form_inventory", formInventory);
8635
- await pipelineCtx.save("form_inventory", {
8636
- id,
8637
- pageCount,
8638
- classifyResult,
8639
- formInventory,
8640
- memory: Object.fromEntries(memory)
8641
- });
8642
8084
  } else {
8643
8085
  onProgress?.(`Building form inventory for ${primaryType} ${documentType}...`);
8644
8086
  const budget = resolveBudget("extraction_form_inventory", 2048);
@@ -8679,20 +8121,6 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
8679
8121
  if (resumed?.pageAssignments && pipelineCtx.isPhaseComplete("page_map")) {
8680
8122
  pageAssignments = resumed.pageAssignments;
8681
8123
  onProgress?.("Resuming from checkpoint (page map complete)...");
8682
- } else if (sourceSpans.length > 0) {
8683
- onProgress?.(`Mapping document pages from source spans for ${primaryType} ${documentType}...`);
8684
- pageAssignments = normalizePageAssignments(
8685
- buildDeterministicPageAssignments(sourceSpans, pageCount),
8686
- formInventory
8687
- );
8688
- await pipelineCtx.save("page_map", {
8689
- id,
8690
- pageCount,
8691
- classifyResult,
8692
- formInventory,
8693
- pageAssignments,
8694
- memory: Object.fromEntries(memory)
8695
- });
8696
8124
  } else {
8697
8125
  onProgress?.(`Mapping document pages for ${primaryType} ${documentType}...`);
8698
8126
  const chunkSize = 8;
@@ -8709,7 +8137,7 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
8709
8137
  pageMapChunks.map(
8710
8138
  ({ startPage, endPage }) => pageMapLimit(async () => {
8711
8139
  const pagesPdf = doclingDocument ? void 0 : await getPageRangePdf(startPage, endPage);
8712
- const pagesText = doclingDocument ? await getPageRangeText(startPage, endPage) : "";
8140
+ const pagesText = await getPageRangeText(startPage, endPage);
8713
8141
  const budget = resolveBudget("extraction_page_map", 2048);
8714
8142
  const startedAt = Date.now();
8715
8143
  const mapResponse = await safeGenerateObject(
@@ -8816,7 +8244,7 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
8816
8244
  completedPageRangePdfCache,
8817
8245
  getPageRangePdf,
8818
8246
  convertPdfToImages ? getPageImages : void 0,
8819
- doclingDocument ? getPageRangeText : void 0
8247
+ sourceSpans.length > 0 || doclingDocument ? getPageRangeText : void 0
8820
8248
  );
8821
8249
  })
8822
8250
  )
@@ -8849,7 +8277,7 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
8849
8277
  pageRangeCache: completedPageRangePdfCache,
8850
8278
  getPageRangePdf,
8851
8279
  getPageImages: convertPdfToImages ? getPageImages : void 0,
8852
- getPageRangeText: doclingDocument ? getPageRangeText : void 0
8280
+ getPageRangeText: sourceSpans.length > 0 || doclingDocument ? getPageRangeText : void 0
8853
8281
  });
8854
8282
  trackUsage(supplementaryResult.usage, {
8855
8283
  taskKind: "extraction_focused",
@@ -8885,7 +8313,7 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
8885
8313
  concurrency,
8886
8314
  getPageRangePdf,
8887
8315
  getPageImages: convertPdfToImages ? getPageImages : void 0,
8888
- getPageRangeText: doclingDocument ? getPageRangeText : void 0,
8316
+ getPageRangeText: sourceSpans.length > 0 || doclingDocument ? getPageRangeText : void 0,
8889
8317
  providerOptions: activeProviderOptions,
8890
8318
  modelCapabilities,
8891
8319
  modelBudgetConstraints,
@@ -8981,7 +8409,7 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
8981
8409
  completedPageRangePdfCache,
8982
8410
  getPageRangePdf,
8983
8411
  convertPdfToImages ? getPageImages : void 0,
8984
- doclingDocument ? getPageRangeText : void 0
8412
+ sourceSpans.length > 0 || doclingDocument ? getPageRangeText : void 0
8985
8413
  );
8986
8414
  })
8987
8415
  )