@claritylabs/cl-sdk 1.3.8 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -103,6 +103,13 @@ __export(index_exports, {
103
103
  DeductibleTypeSchema: () => DeductibleTypeSchema,
104
104
  DefenseCostTreatmentSchema: () => DefenseCostTreatmentSchema,
105
105
  DefinitionSchema: () => DefinitionSchema,
106
+ DocumentAgentGuidanceSchema: () => DocumentAgentGuidanceSchema,
107
+ DocumentMetadataSchema: () => DocumentMetadataSchema,
108
+ DocumentNodeSchema: () => DocumentNodeSchema,
109
+ DocumentPageMapEntrySchema: () => DocumentPageMapEntrySchema,
110
+ DocumentSourceNodeKindSchema: () => DocumentSourceNodeKindSchema,
111
+ DocumentSourceNodeSchema: () => DocumentSourceNodeSchema,
112
+ DocumentTableOfContentsEntrySchema: () => DocumentTableOfContentsEntrySchema,
106
113
  DocumentTypeSchema: () => DocumentTypeSchema,
107
114
  DriverRecordSchema: () => DriverRecordSchema,
108
115
  DwellingDetailsSchema: () => DwellingDetailsSchema,
@@ -157,6 +164,9 @@ __export(index_exports, {
157
164
  MemorySourceStore: () => MemorySourceStore,
158
165
  MissingInfoQuestionSchema: () => MissingInfoQuestionSchema,
159
166
  NamedInsuredSchema: () => NamedInsuredSchema,
167
+ OperationalCoverageLineSchema: () => OperationalCoverageLineSchema,
168
+ OperationalEndorsementSupportSchema: () => OperationalEndorsementSupportSchema,
169
+ OperationalPartySchema: () => OperationalPartySchema,
160
170
  PERSONAL_AUTO_USAGES: () => PERSONAL_AUTO_USAGES,
161
171
  PET_SPECIES: () => PET_SPECIES,
162
172
  PLATFORM_CONFIGS: () => PLATFORM_CONFIGS,
@@ -186,6 +196,7 @@ __export(index_exports, {
186
196
  PolicyChangeStatusSchema: () => PolicyChangeStatusSchema,
187
197
  PolicyConditionSchema: () => PolicyConditionSchema,
188
198
  PolicyDocumentSchema: () => PolicyDocumentSchema,
199
+ PolicyOperationalProfileSchema: () => PolicyOperationalProfileSchema,
189
200
  PolicySectionTypeSchema: () => PolicySectionTypeSchema,
190
201
  PolicyTermTypeSchema: () => PolicyTermTypeSchema,
191
202
  PolicyTypeSchema: () => PolicyTypeSchema,
@@ -217,6 +228,7 @@ __export(index_exports, {
217
228
  ScheduledItemCategorySchema: () => ScheduledItemCategorySchema,
218
229
  SectionSchema: () => SectionSchema,
219
230
  SharedLimitSchema: () => SharedLimitSchema,
231
+ SourceBackedValueSchema: () => SourceBackedValueSchema,
220
232
  SourceChunkSchema: () => SourceChunkSchema,
221
233
  SourceKindSchema: () => SourceKindSchema,
222
234
  SourceSpanBBoxSchema: () => SourceSpanBBoxSchema,
@@ -258,7 +270,9 @@ __export(index_exports, {
258
270
  buildConfirmationSummaryPrompt: () => buildConfirmationSummaryPrompt,
259
271
  buildConversationMemoryGuidance: () => buildConversationMemoryGuidance,
260
272
  buildCoverageGapPrompt: () => buildCoverageGapPrompt,
273
+ buildDeterministicOperationalProfile: () => buildDeterministicOperationalProfile,
261
274
  buildDoclingProviderOptions: () => buildDoclingProviderOptions,
275
+ buildDocumentSourceTree: () => buildDocumentSourceTree,
262
276
  buildFieldExplanationPrompt: () => buildFieldExplanationPrompt,
263
277
  buildFieldExtractionPrompt: () => buildFieldExtractionPrompt,
264
278
  buildFlatPdfMappingPrompt: () => buildFlatPdfMappingPrompt,
@@ -307,9 +321,11 @@ __export(index_exports, {
307
321
  getTemplate: () => getTemplate,
308
322
  isDoclingExtractionInput: () => isDoclingExtractionInput,
309
323
  isFileReference: () => isFileReference,
324
+ mergeOperationalProfile: () => mergeOperationalProfile,
310
325
  mergeQuestionAnswers: () => mergeQuestionAnswers,
311
326
  mergeSourceSpans: () => mergeSourceSpans,
312
327
  normalizeDoclingDocument: () => normalizeDoclingDocument,
328
+ normalizeDocumentSourceTreePaths: () => normalizeDocumentSourceTreePaths,
313
329
  normalizeForMatch: () => normalizeForMatch,
314
330
  orderSourceEvidence: () => orderSourceEvidence,
315
331
  overlayTextOnPdf: () => overlayTextOnPdf,
@@ -905,14 +921,20 @@ var FormReferenceSchema = import_zod3.z.object({
905
921
  title: import_zod3.z.string().optional(),
906
922
  formType: import_zod3.z.enum(["coverage", "endorsement", "declarations", "application", "notice", "other"]),
907
923
  pageStart: import_zod3.z.number().optional(),
908
- pageEnd: import_zod3.z.number().optional()
924
+ pageEnd: import_zod3.z.number().optional(),
925
+ documentNodeId: import_zod3.z.string().optional(),
926
+ sourceSpanIds: import_zod3.z.array(import_zod3.z.string()).optional(),
927
+ sourceTextHash: import_zod3.z.string().optional()
909
928
  });
910
929
  var TaxFeeItemSchema = import_zod3.z.object({
911
930
  name: import_zod3.z.string(),
912
931
  amount: import_zod3.z.string(),
913
932
  amountValue: import_zod3.z.number().optional(),
914
933
  type: import_zod3.z.enum(["tax", "fee", "surcharge", "assessment"]).optional(),
915
- description: import_zod3.z.string().optional()
934
+ description: import_zod3.z.string().optional(),
935
+ documentNodeId: import_zod3.z.string().optional(),
936
+ sourceSpanIds: import_zod3.z.array(import_zod3.z.string()).optional(),
937
+ sourceTextHash: import_zod3.z.string().optional()
916
938
  });
917
939
  var RatingBasisSchema = import_zod3.z.object({
918
940
  type: RatingBasisTypeSchema,
@@ -968,6 +990,7 @@ var CoverageSchema = import_zod4.z.object({
968
990
  sectionRef: import_zod4.z.string().optional(),
969
991
  originalContent: import_zod4.z.string().optional(),
970
992
  recordId: import_zod4.z.string().optional(),
993
+ documentNodeId: import_zod4.z.string().optional(),
971
994
  sourceSpanIds: import_zod4.z.array(import_zod4.z.string()).optional(),
972
995
  sourceTextHash: import_zod4.z.string().optional()
973
996
  });
@@ -997,6 +1020,7 @@ var EnrichedCoverageSchema = import_zod4.z.object({
997
1020
  sectionRef: import_zod4.z.string().optional(),
998
1021
  originalContent: import_zod4.z.string().optional(),
999
1022
  recordId: import_zod4.z.string().optional(),
1023
+ documentNodeId: import_zod4.z.string().optional(),
1000
1024
  sourceSpanIds: import_zod4.z.array(import_zod4.z.string()).optional(),
1001
1025
  sourceTextHash: import_zod4.z.string().optional()
1002
1026
  });
@@ -1025,6 +1049,7 @@ var EndorsementSchema = import_zod5.z.object({
1025
1049
  pageStart: import_zod5.z.number(),
1026
1050
  pageEnd: import_zod5.z.number().optional(),
1027
1051
  recordId: import_zod5.z.string().optional(),
1052
+ documentNodeId: import_zod5.z.string().optional(),
1028
1053
  sourceSpanIds: import_zod5.z.array(import_zod5.z.string()).optional(),
1029
1054
  sourceTextHash: import_zod5.z.string().optional()
1030
1055
  });
@@ -1043,6 +1068,7 @@ var ExclusionSchema = import_zod6.z.object({
1043
1068
  content: import_zod6.z.string(),
1044
1069
  pageNumber: import_zod6.z.number().optional(),
1045
1070
  recordId: import_zod6.z.string().optional(),
1071
+ documentNodeId: import_zod6.z.string().optional(),
1046
1072
  sourceSpanIds: import_zod6.z.array(import_zod6.z.string()).optional(),
1047
1073
  sourceTextHash: import_zod6.z.string().optional()
1048
1074
  });
@@ -1060,6 +1086,7 @@ var PolicyConditionSchema = import_zod7.z.object({
1060
1086
  keyValues: import_zod7.z.array(ConditionKeyValueSchema).optional(),
1061
1087
  pageNumber: import_zod7.z.number().optional(),
1062
1088
  recordId: import_zod7.z.string().optional(),
1089
+ documentNodeId: import_zod7.z.string().optional(),
1063
1090
  sourceSpanIds: import_zod7.z.array(import_zod7.z.string()).optional(),
1064
1091
  sourceTextHash: import_zod7.z.string().optional()
1065
1092
  });
@@ -1636,6 +1663,7 @@ var SubsectionSchema = import_zod16.z.object({
1636
1663
  pageNumber: import_zod16.z.number().optional(),
1637
1664
  excerpt: import_zod16.z.string().optional(),
1638
1665
  content: import_zod16.z.string().optional(),
1666
+ documentNodeId: import_zod16.z.string().optional(),
1639
1667
  sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1640
1668
  sourceTextHash: import_zod16.z.string().optional()
1641
1669
  });
@@ -1650,6 +1678,7 @@ var SectionSchema = import_zod16.z.object({
1650
1678
  content: import_zod16.z.string().optional(),
1651
1679
  subsections: import_zod16.z.array(SubsectionSchema).optional(),
1652
1680
  recordId: import_zod16.z.string().optional(),
1681
+ documentNodeId: import_zod16.z.string().optional(),
1653
1682
  sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1654
1683
  sourceTextHash: import_zod16.z.string().optional()
1655
1684
  });
@@ -1663,13 +1692,19 @@ var UnderwritingConditionSchema = import_zod16.z.object({
1663
1692
  var PremiumLineSchema = import_zod16.z.object({
1664
1693
  line: import_zod16.z.string(),
1665
1694
  amount: import_zod16.z.string(),
1666
- amountValue: import_zod16.z.number().optional()
1695
+ amountValue: import_zod16.z.number().optional(),
1696
+ documentNodeId: import_zod16.z.string().optional(),
1697
+ sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1698
+ sourceTextHash: import_zod16.z.string().optional()
1667
1699
  });
1668
1700
  var AuxiliaryFactSchema = import_zod16.z.object({
1669
1701
  key: import_zod16.z.string(),
1670
1702
  value: import_zod16.z.string(),
1671
1703
  subject: import_zod16.z.string().optional(),
1672
- context: import_zod16.z.string().optional()
1704
+ context: import_zod16.z.string().optional(),
1705
+ documentNodeId: import_zod16.z.string().optional(),
1706
+ sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1707
+ sourceTextHash: import_zod16.z.string().optional()
1673
1708
  });
1674
1709
  var DefinitionSchema = import_zod16.z.object({
1675
1710
  term: import_zod16.z.string(),
@@ -1680,6 +1715,7 @@ var DefinitionSchema = import_zod16.z.object({
1680
1715
  sectionRef: import_zod16.z.string().optional(),
1681
1716
  originalContent: import_zod16.z.string().optional(),
1682
1717
  recordId: import_zod16.z.string().optional(),
1718
+ documentNodeId: import_zod16.z.string().optional(),
1683
1719
  sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1684
1720
  sourceTextHash: import_zod16.z.string().optional()
1685
1721
  });
@@ -1697,9 +1733,62 @@ var CoveredReasonSchema = import_zod16.z.object({
1697
1733
  sectionRef: import_zod16.z.string().optional(),
1698
1734
  originalContent: import_zod16.z.string().optional(),
1699
1735
  recordId: import_zod16.z.string().optional(),
1736
+ documentNodeId: import_zod16.z.string().optional(),
1700
1737
  sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1701
1738
  sourceTextHash: import_zod16.z.string().optional()
1702
1739
  });
1740
+ var DocumentTableOfContentsEntrySchema = import_zod16.z.object({
1741
+ title: import_zod16.z.string(),
1742
+ level: import_zod16.z.number().int().positive().optional(),
1743
+ pageStart: import_zod16.z.number().optional(),
1744
+ pageEnd: import_zod16.z.number().optional(),
1745
+ documentNodeId: import_zod16.z.string().optional(),
1746
+ sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional()
1747
+ });
1748
+ var DocumentPageMapEntrySchema = import_zod16.z.object({
1749
+ page: import_zod16.z.number().int().positive(),
1750
+ label: import_zod16.z.string().optional(),
1751
+ formNumber: import_zod16.z.string().optional(),
1752
+ formTitle: import_zod16.z.string().optional(),
1753
+ sectionTitle: import_zod16.z.string().optional(),
1754
+ extractorNames: import_zod16.z.array(import_zod16.z.string()).optional(),
1755
+ sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional()
1756
+ });
1757
+ var DocumentAgentGuidanceSchema = import_zod16.z.object({
1758
+ kind: import_zod16.z.string(),
1759
+ title: import_zod16.z.string(),
1760
+ detail: import_zod16.z.string(),
1761
+ sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional()
1762
+ });
1763
+ var DocumentMetadataSchema = import_zod16.z.object({
1764
+ sourceTreeVersion: import_zod16.z.string().optional(),
1765
+ sourceTreeCanonical: import_zod16.z.boolean().optional(),
1766
+ formInventory: import_zod16.z.array(FormReferenceSchema).optional(),
1767
+ tableOfContents: import_zod16.z.array(DocumentTableOfContentsEntrySchema).optional(),
1768
+ pageMap: import_zod16.z.array(DocumentPageMapEntrySchema).optional(),
1769
+ agentGuidance: import_zod16.z.array(DocumentAgentGuidanceSchema).optional()
1770
+ });
1771
+ var DocumentNodeSchema = import_zod16.z.lazy(
1772
+ () => import_zod16.z.object({
1773
+ id: import_zod16.z.string(),
1774
+ title: import_zod16.z.string(),
1775
+ originalTitle: import_zod16.z.string().optional(),
1776
+ type: import_zod16.z.string().optional(),
1777
+ label: import_zod16.z.string().optional(),
1778
+ level: import_zod16.z.number().int().positive().optional(),
1779
+ sectionNumber: import_zod16.z.string().optional(),
1780
+ pageStart: import_zod16.z.number().optional(),
1781
+ pageEnd: import_zod16.z.number().optional(),
1782
+ formNumber: import_zod16.z.string().optional(),
1783
+ formTitle: import_zod16.z.string().optional(),
1784
+ excerpt: import_zod16.z.string().optional(),
1785
+ content: import_zod16.z.string().optional(),
1786
+ interpretationLabels: import_zod16.z.array(import_zod16.z.string()).optional(),
1787
+ sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1788
+ sourceTextHash: import_zod16.z.string().optional(),
1789
+ children: import_zod16.z.array(DocumentNodeSchema).optional()
1790
+ })
1791
+ );
1703
1792
  var BaseDocumentFields = {
1704
1793
  id: import_zod16.z.string(),
1705
1794
  carrier: import_zod16.z.string(),
@@ -1710,6 +1799,8 @@ var BaseDocumentFields = {
1710
1799
  summary: import_zod16.z.string().optional(),
1711
1800
  policyTypes: import_zod16.z.array(import_zod16.z.string()).optional(),
1712
1801
  coverages: import_zod16.z.array(CoverageSchema),
1802
+ documentMetadata: DocumentMetadataSchema,
1803
+ documentOutline: import_zod16.z.array(DocumentNodeSchema),
1713
1804
  sections: import_zod16.z.array(SectionSchema).optional(),
1714
1805
  definitions: import_zod16.z.array(DefinitionSchema).optional(),
1715
1806
  coveredReasons: import_zod16.z.array(CoveredReasonSchema).optional(),
@@ -2271,6 +2362,86 @@ var SourceChunkSchema = import_zod20.z.object({
2271
2362
  pageEnd: import_zod20.z.number().int().positive().optional(),
2272
2363
  metadata: import_zod20.z.record(import_zod20.z.string(), import_zod20.z.string()).default({})
2273
2364
  });
2365
+ var DocumentSourceNodeKindSchema = import_zod20.z.enum([
2366
+ "document",
2367
+ "page_group",
2368
+ "page",
2369
+ "form",
2370
+ "endorsement",
2371
+ "section",
2372
+ "schedule",
2373
+ "clause",
2374
+ "table",
2375
+ "table_row",
2376
+ "table_cell",
2377
+ "text"
2378
+ ]);
2379
+ var DocumentSourceNodeSchema = import_zod20.z.object({
2380
+ id: import_zod20.z.string().min(1),
2381
+ documentId: import_zod20.z.string().min(1),
2382
+ parentId: import_zod20.z.string().optional(),
2383
+ kind: DocumentSourceNodeKindSchema,
2384
+ title: import_zod20.z.string(),
2385
+ description: import_zod20.z.string(),
2386
+ textExcerpt: import_zod20.z.string().optional(),
2387
+ sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)),
2388
+ pageStart: import_zod20.z.number().int().positive().optional(),
2389
+ pageEnd: import_zod20.z.number().int().positive().optional(),
2390
+ bbox: import_zod20.z.array(SourceSpanBBoxSchema).optional(),
2391
+ order: import_zod20.z.number().int().nonnegative(),
2392
+ path: import_zod20.z.string(),
2393
+ metadata: import_zod20.z.record(import_zod20.z.string(), import_zod20.z.unknown()).optional()
2394
+ });
2395
+ var SourceBackedValueSchema = import_zod20.z.object({
2396
+ value: import_zod20.z.string(),
2397
+ normalizedValue: import_zod20.z.string().optional(),
2398
+ confidence: import_zod20.z.enum(["low", "medium", "high"]).default("medium"),
2399
+ sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
2400
+ sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([])
2401
+ });
2402
+ var OperationalCoverageLineSchema = import_zod20.z.object({
2403
+ name: import_zod20.z.string(),
2404
+ coverageCode: import_zod20.z.string().optional(),
2405
+ limit: import_zod20.z.string().optional(),
2406
+ deductible: import_zod20.z.string().optional(),
2407
+ premium: import_zod20.z.string().optional(),
2408
+ formNumber: import_zod20.z.string().optional(),
2409
+ sectionRef: import_zod20.z.string().optional(),
2410
+ sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
2411
+ sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([])
2412
+ });
2413
+ var OperationalPartySchema = import_zod20.z.object({
2414
+ role: import_zod20.z.string(),
2415
+ name: import_zod20.z.string(),
2416
+ sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
2417
+ sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([])
2418
+ });
2419
+ var OperationalEndorsementSupportSchema = import_zod20.z.object({
2420
+ kind: import_zod20.z.string(),
2421
+ status: import_zod20.z.enum(["supported", "excluded", "requires_review"]),
2422
+ summary: import_zod20.z.string(),
2423
+ sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
2424
+ sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([])
2425
+ });
2426
+ var PolicyOperationalProfileSchema = import_zod20.z.object({
2427
+ documentType: import_zod20.z.enum(["policy", "quote"]).default("policy"),
2428
+ policyTypes: import_zod20.z.array(import_zod20.z.string()).default(["other"]),
2429
+ policyNumber: SourceBackedValueSchema.optional(),
2430
+ namedInsured: SourceBackedValueSchema.optional(),
2431
+ insurer: SourceBackedValueSchema.optional(),
2432
+ broker: SourceBackedValueSchema.optional(),
2433
+ effectiveDate: SourceBackedValueSchema.optional(),
2434
+ expirationDate: SourceBackedValueSchema.optional(),
2435
+ retroactiveDate: SourceBackedValueSchema.optional(),
2436
+ premium: SourceBackedValueSchema.optional(),
2437
+ coverageTypes: import_zod20.z.array(import_zod20.z.string()).default([]),
2438
+ coverages: import_zod20.z.array(OperationalCoverageLineSchema).default([]),
2439
+ parties: import_zod20.z.array(OperationalPartySchema).default([]),
2440
+ endorsementSupport: import_zod20.z.array(OperationalEndorsementSupportSchema).default([]),
2441
+ sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
2442
+ sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
2443
+ warnings: import_zod20.z.array(import_zod20.z.string()).default([])
2444
+ });
2274
2445
 
2275
2446
  // src/source/ids.ts
2276
2447
  function normalizeText(text) {
@@ -2454,8 +2625,8 @@ function chunkSourceSpans(spans, options = {}) {
2454
2625
  if (current.length === 0) return;
2455
2626
  const text = current.map((span) => span.text).join("\n\n");
2456
2627
  const textHash = sourceSpanTextHash(text);
2457
- const pageStart = firstNumber(current.map((span) => span.pageStart));
2458
- const pageEnd = lastNumber(current.map((span) => span.pageEnd ?? span.pageStart));
2628
+ const pageStart2 = firstNumber(current.map((span) => span.pageStart));
2629
+ const pageEnd2 = lastNumber(current.map((span) => span.pageEnd ?? span.pageStart));
2459
2630
  const chunk = {
2460
2631
  id: `${sanitizeIdPart(current[0].documentId)}:source_chunk:${chunks.length}:${stableHash2({
2461
2632
  sourceSpanIds: current.map((span) => span.id),
@@ -2465,8 +2636,8 @@ function chunkSourceSpans(spans, options = {}) {
2465
2636
  sourceSpanIds: current.map((span) => span.id),
2466
2637
  text,
2467
2638
  textHash,
2468
- pageStart,
2469
- pageEnd,
2639
+ pageStart: pageStart2,
2640
+ pageEnd: pageEnd2,
2470
2641
  metadata: mergeMetadata(current)
2471
2642
  };
2472
2643
  chunks.push(SourceChunkSchema.parse(chunk));
@@ -2619,6 +2790,542 @@ function matchesFilters(span, filters) {
2619
2790
  return true;
2620
2791
  }
2621
2792
 
2793
+ // src/source/tree.ts
2794
+ function normalizeWhitespace2(value) {
2795
+ return value.replace(/\s+/g, " ").trim();
2796
+ }
2797
+ function sanitizeIdPart2(value) {
2798
+ return value.replace(/[^a-zA-Z0-9_.:-]/g, "_");
2799
+ }
2800
+ function truncate(value, maxChars) {
2801
+ const text = normalizeWhitespace2(value);
2802
+ return text.length > maxChars ? `${text.slice(0, maxChars).trimEnd()}...` : text;
2803
+ }
2804
+ function pageStart(span) {
2805
+ return span.pageStart ?? span.location?.page ?? span.location?.startPage;
2806
+ }
2807
+ function pageEnd(span) {
2808
+ return span.pageEnd ?? span.location?.endPage ?? pageStart(span);
2809
+ }
2810
+ function sourceUnit2(span) {
2811
+ return span.sourceUnit ?? span.metadata?.sourceUnit ?? span.metadata?.elementType;
2812
+ }
2813
+ function elementType(span) {
2814
+ return span.metadata?.elementType ?? span.metadata?.sourceUnit ?? span.sourceUnit;
2815
+ }
2816
+ function tableId(span) {
2817
+ return span.table?.tableId ?? span.metadata?.tableId;
2818
+ }
2819
+ function rowSpanId(span) {
2820
+ return span.parentSpanId ?? span.table?.rowSpanId ?? span.metadata?.rowSpanId;
2821
+ }
2822
+ function nodeId(documentId, kind, parts) {
2823
+ return [
2824
+ sanitizeIdPart2(documentId),
2825
+ "source_node",
2826
+ kind,
2827
+ stableHash2(parts.filter((part) => part !== void 0).join("|")).slice(0, 12)
2828
+ ].join(":");
2829
+ }
2830
+ function titleCase(value) {
2831
+ return value.replace(/[_-]+/g, " ").replace(/\b\w/g, (char) => char.toUpperCase()).trim();
2832
+ }
2833
+ function nodeTextDescription(params) {
2834
+ return [
2835
+ params.title,
2836
+ params.kind.replace(/_/g, " "),
2837
+ params.page ? `page ${params.page}` : void 0,
2838
+ params.formNumber ? `form ${params.formNumber}` : void 0,
2839
+ params.text ? truncate(params.text, 1200) : void 0
2840
+ ].filter(Boolean).join(" | ");
2841
+ }
2842
+ function normalizeNodeKind(span) {
2843
+ const unit = sourceUnit2(span);
2844
+ const element = elementType(span);
2845
+ if (unit === "page") return "page";
2846
+ if (unit === "table") return "table";
2847
+ if (unit === "table_row") return "table_row";
2848
+ if (unit === "table_cell") return "table_cell";
2849
+ if (unit === "key_value") return "schedule";
2850
+ if (unit === "section") return "section";
2851
+ if (element === "title" || element === "section_candidate") {
2852
+ const text = span.text.toLowerCase();
2853
+ if (/endorsement/.test(text)) return "endorsement";
2854
+ if (/schedule|declarations?/.test(text)) return "schedule";
2855
+ if (/clause|condition|exclusion|definition/.test(text)) return "clause";
2856
+ return "section";
2857
+ }
2858
+ return "text";
2859
+ }
2860
+ function pageNodeTitle(page) {
2861
+ return `Page ${page}`;
2862
+ }
2863
+ function makeNode(params) {
2864
+ return {
2865
+ id: params.id,
2866
+ documentId: params.documentId,
2867
+ parentId: params.parentId,
2868
+ kind: params.kind,
2869
+ title: params.title,
2870
+ description: params.description ?? nodeTextDescription({
2871
+ kind: params.kind,
2872
+ title: params.title,
2873
+ text: params.textExcerpt,
2874
+ page: params.pageStart,
2875
+ formNumber: typeof params.metadata?.formNumber === "string" ? params.metadata.formNumber : void 0
2876
+ }),
2877
+ textExcerpt: params.textExcerpt,
2878
+ sourceSpanIds: params.sourceSpanIds ?? [],
2879
+ pageStart: params.pageStart,
2880
+ pageEnd: params.pageEnd,
2881
+ bbox: params.bbox,
2882
+ order: params.order,
2883
+ path: "",
2884
+ metadata: params.metadata
2885
+ };
2886
+ }
2887
+ function sortSpans(left, right) {
2888
+ const leftPage = pageStart(left) ?? 0;
2889
+ const rightPage = pageStart(right) ?? 0;
2890
+ if (leftPage !== rightPage) return leftPage - rightPage;
2891
+ const leftRow = left.table?.rowIndex ?? Number(left.metadata?.rowIndex ?? 0);
2892
+ const rightRow = right.table?.rowIndex ?? Number(right.metadata?.rowIndex ?? 0);
2893
+ if (leftRow !== rightRow) return leftRow - rightRow;
2894
+ const leftCol = left.table?.columnIndex ?? Number(left.metadata?.columnIndex ?? 0);
2895
+ const rightCol = right.table?.columnIndex ?? Number(right.metadata?.columnIndex ?? 0);
2896
+ if (leftCol !== rightCol) return leftCol - rightCol;
2897
+ return left.id.localeCompare(right.id);
2898
+ }
2899
+ function normalizeDocumentSourceTreePaths(nodes) {
2900
+ const byParent = /* @__PURE__ */ new Map();
2901
+ for (const node of nodes) {
2902
+ const key = node.parentId;
2903
+ const group = byParent.get(key) ?? [];
2904
+ group.push(node);
2905
+ byParent.set(key, group);
2906
+ }
2907
+ for (const group of byParent.values()) {
2908
+ group.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
2909
+ }
2910
+ const result = [];
2911
+ const visit = (node, path) => {
2912
+ const next = { ...node, path };
2913
+ result.push(next);
2914
+ const children = byParent.get(node.id) ?? [];
2915
+ children.forEach((child, index) => visit(child, `${path}.${index + 1}`));
2916
+ };
2917
+ const roots = byParent.get(void 0) ?? [];
2918
+ roots.forEach((root, index) => visit(root, String(index + 1)));
2919
+ return result;
2920
+ }
2921
+ function buildDocumentSourceTree(sourceSpans, documentId) {
2922
+ const orderedSpans = [...sourceSpans].sort(sortSpans);
2923
+ const resolvedDocumentId = documentId ?? orderedSpans[0]?.documentId ?? "document";
2924
+ const nodes = /* @__PURE__ */ new Map();
2925
+ let order = 0;
2926
+ const rootId = nodeId(resolvedDocumentId, "document", [resolvedDocumentId]);
2927
+ nodes.set(rootId, makeNode({
2928
+ id: rootId,
2929
+ documentId: resolvedDocumentId,
2930
+ kind: "document",
2931
+ title: "Document",
2932
+ description: "Document root for source-native policy hierarchy",
2933
+ sourceSpanIds: orderedSpans.map((span) => span.id).slice(0, 200),
2934
+ pageStart: orderedSpans.map(pageStart).find((value) => typeof value === "number"),
2935
+ pageEnd: [...orderedSpans].reverse().map(pageEnd).find((value) => typeof value === "number"),
2936
+ order: order++,
2937
+ metadata: { sourceTreeVersion: "v3" }
2938
+ }));
2939
+ const pageNodeIds = /* @__PURE__ */ new Map();
2940
+ const tableNodeIds = /* @__PURE__ */ new Map();
2941
+ const rowNodeIds = /* @__PURE__ */ new Map();
2942
+ const ensurePage = (page) => {
2943
+ const existing = pageNodeIds.get(page);
2944
+ if (existing) return existing;
2945
+ const id = nodeId(resolvedDocumentId, "page", [page]);
2946
+ const pageSpan = orderedSpans.find((span) => pageStart(span) === page && sourceUnit2(span) === "page");
2947
+ nodes.set(id, makeNode({
2948
+ id,
2949
+ documentId: resolvedDocumentId,
2950
+ parentId: rootId,
2951
+ kind: "page",
2952
+ title: pageNodeTitle(page),
2953
+ description: pageSpan ? nodeTextDescription({ kind: "page", title: pageNodeTitle(page), text: pageSpan.text, page }) : pageNodeTitle(page),
2954
+ textExcerpt: pageSpan ? truncate(pageSpan.text, 1600) : void 0,
2955
+ sourceSpanIds: pageSpan ? [pageSpan.id] : [],
2956
+ pageStart: page,
2957
+ pageEnd: page,
2958
+ bbox: pageSpan?.bbox,
2959
+ order: order++,
2960
+ metadata: { sourceUnit: "page" }
2961
+ }));
2962
+ pageNodeIds.set(page, id);
2963
+ return id;
2964
+ };
2965
+ const ensureTable = (span, pageParentId) => {
2966
+ const idSource = tableId(span) ?? `${span.documentId}:p${pageStart(span) ?? "na"}:table:${nodes.size}`;
2967
+ const existing = tableNodeIds.get(idSource);
2968
+ if (existing) return existing;
2969
+ const id = nodeId(resolvedDocumentId, "table", [idSource]);
2970
+ nodes.set(id, makeNode({
2971
+ id,
2972
+ documentId: resolvedDocumentId,
2973
+ parentId: pageParentId,
2974
+ kind: "table",
2975
+ title: `Table ${tableNodeIds.size + 1}`,
2976
+ description: `Table on page ${pageStart(span) ?? "unknown"} for source rows and cells`,
2977
+ sourceSpanIds: [],
2978
+ pageStart: pageStart(span),
2979
+ pageEnd: pageEnd(span),
2980
+ order: order++,
2981
+ metadata: { tableId: idSource, sourceUnit: "table" }
2982
+ }));
2983
+ tableNodeIds.set(idSource, id);
2984
+ return id;
2985
+ };
2986
+ const addStandaloneSpanNode = (span, parentId) => {
2987
+ const kind = normalizeNodeKind(span);
2988
+ if (kind === "page") return;
2989
+ const page = pageStart(span);
2990
+ const title = span.sectionId ?? span.formNumber ?? (kind === "table_cell" && span.table?.columnName ? String(span.table.columnName) : void 0) ?? titleCase(kind);
2991
+ const id = nodeId(resolvedDocumentId, kind, [span.id]);
2992
+ nodes.set(id, makeNode({
2993
+ id,
2994
+ documentId: resolvedDocumentId,
2995
+ parentId,
2996
+ kind,
2997
+ title,
2998
+ description: nodeTextDescription({ kind, title, text: span.text, page, formNumber: span.formNumber }),
2999
+ textExcerpt: truncate(span.text, 1600),
3000
+ sourceSpanIds: [span.id],
3001
+ pageStart: page,
3002
+ pageEnd: pageEnd(span),
3003
+ bbox: span.bbox,
3004
+ order: order++,
3005
+ metadata: {
3006
+ ...span.metadata ?? {},
3007
+ formNumber: span.formNumber,
3008
+ sourceUnit: sourceUnit2(span)
3009
+ }
3010
+ }));
3011
+ };
3012
+ for (const span of orderedSpans) {
3013
+ const page = pageStart(span);
3014
+ const pageParentId = page ? ensurePage(page) : rootId;
3015
+ const kind = normalizeNodeKind(span);
3016
+ if (kind === "page") continue;
3017
+ if (kind === "table_row") {
3018
+ const tableParentId = ensureTable(span, pageParentId);
3019
+ const rowKey = span.id;
3020
+ const id = nodeId(resolvedDocumentId, "table_row", [span.id]);
3021
+ nodes.set(id, makeNode({
3022
+ id,
3023
+ documentId: resolvedDocumentId,
3024
+ parentId: tableParentId,
3025
+ kind,
3026
+ title: span.table?.isHeader ? "Header row" : `Row ${(span.table?.rowIndex ?? 0) + 1}`,
3027
+ description: nodeTextDescription({ kind, title: "Table row", text: span.text, page }),
3028
+ textExcerpt: truncate(span.text, 1600),
3029
+ sourceSpanIds: [span.id],
3030
+ pageStart: page,
3031
+ pageEnd: pageEnd(span),
3032
+ bbox: span.bbox,
3033
+ order: order++,
3034
+ metadata: {
3035
+ ...span.metadata ?? {},
3036
+ ...span.table ?? {},
3037
+ sourceUnit: "table_row"
3038
+ }
3039
+ }));
3040
+ rowNodeIds.set(rowKey, id);
3041
+ continue;
3042
+ }
3043
+ if (kind === "table_cell") {
3044
+ const tableParentId = ensureTable(span, pageParentId);
3045
+ const parentRowId2 = rowSpanId(span);
3046
+ const parentId = parentRowId2 ? rowNodeIds.get(parentRowId2) ?? tableParentId : tableParentId;
3047
+ addStandaloneSpanNode(span, parentId);
3048
+ continue;
3049
+ }
3050
+ addStandaloneSpanNode(span, pageParentId);
3051
+ }
3052
+ return normalizeDocumentSourceTreePaths([...nodes.values()]);
3053
+ }
3054
+
3055
+ // src/source/operational-profile.ts
3056
+ function normalizeWhitespace3(value) {
3057
+ return value.replace(/\s+/g, " ").trim();
3058
+ }
3059
+ function cleanValue(value) {
3060
+ if (!value) return void 0;
3061
+ return normalizeWhitespace3(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
3062
+ }
3063
+ function moneyValue(value) {
3064
+ const clean = cleanValue(value);
3065
+ if (!clean) return void 0;
3066
+ if (/^\$/.test(clean)) return clean;
3067
+ if (/^\d{1,3}(?:,\d{3})*(?:\.\d{2})?$/.test(clean)) return `$${clean}`;
3068
+ return clean;
3069
+ }
3070
+ function nodeText(node) {
3071
+ return normalizeWhitespace3([
3072
+ node.title,
3073
+ node.description,
3074
+ node.textExcerpt
3075
+ ].filter(Boolean).join(" "));
3076
+ }
3077
+ function valueFromNode(node, value, confidence = "medium") {
3078
+ return {
3079
+ value,
3080
+ confidence,
3081
+ sourceNodeIds: [node.id],
3082
+ sourceSpanIds: node.sourceSpanIds
3083
+ };
3084
+ }
3085
+ function firstMatch(nodes, patterns) {
3086
+ for (const node of nodes) {
3087
+ const text = nodeText(node);
3088
+ for (const pattern of patterns) {
3089
+ const match = text.match(pattern);
3090
+ const value = cleanValue(match?.[1]);
3091
+ if (value) return valueFromNode(node, value, "high");
3092
+ }
3093
+ }
3094
+ return void 0;
3095
+ }
3096
+ function inferPolicyTypes(nodes) {
3097
+ const text = nodes.slice(0, 40).map(nodeText).join(" ").toLowerCase();
3098
+ const types = [];
3099
+ const add = (pattern, type) => {
3100
+ if (pattern.test(text) && !types.includes(type)) types.push(type);
3101
+ };
3102
+ add(/\b(cyber|network security|privacy liability|data breach)\b/i, "cyber");
3103
+ add(/\b(professional liability|errors?\s*&?\s*omissions|e&o)\b/i, "professional_liability");
3104
+ add(/\b(commercial general liability|general liability|cgl)\b/i, "general_liability");
3105
+ add(/\b(umbrella|excess liability)\b/i, "umbrella");
3106
+ add(/\b(workers'? compensation|employers'? liability)\b/i, "workers_comp");
3107
+ add(/\b(commercial auto|business auto|automobile liability)\b/i, "commercial_auto");
3108
+ add(/\b(commercial property|property coverage|building coverage)\b/i, "commercial_property");
3109
+ return types.length ? types : ["other"];
3110
+ }
3111
+ function inferDocumentType(nodes) {
3112
+ const text = nodes.slice(0, 25).map(nodeText).join(" ").toLowerCase();
3113
+ if (/\b(quote|proposal|quotation|indication)\b/.test(text) && !/\bpolicy number\b/.test(text)) {
3114
+ return "quote";
3115
+ }
3116
+ return "policy";
3117
+ }
3118
+ function coverageNameFromRow(text) {
3119
+ const labelled = text.match(/\b(?:coverage|coverage part|line)\s*:?\s*([^|;$]{3,80})/i)?.[1];
3120
+ if (labelled) return cleanValue(labelled);
3121
+ const parts = text.split(/\s+\|\s+| {2,}|\t/).map(cleanValue).filter(Boolean);
3122
+ const first = parts.find(
3123
+ (part) => !/^(limit|limits?|deductible|premium|amount|basis|rate|retroactive|aggregate|each occurrence)$/i.test(part) && !/^\$?[\d,]+/.test(part)
3124
+ );
3125
+ return cleanValue(first);
3126
+ }
3127
+ function limitFromText(text) {
3128
+ return moneyValue(
3129
+ text.match(/\b(?:limit|liability|aggregate|occurrence|claim)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?|\$?\d[\d,]*\s*(?:each|per|aggregate)[^|;]*)/i)?.[1] ?? text.match(/(\$\s?\d[\d,]*(?:\.\d{2})?)(?=.*\b(limit|aggregate|occurrence|claim|liability)\b)/i)?.[1]
3130
+ );
3131
+ }
3132
+ function deductibleFromText(text) {
3133
+ return moneyValue(text.match(/\b(?:deductible|retention|sir)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
3134
+ }
3135
+ function premiumFromText(text) {
3136
+ return moneyValue(text.match(/\b(?:premium|total premium|total cost|amount due)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
3137
+ }
3138
+ function buildCoverages(nodes) {
3139
+ const rows = nodes.filter((node) => {
3140
+ const text = nodeText(node);
3141
+ return (node.kind === "table_row" || node.kind === "schedule" || node.kind === "text") && /\b(coverage|limit|deductible|aggregate|occurrence|liability|premium)\b/i.test(text);
3142
+ });
3143
+ const coverages = [];
3144
+ const seen = /* @__PURE__ */ new Set();
3145
+ for (const row of rows) {
3146
+ const text = nodeText(row);
3147
+ const name = coverageNameFromRow(text);
3148
+ const limit = limitFromText(text);
3149
+ const deductible = deductibleFromText(text);
3150
+ const premium = premiumFromText(text);
3151
+ if (!name || !limit && !deductible && !premium) continue;
3152
+ const key = [name.toLowerCase(), limit, deductible, premium].join("|");
3153
+ if (seen.has(key)) continue;
3154
+ seen.add(key);
3155
+ coverages.push({
3156
+ name,
3157
+ limit,
3158
+ deductible,
3159
+ premium,
3160
+ formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
3161
+ sourceNodeIds: [row.id],
3162
+ sourceSpanIds: row.sourceSpanIds
3163
+ });
3164
+ if (coverages.length >= 60) break;
3165
+ }
3166
+ return coverages;
3167
+ }
3168
+ function buildParties(profile) {
3169
+ const parties = [];
3170
+ if (profile.namedInsured) {
3171
+ parties.push({
3172
+ role: "named_insured",
3173
+ name: profile.namedInsured.value,
3174
+ sourceNodeIds: profile.namedInsured.sourceNodeIds,
3175
+ sourceSpanIds: profile.namedInsured.sourceSpanIds
3176
+ });
3177
+ }
3178
+ if (profile.insurer) {
3179
+ parties.push({
3180
+ role: "insurer",
3181
+ name: profile.insurer.value,
3182
+ sourceNodeIds: profile.insurer.sourceNodeIds,
3183
+ sourceSpanIds: profile.insurer.sourceSpanIds
3184
+ });
3185
+ }
3186
+ if (profile.broker) {
3187
+ parties.push({
3188
+ role: "broker",
3189
+ name: profile.broker.value,
3190
+ sourceNodeIds: profile.broker.sourceNodeIds,
3191
+ sourceSpanIds: profile.broker.sourceSpanIds
3192
+ });
3193
+ }
3194
+ return parties;
3195
+ }
3196
+ function buildEndorsementSupport(nodes) {
3197
+ const support = [];
3198
+ for (const node of nodes) {
3199
+ const text = nodeText(node);
3200
+ const add = (kind, status) => {
3201
+ if (support.some((item) => item.kind === kind && item.status === status && item.sourceNodeIds.includes(node.id))) {
3202
+ return;
3203
+ }
3204
+ support.push({
3205
+ kind,
3206
+ status,
3207
+ summary: node.textExcerpt ?? node.description,
3208
+ sourceNodeIds: [node.id],
3209
+ sourceSpanIds: node.sourceSpanIds
3210
+ });
3211
+ };
3212
+ if (/additional insured/i.test(text)) add("additional_insured", /not included|requires endorsement|only by endorsement/i.test(text) ? "requires_review" : "supported");
3213
+ if (/waiver of subrogation|subrogation.*waived/i.test(text)) add("waiver_of_subrogation", /not included|requires endorsement|only by endorsement/i.test(text) ? "requires_review" : "supported");
3214
+ if (/primary.*non[-\s]?contributory|non[-\s]?contributory/i.test(text)) add("primary_non_contributory", /not included|requires endorsement|only by endorsement/i.test(text) ? "requires_review" : "supported");
3215
+ if (/loss payee|mortgagee/i.test(text)) add(/mortgagee/i.test(text) ? "mortgagee" : "loss_payee", "supported");
3216
+ if (support.length >= 20) break;
3217
+ }
3218
+ return support;
3219
+ }
3220
+ function buildDeterministicOperationalProfile(params) {
3221
+ const nodes = params.sourceTree.filter((node) => node.kind !== "document");
3222
+ const partial = {
3223
+ documentType: inferDocumentType(nodes),
3224
+ policyTypes: inferPolicyTypes(nodes),
3225
+ policyNumber: firstMatch(nodes, [
3226
+ /\bpolicy\s*(?:number|no\.?|#)\s*:?\s*([A-Z0-9][A-Z0-9-]{4,})/i,
3227
+ /\bpolicy\s*[:#]\s*([A-Z0-9][A-Z0-9-]{4,})/i
3228
+ ]),
3229
+ namedInsured: firstMatch(nodes, [
3230
+ /\b(?:named insured|insured name|insured)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i,
3231
+ /\b(?:applicant|policyholder)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i
3232
+ ]),
3233
+ insurer: firstMatch(nodes, [
3234
+ /\b(?:insurer|carrier|company|security)\s*:?\s*([^|;\n]{3,120})/i,
3235
+ /\bunderwritten by\s+([^|;\n]{3,120})/i
3236
+ ]),
3237
+ broker: firstMatch(nodes, [
3238
+ /\b(?:broker|producer|agent)\s*:?\s*([^|;\n]{3,120})/i
3239
+ ]),
3240
+ effectiveDate: firstMatch(nodes, [
3241
+ /\b(?:effective date|policy period from|from)\s*:?\s*([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})/i,
3242
+ /\b([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})\s+(?:to|through|-)\s+[0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4}/i
3243
+ ]),
3244
+ expirationDate: firstMatch(nodes, [
3245
+ /\b(?:expiration date|expiry date|expires|to)\s*:?\s*([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})/i,
3246
+ /\b[0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4}\s+(?:to|through|-)\s+([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})/i
3247
+ ]),
3248
+ retroactiveDate: firstMatch(nodes, [
3249
+ /\bretroactive date\s*:?\s*([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4}|full prior acts|none)/i
3250
+ ]),
3251
+ premium: firstMatch(nodes, [
3252
+ /\b(?:total premium|premium|total cost|amount due)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i
3253
+ ])
3254
+ };
3255
+ const coverages = buildCoverages(nodes);
3256
+ const coverageTypes = [...new Set(coverages.map((coverage) => coverage.name))];
3257
+ const sourceNodeIds = [.../* @__PURE__ */ new Set([
3258
+ ...Object.values(partial).flatMap(
3259
+ (value) => value && typeof value === "object" && "sourceNodeIds" in value ? value.sourceNodeIds : []
3260
+ ),
3261
+ ...coverages.flatMap((coverage) => coverage.sourceNodeIds)
3262
+ ])];
3263
+ const sourceSpanIds = [.../* @__PURE__ */ new Set([
3264
+ ...Object.values(partial).flatMap(
3265
+ (value) => value && typeof value === "object" && "sourceSpanIds" in value ? value.sourceSpanIds : []
3266
+ ),
3267
+ ...coverages.flatMap((coverage) => coverage.sourceSpanIds)
3268
+ ])];
3269
+ return PolicyOperationalProfileSchema.parse({
3270
+ ...partial,
3271
+ coverageTypes,
3272
+ coverages,
3273
+ parties: buildParties(partial),
3274
+ endorsementSupport: buildEndorsementSupport(nodes),
3275
+ sourceNodeIds,
3276
+ sourceSpanIds,
3277
+ warnings: [
3278
+ ...coverages.length === 0 ? ["No source-backed coverage schedule rows were identified deterministically."] : [],
3279
+ ...!partial.policyNumber ? ["No source-backed policy number was identified deterministically."] : [],
3280
+ ...!partial.namedInsured ? ["No source-backed named insured was identified deterministically."] : []
3281
+ ]
3282
+ });
3283
+ }
3284
+ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3285
+ const keepIds = (ids, valid) => Array.isArray(ids) ? ids.filter((id) => typeof id === "string" && valid.has(id)) : [];
3286
+ const mergeValue = (fallback, next) => {
3287
+ if (!next || typeof next !== "object" || Array.isArray(next)) return fallback;
3288
+ const record = next;
3289
+ const value = typeof record.value === "string" ? cleanValue(record.value) : void 0;
3290
+ if (!value) return fallback;
3291
+ const sourceNodeIds = keepIds(record.sourceNodeIds, validNodeIds);
3292
+ const sourceSpanIds = keepIds(record.sourceSpanIds, validSpanIds);
3293
+ if (sourceNodeIds.length === 0 && sourceSpanIds.length === 0) return fallback;
3294
+ return {
3295
+ value,
3296
+ normalizedValue: typeof record.normalizedValue === "string" ? record.normalizedValue : fallback?.normalizedValue,
3297
+ confidence: record.confidence === "high" || record.confidence === "low" || record.confidence === "medium" ? record.confidence : "medium",
3298
+ sourceNodeIds,
3299
+ sourceSpanIds
3300
+ };
3301
+ };
3302
+ const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => ({
3303
+ ...coverage,
3304
+ sourceNodeIds: keepIds(coverage.sourceNodeIds, validNodeIds),
3305
+ sourceSpanIds: keepIds(coverage.sourceSpanIds, validSpanIds)
3306
+ })).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
3307
+ return PolicyOperationalProfileSchema.parse({
3308
+ ...base,
3309
+ documentType: candidate.documentType === "quote" ? "quote" : candidate.documentType === "policy" ? "policy" : base.documentType,
3310
+ policyTypes: Array.isArray(candidate.policyTypes) && candidate.policyTypes.length > 0 ? candidate.policyTypes : base.policyTypes,
3311
+ policyNumber: mergeValue(base.policyNumber, candidate.policyNumber),
3312
+ namedInsured: mergeValue(base.namedInsured, candidate.namedInsured),
3313
+ insurer: mergeValue(base.insurer, candidate.insurer),
3314
+ broker: mergeValue(base.broker, candidate.broker),
3315
+ effectiveDate: mergeValue(base.effectiveDate, candidate.effectiveDate),
3316
+ expirationDate: mergeValue(base.expirationDate, candidate.expirationDate),
3317
+ retroactiveDate: mergeValue(base.retroactiveDate, candidate.retroactiveDate),
3318
+ premium: mergeValue(base.premium, candidate.premium),
3319
+ coverageTypes: Array.isArray(candidate.coverageTypes) && candidate.coverageTypes.length > 0 ? candidate.coverageTypes : base.coverageTypes,
3320
+ coverages,
3321
+ parties: base.parties,
3322
+ endorsementSupport: base.endorsementSupport,
3323
+ sourceNodeIds: [.../* @__PURE__ */ new Set([...base.sourceNodeIds, ...keepIds(candidate.sourceNodeIds, validNodeIds)])],
3324
+ sourceSpanIds: [.../* @__PURE__ */ new Set([...base.sourceSpanIds, ...keepIds(candidate.sourceSpanIds, validSpanIds)])],
3325
+ warnings: base.warnings
3326
+ });
3327
+ }
3328
+
2622
3329
  // src/extraction/pdf.ts
2623
3330
  var import_pdf_lib = require("pdf-lib");
2624
3331
  function isFileIdRef(input) {
@@ -3000,15 +3707,15 @@ function normalizeItem(ref, item) {
3000
3707
  if (!text) return void 0;
3001
3708
  const table = getItemTable(item);
3002
3709
  const pages = (item.prov ?? []).map((prov) => getPageNumber(prov)).filter((page) => typeof page === "number" && page > 0);
3003
- const pageStart = pages.length ? Math.min(...pages) : void 0;
3004
- const pageEnd = pages.length ? Math.max(...pages) : pageStart;
3710
+ const pageStart2 = pages.length ? Math.min(...pages) : void 0;
3711
+ const pageEnd2 = pages.length ? Math.max(...pages) : pageStart2;
3005
3712
  const bboxes = (item.prov ?? []).map((prov) => toSourceSpanBBox(prov)).filter((bbox) => Boolean(bbox));
3006
3713
  return {
3007
3714
  ref,
3008
3715
  label: typeof item.label === "string" ? item.label : void 0,
3009
3716
  text,
3010
- pageStart,
3011
- pageEnd,
3717
+ pageStart: pageStart2,
3718
+ pageEnd: pageEnd2,
3012
3719
  bboxes: bboxes.length ? bboxes : void 0,
3013
3720
  table
3014
3721
  };
@@ -3020,7 +3727,7 @@ function buildSourceSpansForUnit(unit, index, options) {
3020
3727
  doclingRef: unit.ref,
3021
3728
  ...unit.label ? { doclingLabel: unit.label } : {}
3022
3729
  };
3023
- const tableId = unit.table ? `${unit.ref}:table` : void 0;
3730
+ const tableId2 = unit.table ? `${unit.ref}:table` : void 0;
3024
3731
  const tableSpan = withDoclingKind(buildSourceSpan(
3025
3732
  {
3026
3733
  documentId: options.documentId,
@@ -3030,7 +3737,7 @@ function buildSourceSpansForUnit(unit, index, options) {
3030
3737
  pageEnd: unit.pageEnd,
3031
3738
  sectionId: unit.label,
3032
3739
  sourceUnit: unit.table ? "table" : labelToSourceUnit(unit.label),
3033
- table: tableId ? { tableId } : void 0,
3740
+ table: tableId2 ? { tableId: tableId2 } : void 0,
3034
3741
  metadata: baseMetadata
3035
3742
  },
3036
3743
  index * 1e3
@@ -3054,7 +3761,7 @@ function buildSourceSpansForUnit(unit, index, options) {
3054
3761
  sourceUnit: "table_row",
3055
3762
  parentSpanId: tableSpan.id,
3056
3763
  table: {
3057
- tableId,
3764
+ tableId: tableId2,
3058
3765
  tableSpanId: tableSpan.id,
3059
3766
  rowIndex,
3060
3767
  isHeader
@@ -3062,7 +3769,7 @@ function buildSourceSpansForUnit(unit, index, options) {
3062
3769
  metadata: {
3063
3770
  ...baseMetadata,
3064
3771
  sourceUnit: "table_row",
3065
- tableId: tableId ?? "",
3772
+ tableId: tableId2 ?? "",
3066
3773
  tableSpanId: tableSpan.id,
3067
3774
  rowIndex: String(rowIndex),
3068
3775
  isHeader: String(isHeader)
@@ -3086,7 +3793,7 @@ function buildSourceSpansForUnit(unit, index, options) {
3086
3793
  sourceUnit: "table_cell",
3087
3794
  parentSpanId: rowSpan.id,
3088
3795
  table: {
3089
- tableId,
3796
+ tableId: tableId2,
3090
3797
  tableSpanId: tableSpan.id,
3091
3798
  rowSpanId: rowSpan.id,
3092
3799
  rowIndex,
@@ -3097,7 +3804,7 @@ function buildSourceSpansForUnit(unit, index, options) {
3097
3804
  metadata: {
3098
3805
  ...baseMetadata,
3099
3806
  sourceUnit: "table_cell",
3100
- tableId: tableId ?? "",
3807
+ tableId: tableId2 ?? "",
3101
3808
  tableSpanId: tableSpan.id,
3102
3809
  rowSpanId: rowSpan.id,
3103
3810
  rowIndex: String(rowIndex),
@@ -3252,7 +3959,7 @@ function buildSourceContext(spans, maxChars = 12e3) {
3252
3959
  const lines = [];
3253
3960
  let length = 0;
3254
3961
  for (const span of orderSourceSpansForContext(spans)) {
3255
- const unit = sourceUnit2(span);
3962
+ const unit = sourceUnit3(span);
3256
3963
  const table = span.table;
3257
3964
  const tableContext = [
3258
3965
  unit ? ` unit:${unit}` : "",
@@ -3276,11 +3983,11 @@ ${lines.join("\n\n")}
3276
3983
 
3277
3984
  Use sourceSpan IDs when grounding extracted contractual values.`;
3278
3985
  }
3279
- function sourceUnit2(span) {
3986
+ function sourceUnit3(span) {
3280
3987
  return span.sourceUnit ?? span.metadata?.sourceUnit;
3281
3988
  }
3282
3989
  function sourceContextRank(span) {
3283
- switch (sourceUnit2(span)) {
3990
+ switch (sourceUnit3(span)) {
3284
3991
  case "table_row":
3285
3992
  return 0;
3286
3993
  case "table":
@@ -3299,10 +4006,10 @@ function sourceContextRank(span) {
3299
4006
  }
3300
4007
  function orderSourceSpansForContext(spans) {
3301
4008
  const parentRows = new Set(
3302
- spans.filter((span) => sourceUnit2(span) === "table_row").map((span) => span.id)
4009
+ spans.filter((span) => sourceUnit3(span) === "table_row").map((span) => span.id)
3303
4010
  );
3304
4011
  const filtered = spans.filter((span) => {
3305
- if (sourceUnit2(span) !== "table_cell") return true;
4012
+ if (sourceUnit3(span) !== "table_cell") return true;
3306
4013
  const parent = span.parentSpanId ?? span.table?.rowSpanId ?? span.metadata?.rowSpanId;
3307
4014
  return !parent || !parentRows.has(parent);
3308
4015
  });
@@ -3609,6 +4316,8 @@ function assembleDocument(documentId, documentType, memory) {
3609
4316
  carrier: readRecordValue(carrier, "carrierName") ?? "Unknown",
3610
4317
  insuredName: readRecordValue(insured, "insuredName") ?? "Unknown",
3611
4318
  coverages: coverageRecords,
4319
+ documentMetadata: {},
4320
+ documentOutline: [],
3612
4321
  policyTypes: readRecordValue(classify, "policyTypes"),
3613
4322
  ...sanitizeNulls(carrier ?? {}),
3614
4323
  ...sanitizeNulls(insured ?? {}),
@@ -3660,6 +4369,247 @@ function assembleDocument(documentId, documentType, memory) {
3660
4369
  return doc;
3661
4370
  }
3662
4371
 
4372
+ // src/extraction/document-structure.ts
4373
+ var FACT_ARRAY_PATHS = [
4374
+ "coverages",
4375
+ "enrichedCoverages",
4376
+ "endorsements",
4377
+ "exclusions",
4378
+ "conditions",
4379
+ "definitions",
4380
+ "coveredReasons",
4381
+ "taxesAndFees",
4382
+ "premiumBreakdown",
4383
+ "supplementaryFacts"
4384
+ ];
4385
+ function slugPart(value) {
4386
+ const text = String(value ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4387
+ return text || "node";
4388
+ }
4389
+ function numberValue(record, ...keys) {
4390
+ for (const key of keys) {
4391
+ const value = record[key];
4392
+ if (typeof value === "number" && Number.isFinite(value)) return value;
4393
+ }
4394
+ return void 0;
4395
+ }
4396
+ function stringValue2(record, ...keys) {
4397
+ for (const key of keys) {
4398
+ const value = record[key];
4399
+ if (typeof value === "string" && value.trim()) return value.trim();
4400
+ }
4401
+ return void 0;
4402
+ }
4403
+ function stringArray(value) {
4404
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.length > 0) : [];
4405
+ }
4406
+ function sourceUnit4(span) {
4407
+ return span.sourceUnit ?? span.metadata?.sourceUnit;
4408
+ }
4409
+ function spanPage(span) {
4410
+ return span.pageStart ?? span.location?.page ?? span.location?.startPage;
4411
+ }
4412
+ function spanPageEnd(span) {
4413
+ return span.pageEnd ?? span.location?.endPage ?? spanPage(span);
4414
+ }
4415
+ function sourceSpansForPage(sourceSpans, page) {
4416
+ return sourceSpans.filter((span) => spanPage(span) === page && sourceUnit4(span) === "page").map((span) => span.id);
4417
+ }
4418
+ function nodePageOverlaps(node, record) {
4419
+ const recordStart = numberValue(record, "pageNumber", "pageStart", "resolvedFromPage");
4420
+ const recordEnd = numberValue(record, "pageNumber", "pageEnd", "resolvedFromPage") ?? recordStart;
4421
+ if (!recordStart) return false;
4422
+ const nodeStart = node.pageStart ?? node.pageEnd;
4423
+ const nodeEnd = node.pageEnd ?? node.pageStart;
4424
+ if (!nodeStart) return false;
4425
+ return recordStart <= (nodeEnd ?? nodeStart) && (recordEnd ?? recordStart) >= nodeStart;
4426
+ }
4427
+ function nodeFormMatches(node, record) {
4428
+ const formNumber = stringValue2(record, "formNumber");
4429
+ return Boolean(formNumber && node.formNumber && formNumber.toLowerCase() === node.formNumber.toLowerCase());
4430
+ }
4431
+ function nodeSourceOverlaps(node, record) {
4432
+ const nodeSourceIds = new Set(node.sourceSpanIds ?? []);
4433
+ if (nodeSourceIds.size === 0) return false;
4434
+ return stringArray(record.sourceSpanIds).some((id) => nodeSourceIds.has(id));
4435
+ }
4436
+ function findBestNode(nodes, record) {
4437
+ let best;
4438
+ const visit = (node) => {
4439
+ let score = 0;
4440
+ if (nodeSourceOverlaps(node, record)) score += 8;
4441
+ if (nodeFormMatches(node, record)) score += 4;
4442
+ if (nodePageOverlaps(node, record)) score += 3;
4443
+ if (score > 0 && (!best || score > best.score)) {
4444
+ best = { node, score };
4445
+ }
4446
+ for (const child of node.children ?? []) visit(child);
4447
+ };
4448
+ for (const node of nodes) visit(node);
4449
+ return best?.node;
4450
+ }
4451
+ function attachDocumentNodeIds(document, nodes) {
4452
+ const doc = document;
4453
+ for (const path of FACT_ARRAY_PATHS) {
4454
+ const value = doc[path];
4455
+ if (!Array.isArray(value)) continue;
4456
+ doc[path] = value.map((item) => {
4457
+ if (!item || typeof item !== "object" || Array.isArray(item)) return item;
4458
+ const record = item;
4459
+ if (typeof record.documentNodeId === "string" && record.documentNodeId.length > 0) return record;
4460
+ const node = findBestNode(nodes, record);
4461
+ return node ? { ...record, documentNodeId: node.id } : record;
4462
+ });
4463
+ }
4464
+ }
4465
+ function buildNodeFromSection(section, index) {
4466
+ const title = stringValue2(section, "title", "name", "sectionRef") ?? `Section ${index + 1}`;
4467
+ const id = stringValue2(section, "documentNodeId", "recordId") ?? `section:${index}:${slugPart(title)}`;
4468
+ const pageStart2 = numberValue(section, "pageStart", "pageNumber");
4469
+ const pageEnd2 = numberValue(section, "pageEnd", "pageNumber") ?? pageStart2;
4470
+ const type = stringValue2(section, "type");
4471
+ const coverageType = stringValue2(section, "coverageType");
4472
+ const sourceSpanIds = stringArray(section.sourceSpanIds);
4473
+ const children = Array.isArray(section.subsections) ? section.subsections.filter((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item)).map((subsection, childIndex) => {
4474
+ const childTitle = stringValue2(subsection, "title", "name") ?? `${title} ${childIndex + 1}`;
4475
+ const childId = stringValue2(subsection, "documentNodeId", "recordId") ?? `${id}:subsection:${childIndex}:${slugPart(childTitle)}`;
4476
+ return {
4477
+ id: childId,
4478
+ title: childTitle,
4479
+ originalTitle: childTitle,
4480
+ type,
4481
+ label: type,
4482
+ level: 2,
4483
+ sectionNumber: stringValue2(subsection, "sectionNumber"),
4484
+ pageStart: numberValue(subsection, "pageNumber") ?? pageStart2,
4485
+ pageEnd: numberValue(subsection, "pageNumber") ?? pageStart2,
4486
+ excerpt: stringValue2(subsection, "excerpt"),
4487
+ content: stringValue2(subsection, "content"),
4488
+ sourceSpanIds: stringArray(subsection.sourceSpanIds),
4489
+ sourceTextHash: stringValue2(subsection, "sourceTextHash")
4490
+ };
4491
+ }) : void 0;
4492
+ return {
4493
+ id,
4494
+ title,
4495
+ originalTitle: title,
4496
+ type,
4497
+ label: type,
4498
+ level: 1,
4499
+ sectionNumber: stringValue2(section, "sectionNumber"),
4500
+ pageStart: pageStart2,
4501
+ pageEnd: pageEnd2,
4502
+ formNumber: stringValue2(section, "formNumber"),
4503
+ formTitle: stringValue2(section, "formTitle"),
4504
+ excerpt: stringValue2(section, "excerpt"),
4505
+ content: stringValue2(section, "content"),
4506
+ interpretationLabels: [type, coverageType].filter((value) => Boolean(value)),
4507
+ sourceSpanIds: sourceSpanIds.length > 0 ? sourceSpanIds : void 0,
4508
+ sourceTextHash: stringValue2(section, "sourceTextHash"),
4509
+ children: children && children.length > 0 ? children : void 0
4510
+ };
4511
+ }
4512
+ function buildNodesFromSourceSpans(sourceSpans) {
4513
+ const candidates = sourceSpans.filter((span) => {
4514
+ const unit = sourceUnit4(span);
4515
+ return unit === "section" || unit === "section_candidate" || unit === "page";
4516
+ });
4517
+ return candidates.sort((left, right) => (spanPage(left) ?? 0) - (spanPage(right) ?? 0) || left.id.localeCompare(right.id)).map((span, index) => {
4518
+ const title = span.sectionId ?? span.formNumber ?? (sourceUnit4(span) === "page" && spanPage(span) ? `Page ${spanPage(span)}` : `Source unit ${index + 1}`);
4519
+ return {
4520
+ id: `source:${index}:${slugPart(span.id)}`,
4521
+ title,
4522
+ originalTitle: title,
4523
+ type: sourceUnit4(span),
4524
+ label: sourceUnit4(span),
4525
+ level: 1,
4526
+ pageStart: spanPage(span),
4527
+ pageEnd: spanPageEnd(span),
4528
+ formNumber: span.formNumber,
4529
+ excerpt: span.text.slice(0, 500),
4530
+ sourceSpanIds: [span.id],
4531
+ sourceTextHash: span.textHash ?? span.hash
4532
+ };
4533
+ });
4534
+ }
4535
+ function flattenToc(nodes) {
4536
+ const entries = [];
4537
+ const visit = (node) => {
4538
+ entries.push({
4539
+ title: node.title,
4540
+ level: node.level,
4541
+ pageStart: node.pageStart,
4542
+ pageEnd: node.pageEnd,
4543
+ documentNodeId: node.id,
4544
+ sourceSpanIds: node.sourceSpanIds
4545
+ });
4546
+ for (const child of node.children ?? []) visit(child);
4547
+ };
4548
+ for (const node of nodes) visit(node);
4549
+ return entries;
4550
+ }
4551
+ function buildPageMap(pageAssignments, sourceSpans, document) {
4552
+ const forms = document.formInventory ?? [];
4553
+ return pageAssignments.sort((left, right) => left.localPageNumber - right.localPageNumber).map((assignment) => {
4554
+ const form = forms.find((item) => {
4555
+ const start = item.pageStart;
4556
+ const end = item.pageEnd ?? start;
4557
+ return start != null && end != null && assignment.localPageNumber >= start && assignment.localPageNumber <= end;
4558
+ });
4559
+ return {
4560
+ page: assignment.localPageNumber,
4561
+ label: assignment.notes,
4562
+ formNumber: form?.formNumber,
4563
+ formTitle: form?.title,
4564
+ extractorNames: assignment.extractorNames,
4565
+ sourceSpanIds: sourceSpansForPage(sourceSpans, assignment.localPageNumber)
4566
+ };
4567
+ });
4568
+ }
4569
+ function buildAgentGuidance(document) {
4570
+ const guidance = [
4571
+ {
4572
+ kind: "source_structure",
4573
+ title: "Use the source outline as navigation",
4574
+ detail: "The documentOutline preserves source order and page ranges. Treat interpretation labels as hints, not as a replacement for the source document structure."
4575
+ }
4576
+ ];
4577
+ if (document.declarations) {
4578
+ guidance.push({
4579
+ kind: "declarations",
4580
+ title: "Declarations establish policy facts",
4581
+ detail: "Declarations and schedules generally establish named insured, policy period, limits, deductibles, premium, and rating facts unless modified elsewhere."
4582
+ });
4583
+ }
4584
+ if (document.endorsements?.length || document.formInventory?.some((form) => form.formType === "endorsement")) {
4585
+ guidance.push({
4586
+ kind: "endorsement_override",
4587
+ title: "Endorsements may override base terms",
4588
+ detail: "Endorsements and change forms can add, remove, or override base policy wording. When terms conflict, inspect the effective endorsement language and source page."
4589
+ });
4590
+ }
4591
+ return guidance;
4592
+ }
4593
+ function attachDocumentStructure(params) {
4594
+ const docRecord = params.document;
4595
+ const sections = Array.isArray(params.document.sections) ? params.document.sections : [];
4596
+ const existingOutline = Array.isArray(docRecord.documentOutline) ? docRecord.documentOutline : [];
4597
+ const documentOutline = existingOutline.length > 0 ? existingOutline : sections.length > 0 ? sections.map((section, index) => buildNodeFromSection(section, index)) : buildNodesFromSourceSpans(params.sourceSpans);
4598
+ if (documentOutline.length > 0) {
4599
+ attachDocumentNodeIds(params.document, documentOutline);
4600
+ }
4601
+ const metadata = {
4602
+ ...docRecord.documentMetadata && typeof docRecord.documentMetadata === "object" ? docRecord.documentMetadata : {},
4603
+ ...params.document.formInventory?.length ? { formInventory: params.document.formInventory } : {},
4604
+ ...documentOutline.length > 0 ? { tableOfContents: flattenToc(documentOutline) } : {},
4605
+ ...params.pageAssignments.length > 0 ? { pageMap: buildPageMap(params.pageAssignments, params.sourceSpans, params.document) } : {},
4606
+ agentGuidance: buildAgentGuidance(params.document)
4607
+ };
4608
+ docRecord.documentMetadata = metadata;
4609
+ docRecord.documentOutline = documentOutline;
4610
+ return params.document;
4611
+ }
4612
+
3663
4613
  // src/prompts/coordinator/format.ts
3664
4614
  function buildFormatPrompt(entries) {
3665
4615
  const block = entries.map((e) => `===ENTRY ${e.id}===
@@ -4259,6 +5209,8 @@ function chunkDocument(doc) {
4259
5209
  {
4260
5210
  formNumber: form.formNumber,
4261
5211
  formType: form.formType,
5212
+ documentNodeId: form.documentNodeId,
5213
+ sourceSpanIds: form.sourceSpanIds?.join(","),
4262
5214
  documentType: doc.type
4263
5215
  }
4264
5216
  );
@@ -4285,6 +5237,7 @@ function chunkDocument(doc) {
4285
5237
  formNumber: end.formNumber,
4286
5238
  pageStart: end.pageStart,
4287
5239
  pageEnd: end.pageEnd,
5240
+ documentNodeId: end.documentNodeId,
4288
5241
  sourceSpanIds: end.sourceSpanIds?.join(","),
4289
5242
  sourceTextHash: end.sourceTextHash,
4290
5243
  documentType: doc.type
@@ -4296,6 +5249,8 @@ function chunkDocument(doc) {
4296
5249
  ${exc.content}`.trim(), {
4297
5250
  formNumber: exc.formNumber,
4298
5251
  pageNumber: exc.pageNumber,
5252
+ documentNodeId: exc.documentNodeId,
5253
+ sourceSpanIds: exc.sourceSpanIds?.join(","),
4299
5254
  documentType: doc.type
4300
5255
  });
4301
5256
  });
@@ -4313,6 +5268,8 @@ ${exc.content}`.trim(), {
4313
5268
  conditionName: cond.name,
4314
5269
  conditionType: cond.conditionType,
4315
5270
  pageNumber: cond.pageNumber,
5271
+ documentNodeId: cond.documentNodeId,
5272
+ sourceSpanIds: cond.sourceSpanIds?.join(","),
4316
5273
  documentType: doc.type
4317
5274
  }
4318
5275
  );
@@ -4334,6 +5291,9 @@ ${exc.content}`.trim(), {
4334
5291
  formTitle: firstString2(definition, ["formTitle"]),
4335
5292
  pageNumber: typeof definition.pageNumber === "number" ? definition.pageNumber : void 0,
4336
5293
  sectionRef: firstString2(definition, ["sectionRef", "sectionTitle"]),
5294
+ documentNodeId: firstString2(definition, ["documentNodeId"]),
5295
+ sourceSpanIds: Array.isArray(definition.sourceSpanIds) ? definition.sourceSpanIds.join(",") : void 0,
5296
+ sourceTextHash: firstString2(definition, ["sourceTextHash"]),
4337
5297
  documentType: doc.type
4338
5298
  }
4339
5299
  );
@@ -4362,6 +5322,9 @@ ${exc.content}`.trim(), {
4362
5322
  formTitle: firstString2(coveredReason, ["formTitle"]),
4363
5323
  pageNumber: typeof coveredReason.pageNumber === "number" ? coveredReason.pageNumber : void 0,
4364
5324
  sectionRef: firstString2(coveredReason, ["sectionRef", "sectionTitle"]),
5325
+ documentNodeId: firstString2(coveredReason, ["documentNodeId"]),
5326
+ sourceSpanIds: Array.isArray(coveredReason.sourceSpanIds) ? coveredReason.sourceSpanIds.join(",") : void 0,
5327
+ sourceTextHash: firstString2(coveredReason, ["sourceTextHash"]),
4365
5328
  documentType: doc.type
4366
5329
  }
4367
5330
  );
@@ -4423,6 +5386,7 @@ ${declLines.join("\n")}`, declMeta);
4423
5386
  evidenceKind: "navigation",
4424
5387
  sectionType: sec.type,
4425
5388
  sectionNumber: sec.sectionNumber,
5389
+ documentNodeId: sec.documentNodeId,
4426
5390
  pageStart: sec.pageStart,
4427
5391
  pageEnd: sec.pageEnd,
4428
5392
  sourceSpanIds: sec.sourceSpanIds?.join(","),
@@ -4446,6 +5410,7 @@ ${declLines.join("\n")}`, declMeta);
4446
5410
  sectionType: sec.type,
4447
5411
  parentSection: sec.title,
4448
5412
  sectionNumber: sub.sectionNumber,
5413
+ documentNodeId: sub.documentNodeId,
4449
5414
  pageNumber: sub.pageNumber,
4450
5415
  sourceSpanIds: sub.sourceSpanIds?.join(","),
4451
5416
  sourceTextHash: sub.sourceTextHash,
@@ -4454,6 +5419,31 @@ ${declLines.join("\n")}`, declMeta);
4454
5419
  );
4455
5420
  });
4456
5421
  });
5422
+ asRecordArray(extendedDoc.documentOutline).forEach((node, i) => {
5423
+ const title = firstString2(node, ["title", "originalTitle"]) ?? `Document Node ${i + 1}`;
5424
+ const children = asRecordArray(node.children);
5425
+ pushChunk(
5426
+ `section:outline:${i}`,
5427
+ "section",
5428
+ lines([
5429
+ `Document Outline: ${title}`,
5430
+ firstString2(node, ["label", "type"]) ? `Label: ${firstString2(node, ["label", "type"])}` : null,
5431
+ typeof node.pageStart === "number" ? `Pages: ${node.pageStart}${typeof node.pageEnd === "number" ? `-${node.pageEnd}` : ""}` : null,
5432
+ firstString2(node, ["excerpt", "content"]),
5433
+ children.length > 0 ? `Children: ${children.map((child, childIndex) => firstString2(child, ["title", "originalTitle"]) ?? `Child ${childIndex + 1}`).join(", ")}` : null
5434
+ ]),
5435
+ {
5436
+ evidenceKind: "navigation",
5437
+ documentNodeId: firstString2(node, ["id"]),
5438
+ sectionType: firstString2(node, ["type", "label"]),
5439
+ pageStart: typeof node.pageStart === "number" ? node.pageStart : void 0,
5440
+ pageEnd: typeof node.pageEnd === "number" ? node.pageEnd : void 0,
5441
+ sourceSpanIds: Array.isArray(node.sourceSpanIds) ? node.sourceSpanIds.join(",") : void 0,
5442
+ sourceTextHash: firstString2(node, ["sourceTextHash"]),
5443
+ documentType: doc.type
5444
+ }
5445
+ );
5446
+ });
4457
5447
  doc.locations?.forEach((loc, i) => {
4458
5448
  chunks.push({
4459
5449
  id: `${docId}:location:${i}`,
@@ -7277,13 +8267,13 @@ async function resolveReferentialCoverages(params) {
7277
8267
  function textValue(value) {
7278
8268
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
7279
8269
  }
7280
- function numberValue(value) {
8270
+ function numberValue2(value) {
7281
8271
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
7282
8272
  }
7283
8273
  function normalize(value) {
7284
8274
  return value.toLowerCase().replace(/&/g, "and").replace(/[^a-z0-9]+/g, " ").trim();
7285
8275
  }
7286
- function sourceUnit3(span) {
8276
+ function sourceUnit5(span) {
7287
8277
  return span.sourceUnit ?? span.metadata?.sourceUnit;
7288
8278
  }
7289
8279
  function pageNumber(span) {
@@ -7353,7 +8343,7 @@ function firstField(fields, patterns) {
7353
8343
  }
7354
8344
  function coverageFromRow(span) {
7355
8345
  const rowText = span.text.trim();
7356
- if (!rowText || sourceUnit3(span) !== "table_row") return void 0;
8346
+ if (!rowText || sourceUnit5(span) !== "table_row") return void 0;
7357
8347
  if (span.table?.isHeader || span.metadata?.isHeader === "true") return void 0;
7358
8348
  const fields = splitRowFields(rowText);
7359
8349
  let name;
@@ -7415,7 +8405,7 @@ function coverageKey(coverage) {
7415
8405
  textValue(coverage.name) ?? "",
7416
8406
  textValue(coverage.limit) ?? "",
7417
8407
  textValue(coverage.limitType) ?? "",
7418
- numberValue(coverage.pageNumber) ?? ""
8408
+ numberValue2(coverage.pageNumber) ?? ""
7419
8409
  ].map((part) => normalize(String(part))).join("|");
7420
8410
  }
7421
8411
  function rowMatchesExisting(row, existing) {
@@ -7433,7 +8423,7 @@ function recoverCoverageScheduleRows(params) {
7433
8423
  const payload = params.memory.get("coverage_limits");
7434
8424
  const existing = Array.isArray(payload?.coverages) ? payload.coverages : [];
7435
8425
  const pages = coveragePages(params.pageAssignments);
7436
- const candidates = params.sourceSpans.filter((span) => sourceUnit3(span) === "table_row").filter((span) => {
8426
+ const candidates = params.sourceSpans.filter((span) => sourceUnit5(span) === "table_row").filter((span) => {
7437
8427
  const page = pageNumber(span);
7438
8428
  return page !== void 0 && pages.has(page);
7439
8429
  }).map(coverageFromRow).filter((coverage) => Boolean(coverage));
@@ -8069,13 +9059,13 @@ function buildPlanFromPageAssignments(pageAssignments, pageCount, formInventory)
8069
9059
  const expanded = new Set(pages);
8070
9060
  for (const page of pages) {
8071
9061
  for (const form of contextualForms) {
8072
- const pageStart = form.pageStart;
8073
- const pageEnd = form.pageEnd ?? form.pageStart;
9062
+ const pageStart2 = form.pageStart;
9063
+ const pageEnd2 = form.pageEnd ?? form.pageStart;
8074
9064
  const formType = form.formType;
8075
9065
  const supportsContextualExpansion = extractorName === "endorsements" ? formType === "endorsement" : formType === "coverage" || formType === "endorsement";
8076
9066
  if (!supportsContextualExpansion) continue;
8077
- if (page < pageStart || page > pageEnd) continue;
8078
- for (let current = pageStart; current <= pageEnd; current += 1) {
9067
+ if (page < pageStart2 || page > pageEnd2) continue;
9068
+ for (let current = pageStart2; current <= pageEnd2; current += 1) {
8079
9069
  expanded.add(current);
8080
9070
  }
8081
9071
  }
@@ -8108,7 +9098,10 @@ var ARRAY_PATHS = [
8108
9098
  { memoryKey: "sections", arrayKeys: ["sections"] },
8109
9099
  { memoryKey: "definitions", arrayKeys: ["definitions"] },
8110
9100
  { memoryKey: "covered_reasons", arrayKeys: ["coveredReasons", "covered_reasons"] },
8111
- { memoryKey: "declarations", arrayKeys: ["fields"] }
9101
+ { memoryKey: "declarations", arrayKeys: ["fields"] },
9102
+ { memoryKey: "premium_breakdown", arrayKeys: ["premiumBreakdown", "taxesAndFees"] },
9103
+ { memoryKey: "supplementary", arrayKeys: ["auxiliaryFacts", "supplementaryFacts"] },
9104
+ { memoryKey: "form_inventory", arrayKeys: ["forms"] }
8112
9105
  ];
8113
9106
  function normalize2(value) {
8114
9107
  return value.replace(/\s+/g, " ").trim().toLowerCase();
@@ -8120,7 +9113,7 @@ function textValue2(record, ...keys) {
8120
9113
  }
8121
9114
  return void 0;
8122
9115
  }
8123
- function numberValue2(record, ...keys) {
9116
+ function numberValue3(record, ...keys) {
8124
9117
  for (const key of keys) {
8125
9118
  const value = record[key];
8126
9119
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -8153,11 +9146,11 @@ function textMatches(record, span) {
8153
9146
  function sourceHashFor(spans) {
8154
9147
  return spans.map((span) => span.textHash ?? span.hash).filter(Boolean).join(":") || void 0;
8155
9148
  }
8156
- function sourceUnit4(span) {
9149
+ function sourceUnit6(span) {
8157
9150
  return span.sourceUnit ?? span.metadata?.sourceUnit;
8158
9151
  }
8159
9152
  function hierarchyScore(span) {
8160
- switch (sourceUnit4(span)) {
9153
+ switch (sourceUnit6(span)) {
8161
9154
  case "table_row":
8162
9155
  return 5;
8163
9156
  case "table":
@@ -8180,8 +9173,8 @@ function preferParentRows(matches, sourceSpans) {
8180
9173
  const expanded = [];
8181
9174
  const seen = /* @__PURE__ */ new Set();
8182
9175
  for (const match of matches) {
8183
- const parent = sourceUnit4(match) === "table_cell" ? byId.get(parentRowId(match) ?? "") : void 0;
8184
- const preferred = parent && sourceUnit4(parent) === "table_row" ? parent : match;
9176
+ const parent = sourceUnit6(match) === "table_cell" ? byId.get(parentRowId(match) ?? "") : void 0;
9177
+ const preferred = parent && sourceUnit6(parent) === "table_row" ? parent : match;
8185
9178
  if (seen.has(preferred.id)) continue;
8186
9179
  seen.add(preferred.id);
8187
9180
  expanded.push(preferred);
@@ -8190,11 +9183,11 @@ function preferParentRows(matches, sourceSpans) {
8190
9183
  }
8191
9184
  function findSourceSpansForRecord(record, sourceSpans) {
8192
9185
  if (sourceSpans.length === 0) return [];
8193
- const pageStart = numberValue2(record, "pageNumber", "pageStart");
8194
- const pageEnd = numberValue2(record, "pageNumber", "pageEnd");
9186
+ const pageStart2 = numberValue3(record, "pageNumber", "pageStart");
9187
+ const pageEnd2 = numberValue3(record, "pageNumber", "pageEnd");
8195
9188
  const scored = sourceSpans.map((span) => {
8196
9189
  let score = 0;
8197
- if (pageOverlaps(pageStart, pageEnd, span)) score += 4;
9190
+ if (pageOverlaps(pageStart2, pageEnd2, span)) score += 4;
8198
9191
  if (formMatches(record, span)) score += 3;
8199
9192
  if (textMatches(record, span)) score += 2;
8200
9193
  if (score > 0) score += hierarchyScore(span);
@@ -8233,6 +9226,422 @@ function groundExtractionMemoryWithSourceSpans(memory, sourceSpans) {
8233
9226
  }
8234
9227
  }
8235
9228
 
9229
+ // src/extraction/source-tree-extractor.ts
9230
+ var import_zod41 = require("zod");
9231
+ var ORGANIZABLE_KINDS = [
9232
+ "page_group",
9233
+ "form",
9234
+ "endorsement",
9235
+ "section",
9236
+ "schedule",
9237
+ "clause"
9238
+ ];
9239
+ var SourceTreeOrganizationSchema = import_zod41.z.object({
9240
+ labels: import_zod41.z.array(import_zod41.z.object({
9241
+ nodeId: import_zod41.z.string(),
9242
+ kind: import_zod41.z.enum([
9243
+ "document",
9244
+ "page_group",
9245
+ "page",
9246
+ "form",
9247
+ "endorsement",
9248
+ "section",
9249
+ "schedule",
9250
+ "clause",
9251
+ "table",
9252
+ "table_row",
9253
+ "table_cell",
9254
+ "text"
9255
+ ]).optional(),
9256
+ title: import_zod41.z.string().optional(),
9257
+ description: import_zod41.z.string().optional()
9258
+ })).default([]),
9259
+ groups: import_zod41.z.array(import_zod41.z.object({
9260
+ kind: import_zod41.z.enum(ORGANIZABLE_KINDS),
9261
+ title: import_zod41.z.string(),
9262
+ description: import_zod41.z.string().optional(),
9263
+ childNodeIds: import_zod41.z.array(import_zod41.z.string()).min(1)
9264
+ })).default([])
9265
+ });
9266
+ var SourceBackedValueForPromptSchema = import_zod41.z.object({
9267
+ value: import_zod41.z.string(),
9268
+ normalizedValue: import_zod41.z.string().optional(),
9269
+ confidence: import_zod41.z.enum(["low", "medium", "high"]).optional(),
9270
+ sourceNodeIds: import_zod41.z.array(import_zod41.z.string()).default([]),
9271
+ sourceSpanIds: import_zod41.z.array(import_zod41.z.string()).default([])
9272
+ });
9273
+ var OperationalProfilePromptSchema = import_zod41.z.object({
9274
+ documentType: import_zod41.z.enum(["policy", "quote"]).optional(),
9275
+ policyTypes: import_zod41.z.array(import_zod41.z.string()).optional(),
9276
+ policyNumber: SourceBackedValueForPromptSchema.optional(),
9277
+ namedInsured: SourceBackedValueForPromptSchema.optional(),
9278
+ insurer: SourceBackedValueForPromptSchema.optional(),
9279
+ broker: SourceBackedValueForPromptSchema.optional(),
9280
+ effectiveDate: SourceBackedValueForPromptSchema.optional(),
9281
+ expirationDate: SourceBackedValueForPromptSchema.optional(),
9282
+ retroactiveDate: SourceBackedValueForPromptSchema.optional(),
9283
+ premium: SourceBackedValueForPromptSchema.optional(),
9284
+ coverageTypes: import_zod41.z.array(import_zod41.z.string()).optional(),
9285
+ coverages: import_zod41.z.array(import_zod41.z.object({
9286
+ name: import_zod41.z.string(),
9287
+ coverageCode: import_zod41.z.string().optional(),
9288
+ limit: import_zod41.z.string().optional(),
9289
+ deductible: import_zod41.z.string().optional(),
9290
+ premium: import_zod41.z.string().optional(),
9291
+ formNumber: import_zod41.z.string().optional(),
9292
+ sectionRef: import_zod41.z.string().optional(),
9293
+ sourceNodeIds: import_zod41.z.array(import_zod41.z.string()).default([]),
9294
+ sourceSpanIds: import_zod41.z.array(import_zod41.z.string()).default([])
9295
+ })).optional(),
9296
+ sourceNodeIds: import_zod41.z.array(import_zod41.z.string()).optional(),
9297
+ sourceSpanIds: import_zod41.z.array(import_zod41.z.string()).optional()
9298
+ });
9299
+ function cleanText(value, fallback) {
9300
+ const text = value?.replace(/\s+/g, " ").trim();
9301
+ return text || fallback;
9302
+ }
9303
+ function compactNode(node) {
9304
+ return {
9305
+ id: node.id,
9306
+ kind: node.kind,
9307
+ title: node.title,
9308
+ path: node.path,
9309
+ pageStart: node.pageStart,
9310
+ pageEnd: node.pageEnd,
9311
+ sourceSpanIds: node.sourceSpanIds.slice(0, 8),
9312
+ text: (node.textExcerpt ?? node.description).slice(0, 700)
9313
+ };
9314
+ }
9315
+ function buildOrganizationPrompt(sourceTree) {
9316
+ const nodes = sourceTree.filter((node) => node.kind !== "table_cell").slice(0, 180).map(compactNode);
9317
+ return `You organize an insurance document source tree.
9318
+
9319
+ Rules:
9320
+ - Use only node IDs from the provided list.
9321
+ - Do not invent text, page numbers, source spans, limits, or policy facts.
9322
+ - You may relabel existing nodes and group adjacent top-level/page nodes when they are clearly one form, endorsement, declarations set, schedule, or clause family.
9323
+ - Groups must list existing childNodeIds only.
9324
+ - Keep descriptions short and useful for search.
9325
+
9326
+ Source nodes:
9327
+ ${JSON.stringify(nodes, null, 2)}
9328
+
9329
+ Return JSON with labels and groups only.`;
9330
+ }
9331
+ function buildOperationalProfilePrompt(sourceTree, fallback) {
9332
+ const nodes = sourceTree.filter((node) => node.kind !== "document").slice(0, 240).map(compactNode);
9333
+ return `Extract a source-backed operational profile for an insurance policy or quote.
9334
+
9335
+ Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
9336
+ - policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium
9337
+ - coverage lines with limits, deductibles, premiums, and form references
9338
+ - coverage type labels
9339
+
9340
+ Rules:
9341
+ - Every returned value must include sourceNodeIds or sourceSpanIds from the provided nodes.
9342
+ - If a value is not directly supported, omit it.
9343
+ - Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
9344
+ - Do not copy entire policy wording into fields.
9345
+
9346
+ Deterministic baseline:
9347
+ ${JSON.stringify(fallback, null, 2)}
9348
+
9349
+ Source nodes:
9350
+ ${JSON.stringify(nodes, null, 2)}
9351
+
9352
+ Return JSON for the operational profile.`;
9353
+ }
9354
+ function groupNodeId(documentId, group) {
9355
+ return [
9356
+ documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
9357
+ "source_node",
9358
+ group.kind,
9359
+ group.childNodeIds.join("_").replace(/[^a-zA-Z0-9_.:-]/g, "_").slice(0, 80)
9360
+ ].join(":");
9361
+ }
9362
+ function applyOrganization(sourceTree, organization) {
9363
+ const byId = new Map(sourceTree.map((node) => [node.id, node]));
9364
+ let nextTree = sourceTree.map((node) => {
9365
+ const label = organization.labels.find((item) => item.nodeId === node.id);
9366
+ if (!label) return node;
9367
+ return {
9368
+ ...node,
9369
+ kind: label.kind ?? node.kind,
9370
+ title: cleanText(label.title, node.title),
9371
+ description: cleanText(label.description, node.description)
9372
+ };
9373
+ });
9374
+ for (const group of organization.groups.slice(0, 40)) {
9375
+ const children = group.childNodeIds.map((id2) => byId.get(id2)).filter((node2) => Boolean(node2));
9376
+ if (children.length === 0) continue;
9377
+ const parentId = children[0].parentId;
9378
+ if (!children.every((child) => child.parentId === parentId)) continue;
9379
+ const documentId = children[0].documentId;
9380
+ const id = groupNodeId(documentId, group);
9381
+ if (byId.has(id)) continue;
9382
+ const sourceSpanIds = [...new Set(children.flatMap((child) => child.sourceSpanIds))];
9383
+ const pageStarts = children.map((child) => child.pageStart).filter((page) => typeof page === "number");
9384
+ const pageEnds = children.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
9385
+ const order = Math.min(...children.map((child) => child.order));
9386
+ const node = {
9387
+ id,
9388
+ documentId,
9389
+ parentId,
9390
+ kind: group.kind,
9391
+ title: group.title,
9392
+ description: group.description ?? group.title,
9393
+ textExcerpt: children.map((child) => child.textExcerpt ?? child.description).filter(Boolean).join("\n\n").slice(0, 1600),
9394
+ sourceSpanIds,
9395
+ pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
9396
+ pageEnd: pageEnds.length ? Math.max(...pageEnds) : void 0,
9397
+ bbox: children.flatMap((child) => child.bbox ?? []).slice(0, 12),
9398
+ order,
9399
+ path: "",
9400
+ metadata: { sourceTreeVersion: "v3", organizer: "llm_group" }
9401
+ };
9402
+ nextTree = [
9403
+ ...nextTree.map(
9404
+ (child) => group.childNodeIds.includes(child.id) ? { ...child, parentId: id, order: child.order + 1e-3 } : child
9405
+ ),
9406
+ node
9407
+ ];
9408
+ byId.set(id, node);
9409
+ }
9410
+ return normalizeDocumentSourceTreePaths(nextTree);
9411
+ }
9412
+ function sourceTreeToOutline(sourceTree) {
9413
+ const byParent = /* @__PURE__ */ new Map();
9414
+ for (const node of sourceTree.filter((item) => item.kind !== "document")) {
9415
+ const group = byParent.get(node.parentId) ?? [];
9416
+ group.push(node);
9417
+ byParent.set(node.parentId, group);
9418
+ }
9419
+ const root = sourceTree.find((node) => node.kind === "document");
9420
+ const visit = (node) => ({
9421
+ id: node.id,
9422
+ title: node.title,
9423
+ type: node.kind,
9424
+ label: node.kind,
9425
+ pageStart: node.pageStart,
9426
+ pageEnd: node.pageEnd,
9427
+ excerpt: node.textExcerpt,
9428
+ content: node.textExcerpt,
9429
+ sourceSpanIds: node.sourceSpanIds,
9430
+ sourceTextHash: node.sourceSpanIds.join(":") || void 0,
9431
+ interpretationLabels: [node.kind],
9432
+ children: (byParent.get(node.id) ?? []).map(visit)
9433
+ });
9434
+ return (byParent.get(root?.id) ?? []).map(visit);
9435
+ }
9436
+ function valueOf(profile, key) {
9437
+ const value = profile[key];
9438
+ return value && typeof value === "object" && !Array.isArray(value) && "value" in value ? String(value.value) : void 0;
9439
+ }
9440
+ function materializeDocument(params) {
9441
+ const profile = params.operationalProfile;
9442
+ const policyNumber = valueOf(profile, "policyNumber") ?? "Unknown";
9443
+ const insuredName = valueOf(profile, "namedInsured") ?? "Unknown";
9444
+ const carrier = valueOf(profile, "insurer") ?? "Unknown";
9445
+ const effectiveDate = valueOf(profile, "effectiveDate") ?? "Unknown";
9446
+ const expirationDate = valueOf(profile, "expirationDate") ?? "Unknown";
9447
+ const premium = valueOf(profile, "premium");
9448
+ const coverages = profile.coverages.map((coverage) => ({
9449
+ name: coverage.name,
9450
+ coverageCode: coverage.coverageCode,
9451
+ limit: coverage.limit,
9452
+ deductible: coverage.deductible,
9453
+ premium: coverage.premium,
9454
+ formNumber: coverage.formNumber,
9455
+ sectionRef: coverage.sectionRef,
9456
+ sourceSpanIds: coverage.sourceSpanIds,
9457
+ documentNodeId: coverage.sourceNodeIds[0],
9458
+ originalContent: [coverage.name, coverage.limit, coverage.deductible, coverage.premium].filter(Boolean).join(" | ")
9459
+ }));
9460
+ const documentOutline = sourceTreeToOutline(params.sourceTree);
9461
+ const documentMetadata = {
9462
+ sourceTreeVersion: "v3",
9463
+ sourceTreeCanonical: true,
9464
+ tableOfContents: documentOutline.map((node) => ({
9465
+ title: node.title,
9466
+ pageStart: node.pageStart,
9467
+ pageEnd: node.pageEnd,
9468
+ documentNodeId: node.id,
9469
+ sourceSpanIds: node.sourceSpanIds
9470
+ })),
9471
+ agentGuidance: [
9472
+ {
9473
+ kind: "source_tree",
9474
+ title: "Use the source tree as canonical evidence",
9475
+ detail: "Operational fields are projections from source nodes and source spans. Use source nodes for policy wording and exact provenance."
9476
+ }
9477
+ ]
9478
+ };
9479
+ const summary = [
9480
+ carrier !== "Unknown" ? carrier : void 0,
9481
+ policyNumber !== "Unknown" ? `#${policyNumber}` : void 0,
9482
+ insuredName !== "Unknown" ? `for ${insuredName}` : void 0,
9483
+ profile.coverageTypes.length ? `covering ${profile.coverageTypes.slice(0, 5).join(", ")}` : void 0
9484
+ ].filter(Boolean).join(" ");
9485
+ const base = {
9486
+ id: params.id,
9487
+ type: profile.documentType,
9488
+ carrier,
9489
+ security: carrier,
9490
+ insuredName,
9491
+ premium,
9492
+ policyTypes: profile.policyTypes,
9493
+ coverages,
9494
+ documentMetadata,
9495
+ documentOutline,
9496
+ declarations: {
9497
+ fields: [
9498
+ profile.policyNumber ? { field: "policyNumber", value: profile.policyNumber.value, sourceSpanIds: profile.policyNumber.sourceSpanIds } : void 0,
9499
+ profile.namedInsured ? { field: "namedInsured", value: profile.namedInsured.value, sourceSpanIds: profile.namedInsured.sourceSpanIds } : void 0,
9500
+ profile.insurer ? { field: "insurer", value: profile.insurer.value, sourceSpanIds: profile.insurer.sourceSpanIds } : void 0,
9501
+ profile.effectiveDate ? { field: "policyPeriodStart", value: profile.effectiveDate.value, sourceSpanIds: profile.effectiveDate.sourceSpanIds } : void 0,
9502
+ profile.expirationDate ? { field: "policyPeriodEnd", value: profile.expirationDate.value, sourceSpanIds: profile.expirationDate.sourceSpanIds } : void 0
9503
+ ].filter(Boolean)
9504
+ },
9505
+ supplementaryFacts: profile.endorsementSupport.map((item) => ({
9506
+ key: item.kind,
9507
+ value: item.summary,
9508
+ sourceSpanIds: item.sourceSpanIds,
9509
+ documentNodeId: item.sourceNodeIds[0]
9510
+ })),
9511
+ summary: summary || void 0
9512
+ };
9513
+ if (profile.documentType === "quote") {
9514
+ return {
9515
+ ...base,
9516
+ type: "quote",
9517
+ quoteNumber: policyNumber,
9518
+ proposedEffectiveDate: effectiveDate === "Unknown" ? void 0 : effectiveDate,
9519
+ proposedExpirationDate: expirationDate === "Unknown" ? void 0 : expirationDate
9520
+ };
9521
+ }
9522
+ return {
9523
+ ...base,
9524
+ type: "policy",
9525
+ policyNumber,
9526
+ effectiveDate,
9527
+ expirationDate,
9528
+ retroactiveDate: valueOf(profile, "retroactiveDate")
9529
+ };
9530
+ }
9531
+ async function runSourceTreeExtraction(params) {
9532
+ let sourceTree = buildDocumentSourceTree(params.sourceSpans, params.id);
9533
+ const warnings = [];
9534
+ let modelCalls = 0;
9535
+ let callsWithUsage = 0;
9536
+ let callsMissingUsage = 0;
9537
+ const tokenUsage = { inputTokens: 0, outputTokens: 0 };
9538
+ const performanceReport = { modelCalls: [], totalModelCallDurationMs: 0 };
9539
+ const localTrack = (usage, report) => {
9540
+ modelCalls += 1;
9541
+ if (usage) {
9542
+ callsWithUsage += 1;
9543
+ tokenUsage.inputTokens += usage.inputTokens;
9544
+ tokenUsage.outputTokens += usage.outputTokens;
9545
+ } else {
9546
+ callsMissingUsage += 1;
9547
+ }
9548
+ if (report) {
9549
+ performanceReport.modelCalls.push({ ...report, usage, usageReported: !!usage });
9550
+ if (report.durationMs != null) performanceReport.totalModelCallDurationMs += report.durationMs;
9551
+ }
9552
+ params.trackUsage(usage, report);
9553
+ };
9554
+ try {
9555
+ const budget = params.resolveBudget("extraction_source_tree", 4096);
9556
+ const startedAt = Date.now();
9557
+ const response = await safeGenerateObject(
9558
+ params.generateObject,
9559
+ {
9560
+ prompt: buildOrganizationPrompt(sourceTree),
9561
+ schema: SourceTreeOrganizationSchema,
9562
+ maxTokens: budget.maxTokens,
9563
+ taskKind: "extraction_source_tree",
9564
+ budgetDiagnostics: budget,
9565
+ providerOptions: { ...params.providerOptions, sourceSpans: params.sourceSpans }
9566
+ },
9567
+ {
9568
+ fallback: { labels: [], groups: [] },
9569
+ log: params.log
9570
+ }
9571
+ );
9572
+ localTrack(response.usage, {
9573
+ taskKind: "extraction_source_tree",
9574
+ label: "source_tree_organizer",
9575
+ maxTokens: budget.maxTokens,
9576
+ durationMs: Date.now() - startedAt
9577
+ });
9578
+ sourceTree = applyOrganization(sourceTree, response.object);
9579
+ } catch (error) {
9580
+ warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
9581
+ }
9582
+ const deterministicProfile = buildDeterministicOperationalProfile({
9583
+ sourceTree,
9584
+ sourceSpans: params.sourceSpans
9585
+ });
9586
+ let operationalProfile = deterministicProfile;
9587
+ try {
9588
+ const validNodeIds = new Set(sourceTree.map((node) => node.id));
9589
+ const validSpanIds = new Set(params.sourceSpans.map((span) => span.id));
9590
+ const budget = params.resolveBudget("extraction_operational_profile", 8192);
9591
+ const startedAt = Date.now();
9592
+ const response = await safeGenerateObject(
9593
+ params.generateObject,
9594
+ {
9595
+ prompt: buildOperationalProfilePrompt(sourceTree, deterministicProfile),
9596
+ schema: OperationalProfilePromptSchema,
9597
+ maxTokens: budget.maxTokens,
9598
+ taskKind: "extraction_operational_profile",
9599
+ budgetDiagnostics: budget,
9600
+ providerOptions: { ...params.providerOptions, sourceSpans: params.sourceSpans, sourceTree }
9601
+ },
9602
+ {
9603
+ fallback: deterministicProfile,
9604
+ log: params.log
9605
+ }
9606
+ );
9607
+ localTrack(response.usage, {
9608
+ taskKind: "extraction_operational_profile",
9609
+ label: "operational_profile",
9610
+ maxTokens: budget.maxTokens,
9611
+ durationMs: Date.now() - startedAt
9612
+ });
9613
+ operationalProfile = mergeOperationalProfile(
9614
+ deterministicProfile,
9615
+ response.object,
9616
+ validNodeIds,
9617
+ validSpanIds
9618
+ );
9619
+ } catch (error) {
9620
+ warnings.push(`Operational profile model pass failed; deterministic profile used (${error instanceof Error ? error.message : String(error)})`);
9621
+ }
9622
+ const document = materializeDocument({
9623
+ id: params.id,
9624
+ sourceTree,
9625
+ operationalProfile
9626
+ });
9627
+ return {
9628
+ sourceTree,
9629
+ sourceSpans: params.sourceSpans,
9630
+ sourceChunks: chunkSourceSpans(params.sourceSpans),
9631
+ operationalProfile,
9632
+ document,
9633
+ chunks: [],
9634
+ warnings: [...warnings, ...operationalProfile.warnings],
9635
+ tokenUsage,
9636
+ usageReporting: {
9637
+ modelCalls,
9638
+ callsWithUsage,
9639
+ callsMissingUsage
9640
+ },
9641
+ performanceReport
9642
+ };
9643
+ }
9644
+
8236
9645
  // src/extraction/coordinator.ts
8237
9646
  function createExtractor(config) {
8238
9647
  const {
@@ -8418,17 +9827,17 @@ ${span.text}` : span.text;
8418
9827
  const candidateSpans = spansForPageRange(spans, startPage, endPage).filter((span) => span.text.trim().length > 0).filter((span) => span.metadata?.sourceUnit === "section_candidate" || span.sectionId || span.text.length >= 160);
8419
9828
  return {
8420
9829
  sections: candidateSpans.map((span, index) => {
8421
- const pageStart = span.pageStart ?? span.location?.startPage ?? span.location?.page ?? startPage;
8422
- const pageEnd = span.pageEnd ?? span.location?.endPage ?? pageStart;
8423
- const title = span.sectionId ?? span.formNumber ?? firstHeadingLine(span.text) ?? `Policy text page ${pageStart}`;
9830
+ const pageStart2 = span.pageStart ?? span.location?.startPage ?? span.location?.page ?? startPage;
9831
+ const pageEnd2 = span.pageEnd ?? span.location?.endPage ?? pageStart2;
9832
+ const title = span.sectionId ?? span.formNumber ?? firstHeadingLine(span.text) ?? `Policy text page ${pageStart2}`;
8424
9833
  return {
8425
9834
  title,
8426
9835
  sectionNumber: span.formNumber,
8427
- pageStart,
8428
- pageEnd,
9836
+ pageStart: pageStart2,
9837
+ pageEnd: pageEnd2,
8429
9838
  type: inferSectionType(title, span.text),
8430
9839
  excerpt: span.text.slice(0, 240),
8431
- recordId: `section_index_${pageStart}_${index}`,
9840
+ recordId: `section_index_${pageStart2}_${index}`,
8432
9841
  sourceSpanIds: [span.id],
8433
9842
  sourceTextHash: span.textHash ?? sourceSpanTextHash(span.text)
8434
9843
  };
@@ -8567,6 +9976,51 @@ ${span.text}` : span.text;
8567
9976
  await sourceStore.addSourceChunks(sourceChunks);
8568
9977
  }
8569
9978
  }
9979
+ if (sourceSpans.length > 0) {
9980
+ onProgress?.("Building source-native document tree...");
9981
+ const v3 = await runSourceTreeExtraction({
9982
+ id,
9983
+ sourceSpans,
9984
+ generateObject,
9985
+ providerOptions: activeProviderOptions,
9986
+ resolveBudget,
9987
+ trackUsage,
9988
+ log
9989
+ });
9990
+ const reviewReport2 = {
9991
+ issues: v3.warnings.map((warning) => ({
9992
+ code: "source_tree_warning",
9993
+ severity: "warning",
9994
+ message: warning
9995
+ })),
9996
+ rounds: [],
9997
+ artifacts: [
9998
+ { kind: "source_tree", label: "Source Tree", itemCount: v3.sourceTree.length },
9999
+ { kind: "source_spans", label: "Source Spans", itemCount: v3.sourceSpans.length },
10000
+ { kind: "operational_profile", label: "Operational Profile", itemCount: v3.operationalProfile.coverages.length }
10001
+ ],
10002
+ reviewRoundRecords: [],
10003
+ formInventory: [],
10004
+ qualityGateStatus: v3.warnings.length > 0 ? "warning" : "passed"
10005
+ };
10006
+ if (shouldFailQualityGate(qualityGate, reviewReport2.qualityGateStatus)) {
10007
+ throw new Error("Extraction quality gate failed. See reviewReport for blocking issues.");
10008
+ }
10009
+ onProgress?.("Source-tree extraction complete.");
10010
+ return {
10011
+ document: v3.document,
10012
+ chunks: [],
10013
+ sourceSpans: v3.sourceSpans,
10014
+ sourceChunks: v3.sourceChunks,
10015
+ sourceTree: v3.sourceTree,
10016
+ operationalProfile: v3.operationalProfile,
10017
+ warnings: v3.warnings,
10018
+ tokenUsage: v3.tokenUsage,
10019
+ usageReporting: v3.usageReporting,
10020
+ performanceReport: v3.performanceReport,
10021
+ reviewReport: reviewReport2
10022
+ };
10023
+ }
8570
10024
  const pipelineCtx = createPipelineContext({
8571
10025
  id,
8572
10026
  onSave: onCheckpointSave,
@@ -9134,6 +10588,7 @@ ${pageText}`;
9134
10588
  }));
9135
10589
  onProgress?.("Assembling document...");
9136
10590
  const document = assembleDocument(id, documentType, memory);
10591
+ attachDocumentStructure({ document, pageAssignments, sourceSpans });
9137
10592
  await pipelineCtx.save("assemble", {
9138
10593
  id,
9139
10594
  pageCount,
@@ -9436,8 +10891,8 @@ Respond with JSON only:
9436
10891
  }`;
9437
10892
 
9438
10893
  // src/schemas/application.ts
9439
- var import_zod41 = require("zod");
9440
- var FieldTypeSchema = import_zod41.z.enum([
10894
+ var import_zod42 = require("zod");
10895
+ var FieldTypeSchema = import_zod42.z.enum([
9441
10896
  "text",
9442
10897
  "numeric",
9443
10898
  "currency",
@@ -9446,138 +10901,138 @@ var FieldTypeSchema = import_zod41.z.enum([
9446
10901
  "table",
9447
10902
  "declaration"
9448
10903
  ]);
9449
- var ApplicationFieldSchema = import_zod41.z.object({
9450
- id: import_zod41.z.string(),
9451
- label: import_zod41.z.string(),
9452
- section: import_zod41.z.string(),
10904
+ var ApplicationFieldSchema = import_zod42.z.object({
10905
+ id: import_zod42.z.string(),
10906
+ label: import_zod42.z.string(),
10907
+ section: import_zod42.z.string(),
9453
10908
  fieldType: FieldTypeSchema,
9454
- required: import_zod41.z.boolean(),
9455
- options: import_zod41.z.array(import_zod41.z.string()).optional(),
9456
- columns: import_zod41.z.array(import_zod41.z.string()).optional(),
9457
- requiresExplanationIfYes: import_zod41.z.boolean().optional(),
9458
- condition: import_zod41.z.object({
9459
- dependsOn: import_zod41.z.string(),
9460
- whenValue: import_zod41.z.string()
10909
+ required: import_zod42.z.boolean(),
10910
+ options: import_zod42.z.array(import_zod42.z.string()).optional(),
10911
+ columns: import_zod42.z.array(import_zod42.z.string()).optional(),
10912
+ requiresExplanationIfYes: import_zod42.z.boolean().optional(),
10913
+ condition: import_zod42.z.object({
10914
+ dependsOn: import_zod42.z.string(),
10915
+ whenValue: import_zod42.z.string()
9461
10916
  }).optional(),
9462
- value: import_zod41.z.string().optional(),
9463
- source: import_zod41.z.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
9464
- confidence: import_zod41.z.enum(["confirmed", "high", "medium", "low"]).optional(),
9465
- sourceSpanIds: import_zod41.z.array(import_zod41.z.string()).optional().describe("Stable source spans that support the field value or field anchor"),
9466
- userSourceSpanIds: import_zod41.z.array(import_zod41.z.string()).optional().describe("Message or attachment spans that support user-provided values"),
9467
- pageNumber: import_zod41.z.number().int().positive().optional().describe("Application page where the field label or anchor appears"),
9468
- fieldAnchorId: import_zod41.z.string().optional().describe("Stable field anchor ID derived from page, section, label, and form metadata"),
9469
- acroFormName: import_zod41.z.string().optional().describe("Native PDF AcroForm field name when available"),
9470
- validationStatus: import_zod41.z.enum(["valid", "needs_review", "unsupported", "missing"]).optional()
9471
- });
9472
- var ApplicationClassifyResultSchema = import_zod41.z.object({
9473
- isApplication: import_zod41.z.boolean(),
9474
- confidence: import_zod41.z.number().min(0).max(1),
9475
- applicationType: import_zod41.z.string().nullable()
9476
- });
9477
- var FieldExtractionResultSchema = import_zod41.z.object({
9478
- fields: import_zod41.z.array(ApplicationFieldSchema)
9479
- });
9480
- var AutoFillMatchSchema = import_zod41.z.object({
9481
- fieldId: import_zod41.z.string(),
9482
- value: import_zod41.z.string(),
9483
- confidence: import_zod41.z.enum(["confirmed"]),
9484
- contextKey: import_zod41.z.string()
9485
- });
9486
- var AutoFillResultSchema = import_zod41.z.object({
9487
- matches: import_zod41.z.array(AutoFillMatchSchema)
9488
- });
9489
- var QuestionBatchResultSchema = import_zod41.z.object({
9490
- batches: import_zod41.z.array(import_zod41.z.array(import_zod41.z.string()).describe("Array of field IDs in this batch"))
9491
- });
9492
- var LookupRequestSchema = import_zod41.z.object({
9493
- type: import_zod41.z.string().describe("Type of lookup: 'records', 'website', 'policy'"),
9494
- description: import_zod41.z.string(),
9495
- url: import_zod41.z.string().optional(),
9496
- targetFieldIds: import_zod41.z.array(import_zod41.z.string())
9497
- });
9498
- var ReplyIntentSchema = import_zod41.z.object({
9499
- primaryIntent: import_zod41.z.enum(["answers_only", "question", "lookup_request", "mixed"]),
9500
- hasAnswers: import_zod41.z.boolean(),
9501
- questionText: import_zod41.z.string().optional(),
9502
- questionFieldIds: import_zod41.z.array(import_zod41.z.string()).optional(),
9503
- lookupRequests: import_zod41.z.array(LookupRequestSchema).optional()
9504
- });
9505
- var ParsedAnswerSchema = import_zod41.z.object({
9506
- fieldId: import_zod41.z.string(),
9507
- value: import_zod41.z.string(),
9508
- explanation: import_zod41.z.string().optional()
9509
- });
9510
- var AnswerParsingResultSchema = import_zod41.z.object({
9511
- answers: import_zod41.z.array(ParsedAnswerSchema),
9512
- unanswered: import_zod41.z.array(import_zod41.z.string()).describe("Field IDs that were not answered")
9513
- });
9514
- var LookupFillSchema = import_zod41.z.object({
9515
- fieldId: import_zod41.z.string(),
9516
- value: import_zod41.z.string(),
9517
- source: import_zod41.z.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'"),
9518
- sourceSpanIds: import_zod41.z.array(import_zod41.z.string()).optional()
9519
- });
9520
- var LookupFillResultSchema = import_zod41.z.object({
9521
- fills: import_zod41.z.array(LookupFillSchema),
9522
- unfillable: import_zod41.z.array(import_zod41.z.string()),
9523
- explanation: import_zod41.z.string().optional()
9524
- });
9525
- var FlatPdfPlacementSchema = import_zod41.z.object({
9526
- fieldId: import_zod41.z.string(),
9527
- page: import_zod41.z.number(),
9528
- x: import_zod41.z.number().describe("Percentage from left edge (0-100)"),
9529
- y: import_zod41.z.number().describe("Percentage from top edge (0-100)"),
9530
- text: import_zod41.z.string(),
9531
- fontSize: import_zod41.z.number().optional(),
9532
- isCheckmark: import_zod41.z.boolean().optional()
9533
- });
9534
- var AcroFormMappingSchema = import_zod41.z.object({
9535
- fieldId: import_zod41.z.string(),
9536
- acroFormName: import_zod41.z.string(),
9537
- value: import_zod41.z.string()
9538
- });
9539
- var QualityGateStatusSchema = import_zod41.z.enum(["passed", "warning", "failed"]);
9540
- var QualitySeveritySchema = import_zod41.z.enum(["info", "warning", "blocking"]);
9541
- var ApplicationQualityIssueSchema = import_zod41.z.object({
9542
- code: import_zod41.z.string(),
10917
+ value: import_zod42.z.string().optional(),
10918
+ source: import_zod42.z.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
10919
+ confidence: import_zod42.z.enum(["confirmed", "high", "medium", "low"]).optional(),
10920
+ sourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional().describe("Stable source spans that support the field value or field anchor"),
10921
+ userSourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional().describe("Message or attachment spans that support user-provided values"),
10922
+ pageNumber: import_zod42.z.number().int().positive().optional().describe("Application page where the field label or anchor appears"),
10923
+ fieldAnchorId: import_zod42.z.string().optional().describe("Stable field anchor ID derived from page, section, label, and form metadata"),
10924
+ acroFormName: import_zod42.z.string().optional().describe("Native PDF AcroForm field name when available"),
10925
+ validationStatus: import_zod42.z.enum(["valid", "needs_review", "unsupported", "missing"]).optional()
10926
+ });
10927
+ var ApplicationClassifyResultSchema = import_zod42.z.object({
10928
+ isApplication: import_zod42.z.boolean(),
10929
+ confidence: import_zod42.z.number().min(0).max(1),
10930
+ applicationType: import_zod42.z.string().nullable()
10931
+ });
10932
+ var FieldExtractionResultSchema = import_zod42.z.object({
10933
+ fields: import_zod42.z.array(ApplicationFieldSchema)
10934
+ });
10935
+ var AutoFillMatchSchema = import_zod42.z.object({
10936
+ fieldId: import_zod42.z.string(),
10937
+ value: import_zod42.z.string(),
10938
+ confidence: import_zod42.z.enum(["confirmed"]),
10939
+ contextKey: import_zod42.z.string()
10940
+ });
10941
+ var AutoFillResultSchema = import_zod42.z.object({
10942
+ matches: import_zod42.z.array(AutoFillMatchSchema)
10943
+ });
10944
+ var QuestionBatchResultSchema = import_zod42.z.object({
10945
+ batches: import_zod42.z.array(import_zod42.z.array(import_zod42.z.string()).describe("Array of field IDs in this batch"))
10946
+ });
10947
+ var LookupRequestSchema = import_zod42.z.object({
10948
+ type: import_zod42.z.string().describe("Type of lookup: 'records', 'website', 'policy'"),
10949
+ description: import_zod42.z.string(),
10950
+ url: import_zod42.z.string().optional(),
10951
+ targetFieldIds: import_zod42.z.array(import_zod42.z.string())
10952
+ });
10953
+ var ReplyIntentSchema = import_zod42.z.object({
10954
+ primaryIntent: import_zod42.z.enum(["answers_only", "question", "lookup_request", "mixed"]),
10955
+ hasAnswers: import_zod42.z.boolean(),
10956
+ questionText: import_zod42.z.string().optional(),
10957
+ questionFieldIds: import_zod42.z.array(import_zod42.z.string()).optional(),
10958
+ lookupRequests: import_zod42.z.array(LookupRequestSchema).optional()
10959
+ });
10960
+ var ParsedAnswerSchema = import_zod42.z.object({
10961
+ fieldId: import_zod42.z.string(),
10962
+ value: import_zod42.z.string(),
10963
+ explanation: import_zod42.z.string().optional()
10964
+ });
10965
+ var AnswerParsingResultSchema = import_zod42.z.object({
10966
+ answers: import_zod42.z.array(ParsedAnswerSchema),
10967
+ unanswered: import_zod42.z.array(import_zod42.z.string()).describe("Field IDs that were not answered")
10968
+ });
10969
+ var LookupFillSchema = import_zod42.z.object({
10970
+ fieldId: import_zod42.z.string(),
10971
+ value: import_zod42.z.string(),
10972
+ source: import_zod42.z.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'"),
10973
+ sourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional()
10974
+ });
10975
+ var LookupFillResultSchema = import_zod42.z.object({
10976
+ fills: import_zod42.z.array(LookupFillSchema),
10977
+ unfillable: import_zod42.z.array(import_zod42.z.string()),
10978
+ explanation: import_zod42.z.string().optional()
10979
+ });
10980
+ var FlatPdfPlacementSchema = import_zod42.z.object({
10981
+ fieldId: import_zod42.z.string(),
10982
+ page: import_zod42.z.number(),
10983
+ x: import_zod42.z.number().describe("Percentage from left edge (0-100)"),
10984
+ y: import_zod42.z.number().describe("Percentage from top edge (0-100)"),
10985
+ text: import_zod42.z.string(),
10986
+ fontSize: import_zod42.z.number().optional(),
10987
+ isCheckmark: import_zod42.z.boolean().optional()
10988
+ });
10989
+ var AcroFormMappingSchema = import_zod42.z.object({
10990
+ fieldId: import_zod42.z.string(),
10991
+ acroFormName: import_zod42.z.string(),
10992
+ value: import_zod42.z.string()
10993
+ });
10994
+ var QualityGateStatusSchema = import_zod42.z.enum(["passed", "warning", "failed"]);
10995
+ var QualitySeveritySchema = import_zod42.z.enum(["info", "warning", "blocking"]);
10996
+ var ApplicationQualityIssueSchema = import_zod42.z.object({
10997
+ code: import_zod42.z.string(),
9543
10998
  severity: QualitySeveritySchema,
9544
- message: import_zod41.z.string(),
9545
- fieldId: import_zod41.z.string().optional()
10999
+ message: import_zod42.z.string(),
11000
+ fieldId: import_zod42.z.string().optional()
9546
11001
  });
9547
- var ApplicationQualityRoundSchema = import_zod41.z.object({
9548
- round: import_zod41.z.number(),
9549
- kind: import_zod41.z.string(),
11002
+ var ApplicationQualityRoundSchema = import_zod42.z.object({
11003
+ round: import_zod42.z.number(),
11004
+ kind: import_zod42.z.string(),
9550
11005
  status: QualityGateStatusSchema,
9551
- summary: import_zod41.z.string().optional()
11006
+ summary: import_zod42.z.string().optional()
9552
11007
  });
9553
- var ApplicationQualityArtifactSchema = import_zod41.z.object({
9554
- kind: import_zod41.z.string(),
9555
- label: import_zod41.z.string().optional(),
9556
- itemCount: import_zod41.z.number().optional()
11008
+ var ApplicationQualityArtifactSchema = import_zod42.z.object({
11009
+ kind: import_zod42.z.string(),
11010
+ label: import_zod42.z.string().optional(),
11011
+ itemCount: import_zod42.z.number().optional()
9557
11012
  });
9558
- var ApplicationEmailReviewSchema = import_zod41.z.object({
9559
- issues: import_zod41.z.array(ApplicationQualityIssueSchema),
11013
+ var ApplicationEmailReviewSchema = import_zod42.z.object({
11014
+ issues: import_zod42.z.array(ApplicationQualityIssueSchema),
9560
11015
  qualityGateStatus: QualityGateStatusSchema
9561
11016
  });
9562
- var ApplicationQualityReportSchema = import_zod41.z.object({
9563
- issues: import_zod41.z.array(ApplicationQualityIssueSchema),
9564
- rounds: import_zod41.z.array(ApplicationQualityRoundSchema).optional(),
9565
- artifacts: import_zod41.z.array(ApplicationQualityArtifactSchema).optional(),
11017
+ var ApplicationQualityReportSchema = import_zod42.z.object({
11018
+ issues: import_zod42.z.array(ApplicationQualityIssueSchema),
11019
+ rounds: import_zod42.z.array(ApplicationQualityRoundSchema).optional(),
11020
+ artifacts: import_zod42.z.array(ApplicationQualityArtifactSchema).optional(),
9566
11021
  emailReview: ApplicationEmailReviewSchema.optional(),
9567
11022
  qualityGateStatus: QualityGateStatusSchema
9568
11023
  });
9569
- var ApplicationStateSchema = import_zod41.z.object({
9570
- id: import_zod41.z.string(),
9571
- pdfBase64: import_zod41.z.string().optional().describe("Original PDF, omitted after extraction"),
9572
- title: import_zod41.z.string().optional(),
9573
- applicationType: import_zod41.z.string().nullable().optional(),
9574
- fields: import_zod41.z.array(ApplicationFieldSchema),
9575
- batches: import_zod41.z.array(import_zod41.z.array(import_zod41.z.string())).optional(),
9576
- currentBatchIndex: import_zod41.z.number().default(0),
11024
+ var ApplicationStateSchema = import_zod42.z.object({
11025
+ id: import_zod42.z.string(),
11026
+ pdfBase64: import_zod42.z.string().optional().describe("Original PDF, omitted after extraction"),
11027
+ title: import_zod42.z.string().optional(),
11028
+ applicationType: import_zod42.z.string().nullable().optional(),
11029
+ fields: import_zod42.z.array(ApplicationFieldSchema),
11030
+ batches: import_zod42.z.array(import_zod42.z.array(import_zod42.z.string())).optional(),
11031
+ currentBatchIndex: import_zod42.z.number().default(0),
9577
11032
  qualityReport: ApplicationQualityReportSchema.optional(),
9578
- status: import_zod41.z.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
9579
- createdAt: import_zod41.z.number(),
9580
- updatedAt: import_zod41.z.number()
11033
+ status: import_zod42.z.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
11034
+ createdAt: import_zod42.z.number(),
11035
+ updatedAt: import_zod42.z.number()
9581
11036
  });
9582
11037
 
9583
11038
  // src/application/agents/classifier.ts
@@ -10932,104 +12387,106 @@ Respond with the final answer, deduplicated citations array, overall confidence
10932
12387
  }
10933
12388
 
10934
12389
  // src/schemas/query.ts
10935
- var import_zod42 = require("zod");
10936
- var QueryIntentSchema = import_zod42.z.enum([
12390
+ var import_zod43 = require("zod");
12391
+ var QueryIntentSchema = import_zod43.z.enum([
10937
12392
  "policy_question",
10938
12393
  "coverage_comparison",
10939
12394
  "document_search",
10940
12395
  "claims_inquiry",
10941
12396
  "general_knowledge"
10942
12397
  ]);
10943
- var QueryAttachmentKindSchema = import_zod42.z.enum(["image", "pdf", "text"]);
10944
- var QueryAttachmentSchema = import_zod42.z.object({
10945
- id: import_zod42.z.string().optional().describe("Optional stable attachment ID from the caller"),
12398
+ var QueryAttachmentKindSchema = import_zod43.z.enum(["image", "pdf", "text"]);
12399
+ var QueryAttachmentSchema = import_zod43.z.object({
12400
+ id: import_zod43.z.string().optional().describe("Optional stable attachment ID from the caller"),
10946
12401
  kind: QueryAttachmentKindSchema,
10947
- name: import_zod42.z.string().optional().describe("Original filename or user-facing label"),
10948
- mimeType: import_zod42.z.string().optional().describe("MIME type such as image/jpeg or application/pdf"),
10949
- base64: import_zod42.z.string().optional().describe("Base64-encoded file content for image/pdf attachments"),
10950
- text: import_zod42.z.string().optional().describe("Plain-text attachment content when available"),
10951
- description: import_zod42.z.string().optional().describe("Caller-provided description of the attachment")
12402
+ name: import_zod43.z.string().optional().describe("Original filename or user-facing label"),
12403
+ mimeType: import_zod43.z.string().optional().describe("MIME type such as image/jpeg or application/pdf"),
12404
+ base64: import_zod43.z.string().optional().describe("Base64-encoded file content for image/pdf attachments"),
12405
+ text: import_zod43.z.string().optional().describe("Plain-text attachment content when available"),
12406
+ description: import_zod43.z.string().optional().describe("Caller-provided description of the attachment")
10952
12407
  });
10953
- var QueryRetrievalModeSchema = import_zod42.z.enum([
12408
+ var QueryRetrievalModeSchema = import_zod43.z.enum([
10954
12409
  "graph_only",
10955
12410
  "source_rag",
10956
12411
  "long_context",
10957
12412
  "hybrid"
10958
12413
  ]);
10959
- var SubQuestionSchema = import_zod42.z.object({
10960
- question: import_zod42.z.string().describe("Atomic sub-question to retrieve and answer independently"),
12414
+ var SubQuestionSchema = import_zod43.z.object({
12415
+ question: import_zod43.z.string().describe("Atomic sub-question to retrieve and answer independently"),
10961
12416
  intent: QueryIntentSchema,
10962
- chunkTypes: import_zod42.z.array(import_zod42.z.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
10963
- documentFilters: import_zod42.z.object({
10964
- type: import_zod42.z.enum(["policy", "quote"]).optional(),
10965
- carrier: import_zod42.z.string().optional(),
10966
- insuredName: import_zod42.z.string().optional(),
10967
- policyNumber: import_zod42.z.string().optional(),
10968
- quoteNumber: import_zod42.z.string().optional(),
10969
- policyTypes: import_zod42.z.array(PolicyTypeSchema).optional().describe("Filter by policy type (e.g. homeowners_ho3, renters_ho4, pet) to avoid mixing up similar policies")
12417
+ chunkTypes: import_zod43.z.array(import_zod43.z.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
12418
+ documentFilters: import_zod43.z.object({
12419
+ type: import_zod43.z.enum(["policy", "quote"]).optional(),
12420
+ carrier: import_zod43.z.string().optional(),
12421
+ insuredName: import_zod43.z.string().optional(),
12422
+ policyNumber: import_zod43.z.string().optional(),
12423
+ quoteNumber: import_zod43.z.string().optional(),
12424
+ policyTypes: import_zod43.z.array(PolicyTypeSchema).optional().describe("Filter by policy type (e.g. homeowners_ho3, renters_ho4, pet) to avoid mixing up similar policies")
10970
12425
  }).optional().describe("Structured filters to narrow document lookup")
10971
12426
  });
10972
- var QueryClassifyResultSchema = import_zod42.z.object({
12427
+ var QueryClassifyResultSchema = import_zod43.z.object({
10973
12428
  intent: QueryIntentSchema,
10974
- subQuestions: import_zod42.z.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
10975
- requiresDocumentLookup: import_zod42.z.boolean().describe("Whether structured document lookup is needed"),
10976
- requiresChunkSearch: import_zod42.z.boolean().describe("Whether semantic chunk search is needed"),
10977
- requiresConversationHistory: import_zod42.z.boolean().describe("Whether conversation history is relevant"),
12429
+ subQuestions: import_zod43.z.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
12430
+ requiresDocumentLookup: import_zod43.z.boolean().describe("Whether structured document lookup is needed"),
12431
+ requiresChunkSearch: import_zod43.z.boolean().describe("Whether semantic chunk search is needed"),
12432
+ requiresConversationHistory: import_zod43.z.boolean().describe("Whether conversation history is relevant"),
10978
12433
  retrievalMode: QueryRetrievalModeSchema.optional().describe("Preferred retrieval strategy for the query when source-span retrieval is available")
10979
12434
  });
10980
- var EvidenceItemSchema = import_zod42.z.object({
10981
- source: import_zod42.z.enum(["chunk", "document", "conversation", "attachment", "source_span"]),
10982
- chunkId: import_zod42.z.string().optional(),
10983
- sourceSpanId: import_zod42.z.string().optional(),
10984
- documentId: import_zod42.z.string().optional(),
10985
- turnId: import_zod42.z.string().optional(),
10986
- attachmentId: import_zod42.z.string().optional(),
10987
- text: import_zod42.z.string().describe("Text excerpt from the source"),
10988
- relevance: import_zod42.z.number().min(0).max(1),
12435
+ var EvidenceItemSchema = import_zod43.z.object({
12436
+ source: import_zod43.z.enum(["chunk", "document", "conversation", "attachment", "source_span", "source_node"]),
12437
+ chunkId: import_zod43.z.string().optional(),
12438
+ sourceNodeId: import_zod43.z.string().optional(),
12439
+ sourceSpanId: import_zod43.z.string().optional(),
12440
+ documentId: import_zod43.z.string().optional(),
12441
+ turnId: import_zod43.z.string().optional(),
12442
+ attachmentId: import_zod43.z.string().optional(),
12443
+ text: import_zod43.z.string().describe("Text excerpt from the source"),
12444
+ relevance: import_zod43.z.number().min(0).max(1),
10989
12445
  retrievalMode: QueryRetrievalModeSchema.optional(),
10990
12446
  sourceLocation: SourceSpanLocationSchema.optional(),
10991
- metadata: import_zod42.z.array(import_zod42.z.object({ key: import_zod42.z.string(), value: import_zod42.z.string() })).optional()
10992
- });
10993
- var AttachmentInterpretationSchema = import_zod42.z.object({
10994
- summary: import_zod42.z.string().describe("Concise summary of what the attachment shows or contains"),
10995
- extractedFacts: import_zod42.z.array(import_zod42.z.string()).describe("Specific observable or document facts grounded in the attachment"),
10996
- recommendedFocus: import_zod42.z.array(import_zod42.z.string()).describe("Important details to incorporate when answering follow-up questions"),
10997
- confidence: import_zod42.z.number().min(0).max(1)
10998
- });
10999
- var RetrievalResultSchema = import_zod42.z.object({
11000
- subQuestion: import_zod42.z.string(),
11001
- evidence: import_zod42.z.array(EvidenceItemSchema)
11002
- });
11003
- var CitationSchema = import_zod42.z.object({
11004
- index: import_zod42.z.number().describe("Citation number [1], [2], etc."),
11005
- chunkId: import_zod42.z.string().optional().describe("Source chunk ID, e.g. doc-123:coverage:2"),
11006
- sourceSpanId: import_zod42.z.string().optional().describe("Precise source span ID when available"),
11007
- documentId: import_zod42.z.string(),
11008
- documentType: import_zod42.z.enum(["policy", "quote"]).optional(),
11009
- field: import_zod42.z.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
11010
- quote: import_zod42.z.string().describe("Exact text from source that supports the claim"),
11011
- relevance: import_zod42.z.number().min(0).max(1),
12447
+ metadata: import_zod43.z.array(import_zod43.z.object({ key: import_zod43.z.string(), value: import_zod43.z.string() })).optional()
12448
+ });
12449
+ var AttachmentInterpretationSchema = import_zod43.z.object({
12450
+ summary: import_zod43.z.string().describe("Concise summary of what the attachment shows or contains"),
12451
+ extractedFacts: import_zod43.z.array(import_zod43.z.string()).describe("Specific observable or document facts grounded in the attachment"),
12452
+ recommendedFocus: import_zod43.z.array(import_zod43.z.string()).describe("Important details to incorporate when answering follow-up questions"),
12453
+ confidence: import_zod43.z.number().min(0).max(1)
12454
+ });
12455
+ var RetrievalResultSchema = import_zod43.z.object({
12456
+ subQuestion: import_zod43.z.string(),
12457
+ evidence: import_zod43.z.array(EvidenceItemSchema)
12458
+ });
12459
+ var CitationSchema = import_zod43.z.object({
12460
+ index: import_zod43.z.number().describe("Citation number [1], [2], etc."),
12461
+ chunkId: import_zod43.z.string().optional().describe("Source chunk ID, e.g. doc-123:coverage:2"),
12462
+ sourceNodeId: import_zod43.z.string().optional().describe("Source tree node ID when available"),
12463
+ sourceSpanId: import_zod43.z.string().optional().describe("Precise source span ID when available"),
12464
+ documentId: import_zod43.z.string(),
12465
+ documentType: import_zod43.z.enum(["policy", "quote"]).optional(),
12466
+ field: import_zod43.z.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
12467
+ quote: import_zod43.z.string().describe("Exact text from source that supports the claim"),
12468
+ relevance: import_zod43.z.number().min(0).max(1),
11012
12469
  retrievalMode: QueryRetrievalModeSchema.optional(),
11013
12470
  sourceLocation: SourceSpanLocationSchema.optional()
11014
12471
  });
11015
- var SubAnswerSchema = import_zod42.z.object({
11016
- subQuestion: import_zod42.z.string(),
11017
- answer: import_zod42.z.string(),
11018
- citations: import_zod42.z.array(CitationSchema),
11019
- confidence: import_zod42.z.number().min(0).max(1),
11020
- needsMoreContext: import_zod42.z.boolean().describe("True if evidence was insufficient to answer fully")
11021
- });
11022
- var VerifyResultSchema = import_zod42.z.object({
11023
- approved: import_zod42.z.boolean().describe("Whether all sub-answers are adequately grounded"),
11024
- issues: import_zod42.z.array(import_zod42.z.string()).describe("Specific grounding or consistency issues found"),
11025
- retrySubQuestions: import_zod42.z.array(import_zod42.z.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
11026
- });
11027
- var QueryResultSchema = import_zod42.z.object({
11028
- answer: import_zod42.z.string(),
11029
- citations: import_zod42.z.array(CitationSchema),
12472
+ var SubAnswerSchema = import_zod43.z.object({
12473
+ subQuestion: import_zod43.z.string(),
12474
+ answer: import_zod43.z.string(),
12475
+ citations: import_zod43.z.array(CitationSchema),
12476
+ confidence: import_zod43.z.number().min(0).max(1),
12477
+ needsMoreContext: import_zod43.z.boolean().describe("True if evidence was insufficient to answer fully")
12478
+ });
12479
+ var VerifyResultSchema = import_zod43.z.object({
12480
+ approved: import_zod43.z.boolean().describe("Whether all sub-answers are adequately grounded"),
12481
+ issues: import_zod43.z.array(import_zod43.z.string()).describe("Specific grounding or consistency issues found"),
12482
+ retrySubQuestions: import_zod43.z.array(import_zod43.z.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
12483
+ });
12484
+ var QueryResultSchema = import_zod43.z.object({
12485
+ answer: import_zod43.z.string(),
12486
+ citations: import_zod43.z.array(CitationSchema),
11030
12487
  intent: QueryIntentSchema,
11031
- confidence: import_zod42.z.number().min(0).max(1),
11032
- followUp: import_zod42.z.string().optional().describe("Suggested follow-up question if applicable")
12488
+ confidence: import_zod43.z.number().min(0).max(1),
12489
+ followUp: import_zod43.z.string().optional().describe("Suggested follow-up question if applicable")
11033
12490
  });
11034
12491
 
11035
12492
  // src/query/retriever.ts
@@ -11044,6 +12501,35 @@ async function retrieve(subQuestion, conversationId, config) {
11044
12501
  tasks.push(
11045
12502
  (async () => {
11046
12503
  try {
12504
+ const nodeResults = await sourceRetriever?.searchSourceNodes?.({
12505
+ question: subQuestion.question,
12506
+ limit: retrievalLimit,
12507
+ mode: retrievalMode
12508
+ }) ?? [];
12509
+ for (const result of nodeResults) {
12510
+ const hierarchyText = result.hierarchy.map((node) => `${node.path} ${node.title}: ${node.textExcerpt ?? node.description}`).join("\n");
12511
+ const spanText = result.spans.map((span) => `[source-span:${span.id}${span.pageStart ? ` p.${span.pageStart}` : ""}]
12512
+ ${span.text}`).join("\n\n");
12513
+ evidence.push({
12514
+ source: "source_node",
12515
+ sourceNodeId: result.node.id,
12516
+ sourceSpanId: result.spans[0]?.id,
12517
+ documentId: result.node.documentId,
12518
+ text: [hierarchyText, spanText].filter(Boolean).join("\n\n"),
12519
+ relevance: result.relevance,
12520
+ retrievalMode,
12521
+ sourceLocation: result.spans[0]?.location ?? (result.node.pageStart ? { page: result.node.pageStart } : void 0),
12522
+ metadata: [
12523
+ { key: "kind", value: result.node.kind },
12524
+ { key: "path", value: result.node.path },
12525
+ { key: "title", value: result.node.title },
12526
+ ...result.node.metadata ? recordToKVArray(Object.fromEntries(
12527
+ Object.entries(result.node.metadata).filter(([, value]) => typeof value === "string").map(([key, value]) => [key, value])
12528
+ )) : []
12529
+ ]
12530
+ });
12531
+ }
12532
+ if (nodeResults.length > 0) return;
11047
12533
  const sourceResults = await sourceRetriever?.searchSourceSpans({
11048
12534
  question: subQuestion.question,
11049
12535
  limit: retrievalLimit,
@@ -11063,7 +12549,7 @@ async function retrieve(subQuestion, conversationId, config) {
11063
12549
  });
11064
12550
  }
11065
12551
  } catch (e) {
11066
- await log?.(`Source span search failed for "${subQuestion.question}": ${e}`);
12552
+ await log?.(`Source tree search failed for "${subQuestion.question}": ${e}`);
11067
12553
  }
11068
12554
  })()
11069
12555
  );
@@ -11265,7 +12751,7 @@ Answer the sub-question based on the evidence above. For every factual claim, in
11265
12751
  async function reason(subQuestion, intent, evidence, config) {
11266
12752
  const { generateObject, providerOptions } = config;
11267
12753
  const evidenceText = evidence.map((e, i) => {
11268
- const sourceLabel = e.source === "source_span" ? `[source-span:${e.sourceSpanId}]` : e.source === "chunk" ? `[chunk:${e.chunkId}]` : e.source === "document" ? `[doc:${e.documentId}]` : e.source === "attachment" ? `[attachment:${e.attachmentId}]` : `[turn:${e.turnId}]`;
12754
+ const sourceLabel = e.source === "source_node" ? `[source-node:${e.sourceNodeId} source-span:${e.sourceSpanId ?? "none"}]` : e.source === "source_span" ? `[source-span:${e.sourceSpanId}]` : e.source === "chunk" ? `[chunk:${e.chunkId}]` : e.source === "document" ? `[doc:${e.documentId}]` : e.source === "attachment" ? `[attachment:${e.attachmentId}]` : `[turn:${e.turnId}]`;
11269
12755
  return `Evidence ${i + 1} ${sourceLabel} (relevance: ${e.relevance.toFixed(2)}):
11270
12756
  ${e.text}`;
11271
12757
  }).join("\n\n");
@@ -12067,7 +13553,7 @@ ${sa.answer}`).join("\n\n"),
12067
13553
  }
12068
13554
 
12069
13555
  // src/pce/index.ts
12070
- var import_zod43 = require("zod");
13556
+ var import_zod44 = require("zod");
12071
13557
 
12072
13558
  // src/prompts/pce/index.ts
12073
13559
  function buildPceNormalizePrompt(input) {
@@ -12101,11 +13587,11 @@ ${input.openQuestions.map((question) => `- ${question.id}${question.fieldPath ?
12101
13587
  }
12102
13588
 
12103
13589
  // src/pce/index.ts
12104
- var ReplyAnswersSchema = import_zod43.z.object({
12105
- answers: import_zod43.z.array(import_zod43.z.object({
12106
- questionId: import_zod43.z.string().optional(),
12107
- fieldPath: import_zod43.z.string().optional(),
12108
- answer: import_zod43.z.string()
13590
+ var ReplyAnswersSchema = import_zod44.z.object({
13591
+ answers: import_zod44.z.array(import_zod44.z.object({
13592
+ questionId: import_zod44.z.string().optional(),
13593
+ fieldPath: import_zod44.z.string().optional(),
13594
+ answer: import_zod44.z.string()
12109
13595
  }))
12110
13596
  });
12111
13597
  function createPceAgent(config = {}) {
@@ -12932,6 +14418,13 @@ var AGENT_TOOLS = [
12932
14418
  DeductibleTypeSchema,
12933
14419
  DefenseCostTreatmentSchema,
12934
14420
  DefinitionSchema,
14421
+ DocumentAgentGuidanceSchema,
14422
+ DocumentMetadataSchema,
14423
+ DocumentNodeSchema,
14424
+ DocumentPageMapEntrySchema,
14425
+ DocumentSourceNodeKindSchema,
14426
+ DocumentSourceNodeSchema,
14427
+ DocumentTableOfContentsEntrySchema,
12935
14428
  DocumentTypeSchema,
12936
14429
  DriverRecordSchema,
12937
14430
  DwellingDetailsSchema,
@@ -12986,6 +14479,9 @@ var AGENT_TOOLS = [
12986
14479
  MemorySourceStore,
12987
14480
  MissingInfoQuestionSchema,
12988
14481
  NamedInsuredSchema,
14482
+ OperationalCoverageLineSchema,
14483
+ OperationalEndorsementSupportSchema,
14484
+ OperationalPartySchema,
12989
14485
  PERSONAL_AUTO_USAGES,
12990
14486
  PET_SPECIES,
12991
14487
  PLATFORM_CONFIGS,
@@ -13015,6 +14511,7 @@ var AGENT_TOOLS = [
13015
14511
  PolicyChangeStatusSchema,
13016
14512
  PolicyConditionSchema,
13017
14513
  PolicyDocumentSchema,
14514
+ PolicyOperationalProfileSchema,
13018
14515
  PolicySectionTypeSchema,
13019
14516
  PolicyTermTypeSchema,
13020
14517
  PolicyTypeSchema,
@@ -13046,6 +14543,7 @@ var AGENT_TOOLS = [
13046
14543
  ScheduledItemCategorySchema,
13047
14544
  SectionSchema,
13048
14545
  SharedLimitSchema,
14546
+ SourceBackedValueSchema,
13049
14547
  SourceChunkSchema,
13050
14548
  SourceKindSchema,
13051
14549
  SourceSpanBBoxSchema,
@@ -13087,7 +14585,9 @@ var AGENT_TOOLS = [
13087
14585
  buildConfirmationSummaryPrompt,
13088
14586
  buildConversationMemoryGuidance,
13089
14587
  buildCoverageGapPrompt,
14588
+ buildDeterministicOperationalProfile,
13090
14589
  buildDoclingProviderOptions,
14590
+ buildDocumentSourceTree,
13091
14591
  buildFieldExplanationPrompt,
13092
14592
  buildFieldExtractionPrompt,
13093
14593
  buildFlatPdfMappingPrompt,
@@ -13136,9 +14636,11 @@ var AGENT_TOOLS = [
13136
14636
  getTemplate,
13137
14637
  isDoclingExtractionInput,
13138
14638
  isFileReference,
14639
+ mergeOperationalProfile,
13139
14640
  mergeQuestionAnswers,
13140
14641
  mergeSourceSpans,
13141
14642
  normalizeDoclingDocument,
14643
+ normalizeDocumentSourceTreePaths,
13142
14644
  normalizeForMatch,
13143
14645
  orderSourceEvidence,
13144
14646
  overlayTextOnPdf,