@claritylabs/cl-sdk 1.2.1 → 1.3.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
@@ -1009,7 +1009,8 @@ var EndorsementSchema = import_zod5.z.object({
1009
1009
  namedParties: import_zod5.z.array(EndorsementPartySchema).optional(),
1010
1010
  keyTerms: import_zod5.z.array(import_zod5.z.string()).optional(),
1011
1011
  premiumImpact: import_zod5.z.string().optional(),
1012
- content: import_zod5.z.string(),
1012
+ excerpt: import_zod5.z.string().optional(),
1013
+ content: import_zod5.z.string().optional(),
1013
1014
  pageStart: import_zod5.z.number(),
1014
1015
  pageEnd: import_zod5.z.number().optional(),
1015
1016
  recordId: import_zod5.z.string().optional(),
@@ -1622,7 +1623,10 @@ var SubsectionSchema = import_zod16.z.object({
1622
1623
  title: import_zod16.z.string(),
1623
1624
  sectionNumber: import_zod16.z.string().optional(),
1624
1625
  pageNumber: import_zod16.z.number().optional(),
1625
- content: import_zod16.z.string()
1626
+ excerpt: import_zod16.z.string().optional(),
1627
+ content: import_zod16.z.string().optional(),
1628
+ sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
1629
+ sourceTextHash: import_zod16.z.string().optional()
1626
1630
  });
1627
1631
  var SectionSchema = import_zod16.z.object({
1628
1632
  title: import_zod16.z.string(),
@@ -1631,7 +1635,8 @@ var SectionSchema = import_zod16.z.object({
1631
1635
  pageEnd: import_zod16.z.number().optional(),
1632
1636
  type: import_zod16.z.string(),
1633
1637
  coverageType: import_zod16.z.string().optional(),
1634
- content: import_zod16.z.string(),
1638
+ excerpt: import_zod16.z.string().optional(),
1639
+ content: import_zod16.z.string().optional(),
1635
1640
  subsections: import_zod16.z.array(SubsectionSchema).optional(),
1636
1641
  recordId: import_zod16.z.string().optional(),
1637
1642
  sourceSpanIds: import_zod16.z.array(import_zod16.z.string()).optional(),
@@ -3141,6 +3146,14 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
3141
3146
  maxTokens,
3142
3147
  taskKind,
3143
3148
  budgetDiagnostics,
3149
+ trace: {
3150
+ label: `${name} pages ${startPage}-${endPage}`,
3151
+ extractorName: name,
3152
+ startPage,
3153
+ endPage,
3154
+ phase: "extractor",
3155
+ sourceBacked: !!sourceContext
3156
+ },
3144
3157
  providerOptions: extractorProviderOptions
3145
3158
  })
3146
3159
  );
@@ -4006,21 +4019,30 @@ function collectContentFields(doc) {
4006
4019
  entries.push({ id: id++, path, text });
4007
4020
  }
4008
4021
  }
4022
+ function hasSourceBacking(record) {
4023
+ return Array.isArray(record.sourceSpanIds) && record.sourceSpanIds.length > 0 || !!record.sourceTextHash;
4024
+ }
4009
4025
  add("summary", doc.summary);
4010
4026
  if (doc.sections) {
4011
4027
  for (let i = 0; i < doc.sections.length; i++) {
4012
4028
  const s = doc.sections[i];
4013
- add(`sections[${i}].content`, s.content);
4029
+ if (!hasSourceBacking(s)) {
4030
+ add(`sections[${i}].content`, s.content);
4031
+ }
4014
4032
  if (s.subsections) {
4015
4033
  for (let j = 0; j < s.subsections.length; j++) {
4016
- add(`sections[${i}].subsections[${j}].content`, s.subsections[j].content);
4034
+ if (!hasSourceBacking(s.subsections[j])) {
4035
+ add(`sections[${i}].subsections[${j}].content`, s.subsections[j].content);
4036
+ }
4017
4037
  }
4018
4038
  }
4019
4039
  }
4020
4040
  }
4021
4041
  if (doc.endorsements) {
4022
4042
  for (let i = 0; i < doc.endorsements.length; i++) {
4023
- add(`endorsements[${i}].content`, doc.endorsements[i].content);
4043
+ if (!hasSourceBacking(doc.endorsements[i])) {
4044
+ add(`endorsements[${i}].content`, doc.endorsements[i].content);
4045
+ }
4024
4046
  }
4025
4047
  }
4026
4048
  if (doc.exclusions) {
@@ -4122,6 +4144,12 @@ async function formatDocumentContent(doc, generateText, options) {
4122
4144
  maxTokens: options?.maxTokens ?? 16384,
4123
4145
  taskKind: options?.taskKind,
4124
4146
  budgetDiagnostics: options?.budgetDiagnostics,
4147
+ trace: {
4148
+ label: `format content batch ${batchIdx + 1}/${batches.length}`,
4149
+ phase: "format",
4150
+ batchIndex: batchIdx + 1,
4151
+ batchCount: batches.length
4152
+ },
4125
4153
  providerOptions: options?.providerOptions
4126
4154
  })
4127
4155
  );
@@ -4196,7 +4224,7 @@ function chunkDocument(doc) {
4196
4224
  documentId: docId,
4197
4225
  type,
4198
4226
  text,
4199
- metadata: stringMetadata(metadata)
4227
+ metadata: stringMetadata({ evidenceKind: "structured_fact", ...metadata })
4200
4228
  });
