@claritylabs/cl-sdk 3.0.29 → 3.0.31
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 +86 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2983,6 +2983,88 @@ function firstMatch(nodes, patterns) {
|
|
|
2983
2983
|
}
|
|
2984
2984
|
return void 0;
|
|
2985
2985
|
}
|
|
2986
|
+
var POLICY_NUMBER_PATTERNS = [
|
|
2987
|
+
/\bpolicy\s*(?:number|no\.?|#)\s*:?\s*([A-Z0-9][A-Z0-9,.-]{4,}[A-Z0-9])/i,
|
|
2988
|
+
/\bpolicy\s*[:#]\s*([A-Z0-9][A-Z0-9,.-]{4,}[A-Z0-9])/i
|
|
2989
|
+
];
|
|
2990
|
+
function policyNumberEvidenceScore(node) {
|
|
2991
|
+
const text = normalizeWhitespace3([node.path, nodeText(node)].filter(Boolean).join(" ")).toLowerCase();
|
|
2992
|
+
let score = 0;
|
|
2993
|
+
if (/\b(policy\s+summary|declarations?|declaration\s+page|schedule)\b/.test(text)) score += 80;
|
|
2994
|
+
if (/\b(plan|policy\s+date|insured\s+person|named\s+insured|insurance\s+amount|benefit\s+amount)\b/.test(text)) score += 35;
|
|
2995
|
+
if (node.kind === "table_row" || node.kind === "table_cell" || node.kind === "text") score += 20;
|
|
2996
|
+
if (node.kind === "page") score += 10;
|
|
2997
|
+
if (typeof node.pageStart === "number" && node.pageStart > 1 && node.pageStart <= 10) score += 20;
|
|
2998
|
+
if (typeof node.pageStart === "number" && node.pageStart === 1) score -= 30;
|
|
2999
|
+
if (/\b(notices?\s+and\s+jacket|policy\s+jacket|front\s+matter|table\s+of\s+contents)\b/.test(text)) score -= 70;
|
|
3000
|
+
if (node.kind === "page_group" || node.kind === "form") score -= 30;
|
|
3001
|
+
return score;
|
|
3002
|
+
}
|
|
3003
|
+
function policyNumberFromNodes(nodes) {
|
|
3004
|
+
const candidates = nodes.slice(0, 120).flatMap((node) => {
|
|
3005
|
+
const text = nodeText(node);
|
|
3006
|
+
for (const pattern of POLICY_NUMBER_PATTERNS) {
|
|
3007
|
+
const value = cleanValue(text.match(pattern)?.[1]);
|
|
3008
|
+
if (value) return [{ node, value, score: policyNumberEvidenceScore(node) }];
|
|
3009
|
+
}
|
|
3010
|
+
return [];
|
|
3011
|
+
}).sort(
|
|
3012
|
+
(left, right) => right.score - left.score || (left.node.pageStart ?? Number.MAX_SAFE_INTEGER) - (right.node.pageStart ?? Number.MAX_SAFE_INTEGER) || left.node.order - right.node.order
|
|
3013
|
+
);
|
|
3014
|
+
const candidate = candidates[0];
|
|
3015
|
+
return candidate ? valueFromNode(candidate.node, candidate.value, "high") : void 0;
|
|
3016
|
+
}
|
|
3017
|
+
function compactFactNodes(nodes) {
|
|
3018
|
+
return nodes.filter((node) => {
|
|
3019
|
+
if (node.kind === "document" || node.kind === "page_group" || node.kind === "form") return false;
|
|
3020
|
+
const text = nodeText(node);
|
|
3021
|
+
if (text.length > 900) return false;
|
|
3022
|
+
if (/\b(table of contents|provided solely for your convenience|not to be construed|actual policy issued)\b/i.test(text)) return false;
|
|
3023
|
+
return node.kind === "text" || node.kind === "table_row" || node.kind === "table_cell" || node.kind === "page";
|
|
3024
|
+
});
|
|
3025
|
+
}
|
|
3026
|
+
function firstCleanMatch(nodes, patterns, clean) {
|
|
3027
|
+
for (const node of compactFactNodes(nodes)) {
|
|
3028
|
+
const text = nodeText(node);
|
|
3029
|
+
for (const pattern of patterns) {
|
|
3030
|
+
const raw = cleanValue(text.match(pattern)?.[1]);
|
|
3031
|
+
if (!raw) continue;
|
|
3032
|
+
const value = clean(raw);
|
|
3033
|
+
if (value) return valueFromNode(node, value, "high");
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
return void 0;
|
|
3037
|
+
}
|
|
3038
|
+
function cleanNamedInsured(value) {
|
|
3039
|
+
const clean = cleanValue(value.replace(/\bborn\s+on\b.*$/i, "").replace(/\bage\s+nearest\b.*$/i, "").replace(/\bbeneficiary\b.*$/i, ""));
|
|
3040
|
+
if (!clean || clean.length > 160) return void 0;
|
|
3041
|
+
if (/^(person|persons)\b/i.test(clean)) return void 0;
|
|
3042
|
+
if (/\b(table of contents|policy wording|provided solely|convenience|not to be construed|actual policy issued)\b/i.test(clean)) {
|
|
3043
|
+
return void 0;
|
|
3044
|
+
}
|
|
3045
|
+
return clean;
|
|
3046
|
+
}
|
|
3047
|
+
function namedInsuredFromNodes(nodes) {
|
|
3048
|
+
return firstCleanMatch(nodes, [
|
|
3049
|
+
/\b(?:named insured|insured name|insured persons?|insured person)\s*:?\s*(.+?)(?=\s+(?:insurance amount|benefit amount|policy number|policy date|owner|beneficiary|premium|coverage|risk classification|date this)\b|[|;\n]|$)/i,
|
|
3050
|
+
/\b(?:applicant|policyholder)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i
|
|
3051
|
+
], cleanNamedInsured);
|
|
3052
|
+
}
|
|
3053
|
+
function cleanInsurer(value) {
|
|
3054
|
+
const clean = cleanValue(value);
|
|
3055
|
+
if (!clean || clean.length > 140) return void 0;
|
|
3056
|
+
if (/^(mean|means|we|us|our)\b/i.test(clean)) return void 0;
|
|
3057
|
+
if (/\b(table of contents|policy wording|provided solely|convenience)\b/i.test(clean)) return void 0;
|
|
3058
|
+
const known = clean.match(/\b(Sun Life Assurance Company of Canada|Manulife|The Manufacturers Life Insurance Company)\b/i)?.[1];
|
|
3059
|
+
return known ?? clean;
|
|
3060
|
+
}
|
|
3061
|
+
function insurerFromNodes(nodes) {
|
|
3062
|
+
return firstCleanMatch(nodes, [
|
|
3063
|
+
/\bunderwritten by\s+([^|;\n.]{3,160})/i,
|
|
3064
|
+
/\b(?:insurer|carrier|company|security)\s*:?\s*([^|;\n]{3,120})/i,
|
|
3065
|
+
/\b(Sun Life Assurance Company of Canada|Manulife|The Manufacturers Life Insurance Company)\b/i
|
|
3066
|
+
], cleanInsurer);
|
|
3067
|
+
}
|
|
2986
3068
|
function inferPolicyTypes(nodes) {
|
|
2987
3069
|
const text = nodes.slice(0, 40).map(nodeText).join(" ").toLowerCase();
|
|
2988
3070
|
const types = [];
|
|
@@ -3436,20 +3518,9 @@ function buildDeterministicOperationalProfile(params) {
|
|
|
3436
3518
|
const partial = {
|
|
3437
3519
|
documentType: inferDocumentType(nodes),
|
|
3438
3520
|
policyTypes: inferPolicyTypes(nodes),
|
|
3439
|
-
policyNumber:
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
]),
|
|
3443
|
-
namedInsured: firstMatch(nodes, [
|
|
3444
|
-
/\b(?:named insured|insured name|insured)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i,
|
|
3445
|
-
/\b(?:applicant|policyholder)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i
|
|
3446
|
-
]),
|
|
3447
|
-
insurer: firstMatch(nodes, [
|
|
3448
|
-
/\b(?:insurer|carrier|company|security)\s*:?\s*([^|;\n]{3,120})/i,
|
|
3449
|
-
/\bunderwritten by\s+([^|;\n]{3,120})/i
|
|
3450
|
-
]) ?? firstMatch(nodes, [
|
|
3451
|
-
/\b(Manulife)\b/i
|
|
3452
|
-
]),
|
|
3521
|
+
policyNumber: policyNumberFromNodes(nodes),
|
|
3522
|
+
namedInsured: namedInsuredFromNodes(nodes),
|
|
3523
|
+
insurer: insurerFromNodes(nodes),
|
|
3453
3524
|
broker: firstMatch(nodes, [
|
|
3454
3525
|
/\b(?:broker|producer|agent)\s*:?\s*([^|;\n]{3,120})/i
|
|
3455
3526
|
]),
|
|
@@ -10757,6 +10828,7 @@ Rules:
|
|
|
10757
10828
|
- Every returned value must include sourceNodeIds or sourceSpanIds from the provided nodes.
|
|
10758
10829
|
- If a value is not directly supported, omit it.
|
|
10759
10830
|
- Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
|
|
10831
|
+
- For life, critical illness, disability, and long-term care policies, keep named benefit units and benefit subconditions as operational facts even when they do not have dollar limits. Examples include death benefit, disability benefit, total disability, catastrophic disability, return of premium, waiver, and conversion options. Put subcondition details in coverages[].limits with kind "other" when they belong under a broader benefit.
|
|
10760
10832
|
- Treat an endorsement as one coverage unit when it contains a schedule. Do not split an endorsement schedule into generic rows like "Aggregate Limit".
|
|
10761
10833
|
- For coverage schedules, put each claim, aggregate, sublimit, retention, deductible, and retroactive date values in coverages[].limits with labels and source IDs. Keep the legacy coverages[].limit as the primary display value only.
|
|
10762
10834
|
- Use coverageOrigin: "endorsement" for endorsement units and "core" for declarations/core policy coverage units.
|