@claritylabs/cl-sdk 3.0.21 → 3.0.23
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 +367 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +366 -14
- 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
|
});
|
|
@@ -3350,14 +3375,265 @@ function deductibleFromText(text) {
|
|
|
3350
3375
|
function premiumFromText(text) {
|
|
3351
3376
|
return moneyValue(text.match(/\b(?:premium|total premium|total cost|amount due)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
|
|
3352
3377
|
}
|
|
3378
|
+
function moneyAmount(value) {
|
|
3379
|
+
const match = value?.match(/\$?\s*([0-9][0-9,]*(?:\.\d+)?)/);
|
|
3380
|
+
if (!match) return void 0;
|
|
3381
|
+
const amount = Number(match[1].replace(/,/g, ""));
|
|
3382
|
+
return Number.isFinite(amount) ? amount : void 0;
|
|
3383
|
+
}
|
|
3384
|
+
function normalizeLabel(value) {
|
|
3385
|
+
return normalizeWhitespace3(value ?? "").toLowerCase();
|
|
3386
|
+
}
|
|
3387
|
+
var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
|
|
3388
|
+
"each_claim_limit",
|
|
3389
|
+
"each_occurrence_limit",
|
|
3390
|
+
"each_loss_limit",
|
|
3391
|
+
"aggregate_limit",
|
|
3392
|
+
"sublimit",
|
|
3393
|
+
"retention",
|
|
3394
|
+
"deductible",
|
|
3395
|
+
"retroactive_date",
|
|
3396
|
+
"premium",
|
|
3397
|
+
"other"
|
|
3398
|
+
]);
|
|
3399
|
+
function termKind(label, value) {
|
|
3400
|
+
const text = normalizeLabel(`${label} ${value}`);
|
|
3401
|
+
if (/\bretroactive\b/.test(text)) return "retroactive_date";
|
|
3402
|
+
if (/\b(self[-\s]?insured retention|retention|sir)\b/.test(text)) return "retention";
|
|
3403
|
+
if (/\bdeductible\b/.test(text)) return "deductible";
|
|
3404
|
+
if (/\bpremium\b/.test(text)) return "premium";
|
|
3405
|
+
if (/\bsub[-\s]?limit\b/.test(text)) return "sublimit";
|
|
3406
|
+
if (/\baggregate\b/.test(text)) return "aggregate_limit";
|
|
3407
|
+
if (/\beach\s+claim|per\s+claim\b/.test(text)) return "each_claim_limit";
|
|
3408
|
+
if (/\beach\s+occurrence|per\s+occurrence\b/.test(text)) return "each_occurrence_limit";
|
|
3409
|
+
if (/\beach\s+loss|per\s+loss\b/.test(text)) return "each_loss_limit";
|
|
3410
|
+
if (/\blimit\b/.test(text)) return "other";
|
|
3411
|
+
return "other";
|
|
3412
|
+
}
|
|
3413
|
+
function normalizeTermKind(value, label, termValue) {
|
|
3414
|
+
return typeof value === "string" && OPERATIONAL_COVERAGE_TERM_KINDS.has(value) ? value : termKind(label, termValue);
|
|
3415
|
+
}
|
|
3416
|
+
function isValueCell(label, value) {
|
|
3417
|
+
const normalizedLabel = normalizeLabel(label);
|
|
3418
|
+
const normalizedValue = normalizeLabel(value);
|
|
3419
|
+
if (!value || normalizedValue === "\u2014") return false;
|
|
3420
|
+
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)) {
|
|
3421
|
+
return false;
|
|
3422
|
+
}
|
|
3423
|
+
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);
|
|
3424
|
+
}
|
|
3425
|
+
function isNameCell(label, value) {
|
|
3426
|
+
const normalizedLabel = normalizeLabel(label);
|
|
3427
|
+
const normalizedValue = normalizeLabel(value);
|
|
3428
|
+
if (!value || moneyAmount(value) !== void 0) return false;
|
|
3429
|
+
if (/\b(coverage|coverage part|insuring agreement|description|item|name)\b/.test(normalizedLabel)) {
|
|
3430
|
+
return true;
|
|
3431
|
+
}
|
|
3432
|
+
if (/^column\s+\d+$/.test(normalizedLabel) && /\b(coverage|sub[-\s]?limit|liability|expense|part\s+[a-z])\b/.test(normalizedValue)) {
|
|
3433
|
+
return true;
|
|
3434
|
+
}
|
|
3435
|
+
return false;
|
|
3436
|
+
}
|
|
3437
|
+
function childMap(nodes) {
|
|
3438
|
+
const children = /* @__PURE__ */ new Map();
|
|
3439
|
+
for (const node of nodes) {
|
|
3440
|
+
const group = children.get(node.parentId) ?? [];
|
|
3441
|
+
group.push(node);
|
|
3442
|
+
children.set(node.parentId, group);
|
|
3443
|
+
}
|
|
3444
|
+
for (const group of children.values()) group.sort((left, right) => left.order - right.order);
|
|
3445
|
+
return children;
|
|
3446
|
+
}
|
|
3447
|
+
function cellRows(row, children) {
|
|
3448
|
+
return (children.get(row.id) ?? []).filter((child) => child.kind === "table_cell").map((cell) => ({
|
|
3449
|
+
label: cleanValue(cell.title) ?? "Value",
|
|
3450
|
+
value: cleanValue(cell.textExcerpt ?? cell.description ?? cell.title) ?? "",
|
|
3451
|
+
node: cell
|
|
3452
|
+
})).filter((cell) => cell.value);
|
|
3453
|
+
}
|
|
3454
|
+
function directChildren(parent, children) {
|
|
3455
|
+
return children.get(parent.id) ?? [];
|
|
3456
|
+
}
|
|
3457
|
+
function descendants(parent, children) {
|
|
3458
|
+
const stack = [...directChildren(parent, children)];
|
|
3459
|
+
const result = [];
|
|
3460
|
+
while (stack.length > 0) {
|
|
3461
|
+
const node = stack.shift();
|
|
3462
|
+
result.push(node);
|
|
3463
|
+
stack.unshift(...directChildren(node, children));
|
|
3464
|
+
}
|
|
3465
|
+
return result;
|
|
3466
|
+
}
|
|
3467
|
+
function ancestry(node, byId) {
|
|
3468
|
+
const result = [];
|
|
3469
|
+
let current = node.parentId ? byId.get(node.parentId) : void 0;
|
|
3470
|
+
while (current) {
|
|
3471
|
+
result.push(current);
|
|
3472
|
+
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
3473
|
+
}
|
|
3474
|
+
return result;
|
|
3475
|
+
}
|
|
3476
|
+
function endorsementAncestor(node, byId) {
|
|
3477
|
+
return ancestry(node, byId).find((ancestor) => ancestor.kind === "endorsement");
|
|
3478
|
+
}
|
|
3479
|
+
function endorsementNumberFrom(value) {
|
|
3480
|
+
return cleanValue(value?.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)/i)?.[1]);
|
|
3481
|
+
}
|
|
3482
|
+
function sourceIds(nodes) {
|
|
3483
|
+
return {
|
|
3484
|
+
sourceNodeIds: [...new Set(nodes.map((node) => node.id))],
|
|
3485
|
+
sourceSpanIds: [...new Set(nodes.flatMap((node) => node.sourceSpanIds))]
|
|
3486
|
+
};
|
|
3487
|
+
}
|
|
3488
|
+
function termFromCell(params) {
|
|
3489
|
+
const value = cleanValue(params.value);
|
|
3490
|
+
if (!value) return void 0;
|
|
3491
|
+
const nodes = [params.row, params.cell].filter((node) => Boolean(node));
|
|
3492
|
+
return {
|
|
3493
|
+
kind: termKind(params.label, value),
|
|
3494
|
+
label: params.label,
|
|
3495
|
+
value,
|
|
3496
|
+
...moneyAmount(value) !== void 0 ? { amount: moneyAmount(value) } : {},
|
|
3497
|
+
...params.appliesTo ? { appliesTo: params.appliesTo } : {},
|
|
3498
|
+
...sourceIds(nodes)
|
|
3499
|
+
};
|
|
3500
|
+
}
|
|
3501
|
+
function termsFromRow(row, children) {
|
|
3502
|
+
const cells = cellRows(row, children);
|
|
3503
|
+
if (cells.length > 0) {
|
|
3504
|
+
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));
|
|
3505
|
+
}
|
|
3506
|
+
const text = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
3507
|
+
const terms = [];
|
|
3508
|
+
for (const part of text.split(/\s+\|\s+/)) {
|
|
3509
|
+
const match = part.match(/^([^:]{2,80}):\s*(.+)$/);
|
|
3510
|
+
if (!match) continue;
|
|
3511
|
+
if (!isValueCell(match[1], match[2])) continue;
|
|
3512
|
+
const term = termFromCell({ row, label: cleanValue(match[1]) ?? "Value", value: match[2] });
|
|
3513
|
+
if (term) terms.push(term);
|
|
3514
|
+
}
|
|
3515
|
+
if (terms.length === 0) {
|
|
3516
|
+
const limit = limitFromText(text);
|
|
3517
|
+
if (limit) {
|
|
3518
|
+
const term = termFromCell({ row, label: "Limit", value: limit });
|
|
3519
|
+
if (term) terms.push(term);
|
|
3520
|
+
}
|
|
3521
|
+
const deductible = deductibleFromText(text);
|
|
3522
|
+
if (deductible) {
|
|
3523
|
+
const term = termFromCell({ row, label: "Deductible", value: deductible });
|
|
3524
|
+
if (term) terms.push(term);
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3527
|
+
return terms;
|
|
3528
|
+
}
|
|
3529
|
+
function nameFromRow(row, children) {
|
|
3530
|
+
const cells = cellRows(row, children);
|
|
3531
|
+
const named = cells.find((cell) => isNameCell(cell.label, cell.value));
|
|
3532
|
+
if (named) return cleanValue(named.value);
|
|
3533
|
+
return coverageNameFromRow(nodeText(row));
|
|
3534
|
+
}
|
|
3535
|
+
function legacyLimit(terms) {
|
|
3536
|
+
return terms.find(
|
|
3537
|
+
(term) => ["each_claim_limit", "each_occurrence_limit", "each_loss_limit", "aggregate_limit", "sublimit", "other"].includes(term.kind)
|
|
3538
|
+
)?.value;
|
|
3539
|
+
}
|
|
3540
|
+
function legacyDeductible(terms) {
|
|
3541
|
+
return terms.find((term) => term.kind === "deductible" || term.kind === "retention")?.value;
|
|
3542
|
+
}
|
|
3543
|
+
function legacyPremium(terms) {
|
|
3544
|
+
return terms.find((term) => term.kind === "premium")?.value;
|
|
3545
|
+
}
|
|
3546
|
+
function retroDate(terms) {
|
|
3547
|
+
return terms.find((term) => term.kind === "retroactive_date")?.value;
|
|
3548
|
+
}
|
|
3549
|
+
function uniqueTerms(terms) {
|
|
3550
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3551
|
+
const result = [];
|
|
3552
|
+
for (const term of terms) {
|
|
3553
|
+
const key = [term.kind, term.label.toLowerCase(), term.value.toLowerCase(), term.appliesTo ?? ""].join("|");
|
|
3554
|
+
if (seen.has(key)) continue;
|
|
3555
|
+
seen.add(key);
|
|
3556
|
+
result.push(term);
|
|
3557
|
+
}
|
|
3558
|
+
return result;
|
|
3559
|
+
}
|
|
3560
|
+
function coverageFromTableRow(row, children, byId) {
|
|
3561
|
+
if (row.metadata?.isHeader === true || row.metadata?.isHeader === "true") return void 0;
|
|
3562
|
+
const name = nameFromRow(row, children);
|
|
3563
|
+
const terms = uniqueTerms(termsFromRow(row, children));
|
|
3564
|
+
if (!name || terms.length === 0) return void 0;
|
|
3565
|
+
const ids = sourceIds([row, ...directChildren(row, children)]);
|
|
3566
|
+
const endorsement = endorsementAncestor(row, byId);
|
|
3567
|
+
return {
|
|
3568
|
+
name,
|
|
3569
|
+
limit: legacyLimit(terms),
|
|
3570
|
+
deductible: legacyDeductible(terms),
|
|
3571
|
+
premium: legacyPremium(terms),
|
|
3572
|
+
retroactiveDate: retroDate(terms),
|
|
3573
|
+
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3574
|
+
sectionRef: endorsement?.title,
|
|
3575
|
+
coverageOrigin: endorsement ? "endorsement" : "core",
|
|
3576
|
+
endorsementNumber: endorsementNumberFrom(endorsement?.title),
|
|
3577
|
+
limits: terms,
|
|
3578
|
+
...ids
|
|
3579
|
+
};
|
|
3580
|
+
}
|
|
3581
|
+
function coverageFromEndorsement(endorsement, children) {
|
|
3582
|
+
const rows = descendants(endorsement, children).filter((node) => node.kind === "table_row");
|
|
3583
|
+
const terms = uniqueTerms(rows.flatMap(
|
|
3584
|
+
(row) => termsFromRow(row, children).map((term) => {
|
|
3585
|
+
const appliesTo = nameFromRow(row, children);
|
|
3586
|
+
return appliesTo && !/^(each claim limit|aggregate limit|retroactive date)$/i.test(appliesTo) ? { ...term, appliesTo } : term;
|
|
3587
|
+
})
|
|
3588
|
+
));
|
|
3589
|
+
if (terms.length === 0) return void 0;
|
|
3590
|
+
const ids = sourceIds([endorsement, ...rows, ...rows.flatMap((row) => directChildren(row, children))]);
|
|
3591
|
+
return {
|
|
3592
|
+
name: endorsement.title,
|
|
3593
|
+
limit: legacyLimit(terms),
|
|
3594
|
+
deductible: legacyDeductible(terms),
|
|
3595
|
+
premium: legacyPremium(terms),
|
|
3596
|
+
retroactiveDate: retroDate(terms),
|
|
3597
|
+
formNumber: typeof endorsement.metadata?.formNumber === "string" ? endorsement.metadata.formNumber : void 0,
|
|
3598
|
+
sectionRef: endorsement.title,
|
|
3599
|
+
coverageOrigin: "endorsement",
|
|
3600
|
+
endorsementNumber: endorsementNumberFrom(endorsement.title),
|
|
3601
|
+
limits: terms,
|
|
3602
|
+
...ids
|
|
3603
|
+
};
|
|
3604
|
+
}
|
|
3353
3605
|
function buildCoverages(nodes) {
|
|
3606
|
+
const children = childMap(nodes);
|
|
3607
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
3608
|
+
const coverages = [];
|
|
3609
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3610
|
+
for (const endorsement of nodes.filter((node) => node.kind === "endorsement")) {
|
|
3611
|
+
const coverage = coverageFromEndorsement(endorsement, children);
|
|
3612
|
+
if (!coverage) continue;
|
|
3613
|
+
const key = [coverage.name.toLowerCase(), coverage.sourceNodeIds.join(",")].join("|");
|
|
3614
|
+
if (seen.has(key)) continue;
|
|
3615
|
+
seen.add(key);
|
|
3616
|
+
coverages.push(coverage);
|
|
3617
|
+
}
|
|
3354
3618
|
const rows = nodes.filter((node) => {
|
|
3355
3619
|
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);
|
|
3620
|
+
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
3621
|
});
|
|
3358
|
-
const coverages = [];
|
|
3359
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3360
3622
|
for (const row of rows) {
|
|
3623
|
+
if (endorsementAncestor(row, byId)) continue;
|
|
3624
|
+
const structured = row.kind === "table_row" ? coverageFromTableRow(row, children, byId) : void 0;
|
|
3625
|
+
if (structured) {
|
|
3626
|
+
const key2 = [
|
|
3627
|
+
structured.name.toLowerCase(),
|
|
3628
|
+
structured.limits.map((term) => `${term.kind}:${term.value}`).join(","),
|
|
3629
|
+
structured.sourceNodeIds.join(",")
|
|
3630
|
+
].join("|");
|
|
3631
|
+
if (seen.has(key2)) continue;
|
|
3632
|
+
seen.add(key2);
|
|
3633
|
+
coverages.push(structured);
|
|
3634
|
+
if (coverages.length >= 60) break;
|
|
3635
|
+
continue;
|
|
3636
|
+
}
|
|
3361
3637
|
const text = nodeText(row);
|
|
3362
3638
|
const name = coverageNameFromRow(text);
|
|
3363
3639
|
const limit = limitFromText(text);
|
|
@@ -3373,6 +3649,8 @@ function buildCoverages(nodes) {
|
|
|
3373
3649
|
deductible,
|
|
3374
3650
|
premium,
|
|
3375
3651
|
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3652
|
+
coverageOrigin: "core",
|
|
3653
|
+
limits: [],
|
|
3376
3654
|
sourceNodeIds: [row.id],
|
|
3377
3655
|
sourceSpanIds: row.sourceSpanIds
|
|
3378
3656
|
});
|
|
@@ -3514,11 +3792,33 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
|
|
|
3514
3792
|
sourceSpanIds
|
|
3515
3793
|
};
|
|
3516
3794
|
};
|
|
3517
|
-
const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) =>
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3795
|
+
const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
|
|
3796
|
+
const record = coverage;
|
|
3797
|
+
const limits = Array.isArray(record.limits) ? record.limits.filter(
|
|
3798
|
+
(term) => Boolean(term) && typeof term === "object" && !Array.isArray(term)
|
|
3799
|
+
).flatMap((term) => {
|
|
3800
|
+
const label = typeof term.label === "string" ? cleanValue(term.label) : void 0;
|
|
3801
|
+
const value = typeof term.value === "string" ? cleanValue(term.value) : void 0;
|
|
3802
|
+
const sourceNodeIds = keepIds(term.sourceNodeIds, validNodeIds);
|
|
3803
|
+
const sourceSpanIds = keepIds(term.sourceSpanIds, validSpanIds);
|
|
3804
|
+
if (!label || !value || sourceNodeIds.length === 0 && sourceSpanIds.length === 0) return [];
|
|
3805
|
+
return [{
|
|
3806
|
+
kind: normalizeTermKind(term.kind, label, value),
|
|
3807
|
+
label,
|
|
3808
|
+
value,
|
|
3809
|
+
amount: typeof term.amount === "number" && Number.isFinite(term.amount) ? term.amount : void 0,
|
|
3810
|
+
appliesTo: typeof term.appliesTo === "string" ? term.appliesTo : void 0,
|
|
3811
|
+
sourceNodeIds,
|
|
3812
|
+
sourceSpanIds
|
|
3813
|
+
}];
|
|
3814
|
+
}) : [];
|
|
3815
|
+
return {
|
|
3816
|
+
...coverage,
|
|
3817
|
+
limits,
|
|
3818
|
+
sourceNodeIds: keepIds(record.sourceNodeIds, validNodeIds),
|
|
3819
|
+
sourceSpanIds: keepIds(record.sourceSpanIds, validSpanIds)
|
|
3820
|
+
};
|
|
3821
|
+
}).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
|
|
3522
3822
|
return PolicyOperationalProfileSchema.parse({
|
|
3523
3823
|
...base,
|
|
3524
3824
|
documentType: candidate.documentType === "quote" ? "quote" : candidate.documentType === "policy" ? "policy" : base.documentType,
|
|
@@ -9520,8 +9820,31 @@ var OperationalProfilePromptSchema = import_zod41.z.object({
|
|
|
9520
9820
|
limit: import_zod41.z.string().optional(),
|
|
9521
9821
|
deductible: import_zod41.z.string().optional(),
|
|
9522
9822
|
premium: import_zod41.z.string().optional(),
|
|
9823
|
+
retroactiveDate: import_zod41.z.string().optional(),
|
|
9523
9824
|
formNumber: import_zod41.z.string().optional(),
|
|
9524
9825
|
sectionRef: import_zod41.z.string().optional(),
|
|
9826
|
+
coverageOrigin: import_zod41.z.enum(["core", "endorsement"]).optional(),
|
|
9827
|
+
endorsementNumber: import_zod41.z.string().optional(),
|
|
9828
|
+
limits: import_zod41.z.array(import_zod41.z.object({
|
|
9829
|
+
kind: import_zod41.z.enum([
|
|
9830
|
+
"each_claim_limit",
|
|
9831
|
+
"each_occurrence_limit",
|
|
9832
|
+
"each_loss_limit",
|
|
9833
|
+
"aggregate_limit",
|
|
9834
|
+
"sublimit",
|
|
9835
|
+
"retention",
|
|
9836
|
+
"deductible",
|
|
9837
|
+
"retroactive_date",
|
|
9838
|
+
"premium",
|
|
9839
|
+
"other"
|
|
9840
|
+
]).optional(),
|
|
9841
|
+
label: import_zod41.z.string(),
|
|
9842
|
+
value: import_zod41.z.string(),
|
|
9843
|
+
amount: import_zod41.z.number().optional(),
|
|
9844
|
+
appliesTo: import_zod41.z.string().optional(),
|
|
9845
|
+
sourceNodeIds: import_zod41.z.array(import_zod41.z.string()),
|
|
9846
|
+
sourceSpanIds: import_zod41.z.array(import_zod41.z.string())
|
|
9847
|
+
})).optional(),
|
|
9525
9848
|
sourceNodeIds: import_zod41.z.array(import_zod41.z.string()),
|
|
9526
9849
|
sourceSpanIds: import_zod41.z.array(import_zod41.z.string())
|
|
9527
9850
|
})).optional(),
|
|
@@ -9675,6 +9998,25 @@ function pageTitleFromText(text, fallback) {
|
|
|
9675
9998
|
if (firstSentence && firstSentence.length <= 120) return firstSentence.replace(/[.]$/, "");
|
|
9676
9999
|
return fallback;
|
|
9677
10000
|
}
|
|
10001
|
+
function pageHeadingTitleFromText(text, fallback) {
|
|
10002
|
+
const normalized = cleanText(text, "");
|
|
10003
|
+
const headingText = normalized.replace(/^page\s+\d+\s*(?:\|\s*page\s*\|\s*page\s+\d+\s*\|?)?/i, "").slice(0, 700);
|
|
10004
|
+
const patterns = [
|
|
10005
|
+
/\bIMPORTANT NOTICE\s+[—-]\s+HOW TO REPORT A CLAIM\b/i,
|
|
10006
|
+
/\bPRIVACY NOTICE TO POLICYHOLDERS\b/i,
|
|
10007
|
+
/\bOFAC ADVISORY NOTICE\b/i,
|
|
10008
|
+
/\bTERRORISM RISK INSURANCE ACT\s*\(TRIA\)\s*DISCLOSURE AND REJECTION\b/i,
|
|
10009
|
+
/\bDECLARATIONS PAGE\b/i,
|
|
10010
|
+
/\bTECHNOLOGY ERRORS?\s*&\s*OMISSIONS AND CYBER LIABILITY INSURANCE POLICY\b/i,
|
|
10011
|
+
/\bTRADE OR ECONOMIC SANCTIONS LIMITATION\b/i,
|
|
10012
|
+
/\bFORMS? AND ENDORSEMENTS\b/i
|
|
10013
|
+
];
|
|
10014
|
+
for (const pattern of patterns) {
|
|
10015
|
+
const match = headingText.match(pattern)?.[0];
|
|
10016
|
+
if (match) return cleanText(match, fallback);
|
|
10017
|
+
}
|
|
10018
|
+
return fallback;
|
|
10019
|
+
}
|
|
9678
10020
|
function pageFormTypeFromText(text) {
|
|
9679
10021
|
if (/\b(declarations?\s+page|declarations?\s+schedule)\b/i.test(text)) return "declarations";
|
|
9680
10022
|
if (/\b(endorsement\s+(?:no\.?|number|#)|this endorsement changes the policy|[A-Z]{2,}-END\s+\d{2,})\b/i.test(text)) return "endorsement";
|
|
@@ -9938,7 +10280,7 @@ function applySemanticPageGrouping(sourceTree) {
|
|
|
9938
10280
|
if (node.kind === "document" || node.kind === "page_group") return node;
|
|
9939
10281
|
let nextNode = node;
|
|
9940
10282
|
if (node.kind === "page" && /^page\s+\d+$/i.test(node.title)) {
|
|
9941
|
-
const title =
|
|
10283
|
+
const title = pageHeadingTitleFromText([node.textExcerpt, node.description].filter(Boolean).join(" "), node.title);
|
|
9942
10284
|
if (title !== node.title) {
|
|
9943
10285
|
nextNode = {
|
|
9944
10286
|
...node,
|
|
@@ -10316,8 +10658,8 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
10316
10658
|
const current = updates.get(child.id) ?? child;
|
|
10317
10659
|
const heading = sectionHeadingTitle(current, container);
|
|
10318
10660
|
if (heading) {
|
|
10319
|
-
const
|
|
10320
|
-
const hasOwnContent =
|
|
10661
|
+
const descendants2 = byParent.get(child.id) ?? [];
|
|
10662
|
+
const hasOwnContent = descendants2.some((descendant) => descendant.kind !== "table_row" && descendant.kind !== "table_cell");
|
|
10321
10663
|
let hasFollowingContent = false;
|
|
10322
10664
|
for (const nextChild of directPageChildren.slice(index + 1)) {
|
|
10323
10665
|
const next = updates.get(nextChild.id) ?? nextChild;
|
|
@@ -10335,7 +10677,7 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
10335
10677
|
parentId: container.id,
|
|
10336
10678
|
kind: sectionKindForTitle(heading),
|
|
10337
10679
|
title: heading,
|
|
10338
|
-
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...
|
|
10680
|
+
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...descendants2]),
|
|
10339
10681
|
metadata: {
|
|
10340
10682
|
...current.metadata,
|
|
10341
10683
|
organizer: "title_section",
|
|
@@ -10665,13 +11007,16 @@ function buildOperationalProfilePrompt(sourceTree, fallback) {
|
|
|
10665
11007
|
|
|
10666
11008
|
Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
|
|
10667
11009
|
- policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium
|
|
10668
|
-
- coverage
|
|
11010
|
+
- coverage units with their own nested limit terms, deductibles/retentions, retroactive dates, premiums, and form references
|
|
10669
11011
|
- coverage type labels
|
|
10670
11012
|
|
|
10671
11013
|
Rules:
|
|
10672
11014
|
- Every returned value must include sourceNodeIds or sourceSpanIds from the provided nodes.
|
|
10673
11015
|
- If a value is not directly supported, omit it.
|
|
10674
11016
|
- Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
|
|
11017
|
+
- Treat an endorsement as one coverage unit when it contains a schedule. Do not split an endorsement schedule into generic rows like "Aggregate Limit".
|
|
11018
|
+
- 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.
|
|
11019
|
+
- Use coverageOrigin: "endorsement" for endorsement units and "core" for declarations/core policy coverage units.
|
|
10675
11020
|
- Do not copy entire policy wording into fields.
|
|
10676
11021
|
|
|
10677
11022
|
Deterministic baseline:
|
|
@@ -10787,11 +11132,18 @@ function materializeDocument(params) {
|
|
|
10787
11132
|
limit: coverage.limit,
|
|
10788
11133
|
deductible: coverage.deductible,
|
|
10789
11134
|
premium: coverage.premium,
|
|
11135
|
+
retroactiveDate: coverage.retroactiveDate,
|
|
10790
11136
|
formNumber: coverage.formNumber,
|
|
10791
11137
|
sectionRef: coverage.sectionRef,
|
|
11138
|
+
coverageOrigin: coverage.coverageOrigin,
|
|
11139
|
+
endorsementNumber: coverage.endorsementNumber,
|
|
11140
|
+
limits: coverage.limits,
|
|
10792
11141
|
sourceSpanIds: coverage.sourceSpanIds,
|
|
10793
11142
|
documentNodeId: coverage.sourceNodeIds[0],
|
|
10794
|
-
originalContent: [
|
|
11143
|
+
originalContent: [
|
|
11144
|
+
coverage.name,
|
|
11145
|
+
...coverage.limits?.length ? coverage.limits.map((term) => `${term.label}: ${term.value}`) : [coverage.limit, coverage.deductible, coverage.premium]
|
|
11146
|
+
].filter(Boolean).join(" | ")
|
|
10795
11147
|
}));
|
|
10796
11148
|
const documentOutline = sourceTreeToOutline(params.sourceTree);
|
|
10797
11149
|
const documentMetadata = {
|
|
@@ -15918,6 +16270,7 @@ var AGENT_TOOLS = [
|
|
|
15918
16270
|
MissingInfoQuestionSchema,
|
|
15919
16271
|
NamedInsuredSchema,
|
|
15920
16272
|
OperationalCoverageLineSchema,
|
|
16273
|
+
OperationalCoverageTermSchema,
|
|
15921
16274
|
OperationalEndorsementSupportSchema,
|
|
15922
16275
|
OperationalPartySchema,
|
|
15923
16276
|
PERSONAL_AUTO_USAGES,
|