4201
4229
  }
4202
4230
  pushChunk(
@@ -4475,16 +4503,29 @@ function chunkDocument(doc) {
4475
4503
  );
4476
4504
  });
4477
4505
  doc.endorsements?.forEach((end, i) => {
4506
+ const text = lines([
4507
+ `Endorsement: ${end.title}`,
4508
+ end.formNumber ? `Form: ${end.formNumber}` : null,
4509
+ end.editionDate ? `Edition: ${end.editionDate}` : null,
4510
+ `Type: ${end.endorsementType}`,
4511
+ end.effectiveDate ? `Effective Date: ${end.effectiveDate}` : null,
4512
+ end.affectedCoverageParts?.length ? `Affected Coverage Parts: ${end.affectedCoverageParts.join(", ")}` : null,
4513
+ end.keyTerms?.length ? `Key Terms: ${end.keyTerms.join("; ")}` : null,
4514
+ end.premiumImpact ? `Premium Impact: ${end.premiumImpact}` : null,
4515
+ end.excerpt ? `Excerpt: ${end.excerpt}` : null
4516
+ ]);
4517
+ if (!text.trim()) return;
4478
4518
  pushChunk(
4479
4519
  `endorsement:${i}`,
4480
4520
  "endorsement",
4481
- `Endorsement: ${end.title}
4482
- ${end.content}`.trim(),
4521
+ text,
4483
4522
  {
4484
4523
  endorsementType: end.endorsementType,
4485
4524
  formNumber: end.formNumber,
4486
4525
  pageStart: end.pageStart,
4487
4526
  pageEnd: end.pageEnd,
4527
+ sourceSpanIds: end.sourceSpanIds?.join(","),
4528
+ sourceTextHash: end.sourceTextHash,
4488
4529
  documentType: doc.type
4489
4530
  }
4490
4531
  );
@@ -4606,93 +4647,51 @@ ${declLines.join("\n")}`, declMeta);
4606
4647
  }
4607
4648
  doc.sections?.forEach((sec, i) => {
4608
4649
  const hasSubsections = sec.subsections && sec.subsections.length > 0;
4609
- const contentLength = sec.content.length;
4610
- if (hasSubsections) {
4611
- pushChunk(
4612
- `section:${i}`,
4613
- "section",
4614
- `Section: ${sec.title}
4615
- ${sec.content}`,
4616
- {
4617
- sectionType: sec.type,
4618
- sectionNumber: sec.sectionNumber,
4619
- pageStart: sec.pageStart,
4620
- pageEnd: sec.pageEnd,
4621
- documentType: doc.type,
4622
- hasSubsections: "true"
4623
- }
4624
- );
4625
- sec.subsections.forEach((sub, j) => {
4626
- pushChunk(
4627
- `section:${i}:sub:${j}`,
4628
- "section",
4629
- `${sec.title} > ${sub.title}
4630
- ${sub.content}`,
4631
- {
4632
- sectionType: sec.type,
4633
- parentSection: sec.title,
4634
- sectionNumber: sub.sectionNumber,
4635
- pageNumber: sub.pageNumber,
4636
- documentType: doc.type
4637
- }
4638
- );
4639
- });
4640
- } else if (contentLength > 2e3) {
4641
- const paragraphs = sec.content.split(/\n\n+/);
4642
- let currentChunk = "";
4643
- let chunkIndex = 0;
4644
- for (const para of paragraphs) {
4645
- if (currentChunk.length + para.length > 1e3 && currentChunk.length > 0) {
4646
- pushChunk(
4647
- `section:${i}:part:${chunkIndex}`,
4648
- "section",
4649
- `Section: ${sec.title} (part ${chunkIndex + 1})
4650
- ${currentChunk.trim()}`,
4651
- {
4652
- sectionType: sec.type,
4653
- sectionNumber: sec.sectionNumber,
4654
- pageStart: sec.pageStart,
4655
- pageEnd: sec.pageEnd,
4656
- documentType: doc.type,
4657
- partIndex: chunkIndex
4658
- }
4659
- );
4660
- currentChunk = "";
4661
- chunkIndex++;
4662
- }
4663
- currentChunk += (currentChunk ? "\n\n" : "") + para;
4664
- }
4665
- if (currentChunk.trim()) {
4666
- pushChunk(
4667
- `section:${i}:part:${chunkIndex}`,
4668
- "section",
4669
- `Section: ${sec.title} (part ${chunkIndex + 1})
4670
- ${currentChunk.trim()}`,
4671
- {
4672
- sectionType: sec.type,
4673
- sectionNumber: sec.sectionNumber,
4674
- pageStart: sec.pageStart,
4675
- pageEnd: sec.pageEnd,
4676
- documentType: doc.type,
4677
- partIndex: chunkIndex
4678
- }
4679
- );
4650
+ pushChunk(
4651
+ `section:${i}`,
4652
+ "section",
4653
+ lines([
4654
+ `Section: ${sec.title}`,
4655
+ `Type: ${sec.type}`,
4656
+ sec.sectionNumber ? `Section Number: ${sec.sectionNumber}` : null,
4657
+ `Pages: ${sec.pageStart}${sec.pageEnd ? `-${sec.pageEnd}` : ""}`,
4658
+ sec.excerpt ? `Excerpt: ${sec.excerpt}` : null,
4659
+ hasSubsections ? `Subsections: ${sec.subsections.map((sub) => sub.title).join(", ")}` : null
4660
+ ]),
4661
+ {
4662
+ evidenceKind: "navigation",
4663
+ sectionType: sec.type,
4664
+ sectionNumber: sec.sectionNumber,
4665
+ pageStart: sec.pageStart,
4666
+ pageEnd: sec.pageEnd,
4667
+ sourceSpanIds: sec.sourceSpanIds?.join(","),
4668
+ sourceTextHash: sec.sourceTextHash,
4669
+ documentType: doc.type,
4670
+ hasSubsections
4680
4671
  }
4681
- } else {
4672
+ );
4673
+ sec.subsections?.forEach((sub, j) => {
4682
4674
  pushChunk(
4683
- `section:${i}`,
4675
+ `section:${i}:sub:${j}`,
4684
4676
  "section",
4685
- `Section: ${sec.title}
4686
- ${sec.content}`,
4677
+ lines([
4678
+ `Section: ${sec.title} > ${sub.title}`,
4679
+ sub.sectionNumber ? `Section Number: ${sub.sectionNumber}` : null,
4680
+ sub.pageNumber ? `Page: ${sub.pageNumber}` : null,
4681
+ sub.excerpt ? `Excerpt: ${sub.excerpt}` : null
4682
+ ]),
4687
4683
  {
4684
+ evidenceKind: "navigation",
4688
4685
  sectionType: sec.type,
4689
- sectionNumber: sec.sectionNumber,
4690
- pageStart: sec.pageStart,
4691
- pageEnd: sec.pageEnd,
4686
+ parentSection: sec.title,
4687
+ sectionNumber: sub.sectionNumber,
4688
+ pageNumber: sub.pageNumber,
4689
+ sourceSpanIds: sub.sourceSpanIds?.join(","),
4690
+ sourceTextHash: sub.sourceTextHash,
4692
4691
  documentType: doc.type
4693
4692
  }
4694
4693
  );
4695
- }
4694
+ });
4696
4695
  });
4697
4696
  doc.locations?.forEach((loc, i) => {
4698
4697
  chunks.push({
@@ -6564,14 +6563,17 @@ var EndorsementsSchema = import_zod29.z.object({
6564
6563
  ).optional().describe("Named parties (additional insureds, loss payees, etc.)"),
6565
6564
  keyTerms: import_zod29.z.array(import_zod29.z.string()).optional().describe("Key terms or notable provisions in the endorsement"),
6566
6565
  premiumImpact: import_zod29.z.string().optional().describe("Additional premium or credit"),
6567
- content: import_zod29.z.string().describe("Full verbatim text of the endorsement"),
6566
+ excerpt: import_zod29.z.string().optional().describe("Short source excerpt, not full verbatim text"),
6567
+ content: import_zod29.z.string().optional().describe("Legacy fallback only; do not return full text when sourceSpanIds are available"),
6568
6568
  pageStart: import_zod29.z.number().describe("Starting page number of this endorsement"),
6569
- pageEnd: import_zod29.z.number().optional().describe("Ending page number of this endorsement")
6569
+ pageEnd: import_zod29.z.number().optional().describe("Ending page number of this endorsement"),
6570
+ sourceSpanIds: import_zod29.z.array(import_zod29.z.string()).optional().describe("Source span IDs grounding this endorsement"),
6571
+ sourceTextHash: import_zod29.z.string().optional().describe("Hash of the source text when available")
6570
6572
  })
6571
6573
  ).describe("All endorsements found in the document")
6572
6574
  });
6573
6575
  function buildEndorsementsPrompt() {
6574
- return `You are an expert insurance document analyst. Extract ALL endorsements from this document. Preserve original language verbatim.
6576
+ return `You are an expert insurance document analyst. Build a compact source-backed endorsement index for this document. Do not reproduce full endorsement language in the JSON output.
6575
6577
 
6576
6578
  For EACH endorsement, extract:
6577
6579
  - formNumber: the form identifier (e.g. "CG 21 47") \u2014 REQUIRED
@@ -6583,7 +6585,9 @@ For EACH endorsement, extract:
6583
6585
  - namedParties: for each party, extract name, role (additional_insured, loss_payee, mortgage_holder, certificate_holder, waiver_beneficiary, designated_person, other), relationship, and scope
6584
6586
  - keyTerms: notable provisions or key terms
6585
6587
  - premiumImpact: additional premium or credit if shown
6586
- - content: full verbatim text \u2014 REQUIRED
6588
+ - excerpt: short identifying source excerpt, capped at 300 characters
6589
+ - sourceSpanIds: source span IDs from the provided SOURCE SPANS that ground this endorsement
6590
+ - content: legacy fallback only; omit/null when sourceSpanIds are available
6587
6591
  - pageStart: page number where endorsement begins \u2014 REQUIRED
6588
6592
  - pageEnd: page number where endorsement ends
6589
6593
 
@@ -6593,6 +6597,11 @@ PERSONAL LINES ENDORSEMENT RECOGNITION:
6593
6597
  - HO 17 XX series: mobilehome endorsements
6594
6598
  - DP 04 XX series: dwelling fire endorsements
6595
6599
 
6600
+ Critical rules:
6601
+ - Return compact metadata plus source references. The original endorsement wording lives in source spans.
6602
+ - Do not return full endorsement text in content when sourceSpanIds are available.
6603
+ - Prefer sourceSpanIds over generated prose for evidence.
6604
+
6596
6605
  Return JSON only.`;
6597
6606
  }
6598
6607
 
@@ -6839,7 +6848,10 @@ var SubsectionSchema2 = import_zod35.z.object({
6839
6848
  title: import_zod35.z.string().describe("Subsection title"),
6840
6849
  sectionNumber: import_zod35.z.string().optional().describe("Subsection number"),
6841
6850
  pageNumber: import_zod35.z.number().optional().describe("Page number"),
6842
- content: import_zod35.z.string().describe("Full verbatim text")
6851
+ excerpt: import_zod35.z.string().optional().describe("Short source excerpt, not full verbatim text"),
6852
+ content: import_zod35.z.string().optional().describe("Legacy fallback only; do not return full text when sourceSpanIds are available"),
6853
+ sourceSpanIds: import_zod35.z.array(import_zod35.z.string()).optional().describe("Source span IDs grounding this subsection"),
6854
+ sourceTextHash: import_zod35.z.string().optional().describe("Hash of the source text when available")
6843
6855
  });
6844
6856
  var SectionsSchema = import_zod35.z.object({
6845
6857
  sections: import_zod35.z.array(
@@ -6860,15 +6872,18 @@ var SectionsSchema = import_zod35.z.object({
6860
6872
  "regulatory",
6861
6873
  "other"
6862
6874
  ]).describe("Section type classification"),
6863
- content: import_zod35.z.string().describe("Full verbatim text of the section"),
6875
+ excerpt: import_zod35.z.string().optional().describe("Short source excerpt, not full verbatim text"),
6876
+ content: import_zod35.z.string().optional().describe("Legacy fallback only; do not return full text when sourceSpanIds are available"),
6864
6877
  pageStart: import_zod35.z.number().describe("Starting page number"),
6865
6878
  pageEnd: import_zod35.z.number().optional().describe("Ending page number"),
6879
+ sourceSpanIds: import_zod35.z.array(import_zod35.z.string()).optional().describe("Source span IDs grounding this section"),
6880
+ sourceTextHash: import_zod35.z.string().optional().describe("Hash of the source text when available"),
6866
6881
  subsections: import_zod35.z.array(SubsectionSchema2).optional().describe("Subsections within this section")
6867
6882
  })
6868
6883
  ).describe("All document sections")
6869
6884
  });
