@claritylabs/cl-sdk 1.2.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -223,7 +223,8 @@ function resolveModelBudget(params) {
223
223
  const schemaTokens = estimateTokens(params.schemaSizeBytes) ?? 0;
224
224
  const expectedListLength = positiveInteger(params.expectedListLength) ?? 0;
225
225
  const warnings = [];
226
- let maxTokens = constrainedPreference ?? taskCapability ?? longListCapability ?? defaultCapability ?? hintTokens;
226
+ const preferredOutputTokens = constrainedPreference ?? taskCapability ?? longListCapability ?? defaultCapability ?? hintTokens;
227
+ let maxTokens = hardMaxOutputTokens ?? modelMaxOutputTokens ?? preferredOutputTokens;
227
228
  if (minOutputTokens) {
228
229
  maxTokens = Math.max(maxTokens, minOutputTokens);
229
230
  }
@@ -252,6 +253,7 @@ function resolveModelBudget(params) {
252
253
  taskKind,
253
254
  maxTokens,
254
255
  hintTokens,
256
+ preferredOutputTokens,
255
257
  modelMaxOutputTokens,
256
258
  hardMaxOutputTokens,
257
259
  estimatedInputTokens,
@@ -673,7 +675,8 @@ var EndorsementSchema = z5.object({
673
675
  namedParties: z5.array(EndorsementPartySchema).optional(),
674
676
  keyTerms: z5.array(z5.string()).optional(),
675
677
  premiumImpact: z5.string().optional(),
676
- content: z5.string(),
678
+ excerpt: z5.string().optional(),
679
+ content: z5.string().optional(),
677
680
  pageStart: z5.number(),
678
681
  pageEnd: z5.number().optional(),
679
682
  recordId: z5.string().optional(),
@@ -1286,7 +1289,10 @@ var SubsectionSchema = z16.object({
1286
1289
  title: z16.string(),
1287
1290
  sectionNumber: z16.string().optional(),
1288
1291
  pageNumber: z16.number().optional(),
1289
- content: z16.string()
1292
+ excerpt: z16.string().optional(),
1293
+ content: z16.string().optional(),
1294
+ sourceSpanIds: z16.array(z16.string()).optional(),
1295
+ sourceTextHash: z16.string().optional()
1290
1296
  });
1291
1297
  var SectionSchema = z16.object({
1292
1298
  title: z16.string(),
@@ -1295,7 +1301,8 @@ var SectionSchema = z16.object({
1295
1301
  pageEnd: z16.number().optional(),
1296
1302
  type: z16.string(),
1297
1303
  coverageType: z16.string().optional(),
1298
- content: z16.string(),
1304
+ excerpt: z16.string().optional(),
1305
+ content: z16.string().optional(),
1299
1306
  subsections: z16.array(SubsectionSchema).optional(),
1300
1307
  recordId: z16.string().optional(),
1301
1308
  sourceSpanIds: z16.array(z16.string()).optional(),
@@ -2813,6 +2820,14 @@ ${pageText || "(No Docling text was available for this page range.)"}`;
2813
2820
  maxTokens,
2814
2821
  taskKind,
2815
2822
  budgetDiagnostics,
2823
+ trace: {
2824
+ label: `${name} pages ${startPage}-${endPage}`,
2825
+ extractorName: name,
2826
+ startPage,
2827
+ endPage,
2828
+ phase: "extractor",
2829
+ sourceBacked: !!sourceContext
2830
+ },
2816
2831
  providerOptions: extractorProviderOptions
2817
2832
  })
2818
2833
  );
@@ -3678,21 +3693,30 @@ function collectContentFields(doc) {
3678
3693
  entries.push({ id: id++, path, text });
3679
3694
  }
3680
3695
  }
3696
+ function hasSourceBacking(record) {
3697
+ return Array.isArray(record.sourceSpanIds) && record.sourceSpanIds.length > 0 || !!record.sourceTextHash;
3698
+ }
3681
3699
  add("summary", doc.summary);
3682
3700
  if (doc.sections) {
3683
3701
  for (let i = 0; i < doc.sections.length; i++) {
3684
3702
  const s = doc.sections[i];
3685
- add(`sections[${i}].content`, s.content);
3703
+ if (!hasSourceBacking(s)) {
3704
+ add(`sections[${i}].content`, s.content);
3705
+ }
3686
3706
  if (s.subsections) {
3687
3707
  for (let j = 0; j < s.subsections.length; j++) {
3688
- add(`sections[${i}].subsections[${j}].content`, s.subsections[j].content);
3708
+ if (!hasSourceBacking(s.subsections[j])) {
3709
+ add(`sections[${i}].subsections[${j}].content`, s.subsections[j].content);
3710
+ }
3689
3711
  }
3690
3712
  }
3691
3713
  }
3692
3714
  }
3693
3715
  if (doc.endorsements) {
3694
3716
  for (let i = 0; i < doc.endorsements.length; i++) {
3695
- add(`endorsements[${i}].content`, doc.endorsements[i].content);
3717
+ if (!hasSourceBacking(doc.endorsements[i])) {
3718
+ add(`endorsements[${i}].content`, doc.endorsements[i].content);
3719
+ }
3696
3720
  }
3697
3721
  }
3698
3722
  if (doc.exclusions) {
@@ -3794,6 +3818,12 @@ async function formatDocumentContent(doc, generateText, options) {
3794
3818
  maxTokens: options?.maxTokens ?? 16384,
3795
3819
  taskKind: options?.taskKind,
3796
3820
  budgetDiagnostics: options?.budgetDiagnostics,
3821
+ trace: {
3822
+ label: `format content batch ${batchIdx + 1}/${batches.length}`,
3823
+ phase: "format",
3824
+ batchIndex: batchIdx + 1,
3825
+ batchCount: batches.length
3826
+ },
3797
3827
  providerOptions: options?.providerOptions
3798
3828
  })
3799
3829
  );
@@ -3868,7 +3898,7 @@ function chunkDocument(doc) {
3868
3898
  documentId: docId,
3869
3899
  type,
3870
3900
  text,
3871
- metadata: stringMetadata(metadata)
3901
+ metadata: stringMetadata({ evidenceKind: "structured_fact", ...metadata })
3872
3902
  });
3873
3903
  }
3874
3904
  pushChunk(
@@ -4147,16 +4177,29 @@ function chunkDocument(doc) {
4147
4177
  );
4148
4178
  });
4149
4179
  doc.endorsements?.forEach((end, i) => {
4180
+ const text = lines([
4181
+ `Endorsement: ${end.title}`,
4182
+ end.formNumber ? `Form: ${end.formNumber}` : null,
4183
+ end.editionDate ? `Edition: ${end.editionDate}` : null,
4184
+ `Type: ${end.endorsementType}`,
4185
+ end.effectiveDate ? `Effective Date: ${end.effectiveDate}` : null,
4186
+ end.affectedCoverageParts?.length ? `Affected Coverage Parts: ${end.affectedCoverageParts.join(", ")}` : null,
4187
+ end.keyTerms?.length ? `Key Terms: ${end.keyTerms.join("; ")}` : null,
4188
+ end.premiumImpact ? `Premium Impact: ${end.premiumImpact}` : null,
4189
+ end.excerpt ? `Excerpt: ${end.excerpt}` : null
4190
+ ]);
4191
+ if (!text.trim()) return;
4150
4192
  pushChunk(
4151
4193
  `endorsement:${i}`,
4152
4194
  "endorsement",
4153
- `Endorsement: ${end.title}
4154
- ${end.content}`.trim(),
4195
+ text,
4155
4196
  {
4156
4197
  endorsementType: end.endorsementType,
4157
4198
  formNumber: end.formNumber,
4158
4199
  pageStart: end.pageStart,
4159
4200
  pageEnd: end.pageEnd,
4201
+ sourceSpanIds: end.sourceSpanIds?.join(","),
4202
+ sourceTextHash: end.sourceTextHash,
4160
4203
  documentType: doc.type
4161
4204
  }
4162
4205
  );
@@ -4278,93 +4321,51 @@ ${declLines.join("\n")}`, declMeta);
4278
4321
  }
4279
4322
  doc.sections?.forEach((sec, i) => {
4280
4323
  const hasSubsections = sec.subsections && sec.subsections.length > 0;
4281
- const contentLength = sec.content.length;
4282
- if (hasSubsections) {
4283
- pushChunk(
4284
- `section:${i}`,
4285
- "section",
4286
- `Section: ${sec.title}
4287
- ${sec.content}`,
4288
- {
4289
- sectionType: sec.type,
4290
- sectionNumber: sec.sectionNumber,
4291
- pageStart: sec.pageStart,
4292
- pageEnd: sec.pageEnd,
4293
- documentType: doc.type,
4294
- hasSubsections: "true"
4295
- }
4296
- );
4297
- sec.subsections.forEach((sub, j) => {
4298
- pushChunk(
4299
- `section:${i}:sub:${j}`,
4300
- "section",
4301
- `${sec.title} > ${sub.title}
4302
- ${sub.content}`,
4303
- {
4304
- sectionType: sec.type,
4305
- parentSection: sec.title,
4306
- sectionNumber: sub.sectionNumber,
4307
- pageNumber: sub.pageNumber,
4308
- documentType: doc.type
4309
- }
4310
- );
4311
- });
4312
- } else if (contentLength > 2e3) {
4313
- const paragraphs = sec.content.split(/\n\n+/);
4314
- let currentChunk = "";
4315
- let chunkIndex = 0;
4316
- for (const para of paragraphs) {
4317
- if (currentChunk.length + para.length > 1e3 && currentChunk.length > 0) {
4318
- pushChunk(
4319
- `section:${i}:part:${chunkIndex}`,
4320
- "section",
4321
- `Section: ${sec.title} (part ${chunkIndex + 1})
4322
- ${currentChunk.trim()}`,
4323
- {
4324
- sectionType: sec.type,
4325
- sectionNumber: sec.sectionNumber,
4326
- pageStart: sec.pageStart,
4327
- pageEnd: sec.pageEnd,
4328
- documentType: doc.type,
4329
- partIndex: chunkIndex
4330
- }
4331
- );
4332
- currentChunk = "";
4333
- chunkIndex++;
4334
- }
4335
- currentChunk += (currentChunk ? "\n\n" : "") + para;
4336
- }
4337
- if (currentChunk.trim()) {
4338
- pushChunk(
4339
- `section:${i}:part:${chunkIndex}`,
4340
- "section",
4341
- `Section: ${sec.title} (part ${chunkIndex + 1})
4342
- ${currentChunk.trim()}`,
4343
- {
4344
- sectionType: sec.type,
4345
- sectionNumber: sec.sectionNumber,
4346
- pageStart: sec.pageStart,
4347
- pageEnd: sec.pageEnd,
4348
- documentType: doc.type,
4349
- partIndex: chunkIndex
4350
- }
4351
- );
4324
+ pushChunk(
4325
+ `section:${i}`,
4326
+ "section",
4327
+ lines([
4328
+ `Section: ${sec.title}`,
4329
+ `Type: ${sec.type}`,
4330
+ sec.sectionNumber ? `Section Number: ${sec.sectionNumber}` : null,
4331
+ `Pages: ${sec.pageStart}${sec.pageEnd ? `-${sec.pageEnd}` : ""}`,
4332
+ sec.excerpt ? `Excerpt: ${sec.excerpt}` : null,
4333
+ hasSubsections ? `Subsections: ${sec.subsections.map((sub) => sub.title).join(", ")}` : null
4334
+ ]),
4335
+ {
4336
+ evidenceKind: "navigation",
4337
+ sectionType: sec.type,
4338
+ sectionNumber: sec.sectionNumber,
4339
+ pageStart: sec.pageStart,
4340
+ pageEnd: sec.pageEnd,
4341
+ sourceSpanIds: sec.sourceSpanIds?.join(","),
4342
+ sourceTextHash: sec.sourceTextHash,
4343
+ documentType: doc.type,
4344
+ hasSubsections
4352
4345
  }
4353
- } else {
4346
+ );
4347
+ sec.subsections?.forEach((sub, j) => {
4354
4348
  pushChunk(
4355
- `section:${i}`,
4349
+ `section:${i}:sub:${j}`,
4356
4350
  "section",
4357
- `Section: ${sec.title}
4358
- ${sec.content}`,
4351
+ lines([
4352
+ `Section: ${sec.title} > ${sub.title}`,
4353
+ sub.sectionNumber ? `Section Number: ${sub.sectionNumber}` : null,
4354
+ sub.pageNumber ? `Page: ${sub.pageNumber}` : null,
4355
+ sub.excerpt ? `Excerpt: ${sub.excerpt}` : null
4356
+ ]),
4359
4357
  {
4358
+ evidenceKind: "navigation",
4360
4359
  sectionType: sec.type,
4361
- sectionNumber: sec.sectionNumber,
4362
- pageStart: sec.pageStart,
4363
- pageEnd: sec.pageEnd,
4360
+ parentSection: sec.title,
4361
+ sectionNumber: sub.sectionNumber,
4362
+ pageNumber: sub.pageNumber,
4363
+ sourceSpanIds: sub.sourceSpanIds?.join(","),
4364
+ sourceTextHash: sub.sourceTextHash,
4364
4365
  documentType: doc.type
4365
4366
  }
4366
4367
  );
4367
- }
4368
+ });
4368
4369
  });
4369
4370
  doc.locations?.forEach((loc, i) => {
4370
4371
  chunks.push({
@@ -6236,14 +6237,17 @@ var EndorsementsSchema = z29.object({
6236
6237
  ).optional().describe("Named parties (additional insureds, loss payees, etc.)"),
6237
6238
  keyTerms: z29.array(z29.string()).optional().describe("Key terms or notable provisions in the endorsement"),
6238
6239
  premiumImpact: z29.string().optional().describe("Additional premium or credit"),
6239
- content: z29.string().describe("Full verbatim text of the endorsement"),
6240
+ excerpt: z29.string().optional().describe("Short source excerpt, not full verbatim text"),
6241
+ content: z29.string().optional().describe("Legacy fallback only; do not return full text when sourceSpanIds are available"),
6240
6242
  pageStart: z29.number().describe("Starting page number of this endorsement"),
6241
- pageEnd: z29.number().optional().describe("Ending page number of this endorsement")
6243
+ pageEnd: z29.number().optional().describe("Ending page number of this endorsement"),
6244
+ sourceSpanIds: z29.array(z29.string()).optional().describe("Source span IDs grounding this endorsement"),
6245
+ sourceTextHash: z29.string().optional().describe("Hash of the source text when available")
6242
6246
  })
6243
6247
  ).describe("All endorsements found in the document")
6244
6248
  });
6245
6249
  function buildEndorsementsPrompt() {
6246
- return `You are an expert insurance document analyst. Extract ALL endorsements from this document. Preserve original language verbatim.
6250
+ 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.
6247
6251
 
6248
6252
  For EACH endorsement, extract:
6249
6253
  - formNumber: the form identifier (e.g. "CG 21 47") \u2014 REQUIRED
@@ -6255,7 +6259,9 @@ For EACH endorsement, extract:
6255
6259
  - namedParties: for each party, extract name, role (additional_insured, loss_payee, mortgage_holder, certificate_holder, waiver_beneficiary, designated_person, other), relationship, and scope
6256
6260
  - keyTerms: notable provisions or key terms
6257
6261
  - premiumImpact: additional premium or credit if shown
6258
- - content: full verbatim text \u2014 REQUIRED
6262
+ - excerpt: short identifying source excerpt, capped at 300 characters
6263
+ - sourceSpanIds: source span IDs from the provided SOURCE SPANS that ground this endorsement
6264
+ - content: legacy fallback only; omit/null when sourceSpanIds are available
6259
6265
  - pageStart: page number where endorsement begins \u2014 REQUIRED
6260
6266
  - pageEnd: page number where endorsement ends
6261
6267
 
@@ -6265,6 +6271,11 @@ PERSONAL LINES ENDORSEMENT RECOGNITION:
6265
6271
  - HO 17 XX series: mobilehome endorsements
6266
6272
  - DP 04 XX series: dwelling fire endorsements
6267
6273
 
6274
+ Critical rules:
6275
+ - Return compact metadata plus source references. The original endorsement wording lives in source spans.
6276
+ - Do not return full endorsement text in content when sourceSpanIds are available.
6277
+ - Prefer sourceSpanIds over generated prose for evidence.
6278
+
6268
6279
  Return JSON only.`;
6269
6280
  }
6270
6281
 
@@ -6511,7 +6522,10 @@ var SubsectionSchema2 = z35.object({
6511
6522
  title: z35.string().describe("Subsection title"),
6512
6523
  sectionNumber: z35.string().optional().describe("Subsection number"),
6513
6524
  pageNumber: z35.number().optional().describe("Page number"),
6514
- content: z35.string().describe("Full verbatim text")
6525
+ excerpt: z35.string().optional().describe("Short source excerpt, not full verbatim text"),
6526
+ content: z35.string().optional().describe("Legacy fallback only; do not return full text when sourceSpanIds are available"),
6527
+ sourceSpanIds: z35.array(z35.string()).optional().describe("Source span IDs grounding this subsection"),
6528
+ sourceTextHash: z35.string().optional().describe("Hash of the source text when available")
6515
6529
  });
6516
6530
  var SectionsSchema = z35.object({
6517
6531
  sections: z35.array(
@@ -6532,15 +6546,18 @@ var SectionsSchema = z35.object({
6532
6546
  "regulatory",
6533
6547
  "other"
6534
6548
  ]).describe("Section type classification"),
6535
- content: z35.string().describe("Full verbatim text of the section"),
6549
+ excerpt: z35.string().optional().describe("Short source excerpt, not full verbatim text"),
6550
+ content: z35.string().optional().describe("Legacy fallback only; do not return full text when sourceSpanIds are available"),
6536
6551
  pageStart: z35.number().describe("Starting page number"),
6537
6552
  pageEnd: z35.number().optional().describe("Ending page number"),
6553
+ sourceSpanIds: z35.array(z35.string()).optional().describe("Source span IDs grounding this section"),
6554
+ sourceTextHash: z35.string().optional().describe("Hash of the source text when available"),
6538
6555
  subsections: z35.array(SubsectionSchema2).optional().describe("Subsections within this section")
6539
6556
  })
6540
6557
  ).describe("All document sections")
6541
6558
  });
6542
6559
  function buildSectionsPrompt() {
6543
- 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.
6560
+ 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.
6544
6561
 
6545
6562
  For each section, classify its type:
6546
6563
  - "declarations" \u2014 declarations page(s) listing named insured, policy period, limits, premiums
@@ -6554,10 +6571,13 @@ For each section, classify its type:
6554
6571
  - "notice", "regulatory" \u2014 notice provisions or regulatory disclosures
6555
6572
  - "other" \u2014 anything that doesn't fit the above categories
6556
6573
 
6557
- Include accurate page numbers for every section. Include subsections only if the section has clearly defined subsections with their own titles.
6574
+ 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.
6558
6575
  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.
6559
6576
 
6560
6577
  Critical rules:
6578
+ - Return compact metadata plus source references. The original policy wording lives in source spans.
6579
+ - Use excerpt only for a short identifying snippet, capped at 300 characters.
6580
+ - Do not return full section text in content when sourceSpanIds are available. Leave content omitted/null in source-backed mode.
6561
6581
  - Ignore table-of-contents entries, page-number references, repeating headers/footers, and other navigational artifacts.
6562
6582
  - 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.
6563
6583
  - When a section spans multiple pages, keep it as one section with pageStart/pageEnd covering the full span represented in this extraction.