@claritylabs/cl-sdk 3.0.19 → 3.0.21
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 +77 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +77 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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);
|
|
@@ -9311,6 +9324,7 @@ function pageTitleFromText(text, fallback) {
|
|
|
9311
9324
|
const endorsement = normalized.match(/\bENDORSEMENT\s+(?:NO\.?|NUMBER|#)\s*[A-Z0-9][A-Z0-9.-]*\b/i)?.[0];
|
|
9312
9325
|
if (endorsement) return cleanText(endorsement, fallback);
|
|
9313
9326
|
const firstSentence = normalized.split(/(?<=\.)\s+/)[0];
|
|
9327
|
+
if (/^page\s+\d+\b/i.test(firstSentence)) return fallback;
|
|
9314
9328
|
if (firstSentence && firstSentence.length <= 120) return firstSentence.replace(/[.]$/, "");
|
|
9315
9329
|
return fallback;
|
|
9316
9330
|
}
|
|
@@ -9321,7 +9335,16 @@ function pageFormTypeFromText(text) {
|
|
|
9321
9335
|
if (/\b(important notice|privacy notice|ofac advisory|terrorism risk insurance act|tria|trade or economic sanctions)\b/i.test(text)) return "notice";
|
|
9322
9336
|
return "other";
|
|
9323
9337
|
}
|
|
9324
|
-
function
|
|
9338
|
+
function administrativeFormTypeFromText(text) {
|
|
9339
|
+
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)) {
|
|
9340
|
+
return "notice";
|
|
9341
|
+
}
|
|
9342
|
+
if (/\b(specimen policy|policy jacket|countersigned|countersignature|licensed resident agent|corporate secretary|president and ceo|application of insurance executed)\b/i.test(text)) {
|
|
9343
|
+
return "other";
|
|
9344
|
+
}
|
|
9345
|
+
return void 0;
|
|
9346
|
+
}
|
|
9347
|
+
function pageTextByNumber(sourceSpans) {
|
|
9325
9348
|
const pageTexts = /* @__PURE__ */ new Map();
|
|
9326
9349
|
const pageSpanTexts = /* @__PURE__ */ new Map();
|
|
9327
9350
|
for (const span of sourceSpans) {
|
|
@@ -9337,9 +9360,28 @@ function inferFormHintsFromSourceSpans(sourceSpans) {
|
|
|
9337
9360
|
if (existing.length < 4e3) pageTexts.set(page, cleanText([existing, span.text].filter(Boolean).join(" "), ""));
|
|
9338
9361
|
}
|
|
9339
9362
|
}
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9363
|
+
return new Map([.../* @__PURE__ */ new Set([...pageTexts.keys(), ...pageSpanTexts.keys()])].map((page) => [
|
|
9364
|
+
page,
|
|
9365
|
+
pageSpanTexts.get(page) ?? pageTexts.get(page) ?? ""
|
|
9366
|
+
]));
|
|
9367
|
+
}
|
|
9368
|
+
function reconcileFormTypeWithSourceText(form, pageTexts) {
|
|
9369
|
+
const pages = [];
|
|
9370
|
+
const start = form.pageStart;
|
|
9371
|
+
const end = form.pageEnd ?? start;
|
|
9372
|
+
if (typeof start === "number" && typeof end === "number") {
|
|
9373
|
+
for (let page = start; page <= end; page += 1) pages.push(pageTexts.get(page) ?? "");
|
|
9374
|
+
}
|
|
9375
|
+
const text = cleanText([form.title, form.formNumber, ...pages].filter(Boolean).join(" "), "");
|
|
9376
|
+
const administrativeType = administrativeFormTypeFromText(text);
|
|
9377
|
+
if (administrativeType && form.formType !== administrativeType) return administrativeType;
|
|
9378
|
+
return form.formType;
|
|
9379
|
+
}
|
|
9380
|
+
function inferFormHintsFromSourceSpans(sourceSpans) {
|
|
9381
|
+
const pageTexts = pageTextByNumber(sourceSpans);
|
|
9382
|
+
if (pageTexts.size === 0) return [];
|
|
9383
|
+
const pageHints = [...pageTexts.keys()].sort((left, right) => left - right).map((page) => {
|
|
9384
|
+
const text = pageTexts.get(page) ?? "";
|
|
9343
9385
|
const formNumber = formNumberFromText(text);
|
|
9344
9386
|
return {
|
|
9345
9387
|
formNumber,
|
|
@@ -9367,10 +9409,12 @@ function inferFormHintsFromSourceSpans(sourceSpans) {
|
|
|
9367
9409
|
return merged;
|
|
9368
9410
|
}
|
|
9369
9411
|
function normalizeFormHints(forms, sourceSpans) {
|
|
9412
|
+
const pageTexts = pageTextByNumber(sourceSpans);
|
|
9370
9413
|
const provided = (forms ?? []).filter(
|
|
9371
9414
|
(form) => typeof form.pageStart === "number" && typeof form.pageEnd === "number" && form.pageStart > 0 && form.pageEnd >= form.pageStart
|
|
9372
9415
|
).map((form) => ({
|
|
9373
9416
|
...form,
|
|
9417
|
+
formType: reconcileFormTypeWithSourceText(form, pageTexts),
|
|
9374
9418
|
title: form.title ? cleanText(form.title, "") : void 0
|
|
9375
9419
|
})).sort(
|
|
9376
9420
|
(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)
|
|
@@ -9545,33 +9589,44 @@ function reparentNodes(sourceTree, childIds, parentId, organizerRepair) {
|
|
|
9545
9589
|
function applySemanticPageGrouping(sourceTree) {
|
|
9546
9590
|
const relabeled = sourceTree.map((node) => {
|
|
9547
9591
|
if (node.kind === "document" || node.kind === "page_group") return node;
|
|
9548
|
-
|
|
9549
|
-
if (
|
|
9592
|
+
let nextNode = node;
|
|
9593
|
+
if (node.kind === "page" && /^page\s+\d+$/i.test(node.title)) {
|
|
9594
|
+
const title = pageTitleFromText(sourceNodeText(node), node.title);
|
|
9595
|
+
if (title !== node.title) {
|
|
9596
|
+
nextNode = {
|
|
9597
|
+
...node,
|
|
9598
|
+
title: simplifyOrganizerTitle(title, title, node.kind),
|
|
9599
|
+
metadata: { ...node.metadata, organizerRepair: "semantic_page_title" }
|
|
9600
|
+
};
|
|
9601
|
+
}
|
|
9602
|
+
}
|
|
9603
|
+
const endorsement = endorsementStartTitle(nextNode);
|
|
9604
|
+
if (endorsement && nextNode.kind === "page") {
|
|
9550
9605
|
return {
|
|
9551
|
-
...
|
|
9606
|
+
...nextNode,
|
|
9552
9607
|
kind: "endorsement",
|
|
9553
9608
|
title: endorsement,
|
|
9554
|
-
description: endorsementDescription(endorsement,
|
|
9555
|
-
metadata: { ...
|
|
9609
|
+
description: endorsementDescription(endorsement, nextNode),
|
|
9610
|
+
metadata: { ...nextNode.metadata, organizerRepair: "semantic_page_grouping" }
|
|
9556
9611
|
};
|
|
9557
9612
|
}
|
|
9558
|
-
if (
|
|
9613
|
+
if (nextNode.kind === "page" && looksLikeDeclarationsStart(nextNode)) {
|
|
9559
9614
|
return {
|
|
9560
|
-
...
|
|
9615
|
+
...nextNode,
|
|
9561
9616
|
title: "Declarations",
|
|
9562
|
-
description: cleanText([
|
|
9563
|
-
metadata: { ...
|
|
9617
|
+
description: cleanText([nextNode.description, "Declarations"].join(" "), "Declarations"),
|
|
9618
|
+
metadata: { ...nextNode.metadata, organizerRepair: "semantic_page_grouping" }
|
|
9564
9619
|
};
|
|
9565
9620
|
}
|
|
9566
|
-
if (
|
|
9621
|
+
if (nextNode.kind === "page" && looksLikePolicyFormStart(nextNode)) {
|
|
9567
9622
|
return {
|
|
9568
|
-
...
|
|
9623
|
+
...nextNode,
|
|
9569
9624
|
title: "Policy Form",
|
|
9570
|
-
description: cleanText([
|
|
9571
|
-
metadata: { ...
|
|
9625
|
+
description: cleanText([nextNode.description, "Policy Form"].join(" "), "Policy Form"),
|
|
9626
|
+
metadata: { ...nextNode.metadata, organizerRepair: "semantic_page_grouping" }
|
|
9572
9627
|
};
|
|
9573
9628
|
}
|
|
9574
|
-
return
|
|
9629
|
+
return nextNode;
|
|
9575
9630
|
});
|
|
9576
9631
|
const rootId = sourceTreeRootId(relabeled);
|
|
9577
9632
|
const children = (nodesByParent(relabeled).get(rootId) ?? []).filter((node) => node.kind !== "document").sort((left, right) => left.order - right.order);
|
|
@@ -10970,7 +11025,7 @@ ${span.text}` : span.text;
|
|
|
10970
11025
|
onProgress?.("Building form inventory from source spans...");
|
|
10971
11026
|
const budget = resolveBudget("extraction_form_inventory", 2048);
|
|
10972
11027
|
const startedAt = Date.now();
|
|
10973
|
-
const templateHints2 =
|
|
11028
|
+
const templateHints2 = buildFormInventoryHints("other", "policy", pageCount2, getTemplate("other"));
|
|
10974
11029
|
const sourceText = formatSourceSpanText(sourceSpans);
|
|
10975
11030
|
const prompt = `${buildFormInventoryPrompt(templateHints2)}
|
|
10976
11031
|
|
|
@@ -11233,7 +11288,9 @@ ${pageText}`;
|
|
|
11233
11288
|
const formInventoryResponse = await safeGenerateObject(
|
|
11234
11289
|
generateObject,
|
|
11235
11290
|
{
|
|
11236
|
-
prompt: withFullDocumentTextContext(buildFormInventoryPrompt(
|
|
11291
|
+
prompt: withFullDocumentTextContext(buildFormInventoryPrompt(
|
|
11292
|
+
buildFormInventoryHints(primaryType, documentType, pageCount, template)
|
|
11293
|
+
)),
|
|
11237
11294
|
schema: FormInventorySchema,
|
|
11238
11295
|
maxTokens: budget.maxTokens,
|
|
11239
11296
|
taskKind: "extraction_form_inventory",
|