@claritylabs/cl-sdk 3.0.31 → 3.0.33
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 +147 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +147 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3313,6 +3313,15 @@ function moneyValue(value) {
|
|
|
3313
3313
|
if (/^\d{1,3}(?:,\d{3})*(?:\.\d{2})?$/.test(clean)) return `$${clean}`;
|
|
3314
3314
|
return clean;
|
|
3315
3315
|
}
|
|
3316
|
+
function premiumValue(value) {
|
|
3317
|
+
const clean = cleanValue(value);
|
|
3318
|
+
if (!clean) return void 0;
|
|
3319
|
+
if (/\$[A-Z0-9]/i.test(clean)) return clean;
|
|
3320
|
+
if (/\b(?:CAD|USD)\b/i.test(clean) && /(?:\d|X{2,})/i.test(clean)) return clean;
|
|
3321
|
+
if (/^\d{1,3}(?:,\d{3})+\.\d{2}$/.test(clean) || /^\d+\.\d{2}$/.test(clean)) return `$${clean}`;
|
|
3322
|
+
if (/^X{2,}(?:,X{3})*(?:\.X{2})$/i.test(clean)) return clean;
|
|
3323
|
+
return void 0;
|
|
3324
|
+
}
|
|
3316
3325
|
function nodeText(node) {
|
|
3317
3326
|
return normalizeWhitespace3([
|
|
3318
3327
|
node.title,
|
|
@@ -3328,6 +3337,14 @@ function valueFromNode(node, value, confidence = "medium") {
|
|
|
3328
3337
|
sourceSpanIds: node.sourceSpanIds
|
|
3329
3338
|
};
|
|
3330
3339
|
}
|
|
3340
|
+
function valueFromNodes(nodes, value, confidence = "medium", normalizedValue) {
|
|
3341
|
+
return {
|
|
3342
|
+
value,
|
|
3343
|
+
...normalizedValue ? { normalizedValue } : {},
|
|
3344
|
+
confidence,
|
|
3345
|
+
...sourceIds(nodes)
|
|
3346
|
+
};
|
|
3347
|
+
}
|
|
3331
3348
|
function firstMatch(nodes, patterns) {
|
|
3332
3349
|
for (const node of nodes) {
|
|
3333
3350
|
const text = nodeText(node);
|
|
@@ -3394,27 +3411,96 @@ function firstCleanMatch(nodes, patterns, clean) {
|
|
|
3394
3411
|
function cleanNamedInsured(value) {
|
|
3395
3412
|
const clean = cleanValue(value.replace(/\bborn\s+on\b.*$/i, "").replace(/\bage\s+nearest\b.*$/i, "").replace(/\bbeneficiary\b.*$/i, ""));
|
|
3396
3413
|
if (!clean || clean.length > 160) return void 0;
|
|
3414
|
+
if (!/[A-Za-z0-9]/.test(clean)) return void 0;
|
|
3397
3415
|
if (/^(person|persons)\b/i.test(clean)) return void 0;
|
|
3416
|
+
if (/^(insurance amount|benefit amount|policy number|policy date|owner|beneficiary|premium|coverage|risk classification)\b/i.test(clean)) {
|
|
3417
|
+
return void 0;
|
|
3418
|
+
}
|
|
3398
3419
|
if (/\b(table of contents|policy wording|provided solely|convenience|not to be construed|actual policy issued)\b/i.test(clean)) {
|
|
3399
3420
|
return void 0;
|
|
3400
3421
|
}
|
|
3401
3422
|
return clean;
|
|
3402
3423
|
}
|
|
3424
|
+
var PARTY_LABEL_PATTERNS = {
|
|
3425
|
+
namedInsured: /^(?:item\s*\d+[.)]?\s*)?(?:named insured(?:\s+and\s+address)?|insured name)$/i,
|
|
3426
|
+
insurer: /^(?:carrier|insurer|security)$/i,
|
|
3427
|
+
broker: /^(?:broker(?:\s+of\s+record)?|producer|agent)$/i
|
|
3428
|
+
};
|
|
3429
|
+
function partyLabelKind(value) {
|
|
3430
|
+
const clean = cleanValue(value.replace(/^\s*column\s+\d+\s*:\s*/i, ""));
|
|
3431
|
+
if (!clean) return void 0;
|
|
3432
|
+
if (PARTY_LABEL_PATTERNS.namedInsured.test(clean)) return "namedInsured";
|
|
3433
|
+
if (PARTY_LABEL_PATTERNS.insurer.test(clean)) return "insurer";
|
|
3434
|
+
if (PARTY_LABEL_PATTERNS.broker.test(clean)) return "broker";
|
|
3435
|
+
return void 0;
|
|
3436
|
+
}
|
|
3437
|
+
function isRejectedPartyValue(value) {
|
|
3438
|
+
const clean = normalizeWhitespace3(value);
|
|
3439
|
+
return /^(?:and address|of record|insurer|carrier|security|broker|producer|agent|the|a|an|is|are|was|were|agrees?|means?|includes?|shall|will)\b/i.test(clean);
|
|
3440
|
+
}
|
|
3441
|
+
function identityWithoutAddress(value) {
|
|
3442
|
+
const clean = cleanValue(value.replace(/\b(?:phone|tel|telephone|email|e-mail)\b.*$/i, "").replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b.*$/i, ""));
|
|
3443
|
+
if (!clean) return void 0;
|
|
3444
|
+
const beforeStreet = clean.match(/^(.+?)\s+\d{1,6}\s+[A-Za-z0-9.'-]+(?:\s+[A-Za-z0-9.'-]+){0,5}\s+(?:street|st\.?|avenue|ave\.?|road|rd\.?|drive|dr\.?|lane|ln\.?|boulevard|blvd\.?|suite|ste\.?|floor|fl\.?|way|court|ct\.?)\b/i)?.[1];
|
|
3445
|
+
const beforeCityState = clean.match(/^(.+?)\s+[A-Z][A-Za-z.'-]+(?:\s+[A-Z][A-Za-z.'-]+)*,\s*[A-Z]{2}\s+\d{5}(?:-\d{4})?\b/)?.[1];
|
|
3446
|
+
return cleanValue(beforeStreet ?? beforeCityState ?? clean);
|
|
3447
|
+
}
|
|
3448
|
+
function cleanPartyIdentity(value, clean) {
|
|
3449
|
+
const raw = cleanValue(value);
|
|
3450
|
+
if (!raw || isRejectedPartyValue(raw)) return void 0;
|
|
3451
|
+
const identity = identityWithoutAddress(raw);
|
|
3452
|
+
const cleaned = identity ? clean(identity) : void 0;
|
|
3453
|
+
if (!cleaned || isRejectedPartyValue(cleaned)) return void 0;
|
|
3454
|
+
return {
|
|
3455
|
+
value: cleaned,
|
|
3456
|
+
...cleaned !== raw ? { normalizedValue: cleaned } : {}
|
|
3457
|
+
};
|
|
3458
|
+
}
|
|
3459
|
+
function partyFromTableRows(nodes, wanted, clean) {
|
|
3460
|
+
const children = childMap(nodes);
|
|
3461
|
+
for (const row of compactFactNodes(nodes).filter((node) => node.kind === "table_row")) {
|
|
3462
|
+
const cells = cellRows(row, children);
|
|
3463
|
+
for (const [index, cell] of cells.entries()) {
|
|
3464
|
+
const labelKind = partyLabelKind(cell.value) ?? partyLabelKind(cell.label);
|
|
3465
|
+
if (labelKind !== wanted) continue;
|
|
3466
|
+
const valueCell = cells.slice(index + 1).find((candidate) => !partyLabelKind(candidate.value) && !partyLabelKind(candidate.label));
|
|
3467
|
+
if (!valueCell) continue;
|
|
3468
|
+
const cleaned = cleanPartyIdentity(valueCell.value, clean);
|
|
3469
|
+
if (cleaned) return valueFromNodes([row, valueCell.node], cleaned.value, "high", cleaned.normalizedValue);
|
|
3470
|
+
}
|
|
3471
|
+
const parts = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row)).split(/\s+\|\s+|\t/).map(cleanValue).filter((part) => Boolean(part));
|
|
3472
|
+
for (const [index, part] of parts.entries()) {
|
|
3473
|
+
const labelKind = partyLabelKind(part);
|
|
3474
|
+
if (labelKind !== wanted) continue;
|
|
3475
|
+
const cleaned = cleanPartyIdentity(parts[index + 1] ?? "", clean);
|
|
3476
|
+
if (cleaned) return valueFromNodes([row], cleaned.value, "high", cleaned.normalizedValue);
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
return void 0;
|
|
3480
|
+
}
|
|
3403
3481
|
function namedInsuredFromNodes(nodes) {
|
|
3404
|
-
return firstCleanMatch(nodes, [
|
|
3405
|
-
/\b(?:named insured|insured name
|
|
3482
|
+
return partyFromTableRows(nodes, "namedInsured", cleanNamedInsured) ?? firstCleanMatch(nodes, [
|
|
3483
|
+
/\b(?:named insured|insured name)\s*:?\s*(.+?)(?=\s+(?:insurance amount|benefit amount|policy number|policy date|owner|beneficiary|premium|coverage|risk classification|date this)\b|[|;\n]|$)/i,
|
|
3484
|
+
/\b(?: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,
|
|
3406
3485
|
/\b(?:applicant|policyholder)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i
|
|
3407
3486
|
], cleanNamedInsured);
|
|
3408
3487
|
}
|
|
3409
3488
|
function cleanInsurer(value) {
|
|
3410
3489
|
const clean = cleanValue(value);
|
|
3411
3490
|
if (!clean || clean.length > 140) return void 0;
|
|
3412
|
-
if (/^(mean|means|we|us|our)\b/i.test(clean)) return void 0;
|
|
3491
|
+
if (/^(mean|means|we|us|our|the|a|an|agrees?|shall|will)\b/i.test(clean)) return void 0;
|
|
3413
3492
|
if (/\b(table of contents|policy wording|provided solely|convenience)\b/i.test(clean)) return void 0;
|
|
3414
3493
|
const known = clean.match(/\b(Sun Life Assurance Company of Canada|Manulife|The Manufacturers Life Insurance Company)\b/i)?.[1];
|
|
3415
3494
|
return known ?? clean;
|
|
3416
3495
|
}
|
|
3417
3496
|
function insurerFromNodes(nodes) {
|
|
3497
|
+
const tableValue = partyFromTableRows(nodes, "insurer", cleanInsurer);
|
|
3498
|
+
if (tableValue) return tableValue;
|
|
3499
|
+
for (const node of compactFactNodes(nodes)) {
|
|
3500
|
+
const text = nodeText(node);
|
|
3501
|
+
const value = cleanInsurer(text.match(/\b([A-Z][A-Za-z&.,' -]{2,120}?(?:Insurance|Assurance|Indemnity|Casualty|Underwriting|Mutual|Risk|Reinsurance)\s+Company(?:\s+of\s+[A-Z][A-Za-z .'-]+)?)\s*\(\s*the\s+["']?Insurer["']?\s*\)/i)?.[1] ?? "");
|
|
3502
|
+
if (value) return valueFromNode(node, value, "high");
|
|
3503
|
+
}
|
|
3418
3504
|
return firstCleanMatch(nodes, [
|
|
3419
3505
|
/\bunderwritten by\s+([^|;\n.]{3,160})/i,
|
|
3420
3506
|
/\b(?:insurer|carrier|company|security)\s*:?\s*([^|;\n]{3,120})/i,
|
|
@@ -3460,6 +3546,19 @@ function coverageNameFromRow(text) {
|
|
|
3460
3546
|
);
|
|
3461
3547
|
return cleanCoverageLabel(first);
|
|
3462
3548
|
}
|
|
3549
|
+
function isDeclarationLimitLabel(value) {
|
|
3550
|
+
const label = normalizeLabel(value);
|
|
3551
|
+
return /\bitem\s*\d+[.)]?\s*limits?\s+of\s+liability\b/.test(label) || /^limits?\s+of\s+liability$/.test(label) || /^policy\s+limits?$/.test(label);
|
|
3552
|
+
}
|
|
3553
|
+
function declarationCoverageNameFromRow(row, children) {
|
|
3554
|
+
const cells = cellRows(row, children);
|
|
3555
|
+
const candidates = [
|
|
3556
|
+
row.title,
|
|
3557
|
+
...cells.flatMap((cell) => [cell.label, cell.value])
|
|
3558
|
+
];
|
|
3559
|
+
if (!candidates.some(isDeclarationLimitLabel)) return void 0;
|
|
3560
|
+
return candidates.some((candidate) => /\blimits?\s+of\s+liability\b/i.test(candidate ?? "")) ? "Limits of Liability" : "Policy Limits";
|
|
3561
|
+
}
|
|
3463
3562
|
function limitFromText(text) {
|
|
3464
3563
|
return moneyValue(
|
|
3465
3564
|
text.match(/\b(?:limit|liability|aggregate|occurrence|claim)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?|\$?\d[\d,]*\s*(?:each|per|aggregate)[^|;]*)/i)?.[1] ?? text.match(/(\$\s?\d[\d,]*(?:\.\d{2})?)(?=.*\b(limit|aggregate|occurrence|claim|liability)\b)/i)?.[1]
|
|
@@ -3469,10 +3568,22 @@ function deductibleFromText(text) {
|
|
|
3469
3568
|
return moneyValue(text.match(/\b(?:deductible|retention|sir)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
|
|
3470
3569
|
}
|
|
3471
3570
|
function premiumFromText(text) {
|
|
3472
|
-
return
|
|
3571
|
+
return premiumValue(text.match(/\b(?:premium|total premium|total cost|amount due)\b(?:\s*(?:is|:|-))?\s*(\$?(?:\d[\d,]*(?:\.\d{2})?|X{2,}(?:,X{3})*(?:\.X{2})?))/i)?.[1]);
|
|
3572
|
+
}
|
|
3573
|
+
function premiumFromNodes(nodes) {
|
|
3574
|
+
for (const node of compactFactNodes(nodes)) {
|
|
3575
|
+
const value = premiumFromText(nodeText(node));
|
|
3576
|
+
if (value) return valueFromNode(node, value, "high");
|
|
3577
|
+
}
|
|
3578
|
+
return void 0;
|
|
3473
3579
|
}
|
|
3474
3580
|
function moneyAmount(value) {
|
|
3475
|
-
const
|
|
3581
|
+
const clean = cleanValue(value);
|
|
3582
|
+
if (!clean) return void 0;
|
|
3583
|
+
const currency = clean.match(/\$\s*([0-9][0-9,]*(?:\.\d+)?)/);
|
|
3584
|
+
const percent = clean.match(/\b([0-9][0-9,]*(?:\.\d+)?)\s*%/);
|
|
3585
|
+
const explicitNumeric = !/\bitem\s*\d+\b/i.test(clean) && /\b(?:limit|aggregate|claim|occurrence|loss|retention|deductible|sir|premium|amount)\b/i.test(clean) ? clean.match(/\b([0-9][0-9,]*(?:\.\d+)?)\b/) : void 0;
|
|
3586
|
+
const match = currency ?? percent ?? explicitNumeric;
|
|
3476
3587
|
if (!match) return void 0;
|
|
3477
3588
|
const amount = Number(match[1].replace(/,/g, ""));
|
|
3478
3589
|
return Number.isFinite(amount) ? amount : void 0;
|
|
@@ -3518,6 +3629,10 @@ function isValueCell(label, value) {
|
|
|
3518
3629
|
}
|
|
3519
3630
|
return /\b(limit|aggregate|retention|deductible|sir|retroactive|premium|amount)\b/.test(normalizedLabel) || moneyAmount(value) !== void 0 || /\b(full prior acts|none|included|not included|as stated)\b/.test(normalizedValue);
|
|
3520
3631
|
}
|
|
3632
|
+
function isCoverageTermLabel(value) {
|
|
3633
|
+
const label = normalizeLabel(value);
|
|
3634
|
+
return /\b(limit|aggregate|retention|deductible|sir|retroactive|premium|amount|sub[-\s]?limit)\b/.test(label);
|
|
3635
|
+
}
|
|
3521
3636
|
function isNameCell(label, value) {
|
|
3522
3637
|
const normalizedLabel = normalizeLabel(label);
|
|
3523
3638
|
const normalizedValue = normalizeLabel(value);
|
|
@@ -3619,6 +3734,16 @@ function termFromCell(params) {
|
|
|
3619
3734
|
function termsFromRow(row, children) {
|
|
3620
3735
|
const cells = cellRows(row, children);
|
|
3621
3736
|
if (cells.length > 0) {
|
|
3737
|
+
const pairedTerms = [];
|
|
3738
|
+
for (const [index, cell] of cells.entries()) {
|
|
3739
|
+
const next = cells[index + 1];
|
|
3740
|
+
if (!next) continue;
|
|
3741
|
+
if (!isCoverageTermLabel(cell.value)) continue;
|
|
3742
|
+
if (isCoverageTermLabel(next.value) && moneyAmount(next.value) === void 0) continue;
|
|
3743
|
+
const term = termFromCell({ row, cell: next.node, label: cell.value, value: next.value });
|
|
3744
|
+
if (term) pairedTerms.push(term);
|
|
3745
|
+
}
|
|
3746
|
+
if (pairedTerms.length > 0) return pairedTerms;
|
|
3622
3747
|
return cells.filter((cell) => isValueCell(cell.label, cell.value)).map((cell) => termFromCell({ row, cell: cell.node, label: cell.label, value: cell.value })).filter((term) => Boolean(term));
|
|
3623
3748
|
}
|
|
3624
3749
|
const text = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
@@ -3645,6 +3770,8 @@ function termsFromRow(row, children) {
|
|
|
3645
3770
|
return terms;
|
|
3646
3771
|
}
|
|
3647
3772
|
function nameFromRow(row, children) {
|
|
3773
|
+
const declarationName = declarationCoverageNameFromRow(row, children);
|
|
3774
|
+
if (declarationName) return declarationName;
|
|
3648
3775
|
const cells = cellRows(row, children);
|
|
3649
3776
|
const named = cells.find((cell) => isNameCell(cell.label, cell.value));
|
|
3650
3777
|
if (named) return cleanValue(named.value);
|
|
@@ -3822,7 +3949,7 @@ function buildParties(profile) {
|
|
|
3822
3949
|
if (profile.namedInsured) {
|
|
3823
3950
|
parties.push({
|
|
3824
3951
|
role: "named_insured",
|
|
3825
|
-
name: profile.namedInsured.value,
|
|
3952
|
+
name: profile.namedInsured.normalizedValue ?? profile.namedInsured.value,
|
|
3826
3953
|
sourceNodeIds: profile.namedInsured.sourceNodeIds,
|
|
3827
3954
|
sourceSpanIds: profile.namedInsured.sourceSpanIds
|
|
3828
3955
|
});
|
|
@@ -3830,7 +3957,7 @@ function buildParties(profile) {
|
|
|
3830
3957
|
if (profile.insurer) {
|
|
3831
3958
|
parties.push({
|
|
3832
3959
|
role: "insurer",
|
|
3833
|
-
name: profile.insurer.value,
|
|
3960
|
+
name: profile.insurer.normalizedValue ?? profile.insurer.value,
|
|
3834
3961
|
sourceNodeIds: profile.insurer.sourceNodeIds,
|
|
3835
3962
|
sourceSpanIds: profile.insurer.sourceSpanIds
|
|
3836
3963
|
});
|
|
@@ -3838,7 +3965,7 @@ function buildParties(profile) {
|
|
|
3838
3965
|
if (profile.broker) {
|
|
3839
3966
|
parties.push({
|
|
3840
3967
|
role: "broker",
|
|
3841
|
-
name: profile.broker.value,
|
|
3968
|
+
name: profile.broker.normalizedValue ?? profile.broker.value,
|
|
3842
3969
|
sourceNodeIds: profile.broker.sourceNodeIds,
|
|
3843
3970
|
sourceSpanIds: profile.broker.sourceSpanIds
|
|
3844
3971
|
});
|
|
@@ -3891,9 +4018,7 @@ function buildDeterministicOperationalProfile(params) {
|
|
|
3891
4018
|
retroactiveDate: firstMatch(nodes, [
|
|
3892
4019
|
/\bretroactive date\s*:?\s*([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4}|full prior acts|none)/i
|
|
3893
4020
|
]),
|
|
3894
|
-
premium:
|
|
3895
|
-
/\b(?:total premium|premium|total cost|amount due)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i
|
|
3896
|
-
])
|
|
4021
|
+
premium: premiumFromNodes(nodes)
|
|
3897
4022
|
};
|
|
3898
4023
|
const coverages = buildCoverages(nodes);
|
|
3899
4024
|
const coverageTypes = [...new Set(coverages.map((coverage) => coverage.name))];
|
|
@@ -11277,9 +11402,19 @@ function sourceTreeToOutline(sourceTree) {
|
|
|
11277
11402
|
});
|
|
11278
11403
|
return (byParent.get(root?.id) ?? []).map(visit);
|
|
11279
11404
|
}
|
|
11405
|
+
var NORMALIZED_COMPATIBILITY_FIELDS = /* @__PURE__ */ new Set([
|
|
11406
|
+
"policyNumber",
|
|
11407
|
+
"namedInsured",
|
|
11408
|
+
"insurer",
|
|
11409
|
+
"broker"
|
|
11410
|
+
]);
|
|
11280
11411
|
function valueOf(profile, key) {
|
|
11281
11412
|
const value = profile[key];
|
|
11282
|
-
|
|
11413
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || !("value" in value)) return void 0;
|
|
11414
|
+
if (NORMALIZED_COMPATIBILITY_FIELDS.has(key) && "normalizedValue" in value && typeof value.normalizedValue === "string" && value.normalizedValue.trim()) {
|
|
11415
|
+
return value.normalizedValue;
|
|
11416
|
+
}
|
|
11417
|
+
return String(value.value);
|
|
11283
11418
|
}
|
|
11284
11419
|
function materializeDocument(params) {
|
|
11285
11420
|
const profile = params.operationalProfile;
|