@claritylabs/cl-sdk 3.0.22 → 3.0.24
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/README.md +1 -1
- package/dist/index.d.mts +155 -1
- package/dist/index.d.ts +155 -1
- package/dist/index.js +380 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +379 -16
- package/dist/index.mjs.map +1 -1
- package/dist/storage-sqlite.js +24 -0
- package/dist/storage-sqlite.js.map +1 -1
- package/dist/storage-sqlite.mjs +24 -0
- package/dist/storage-sqlite.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -165,6 +165,7 @@ __export(index_exports, {
|
|
|
165
165
|
MissingInfoQuestionSchema: () => MissingInfoQuestionSchema,
|
|
166
166
|
NamedInsuredSchema: () => NamedInsuredSchema,
|
|
167
167
|
OperationalCoverageLineSchema: () => OperationalCoverageLineSchema,
|
|
168
|
+
OperationalCoverageTermSchema: () => OperationalCoverageTermSchema,
|
|
168
169
|
OperationalEndorsementSupportSchema: () => OperationalEndorsementSupportSchema,
|
|
169
170
|
OperationalPartySchema: () => OperationalPartySchema,
|
|
170
171
|
PERSONAL_AUTO_USAGES: () => PERSONAL_AUTO_USAGES,
|
|
@@ -2400,14 +2401,38 @@ var SourceBackedValueSchema = import_zod20.z.object({
|
|
|
2400
2401
|
sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
|
|
2401
2402
|
sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([])
|
|
2402
2403
|
});
|
|
2404
|
+
var OperationalCoverageTermSchema = import_zod20.z.object({
|
|
2405
|
+
kind: import_zod20.z.enum([
|
|
2406
|
+
"each_claim_limit",
|
|
2407
|
+
"each_occurrence_limit",
|
|
2408
|
+
"each_loss_limit",
|
|
2409
|
+
"aggregate_limit",
|
|
2410
|
+
"sublimit",
|
|
2411
|
+
"retention",
|
|
2412
|
+
"deductible",
|
|
2413
|
+
"retroactive_date",
|
|
2414
|
+
"premium",
|
|
2415
|
+
"other"
|
|
2416
|
+
]).default("other"),
|
|
2417
|
+
label: import_zod20.z.string(),
|
|
2418
|
+
value: import_zod20.z.string(),
|
|
2419
|
+
amount: import_zod20.z.number().optional(),
|
|
2420
|
+
appliesTo: import_zod20.z.string().optional(),
|
|
2421
|
+
sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
|
|
2422
|
+
sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([])
|
|
2423
|
+
});
|
|
2403
2424
|
var OperationalCoverageLineSchema = import_zod20.z.object({
|
|
2404
2425
|
name: import_zod20.z.string(),
|
|
2405
2426
|
coverageCode: import_zod20.z.string().optional(),
|
|
2406
2427
|
limit: import_zod20.z.string().optional(),
|
|
2407
2428
|
deductible: import_zod20.z.string().optional(),
|
|
2408
2429
|
premium: import_zod20.z.string().optional(),
|
|
2430
|
+
retroactiveDate: import_zod20.z.string().optional(),
|
|
2409
2431
|
formNumber: import_zod20.z.string().optional(),
|
|
2410
2432
|
sectionRef: import_zod20.z.string().optional(),
|
|
2433
|
+
coverageOrigin: import_zod20.z.enum(["core", "endorsement"]).optional(),
|
|
2434
|
+
endorsementNumber: import_zod20.z.string().optional(),
|
|
2435
|
+
limits: import_zod20.z.array(OperationalCoverageTermSchema).default([]),
|
|
2411
2436
|
sourceNodeIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([]),
|
|
2412
2437
|
sourceSpanIds: import_zod20.z.array(import_zod20.z.string().min(1)).default([])
|
|
2413
2438
|
});
|
|
@@ -3275,6 +3300,9 @@ function cleanValue(value) {
|
|
|
3275
3300
|
if (!value) return void 0;
|
|
3276
3301
|
return normalizeWhitespace3(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
|
|
3277
3302
|
}
|
|
3303
|
+
function cleanCoverageLabel(value) {
|
|
3304
|
+
return cleanValue(value)?.replace(/^column\s+\d+\s*:\s*/i, "");
|
|
3305
|
+
}
|
|
3278
3306
|
function moneyValue(value) {
|
|
3279
3307
|
const clean = cleanValue(value);
|
|
3280
3308
|
if (!clean) return void 0;
|
|
@@ -3332,12 +3360,12 @@ function inferDocumentType(nodes) {
|
|
|
3332
3360
|
}
|
|
3333
3361
|
function coverageNameFromRow(text) {
|
|
3334
3362
|
const labelled = text.match(/\b(?:coverage|coverage part|line)\s*:?\s*([^|;$]{3,80})/i)?.[1];
|
|
3335
|
-
if (labelled) return
|
|
3336
|
-
const parts = text.split(/\s+\|\s+| {2,}|\t/).map(
|
|
3363
|
+
if (labelled) return cleanCoverageLabel(labelled);
|
|
3364
|
+
const parts = text.split(/\s+\|\s+| {2,}|\t/).map(cleanCoverageLabel).filter(Boolean);
|
|
3337
3365
|
const first = parts.find(
|
|
3338
3366
|
(part) => !/^(limit|limits?|deductible|premium|amount|basis|rate|retroactive|aggregate|each occurrence)$/i.test(part) && !/^\$?[\d,]+/.test(part)
|
|
3339
3367
|
);
|
|
3340
|
-
return
|
|
3368
|
+
return cleanCoverageLabel(first);
|
|
3341
3369
|
}
|
|
3342
3370
|
function limitFromText(text) {
|
|
3343
3371
|
return moneyValue(
|
|
@@ -3350,14 +3378,292 @@ function deductibleFromText(text) {
|
|
|
3350
3378
|
function premiumFromText(text) {
|
|
3351
3379
|
return moneyValue(text.match(/\b(?:premium|total premium|total cost|amount due)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
|
|
3352
3380
|
}
|
|
3381
|
+
function moneyAmount(value) {
|
|
3382
|
+
const match = value?.match(/\$?\s*([0-9][0-9,]*(?:\.\d+)?)/);
|
|
3383
|
+
if (!match) return void 0;
|
|
3384
|
+
const amount = Number(match[1].replace(/,/g, ""));
|
|
3385
|
+
return Number.isFinite(amount) ? amount : void 0;
|
|
3386
|
+
}
|
|
3387
|
+
function normalizeLabel(value) {
|
|
3388
|
+
return normalizeWhitespace3(value ?? "").toLowerCase();
|
|
3389
|
+
}
|
|
3390
|
+
var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
|
|
3391
|
+
"each_claim_limit",
|
|
3392
|
+
"each_occurrence_limit",
|
|
3393
|
+
"each_loss_limit",
|
|
3394
|
+
"aggregate_limit",
|
|
3395
|
+
"sublimit",
|
|
3396
|
+
"retention",
|
|
3397
|
+
"deductible",
|
|
3398
|
+
"retroactive_date",
|
|
3399
|
+
"premium",
|
|
3400
|
+
"other"
|
|
3401
|
+
]);
|
|
3402
|
+
function termKind(label, value) {
|
|
3403
|
+
const text = normalizeLabel(`${label} ${value}`);
|
|
3404
|
+
if (/\bretroactive\b/.test(text)) return "retroactive_date";
|
|
3405
|
+
if (/\b(self[-\s]?insured retention|retention|sir)\b/.test(text)) return "retention";
|
|
3406
|
+
if (/\bdeductible\b/.test(text)) return "deductible";
|
|
3407
|
+
if (/\bpremium\b/.test(text)) return "premium";
|
|
3408
|
+
if (/\bsub[-\s]?limit\b/.test(text)) return "sublimit";
|
|
3409
|
+
if (/\baggregate\b/.test(text)) return "aggregate_limit";
|
|
3410
|
+
if (/\beach\s+claim|per\s+claim\b/.test(text)) return "each_claim_limit";
|
|
3411
|
+
if (/\beach\s+occurrence|per\s+occurrence\b/.test(text)) return "each_occurrence_limit";
|
|
3412
|
+
if (/\beach\s+loss|per\s+loss\b/.test(text)) return "each_loss_limit";
|
|
3413
|
+
if (/\blimit\b/.test(text)) return "other";
|
|
3414
|
+
return "other";
|
|
3415
|
+
}
|
|
3416
|
+
function normalizeTermKind(value, label, termValue) {
|
|
3417
|
+
return typeof value === "string" && OPERATIONAL_COVERAGE_TERM_KINDS.has(value) ? value : termKind(label, termValue);
|
|
3418
|
+
}
|
|
3419
|
+
function isValueCell(label, value) {
|
|
3420
|
+
const normalizedLabel = normalizeLabel(label);
|
|
3421
|
+
const normalizedValue = normalizeLabel(value);
|
|
3422
|
+
if (!value || normalizedValue === "\u2014") return false;
|
|
3423
|
+
if (/\b(policy\s*(number|no|#)|named insured|insured|carrier|company|broker|producer|agent|coverage|coverage part|description|item|name|form|source)\b/.test(normalizedLabel)) {
|
|
3424
|
+
return false;
|
|
3425
|
+
}
|
|
3426
|
+
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);
|
|
3427
|
+
}
|
|
3428
|
+
function isNameCell(label, value) {
|
|
3429
|
+
const normalizedLabel = normalizeLabel(label);
|
|
3430
|
+
const normalizedValue = normalizeLabel(value);
|
|
3431
|
+
if (!value || moneyAmount(value) !== void 0) return false;
|
|
3432
|
+
if (/\b(coverage|coverage part|insuring agreement|description|item|name)\b/.test(normalizedLabel)) {
|
|
3433
|
+
return true;
|
|
3434
|
+
}
|
|
3435
|
+
if (/^column\s+\d+$/.test(normalizedLabel) && /\b(coverage|sub[-\s]?limit|liability|expense|part\s+[a-z])\b/.test(normalizedValue)) {
|
|
3436
|
+
return true;
|
|
3437
|
+
}
|
|
3438
|
+
return false;
|
|
3439
|
+
}
|
|
3440
|
+
function childMap(nodes) {
|
|
3441
|
+
const children = /* @__PURE__ */ new Map();
|
|
3442
|
+
for (const node of nodes) {
|
|
3443
|
+
const group = children.get(node.parentId) ?? [];
|
|
3444
|
+
group.push(node);
|
|
3445
|
+
children.set(node.parentId, group);
|
|
3446
|
+
}
|
|
3447
|
+
for (const group of children.values()) group.sort((left, right) => left.order - right.order);
|
|
3448
|
+
return children;
|
|
3449
|
+
}
|
|
3450
|
+
function cellRows(row, children) {
|
|
3451
|
+
return (children.get(row.id) ?? []).filter((child) => child.kind === "table_cell").map((cell) => ({
|
|
3452
|
+
label: cleanValue(cell.title) ?? "Value",
|
|
3453
|
+
value: cleanValue(cell.textExcerpt ?? cell.description ?? cell.title) ?? "",
|
|
3454
|
+
node: cell
|
|
3455
|
+
})).filter((cell) => cell.value);
|
|
3456
|
+
}
|
|
3457
|
+
function directChildren(parent, children) {
|
|
3458
|
+
return children.get(parent.id) ?? [];
|
|
3459
|
+
}
|
|
3460
|
+
function descendants(parent, children) {
|
|
3461
|
+
const stack = [...directChildren(parent, children)];
|
|
3462
|
+
const result = [];
|
|
3463
|
+
while (stack.length > 0) {
|
|
3464
|
+
const node = stack.shift();
|
|
3465
|
+
result.push(node);
|
|
3466
|
+
stack.unshift(...directChildren(node, children));
|
|
3467
|
+
}
|
|
3468
|
+
return result;
|
|
3469
|
+
}
|
|
3470
|
+
function ancestry(node, byId) {
|
|
3471
|
+
const result = [];
|
|
3472
|
+
let current = node.parentId ? byId.get(node.parentId) : void 0;
|
|
3473
|
+
while (current) {
|
|
3474
|
+
result.push(current);
|
|
3475
|
+
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
3476
|
+
}
|
|
3477
|
+
return result;
|
|
3478
|
+
}
|
|
3479
|
+
function endorsementAncestor(node, byId) {
|
|
3480
|
+
return ancestry(node, byId).find((ancestor) => ancestor.kind === "endorsement");
|
|
3481
|
+
}
|
|
3482
|
+
function endorsementNumberFrom(value) {
|
|
3483
|
+
return cleanValue(value?.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)/i)?.[1]);
|
|
3484
|
+
}
|
|
3485
|
+
function endorsementNameFrom(node) {
|
|
3486
|
+
const candidates = [node.title, node.textExcerpt, node.description, nodeText(node)].filter(Boolean);
|
|
3487
|
+
for (const candidate of candidates) {
|
|
3488
|
+
const match = candidate.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)\s*[—-]\s*(.{3,140}?)(?=\s+This\s+endorsement\b|\.|$)/i);
|
|
3489
|
+
if (match) return cleanValue(`Endorsement No. ${match[1]} - ${match[2]}`) ?? node.title;
|
|
3490
|
+
}
|
|
3491
|
+
return node.title;
|
|
3492
|
+
}
|
|
3493
|
+
function sourceIds(nodes) {
|
|
3494
|
+
return {
|
|
3495
|
+
sourceNodeIds: [...new Set(nodes.map((node) => node.id))],
|
|
3496
|
+
sourceSpanIds: [...new Set(nodes.flatMap((node) => node.sourceSpanIds))]
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
function relabelGenericTerm(term, label) {
|
|
3500
|
+
const cleanLabel = cleanValue(label);
|
|
3501
|
+
if (!cleanLabel || !/^column\s+\d+$/i.test(term.label)) return term;
|
|
3502
|
+
return {
|
|
3503
|
+
...term,
|
|
3504
|
+
kind: termKind(cleanLabel, term.value),
|
|
3505
|
+
label: cleanLabel
|
|
3506
|
+
};
|
|
3507
|
+
}
|
|
3508
|
+
function termFromCell(params) {
|
|
3509
|
+
const value = cleanValue(params.value);
|
|
3510
|
+
if (!value) return void 0;
|
|
3511
|
+
const nodes = [params.row, params.cell].filter((node) => Boolean(node));
|
|
3512
|
+
const kind = termKind(params.label, value);
|
|
3513
|
+
const amount = moneyAmount(value);
|
|
3514
|
+
return {
|
|
3515
|
+
kind,
|
|
3516
|
+
label: params.label,
|
|
3517
|
+
value,
|
|
3518
|
+
...amount !== void 0 && kind !== "retroactive_date" ? { amount } : {},
|
|
3519
|
+
...params.appliesTo ? { appliesTo: params.appliesTo } : {},
|
|
3520
|
+
...sourceIds(nodes)
|
|
3521
|
+
};
|
|
3522
|
+
}
|
|
3523
|
+
function termsFromRow(row, children) {
|
|
3524
|
+
const cells = cellRows(row, children);
|
|
3525
|
+
if (cells.length > 0) {
|
|
3526
|
+
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));
|
|
3527
|
+
}
|
|
3528
|
+
const text = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
3529
|
+
const terms = [];
|
|
3530
|
+
for (const part of text.split(/\s+\|\s+/)) {
|
|
3531
|
+
const match = part.match(/^([^:]{2,80}):\s*(.+)$/);
|
|
3532
|
+
if (!match) continue;
|
|
3533
|
+
if (!isValueCell(match[1], match[2])) continue;
|
|
3534
|
+
const term = termFromCell({ row, label: cleanValue(match[1]) ?? "Value", value: match[2] });
|
|
3535
|
+
if (term) terms.push(term);
|
|
3536
|
+
}
|
|
3537
|
+
if (terms.length === 0) {
|
|
3538
|
+
const limit = limitFromText(text);
|
|
3539
|
+
if (limit) {
|
|
3540
|
+
const term = termFromCell({ row, label: "Limit", value: limit });
|
|
3541
|
+
if (term) terms.push(term);
|
|
3542
|
+
}
|
|
3543
|
+
const deductible = deductibleFromText(text);
|
|
3544
|
+
if (deductible) {
|
|
3545
|
+
const term = termFromCell({ row, label: "Deductible", value: deductible });
|
|
3546
|
+
if (term) terms.push(term);
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
return terms;
|
|
3550
|
+
}
|
|
3551
|
+
function nameFromRow(row, children) {
|
|
3552
|
+
const cells = cellRows(row, children);
|
|
3553
|
+
const named = cells.find((cell) => isNameCell(cell.label, cell.value));
|
|
3554
|
+
if (named) return cleanValue(named.value);
|
|
3555
|
+
return coverageNameFromRow(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
3556
|
+
}
|
|
3557
|
+
function legacyLimit(terms) {
|
|
3558
|
+
return terms.find(
|
|
3559
|
+
(term) => ["each_claim_limit", "each_occurrence_limit", "each_loss_limit", "aggregate_limit", "sublimit", "other"].includes(term.kind)
|
|
3560
|
+
)?.value;
|
|
3561
|
+
}
|
|
3562
|
+
function legacyDeductible(terms) {
|
|
3563
|
+
return terms.find((term) => term.kind === "deductible" || term.kind === "retention")?.value;
|
|
3564
|
+
}
|
|
3565
|
+
function legacyPremium(terms) {
|
|
3566
|
+
return terms.find((term) => term.kind === "premium")?.value;
|
|
3567
|
+
}
|
|
3568
|
+
function retroDate(terms) {
|
|
3569
|
+
return terms.find((term) => term.kind === "retroactive_date")?.value;
|
|
3570
|
+
}
|
|
3571
|
+
function uniqueTerms(terms) {
|
|
3572
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3573
|
+
const result = [];
|
|
3574
|
+
for (const term of terms) {
|
|
3575
|
+
const key = [term.kind, term.label.toLowerCase(), term.value.toLowerCase(), term.appliesTo ?? ""].join("|");
|
|
3576
|
+
if (seen.has(key)) continue;
|
|
3577
|
+
seen.add(key);
|
|
3578
|
+
result.push(term);
|
|
3579
|
+
}
|
|
3580
|
+
return result;
|
|
3581
|
+
}
|
|
3582
|
+
function coverageFromTableRow(row, children, byId) {
|
|
3583
|
+
if (row.metadata?.isHeader === true || row.metadata?.isHeader === "true") return void 0;
|
|
3584
|
+
const name = nameFromRow(row, children);
|
|
3585
|
+
const terms = uniqueTerms(termsFromRow(row, children));
|
|
3586
|
+
if (!name || terms.length === 0) return void 0;
|
|
3587
|
+
const ids = sourceIds([row, ...directChildren(row, children)]);
|
|
3588
|
+
const endorsement = endorsementAncestor(row, byId);
|
|
3589
|
+
return {
|
|
3590
|
+
name,
|
|
3591
|
+
limit: legacyLimit(terms),
|
|
3592
|
+
deductible: legacyDeductible(terms),
|
|
3593
|
+
premium: legacyPremium(terms),
|
|
3594
|
+
retroactiveDate: retroDate(terms),
|
|
3595
|
+
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3596
|
+
sectionRef: endorsement?.title,
|
|
3597
|
+
coverageOrigin: endorsement ? "endorsement" : "core",
|
|
3598
|
+
endorsementNumber: endorsementNumberFrom(endorsement?.title),
|
|
3599
|
+
limits: terms,
|
|
3600
|
+
...ids
|
|
3601
|
+
};
|
|
3602
|
+
}
|
|
3603
|
+
function coverageFromEndorsement(endorsement, children) {
|
|
3604
|
+
const rows = descendants(endorsement, children).filter((node) => node.kind === "table_row");
|
|
3605
|
+
const terms = uniqueTerms(rows.flatMap(
|
|
3606
|
+
(row) => termsFromRow(row, children).map((term) => {
|
|
3607
|
+
const appliesTo = nameFromRow(row, children);
|
|
3608
|
+
const labelled = relabelGenericTerm(term, appliesTo);
|
|
3609
|
+
return appliesTo && labelled.label !== appliesTo ? { ...labelled, appliesTo } : labelled;
|
|
3610
|
+
})
|
|
3611
|
+
));
|
|
3612
|
+
if (terms.length === 0) return void 0;
|
|
3613
|
+
const ids = sourceIds([endorsement, ...rows, ...rows.flatMap((row) => directChildren(row, children))]);
|
|
3614
|
+
const name = endorsementNameFrom(endorsement);
|
|
3615
|
+
return {
|
|
3616
|
+
name,
|
|
3617
|
+
limit: legacyLimit(terms),
|
|
3618
|
+
deductible: legacyDeductible(terms),
|
|
3619
|
+
premium: legacyPremium(terms),
|
|
3620
|
+
retroactiveDate: retroDate(terms),
|
|
3621
|
+
formNumber: typeof endorsement.metadata?.formNumber === "string" ? endorsement.metadata.formNumber : void 0,
|
|
3622
|
+
sectionRef: name,
|
|
3623
|
+
coverageOrigin: "endorsement",
|
|
3624
|
+
endorsementNumber: endorsementNumberFrom(name),
|
|
3625
|
+
limits: terms,
|
|
3626
|
+
...ids
|
|
3627
|
+
};
|
|
3628
|
+
}
|
|
3629
|
+
function hasDescendantEndorsementWithTableRows(endorsement, children) {
|
|
3630
|
+
return descendants(endorsement, children).some(
|
|
3631
|
+
(node) => node.kind === "endorsement" && descendants(node, children).some((descendant) => descendant.kind === "table_row")
|
|
3632
|
+
);
|
|
3633
|
+
}
|
|
3353
3634
|
function buildCoverages(nodes) {
|
|
3635
|
+
const children = childMap(nodes);
|
|
3636
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
3637
|
+
const coverages = [];
|
|
3638
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3639
|
+
for (const endorsement of nodes.filter((node) => node.kind === "endorsement")) {
|
|
3640
|
+
if (hasDescendantEndorsementWithTableRows(endorsement, children)) continue;
|
|
3641
|
+
const coverage = coverageFromEndorsement(endorsement, children);
|
|
3642
|
+
if (!coverage) continue;
|
|
3643
|
+
const key = [coverage.name.toLowerCase(), coverage.sourceNodeIds.join(",")].join("|");
|
|
3644
|
+
if (seen.has(key)) continue;
|
|
3645
|
+
seen.add(key);
|
|
3646
|
+
coverages.push(coverage);
|
|
3647
|
+
}
|
|
3354
3648
|
const rows = nodes.filter((node) => {
|
|
3355
3649
|
const text = nodeText(node);
|
|
3356
|
-
return (node.kind === "table_row" || node.kind === "schedule" || node.kind === "text") && /\b(coverage|limit|deductible|aggregate|occurrence|liability|premium)\b/i.test(text);
|
|
3650
|
+
return (node.kind === "table_row" || node.kind === "schedule" || node.kind === "text") && /\b(coverage|limit|deductible|aggregate|occurrence|liability|premium|retroactive|retention)\b/i.test(text);
|
|
3357
3651
|
});
|
|
3358
|
-
const coverages = [];
|
|
3359
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3360
3652
|
for (const row of rows) {
|
|
3653
|
+
if (endorsementAncestor(row, byId)) continue;
|
|
3654
|
+
const structured = row.kind === "table_row" ? coverageFromTableRow(row, children, byId) : void 0;
|
|
3655
|
+
if (structured) {
|
|
3656
|
+
const key2 = [
|
|
3657
|
+
structured.name.toLowerCase(),
|
|
3658
|
+
structured.limits.map((term) => `${term.kind}:${term.value}`).join(","),
|
|
3659
|
+
structured.sourceNodeIds.join(",")
|
|
3660
|
+
].join("|");
|
|
3661
|
+
if (seen.has(key2)) continue;
|
|
3662
|
+
seen.add(key2);
|
|
3663
|
+
coverages.push(structured);
|
|
3664
|
+
if (coverages.length >= 60) break;
|
|
3665
|
+
continue;
|
|
3666
|
+
}
|
|
3361
3667
|
const text = nodeText(row);
|
|
3362
3668
|
const name = coverageNameFromRow(text);
|
|
3363
3669
|
const limit = limitFromText(text);
|
|
@@ -3373,6 +3679,8 @@ function buildCoverages(nodes) {
|
|
|
3373
3679
|
deductible,
|
|
3374
3680
|
premium,
|
|
3375
3681
|
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3682
|
+
coverageOrigin: "core",
|
|
3683
|
+
limits: [],
|
|
3376
3684
|
sourceNodeIds: [row.id],
|
|
3377
3685
|
sourceSpanIds: row.sourceSpanIds
|
|
3378
3686
|
});
|
|
@@ -3514,11 +3822,33 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
|
|
|
3514
3822
|
sourceSpanIds
|
|
3515
3823
|
};
|
|
3516
3824
|
};
|
|
3517
|
-
const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) =>
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3825
|
+
const coverages = base.coverages.length > 0 ? base.coverages : Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
|
|
3826
|
+
const record = coverage;
|
|
3827
|
+
const limits = Array.isArray(record.limits) ? record.limits.filter(
|
|
3828
|
+
(term) => Boolean(term) && typeof term === "object" && !Array.isArray(term)
|
|
3829
|
+
).flatMap((term) => {
|
|
3830
|
+
const label = typeof term.label === "string" ? cleanValue(term.label) : void 0;
|
|
3831
|
+
const value = typeof term.value === "string" ? cleanValue(term.value) : void 0;
|
|
3832
|
+
const sourceNodeIds = keepIds(term.sourceNodeIds, validNodeIds);
|
|
3833
|
+
const sourceSpanIds = keepIds(term.sourceSpanIds, validSpanIds);
|
|
3834
|
+
if (!label || !value || sourceNodeIds.length === 0 && sourceSpanIds.length === 0) return [];
|
|
3835
|
+
return [{
|
|
3836
|
+
kind: normalizeTermKind(term.kind, label, value),
|
|
3837
|
+
label,
|
|
3838
|
+
value,
|
|
3839
|
+
amount: typeof term.amount === "number" && Number.isFinite(term.amount) ? term.amount : void 0,
|
|
3840
|
+
appliesTo: typeof term.appliesTo === "string" ? term.appliesTo : void 0,
|
|
3841
|
+
sourceNodeIds,
|
|
3842
|
+
sourceSpanIds
|
|
3843
|
+
}];
|
|
3844
|
+
}) : [];
|
|
3845
|
+
return {
|
|
3846
|
+
...coverage,
|
|
3847
|
+
limits,
|
|
3848
|
+
sourceNodeIds: keepIds(record.sourceNodeIds, validNodeIds),
|
|
3849
|
+
sourceSpanIds: keepIds(record.sourceSpanIds, validSpanIds)
|
|
3850
|
+
};
|
|
3851
|
+
}).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
|
|
3522
3852
|
return PolicyOperationalProfileSchema.parse({
|
|
3523
3853
|
...base,
|
|
3524
3854
|
documentType: candidate.documentType === "quote" ? "quote" : candidate.documentType === "policy" ? "policy" : base.documentType,
|
|
@@ -9520,8 +9850,31 @@ var OperationalProfilePromptSchema = import_zod41.z.object({
|
|
|
9520
9850
|
limit: import_zod41.z.string().optional(),
|
|
9521
9851
|
deductible: import_zod41.z.string().optional(),
|
|
9522
9852
|
premium: import_zod41.z.string().optional(),
|
|
9853
|
+
retroactiveDate: import_zod41.z.string().optional(),
|
|
9523
9854
|
formNumber: import_zod41.z.string().optional(),
|
|
9524
9855
|
sectionRef: import_zod41.z.string().optional(),
|
|
9856
|
+
coverageOrigin: import_zod41.z.enum(["core", "endorsement"]).optional(),
|
|
9857
|
+
endorsementNumber: import_zod41.z.string().optional(),
|
|
9858
|
+
limits: import_zod41.z.array(import_zod41.z.object({
|
|
9859
|
+
kind: import_zod41.z.enum([
|
|
9860
|
+
"each_claim_limit",
|
|
9861
|
+
"each_occurrence_limit",
|
|
9862
|
+
"each_loss_limit",
|
|
9863
|
+
"aggregate_limit",
|
|
9864
|
+
"sublimit",
|
|
9865
|
+
"retention",
|
|
9866
|
+
"deductible",
|
|
9867
|
+
"retroactive_date",
|
|
9868
|
+
"premium",
|
|
9869
|
+
"other"
|
|
9870
|
+
]).optional(),
|
|
9871
|
+
label: import_zod41.z.string(),
|
|
9872
|
+
value: import_zod41.z.string(),
|
|
9873
|
+
amount: import_zod41.z.number().optional(),
|
|
9874
|
+
appliesTo: import_zod41.z.string().optional(),
|
|
9875
|
+
sourceNodeIds: import_zod41.z.array(import_zod41.z.string()),
|
|
9876
|
+
sourceSpanIds: import_zod41.z.array(import_zod41.z.string())
|
|
9877
|
+
})).optional(),
|
|
9525
9878
|
sourceNodeIds: import_zod41.z.array(import_zod41.z.string()),
|
|
9526
9879
|
sourceSpanIds: import_zod41.z.array(import_zod41.z.string())
|
|
9527
9880
|
})).optional(),
|
|
@@ -10335,8 +10688,8 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
10335
10688
|
const current = updates.get(child.id) ?? child;
|
|
10336
10689
|
const heading = sectionHeadingTitle(current, container);
|
|
10337
10690
|
if (heading) {
|
|
10338
|
-
const
|
|
10339
|
-
const hasOwnContent =
|
|
10691
|
+
const descendants2 = byParent.get(child.id) ?? [];
|
|
10692
|
+
const hasOwnContent = descendants2.some((descendant) => descendant.kind !== "table_row" && descendant.kind !== "table_cell");
|
|
10340
10693
|
let hasFollowingContent = false;
|
|
10341
10694
|
for (const nextChild of directPageChildren.slice(index + 1)) {
|
|
10342
10695
|
const next = updates.get(nextChild.id) ?? nextChild;
|
|
@@ -10354,7 +10707,7 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
10354
10707
|
parentId: container.id,
|
|
10355
10708
|
kind: sectionKindForTitle(heading),
|
|
10356
10709
|
title: heading,
|
|
10357
|
-
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...
|
|
10710
|
+
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...descendants2]),
|
|
10358
10711
|
metadata: {
|
|
10359
10712
|
...current.metadata,
|
|
10360
10713
|
organizer: "title_section",
|
|
@@ -10684,13 +11037,16 @@ function buildOperationalProfilePrompt(sourceTree, fallback) {
|
|
|
10684
11037
|
|
|
10685
11038
|
Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
|
|
10686
11039
|
- policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium
|
|
10687
|
-
- coverage
|
|
11040
|
+
- coverage units with their own nested limit terms, deductibles/retentions, retroactive dates, premiums, and form references
|
|
10688
11041
|
- coverage type labels
|
|
10689
11042
|
|
|
10690
11043
|
Rules:
|
|
10691
11044
|
- Every returned value must include sourceNodeIds or sourceSpanIds from the provided nodes.
|
|
10692
11045
|
- If a value is not directly supported, omit it.
|
|
10693
11046
|
- Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
|
|
11047
|
+
- Treat an endorsement as one coverage unit when it contains a schedule. Do not split an endorsement schedule into generic rows like "Aggregate Limit".
|
|
11048
|
+
- 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.
|
|
11049
|
+
- Use coverageOrigin: "endorsement" for endorsement units and "core" for declarations/core policy coverage units.
|
|
10694
11050
|
- Do not copy entire policy wording into fields.
|
|
10695
11051
|
|
|
10696
11052
|
Deterministic baseline:
|
|
@@ -10806,11 +11162,18 @@ function materializeDocument(params) {
|
|
|
10806
11162
|
limit: coverage.limit,
|
|
10807
11163
|
deductible: coverage.deductible,
|
|
10808
11164
|
premium: coverage.premium,
|
|
11165
|
+
retroactiveDate: coverage.retroactiveDate,
|
|
10809
11166
|
formNumber: coverage.formNumber,
|
|
10810
11167
|
sectionRef: coverage.sectionRef,
|
|
11168
|
+
coverageOrigin: coverage.coverageOrigin,
|
|
11169
|
+
endorsementNumber: coverage.endorsementNumber,
|
|
11170
|
+
limits: coverage.limits,
|
|
10811
11171
|
sourceSpanIds: coverage.sourceSpanIds,
|
|
10812
11172
|
documentNodeId: coverage.sourceNodeIds[0],
|
|
10813
|
-
originalContent: [
|
|
11173
|
+
originalContent: [
|
|
11174
|
+
coverage.name,
|
|
11175
|
+
...coverage.limits?.length ? coverage.limits.map((term) => `${term.label}: ${term.value}`) : [coverage.limit, coverage.deductible, coverage.premium]
|
|
11176
|
+
].filter(Boolean).join(" | ")
|
|
10814
11177
|
}));
|
|
10815
11178
|
const documentOutline = sourceTreeToOutline(params.sourceTree);
|
|
10816
11179
|
const documentMetadata = {
|
|
@@ -15937,6 +16300,7 @@ var AGENT_TOOLS = [
|
|
|
15937
16300
|
MissingInfoQuestionSchema,
|
|
15938
16301
|
NamedInsuredSchema,
|
|
15939
16302
|
OperationalCoverageLineSchema,
|
|
16303
|
+
OperationalCoverageTermSchema,
|
|
15940
16304
|
OperationalEndorsementSupportSchema,
|
|
15941
16305
|
OperationalPartySchema,
|
|
15942
16306
|
PERSONAL_AUTO_USAGES,
|