6870
6885
  function buildSectionsPrompt() {
6871
- return `You are an expert insurance document analyst. Extract ALL sections, clauses, endorsements, and schedules from this document. Preserve the original language verbatim \u2014 do not summarize or paraphrase.
6886
+ return `You are an expert insurance document analyst. Build a compact source-backed section index for this document. Do not reproduce full policy language in the JSON output.
6872
6887
 
6873
6888
  For each section, classify its type:
6874
6889
  - "declarations" \u2014 declarations page(s) listing named insured, policy period, limits, premiums
@@ -6882,10 +6897,13 @@ For each section, classify its type:
6882
6897
  - "notice", "regulatory" \u2014 notice provisions or regulatory disclosures
6883
6898
  - "other" \u2014 anything that doesn't fit the above categories
6884
6899
 
6885
- Include accurate page numbers for every section. Include subsections only if the section has clearly defined subsections with their own titles.
6900
+ Include accurate page numbers for every section. Include sourceSpanIds from the provided SOURCE SPANS whenever available. Include subsections only if the section has clearly defined subsections with their own titles.
6886
6901
  If a page begins or ends in the middle of a section, treat it as a continuation of the existing section instead of creating a new orphan section from the fragment.
6887
6902
 
6888
6903
  Critical rules:
6904
+ - Return compact metadata plus source references. The original policy wording lives in source spans.
6905
+ - Use excerpt only for a short identifying snippet, capped at 300 characters.
6906
+ - Do not return full section text in content when sourceSpanIds are available. Leave content omitted/null in source-backed mode.
6889
6907
  - Ignore table-of-contents entries, page-number references, repeating headers/footers, and other navigational artifacts.
6890
6908
  - Do not create a new section from a lone continuation fragment such as a single paragraph tail or list item that clearly belongs to the previous page's section.
6891
6909
  - When a section spans multiple pages, keep it as one section with pageStart/pageEnd covering the full span represented in this extraction.