@claritylabs/cl-sdk 3.0.18 → 3.0.20

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
@@ -6757,6 +6757,8 @@ For EACH form, extract:
6757
6757
 
6758
6758
  Critical rules:
6759
6759
  - Include declarations page sets even if they do not show a standard form number.
6760
+ - Do not classify policy jackets, claim-reporting notices, privacy notices, OFAC notices, terrorism/TRIA notices, sanctions notices, signatures, countersignatures, or marketing/admin pages as declarations.
6761
+ - Declarations pages contain policy-specific schedules such as named insured, policy number, policy period, premium, limits, retentions, coverage parts, or forms-and-endorsements schedules.
6760
6762
  - Use original document page numbers, not local chunk page numbers.
6761
6763
  - Do not emit duplicate entries for repeated headers/footers.
6762
6764
  - Multi-page forms should be represented once with pageStart/pageEnd covering the full span when visible.
@@ -8890,6 +8892,17 @@ function buildTemplateHints(primaryType, documentType, pageCount, template) {
8890
8892
  `Total pages: ${pageCount}`
8891
8893
  ].join("\n");
8892
8894
  }
8895
+ function buildFormInventoryHints(primaryType, documentType, pageCount, template) {
8896
+ return [
8897
+ `Document type: ${primaryType} ${documentType}`,
8898
+ `Expected sections: ${template.expectedSections.join(", ")}`,
8899
+ "Expected source order: jacket/front matter and notices, declarations, policy or coverage form, endorsements/amendatory forms.",
8900
+ "Front matter/notices include policy jackets, claim-reporting notices, privacy notices, OFAC notices, terrorism/TRIA notices, sanctions notices, signatures, countersignatures, and marketing/admin pages.",
8901
+ "Declarations include named insured, policy number, policy period, premium, coverage limits, retentions, forms-and-endorsements schedules, and similar schedule rows.",
8902
+ "Do not classify a page as declarations merely because it appears early in the document.",
8903
+ `Total pages: ${pageCount}`
8904
+ ].join("\n");
8905
+ }
8893
8906
  function groupContiguousPages(pages) {
8894
8907
  if (pages.length === 0) return [];
8895
8908
  const sorted = [...new Set(pages)].sort((a, b) => a - b);
@@ -9321,7 +9334,16 @@ function pageFormTypeFromText(text) {
9321
9334
  if (/\b(important notice|privacy notice|ofac advisory|terrorism risk insurance act|tria|trade or economic sanctions)\b/i.test(text)) return "notice";
9322
9335
  return "other";
9323
9336
  }
9324
- function inferFormHintsFromSourceSpans(sourceSpans) {
9337
+ function administrativeFormTypeFromText(text) {
9338
+ if (/\b(important notice|privacy notice|ofac advisory|terrorism risk insurance act|tria|trade or economic sanctions|economic sanctions limitation|how to report a claim)\b/i.test(text)) {
9339
+ return "notice";
9340
+ }
9341
+ if (/\b(specimen policy|policy jacket|countersigned|countersignature|licensed resident agent|corporate secretary|president and ceo|application of insurance executed)\b/i.test(text)) {
9342
+ return "other";
9343
+ }
9344
+ return void 0;
9345
+ }
9346
+ function pageTextByNumber(sourceSpans) {
9325
9347
  const pageTexts = /* @__PURE__ */ new Map();
9326
9348
  const pageSpanTexts = /* @__PURE__ */ new Map();
9327
9349
  for (const span of sourceSpans) {
@@ -9337,9 +9359,28 @@ function inferFormHintsFromSourceSpans(sourceSpans) {
9337
9359
  if (existing.length < 4e3) pageTexts.set(page, cleanText([existing, span.text].filter(Boolean).join(" "), ""));
9338
9360
  }
9339
9361
  }
9340
- if (pageSpanTexts.size === 0) return [];
9341
- const pageHints = [.../* @__PURE__ */ new Set([...pageTexts.keys(), ...pageSpanTexts.keys()])].sort((left, right) => left - right).map((page) => {
9342
- const text = pageSpanTexts.get(page) ?? pageTexts.get(page) ?? "";
9362
+ return new Map([.../* @__PURE__ */ new Set([...pageTexts.keys(), ...pageSpanTexts.keys()])].map((page) => [
9363
+ page,
9364
+ pageSpanTexts.get(page) ?? pageTexts.get(page) ?? ""
9365
+ ]));
9366
+ }
9367
+ function reconcileFormTypeWithSourceText(form, pageTexts) {
9368
+ const pages = [];
9369
+ const start = form.pageStart;
9370
+ const end = form.pageEnd ?? start;
9371
+ if (typeof start === "number" && typeof end === "number") {
9372
+ for (let page = start; page <= end; page += 1) pages.push(pageTexts.get(page) ?? "");
9373
+ }
9374
+ const text = cleanText([form.title, form.formNumber, ...pages].filter(Boolean).join(" "), "");
9375
+ const administrativeType = administrativeFormTypeFromText(text);
9376
+ if (administrativeType && form.formType !== administrativeType) return administrativeType;
9377
+ return form.formType;
9378
+ }
9379
+ function inferFormHintsFromSourceSpans(sourceSpans) {
9380
+ const pageTexts = pageTextByNumber(sourceSpans);
9381
+ if (pageTexts.size === 0) return [];
9382
+ const pageHints = [...pageTexts.keys()].sort((left, right) => left - right).map((page) => {
9383
+ const text = pageTexts.get(page) ?? "";
9343
9384
  const formNumber = formNumberFromText(text);
9344
9385
  return {
9345
9386
  formNumber,
@@ -9367,10 +9408,12 @@ function inferFormHintsFromSourceSpans(sourceSpans) {
9367
9408
  return merged;
9368
9409
  }
9369
9410
  function normalizeFormHints(forms, sourceSpans) {
9411
+ const pageTexts = pageTextByNumber(sourceSpans);
9370
9412
  const provided = (forms ?? []).filter(
9371
9413
  (form) => typeof form.pageStart === "number" && typeof form.pageEnd === "number" && form.pageStart > 0 && form.pageEnd >= form.pageStart
9372
9414
  ).map((form) => ({
9373
9415
  ...form,
9416
+ formType: reconcileFormTypeWithSourceText(form, pageTexts),
9374
9417
  title: form.title ? cleanText(form.title, "") : void 0
9375
9418
  })).sort(
9376
9419
  (left, right) => (left.pageStart ?? Number.MAX_SAFE_INTEGER) - (right.pageStart ?? Number.MAX_SAFE_INTEGER) || (left.pageEnd ?? Number.MAX_SAFE_INTEGER) - (right.pageEnd ?? Number.MAX_SAFE_INTEGER)
@@ -10961,11 +11004,49 @@ ${span.text}` : span.text;
10961
11004
  }
10962
11005
  }
10963
11006
  if (sourceSpans.length > 0) {
11007
+ const pageCount2 = Math.max(
11008
+ 1,
11009
+ ...sourceSpans.map((span) => span.pageEnd ?? span.pageStart ?? span.location?.endPage ?? span.location?.page ?? 1)
11010
+ );
11011
+ let formInventory2 = options?.formInventory;
11012
+ if (!formInventory2) {
11013
+ onProgress?.("Building form inventory from source spans...");
11014
+ const budget = resolveBudget("extraction_form_inventory", 2048);
11015
+ const startedAt = Date.now();
11016
+ const templateHints2 = buildFormInventoryHints("other", "policy", pageCount2, getTemplate("other"));
11017
+ const sourceText = formatSourceSpanText(sourceSpans);
11018
+ const prompt = `${buildFormInventoryPrompt(templateHints2)}
11019
+
11020
+ SOURCE SPAN DOCUMENT TEXT:
11021
+ ${sourceText}`;
11022
+ const response = await safeGenerateObject(
11023
+ generateObject,
11024
+ {
11025
+ prompt,
11026
+ schema: FormInventorySchema,
11027
+ maxTokens: budget.maxTokens,
11028
+ taskKind: "extraction_form_inventory",
11029
+ budgetDiagnostics: budget
11030
+ },
11031
+ {
11032
+ fallback: { forms: [] },
11033
+ log,
11034
+ onError: (err, attempt) => log?.(`Form inventory attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`)
11035
+ }
11036
+ );
11037
+ trackUsage(response.usage, {
11038
+ taskKind: "extraction_form_inventory",
11039
+ label: "form_inventory",
11040
+ maxTokens: budget.maxTokens,
11041
+ durationMs: Date.now() - startedAt
11042
+ });
11043
+ formInventory2 = response.object;
11044
+ }
10964
11045
  onProgress?.("Building source-native document tree...");
10965
11046
  const v3 = await runSourceTreeExtraction({
10966
11047
  id,
10967
11048
  sourceSpans,
10968
- formInventory: options?.formInventory,
11049
+ formInventory: formInventory2,
10969
11050
  generateObject,
10970
11051
  providerOptions: activeProviderOptions,
10971
11052
  resolveBudget,
@@ -11195,7 +11276,9 @@ ${pageText}`;
11195
11276
  const formInventoryResponse = await safeGenerateObject(
11196
11277
  generateObject,
11197
11278
  {
11198
- prompt: withFullDocumentTextContext(buildFormInventoryPrompt(templateHints)),
11279
+ prompt: withFullDocumentTextContext(buildFormInventoryPrompt(
11280
+ buildFormInventoryHints(primaryType, documentType, pageCount, template)
11281
+ )),
11199
11282
  schema: FormInventorySchema,
11200
11283
  maxTokens: budget.maxTokens,
11201
11284
  taskKind: "extraction_form_inventory",