@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.mjs
CHANGED
|
@@ -2045,14 +2045,38 @@ var SourceBackedValueSchema = z20.object({
|
|
|
2045
2045
|
sourceNodeIds: z20.array(z20.string().min(1)).default([]),
|
|
2046
2046
|
sourceSpanIds: z20.array(z20.string().min(1)).default([])
|
|
2047
2047
|
});
|
|
2048
|
+
var OperationalCoverageTermSchema = z20.object({
|
|
2049
|
+
kind: z20.enum([
|
|
2050
|
+
"each_claim_limit",
|
|
2051
|
+
"each_occurrence_limit",
|
|
2052
|
+
"each_loss_limit",
|
|
2053
|
+
"aggregate_limit",
|
|
2054
|
+
"sublimit",
|
|
2055
|
+
"retention",
|
|
2056
|
+
"deductible",
|
|
2057
|
+
"retroactive_date",
|
|
2058
|
+
"premium",
|
|
2059
|
+
"other"
|
|
2060
|
+
]).default("other"),
|
|
2061
|
+
label: z20.string(),
|
|
2062
|
+
value: z20.string(),
|
|
2063
|
+
amount: z20.number().optional(),
|
|
2064
|
+
appliesTo: z20.string().optional(),
|
|
2065
|
+
sourceNodeIds: z20.array(z20.string().min(1)).default([]),
|
|
2066
|
+
sourceSpanIds: z20.array(z20.string().min(1)).default([])
|
|
2067
|
+
});
|
|
2048
2068
|
var OperationalCoverageLineSchema = z20.object({
|
|
2049
2069
|
name: z20.string(),
|
|
2050
2070
|
coverageCode: z20.string().optional(),
|
|
2051
2071
|
limit: z20.string().optional(),
|
|
2052
2072
|
deductible: z20.string().optional(),
|
|
2053
2073
|
premium: z20.string().optional(),
|
|
2074
|
+
retroactiveDate: z20.string().optional(),
|
|
2054
2075
|
formNumber: z20.string().optional(),
|
|
2055
2076
|
sectionRef: z20.string().optional(),
|
|
2077
|
+
coverageOrigin: z20.enum(["core", "endorsement"]).optional(),
|
|
2078
|
+
endorsementNumber: z20.string().optional(),
|
|
2079
|
+
limits: z20.array(OperationalCoverageTermSchema).default([]),
|
|
2056
2080
|
sourceNodeIds: z20.array(z20.string().min(1)).default([]),
|
|
2057
2081
|
sourceSpanIds: z20.array(z20.string().min(1)).default([])
|
|
2058
2082
|
});
|
|
@@ -2920,6 +2944,9 @@ function cleanValue(value) {
|
|
|
2920
2944
|
if (!value) return void 0;
|
|
2921
2945
|
return normalizeWhitespace3(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
|
|
2922
2946
|
}
|
|
2947
|
+
function cleanCoverageLabel(value) {
|
|
2948
|
+
return cleanValue(value)?.replace(/^column\s+\d+\s*:\s*/i, "");
|
|
2949
|
+
}
|
|
2923
2950
|
function moneyValue(value) {
|
|
2924
2951
|
const clean = cleanValue(value);
|
|
2925
2952
|
if (!clean) return void 0;
|
|
@@ -2977,12 +3004,12 @@ function inferDocumentType(nodes) {
|
|
|
2977
3004
|
}
|
|
2978
3005
|
function coverageNameFromRow(text) {
|
|
2979
3006
|
const labelled = text.match(/\b(?:coverage|coverage part|line)\s*:?\s*([^|;$]{3,80})/i)?.[1];
|
|
2980
|
-
if (labelled) return
|
|
2981
|
-
const parts = text.split(/\s+\|\s+| {2,}|\t/).map(
|
|
3007
|
+
if (labelled) return cleanCoverageLabel(labelled);
|
|
3008
|
+
const parts = text.split(/\s+\|\s+| {2,}|\t/).map(cleanCoverageLabel).filter(Boolean);
|
|
2982
3009
|
const first = parts.find(
|
|
2983
3010
|
(part) => !/^(limit|limits?|deductible|premium|amount|basis|rate|retroactive|aggregate|each occurrence)$/i.test(part) && !/^\$?[\d,]+/.test(part)
|
|
2984
3011
|
);
|
|
2985
|
-
return
|
|
3012
|
+
return cleanCoverageLabel(first);
|
|
2986
3013
|
}
|
|
2987
3014
|
function limitFromText(text) {
|
|
2988
3015
|
return moneyValue(
|
|
@@ -2995,14 +3022,292 @@ function deductibleFromText(text) {
|
|
|
2995
3022
|
function premiumFromText(text) {
|
|
2996
3023
|
return moneyValue(text.match(/\b(?:premium|total premium|total cost|amount due)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
|
|
2997
3024
|
}
|
|
3025
|
+
function moneyAmount(value) {
|
|
3026
|
+
const match = value?.match(/\$?\s*([0-9][0-9,]*(?:\.\d+)?)/);
|
|
3027
|
+
if (!match) return void 0;
|
|
3028
|
+
const amount = Number(match[1].replace(/,/g, ""));
|
|
3029
|
+
return Number.isFinite(amount) ? amount : void 0;
|
|
3030
|
+
}
|
|
3031
|
+
function normalizeLabel(value) {
|
|
3032
|
+
return normalizeWhitespace3(value ?? "").toLowerCase();
|
|
3033
|
+
}
|
|
3034
|
+
var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
|
|
3035
|
+
"each_claim_limit",
|
|
3036
|
+
"each_occurrence_limit",
|
|
3037
|
+
"each_loss_limit",
|
|
3038
|
+
"aggregate_limit",
|
|
3039
|
+
"sublimit",
|
|
3040
|
+
"retention",
|
|
3041
|
+
"deductible",
|
|
3042
|
+
"retroactive_date",
|
|
3043
|
+
"premium",
|
|
3044
|
+
"other"
|
|
3045
|
+
]);
|
|
3046
|
+
function termKind(label, value) {
|
|
3047
|
+
const text = normalizeLabel(`${label} ${value}`);
|
|
3048
|
+
if (/\bretroactive\b/.test(text)) return "retroactive_date";
|
|
3049
|
+
if (/\b(self[-\s]?insured retention|retention|sir)\b/.test(text)) return "retention";
|
|
3050
|
+
if (/\bdeductible\b/.test(text)) return "deductible";
|
|
3051
|
+
if (/\bpremium\b/.test(text)) return "premium";
|
|
3052
|
+
if (/\bsub[-\s]?limit\b/.test(text)) return "sublimit";
|
|
3053
|
+
if (/\baggregate\b/.test(text)) return "aggregate_limit";
|
|
3054
|
+
if (/\beach\s+claim|per\s+claim\b/.test(text)) return "each_claim_limit";
|
|
3055
|
+
if (/\beach\s+occurrence|per\s+occurrence\b/.test(text)) return "each_occurrence_limit";
|
|
3056
|
+
if (/\beach\s+loss|per\s+loss\b/.test(text)) return "each_loss_limit";
|
|
3057
|
+
if (/\blimit\b/.test(text)) return "other";
|
|
3058
|
+
return "other";
|
|
3059
|
+
}
|
|
3060
|
+
function normalizeTermKind(value, label, termValue) {
|
|
3061
|
+
return typeof value === "string" && OPERATIONAL_COVERAGE_TERM_KINDS.has(value) ? value : termKind(label, termValue);
|
|
3062
|
+
}
|
|
3063
|
+
function isValueCell(label, value) {
|
|
3064
|
+
const normalizedLabel = normalizeLabel(label);
|
|
3065
|
+
const normalizedValue = normalizeLabel(value);
|
|
3066
|
+
if (!value || normalizedValue === "\u2014") return false;
|
|
3067
|
+
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)) {
|
|
3068
|
+
return false;
|
|
3069
|
+
}
|
|
3070
|
+
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);
|
|
3071
|
+
}
|
|
3072
|
+
function isNameCell(label, value) {
|
|
3073
|
+
const normalizedLabel = normalizeLabel(label);
|
|
3074
|
+
const normalizedValue = normalizeLabel(value);
|
|
3075
|
+
if (!value || moneyAmount(value) !== void 0) return false;
|
|
3076
|
+
if (/\b(coverage|coverage part|insuring agreement|description|item|name)\b/.test(normalizedLabel)) {
|
|
3077
|
+
return true;
|
|
3078
|
+
}
|
|
3079
|
+
if (/^column\s+\d+$/.test(normalizedLabel) && /\b(coverage|sub[-\s]?limit|liability|expense|part\s+[a-z])\b/.test(normalizedValue)) {
|
|
3080
|
+
return true;
|
|
3081
|
+
}
|
|
3082
|
+
return false;
|
|
3083
|
+
}
|
|
3084
|
+
function childMap(nodes) {
|
|
3085
|
+
const children = /* @__PURE__ */ new Map();
|
|
3086
|
+
for (const node of nodes) {
|
|
3087
|
+
const group = children.get(node.parentId) ?? [];
|
|
3088
|
+
group.push(node);
|
|
3089
|
+
children.set(node.parentId, group);
|
|
3090
|
+
}
|
|
3091
|
+
for (const group of children.values()) group.sort((left, right) => left.order - right.order);
|
|
3092
|
+
return children;
|
|
3093
|
+
}
|
|
3094
|
+
function cellRows(row, children) {
|
|
3095
|
+
return (children.get(row.id) ?? []).filter((child) => child.kind === "table_cell").map((cell) => ({
|
|
3096
|
+
label: cleanValue(cell.title) ?? "Value",
|
|
3097
|
+
value: cleanValue(cell.textExcerpt ?? cell.description ?? cell.title) ?? "",
|
|
3098
|
+
node: cell
|
|
3099
|
+
})).filter((cell) => cell.value);
|
|
3100
|
+
}
|
|
3101
|
+
function directChildren(parent, children) {
|
|
3102
|
+
return children.get(parent.id) ?? [];
|
|
3103
|
+
}
|
|
3104
|
+
function descendants(parent, children) {
|
|
3105
|
+
const stack = [...directChildren(parent, children)];
|
|
3106
|
+
const result = [];
|
|
3107
|
+
while (stack.length > 0) {
|
|
3108
|
+
const node = stack.shift();
|
|
3109
|
+
result.push(node);
|
|
3110
|
+
stack.unshift(...directChildren(node, children));
|
|
3111
|
+
}
|
|
3112
|
+
return result;
|
|
3113
|
+
}
|
|
3114
|
+
function ancestry(node, byId) {
|
|
3115
|
+
const result = [];
|
|
3116
|
+
let current = node.parentId ? byId.get(node.parentId) : void 0;
|
|
3117
|
+
while (current) {
|
|
3118
|
+
result.push(current);
|
|
3119
|
+
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
3120
|
+
}
|
|
3121
|
+
return result;
|
|
3122
|
+
}
|
|
3123
|
+
function endorsementAncestor(node, byId) {
|
|
3124
|
+
return ancestry(node, byId).find((ancestor) => ancestor.kind === "endorsement");
|
|
3125
|
+
}
|
|
3126
|
+
function endorsementNumberFrom(value) {
|
|
3127
|
+
return cleanValue(value?.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)/i)?.[1]);
|
|
3128
|
+
}
|
|
3129
|
+
function endorsementNameFrom(node) {
|
|
3130
|
+
const candidates = [node.title, node.textExcerpt, node.description, nodeText(node)].filter(Boolean);
|
|
3131
|
+
for (const candidate of candidates) {
|
|
3132
|
+
const match = candidate.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)\s*[—-]\s*(.{3,140}?)(?=\s+This\s+endorsement\b|\.|$)/i);
|
|
3133
|
+
if (match) return cleanValue(`Endorsement No. ${match[1]} - ${match[2]}`) ?? node.title;
|
|
3134
|
+
}
|
|
3135
|
+
return node.title;
|
|
3136
|
+
}
|
|
3137
|
+
function sourceIds(nodes) {
|
|
3138
|
+
return {
|
|
3139
|
+
sourceNodeIds: [...new Set(nodes.map((node) => node.id))],
|
|
3140
|
+
sourceSpanIds: [...new Set(nodes.flatMap((node) => node.sourceSpanIds))]
|
|
3141
|
+
};
|
|
3142
|
+
}
|
|
3143
|
+
function relabelGenericTerm(term, label) {
|
|
3144
|
+
const cleanLabel = cleanValue(label);
|
|
3145
|
+
if (!cleanLabel || !/^column\s+\d+$/i.test(term.label)) return term;
|
|
3146
|
+
return {
|
|
3147
|
+
...term,
|
|
3148
|
+
kind: termKind(cleanLabel, term.value),
|
|
3149
|
+
label: cleanLabel
|
|
3150
|
+
};
|
|
3151
|
+
}
|
|
3152
|
+
function termFromCell(params) {
|
|
3153
|
+
const value = cleanValue(params.value);
|
|
3154
|
+
if (!value) return void 0;
|
|
3155
|
+
const nodes = [params.row, params.cell].filter((node) => Boolean(node));
|
|
3156
|
+
const kind = termKind(params.label, value);
|
|
3157
|
+
const amount = moneyAmount(value);
|
|
3158
|
+
return {
|
|
3159
|
+
kind,
|
|
3160
|
+
label: params.label,
|
|
3161
|
+
value,
|
|
3162
|
+
...amount !== void 0 && kind !== "retroactive_date" ? { amount } : {},
|
|
3163
|
+
...params.appliesTo ? { appliesTo: params.appliesTo } : {},
|
|
3164
|
+
...sourceIds(nodes)
|
|
3165
|
+
};
|
|
3166
|
+
}
|
|
3167
|
+
function termsFromRow(row, children) {
|
|
3168
|
+
const cells = cellRows(row, children);
|
|
3169
|
+
if (cells.length > 0) {
|
|
3170
|
+
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));
|
|
3171
|
+
}
|
|
3172
|
+
const text = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
3173
|
+
const terms = [];
|
|
3174
|
+
for (const part of text.split(/\s+\|\s+/)) {
|
|
3175
|
+
const match = part.match(/^([^:]{2,80}):\s*(.+)$/);
|
|
3176
|
+
if (!match) continue;
|
|
3177
|
+
if (!isValueCell(match[1], match[2])) continue;
|
|
3178
|
+
const term = termFromCell({ row, label: cleanValue(match[1]) ?? "Value", value: match[2] });
|
|
3179
|
+
if (term) terms.push(term);
|
|
3180
|
+
}
|
|
3181
|
+
if (terms.length === 0) {
|
|
3182
|
+
const limit = limitFromText(text);
|
|
3183
|
+
if (limit) {
|
|
3184
|
+
const term = termFromCell({ row, label: "Limit", value: limit });
|
|
3185
|
+
if (term) terms.push(term);
|
|
3186
|
+
}
|
|
3187
|
+
const deductible = deductibleFromText(text);
|
|
3188
|
+
if (deductible) {
|
|
3189
|
+
const term = termFromCell({ row, label: "Deductible", value: deductible });
|
|
3190
|
+
if (term) terms.push(term);
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
return terms;
|
|
3194
|
+
}
|
|
3195
|
+
function nameFromRow(row, children) {
|
|
3196
|
+
const cells = cellRows(row, children);
|
|
3197
|
+
const named = cells.find((cell) => isNameCell(cell.label, cell.value));
|
|
3198
|
+
if (named) return cleanValue(named.value);
|
|
3199
|
+
return coverageNameFromRow(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
3200
|
+
}
|
|
3201
|
+
function legacyLimit(terms) {
|
|
3202
|
+
return terms.find(
|
|
3203
|
+
(term) => ["each_claim_limit", "each_occurrence_limit", "each_loss_limit", "aggregate_limit", "sublimit", "other"].includes(term.kind)
|
|
3204
|
+
)?.value;
|
|
3205
|
+
}
|
|
3206
|
+
function legacyDeductible(terms) {
|
|
3207
|
+
return terms.find((term) => term.kind === "deductible" || term.kind === "retention")?.value;
|
|
3208
|
+
}
|
|
3209
|
+
function legacyPremium(terms) {
|
|
3210
|
+
return terms.find((term) => term.kind === "premium")?.value;
|
|
3211
|
+
}
|
|
3212
|
+
function retroDate(terms) {
|
|
3213
|
+
return terms.find((term) => term.kind === "retroactive_date")?.value;
|
|
3214
|
+
}
|
|
3215
|
+
function uniqueTerms(terms) {
|
|
3216
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3217
|
+
const result = [];
|
|
3218
|
+
for (const term of terms) {
|
|
3219
|
+
const key = [term.kind, term.label.toLowerCase(), term.value.toLowerCase(), term.appliesTo ?? ""].join("|");
|
|
3220
|
+
if (seen.has(key)) continue;
|
|
3221
|
+
seen.add(key);
|
|
3222
|
+
result.push(term);
|
|
3223
|
+
}
|
|
3224
|
+
return result;
|
|
3225
|
+
}
|
|
3226
|
+
function coverageFromTableRow(row, children, byId) {
|
|
3227
|
+
if (row.metadata?.isHeader === true || row.metadata?.isHeader === "true") return void 0;
|
|
3228
|
+
const name = nameFromRow(row, children);
|
|
3229
|
+
const terms = uniqueTerms(termsFromRow(row, children));
|
|
3230
|
+
if (!name || terms.length === 0) return void 0;
|
|
3231
|
+
const ids = sourceIds([row, ...directChildren(row, children)]);
|
|
3232
|
+
const endorsement = endorsementAncestor(row, byId);
|
|
3233
|
+
return {
|
|
3234
|
+
name,
|
|
3235
|
+
limit: legacyLimit(terms),
|
|
3236
|
+
deductible: legacyDeductible(terms),
|
|
3237
|
+
premium: legacyPremium(terms),
|
|
3238
|
+
retroactiveDate: retroDate(terms),
|
|
3239
|
+
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3240
|
+
sectionRef: endorsement?.title,
|
|
3241
|
+
coverageOrigin: endorsement ? "endorsement" : "core",
|
|
3242
|
+
endorsementNumber: endorsementNumberFrom(endorsement?.title),
|
|
3243
|
+
limits: terms,
|
|
3244
|
+
...ids
|
|
3245
|
+
};
|
|
3246
|
+
}
|
|
3247
|
+
function coverageFromEndorsement(endorsement, children) {
|
|
3248
|
+
const rows = descendants(endorsement, children).filter((node) => node.kind === "table_row");
|
|
3249
|
+
const terms = uniqueTerms(rows.flatMap(
|
|
3250
|
+
(row) => termsFromRow(row, children).map((term) => {
|
|
3251
|
+
const appliesTo = nameFromRow(row, children);
|
|
3252
|
+
const labelled = relabelGenericTerm(term, appliesTo);
|
|
3253
|
+
return appliesTo && labelled.label !== appliesTo ? { ...labelled, appliesTo } : labelled;
|
|
3254
|
+
})
|
|
3255
|
+
));
|
|
3256
|
+
if (terms.length === 0) return void 0;
|
|
3257
|
+
const ids = sourceIds([endorsement, ...rows, ...rows.flatMap((row) => directChildren(row, children))]);
|
|
3258
|
+
const name = endorsementNameFrom(endorsement);
|
|
3259
|
+
return {
|
|
3260
|
+
name,
|
|
3261
|
+
limit: legacyLimit(terms),
|
|
3262
|
+
deductible: legacyDeductible(terms),
|
|
3263
|
+
premium: legacyPremium(terms),
|
|
3264
|
+
retroactiveDate: retroDate(terms),
|
|
3265
|
+
formNumber: typeof endorsement.metadata?.formNumber === "string" ? endorsement.metadata.formNumber : void 0,
|
|
3266
|
+
sectionRef: name,
|
|
3267
|
+
coverageOrigin: "endorsement",
|
|
3268
|
+
endorsementNumber: endorsementNumberFrom(name),
|
|
3269
|
+
limits: terms,
|
|
3270
|
+
...ids
|
|
3271
|
+
};
|
|
3272
|
+
}
|
|
3273
|
+
function hasDescendantEndorsementWithTableRows(endorsement, children) {
|
|
3274
|
+
return descendants(endorsement, children).some(
|
|
3275
|
+
(node) => node.kind === "endorsement" && descendants(node, children).some((descendant) => descendant.kind === "table_row")
|
|
3276
|
+
);
|
|
3277
|
+
}
|
|
2998
3278
|
function buildCoverages(nodes) {
|
|
3279
|
+
const children = childMap(nodes);
|
|
3280
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
3281
|
+
const coverages = [];
|
|
3282
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3283
|
+
for (const endorsement of nodes.filter((node) => node.kind === "endorsement")) {
|
|
3284
|
+
if (hasDescendantEndorsementWithTableRows(endorsement, children)) continue;
|
|
3285
|
+
const coverage = coverageFromEndorsement(endorsement, children);
|
|
3286
|
+
if (!coverage) continue;
|
|
3287
|
+
const key = [coverage.name.toLowerCase(), coverage.sourceNodeIds.join(",")].join("|");
|
|
3288
|
+
if (seen.has(key)) continue;
|
|
3289
|
+
seen.add(key);
|
|
3290
|
+
coverages.push(coverage);
|
|
3291
|
+
}
|
|
2999
3292
|
const rows = nodes.filter((node) => {
|
|
3000
3293
|
const text = nodeText(node);
|
|
3001
|
-
return (node.kind === "table_row" || node.kind === "schedule" || node.kind === "text") && /\b(coverage|limit|deductible|aggregate|occurrence|liability|premium)\b/i.test(text);
|
|
3294
|
+
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);
|
|
3002
3295
|
});
|
|
3003
|
-
const coverages = [];
|
|
3004
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3005
3296
|
for (const row of rows) {
|
|
3297
|
+
if (endorsementAncestor(row, byId)) continue;
|
|
3298
|
+
const structured = row.kind === "table_row" ? coverageFromTableRow(row, children, byId) : void 0;
|
|
3299
|
+
if (structured) {
|
|
3300
|
+
const key2 = [
|
|
3301
|
+
structured.name.toLowerCase(),
|
|
3302
|
+
structured.limits.map((term) => `${term.kind}:${term.value}`).join(","),
|
|
3303
|
+
structured.sourceNodeIds.join(",")
|
|
3304
|
+
].join("|");
|
|
3305
|
+
if (seen.has(key2)) continue;
|
|
3306
|
+
seen.add(key2);
|
|
3307
|
+
coverages.push(structured);
|
|
3308
|
+
if (coverages.length >= 60) break;
|
|
3309
|
+
continue;
|
|
3310
|
+
}
|
|
3006
3311
|
const text = nodeText(row);
|
|
3007
3312
|
const name = coverageNameFromRow(text);
|
|
3008
3313
|
const limit = limitFromText(text);
|
|
@@ -3018,6 +3323,8 @@ function buildCoverages(nodes) {
|
|
|
3018
3323
|
deductible,
|
|
3019
3324
|
premium,
|
|
3020
3325
|
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3326
|
+
coverageOrigin: "core",
|
|
3327
|
+
limits: [],
|
|
3021
3328
|
sourceNodeIds: [row.id],
|
|
3022
3329
|
sourceSpanIds: row.sourceSpanIds
|
|
3023
3330
|
});
|
|
@@ -3159,11 +3466,33 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
|
|
|
3159
3466
|
sourceSpanIds
|
|
3160
3467
|
};
|
|
3161
3468
|
};
|
|
3162
|
-
const coverages = Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) =>
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3469
|
+
const coverages = base.coverages.length > 0 ? base.coverages : Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
|
|
3470
|
+
const record = coverage;
|
|
3471
|
+
const limits = Array.isArray(record.limits) ? record.limits.filter(
|
|
3472
|
+
(term) => Boolean(term) && typeof term === "object" && !Array.isArray(term)
|
|
3473
|
+
).flatMap((term) => {
|
|
3474
|
+
const label = typeof term.label === "string" ? cleanValue(term.label) : void 0;
|
|
3475
|
+
const value = typeof term.value === "string" ? cleanValue(term.value) : void 0;
|
|
3476
|
+
const sourceNodeIds = keepIds(term.sourceNodeIds, validNodeIds);
|
|
3477
|
+
const sourceSpanIds = keepIds(term.sourceSpanIds, validSpanIds);
|
|
3478
|
+
if (!label || !value || sourceNodeIds.length === 0 && sourceSpanIds.length === 0) return [];
|
|
3479
|
+
return [{
|
|
3480
|
+
kind: normalizeTermKind(term.kind, label, value),
|
|
3481
|
+
label,
|
|
3482
|
+
value,
|
|
3483
|
+
amount: typeof term.amount === "number" && Number.isFinite(term.amount) ? term.amount : void 0,
|
|
3484
|
+
appliesTo: typeof term.appliesTo === "string" ? term.appliesTo : void 0,
|
|
3485
|
+
sourceNodeIds,
|
|
3486
|
+
sourceSpanIds
|
|
3487
|
+
}];
|
|
3488
|
+
}) : [];
|
|
3489
|
+
return {
|
|
3490
|
+
...coverage,
|
|
3491
|
+
limits,
|
|
3492
|
+
sourceNodeIds: keepIds(record.sourceNodeIds, validNodeIds),
|
|
3493
|
+
sourceSpanIds: keepIds(record.sourceSpanIds, validSpanIds)
|
|
3494
|
+
};
|
|
3495
|
+
}).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
|
|
3167
3496
|
return PolicyOperationalProfileSchema.parse({
|
|
3168
3497
|
...base,
|
|
3169
3498
|
documentType: candidate.documentType === "quote" ? "quote" : candidate.documentType === "policy" ? "policy" : base.documentType,
|
|
@@ -9173,8 +9502,31 @@ var OperationalProfilePromptSchema = z41.object({
|
|
|
9173
9502
|
limit: z41.string().optional(),
|
|
9174
9503
|
deductible: z41.string().optional(),
|
|
9175
9504
|
premium: z41.string().optional(),
|
|
9505
|
+
retroactiveDate: z41.string().optional(),
|
|
9176
9506
|
formNumber: z41.string().optional(),
|
|
9177
9507
|
sectionRef: z41.string().optional(),
|
|
9508
|
+
coverageOrigin: z41.enum(["core", "endorsement"]).optional(),
|
|
9509
|
+
endorsementNumber: z41.string().optional(),
|
|
9510
|
+
limits: z41.array(z41.object({
|
|
9511
|
+
kind: z41.enum([
|
|
9512
|
+
"each_claim_limit",
|
|
9513
|
+
"each_occurrence_limit",
|
|
9514
|
+
"each_loss_limit",
|
|
9515
|
+
"aggregate_limit",
|
|
9516
|
+
"sublimit",
|
|
9517
|
+
"retention",
|
|
9518
|
+
"deductible",
|
|
9519
|
+
"retroactive_date",
|
|
9520
|
+
"premium",
|
|
9521
|
+
"other"
|
|
9522
|
+
]).optional(),
|
|
9523
|
+
label: z41.string(),
|
|
9524
|
+
value: z41.string(),
|
|
9525
|
+
amount: z41.number().optional(),
|
|
9526
|
+
appliesTo: z41.string().optional(),
|
|
9527
|
+
sourceNodeIds: z41.array(z41.string()),
|
|
9528
|
+
sourceSpanIds: z41.array(z41.string())
|
|
9529
|
+
})).optional(),
|
|
9178
9530
|
sourceNodeIds: z41.array(z41.string()),
|
|
9179
9531
|
sourceSpanIds: z41.array(z41.string())
|
|
9180
9532
|
})).optional(),
|
|
@@ -9988,8 +10340,8 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
9988
10340
|
const current = updates.get(child.id) ?? child;
|
|
9989
10341
|
const heading = sectionHeadingTitle(current, container);
|
|
9990
10342
|
if (heading) {
|
|
9991
|
-
const
|
|
9992
|
-
const hasOwnContent =
|
|
10343
|
+
const descendants2 = byParent.get(child.id) ?? [];
|
|
10344
|
+
const hasOwnContent = descendants2.some((descendant) => descendant.kind !== "table_row" && descendant.kind !== "table_cell");
|
|
9993
10345
|
let hasFollowingContent = false;
|
|
9994
10346
|
for (const nextChild of directPageChildren.slice(index + 1)) {
|
|
9995
10347
|
const next = updates.get(nextChild.id) ?? nextChild;
|
|
@@ -10007,7 +10359,7 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
10007
10359
|
parentId: container.id,
|
|
10008
10360
|
kind: sectionKindForTitle(heading),
|
|
10009
10361
|
title: heading,
|
|
10010
|
-
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...
|
|
10362
|
+
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...descendants2]),
|
|
10011
10363
|
metadata: {
|
|
10012
10364
|
...current.metadata,
|
|
10013
10365
|
organizer: "title_section",
|
|
@@ -10337,13 +10689,16 @@ function buildOperationalProfilePrompt(sourceTree, fallback) {
|
|
|
10337
10689
|
|
|
10338
10690
|
Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
|
|
10339
10691
|
- policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium
|
|
10340
|
-
- coverage
|
|
10692
|
+
- coverage units with their own nested limit terms, deductibles/retentions, retroactive dates, premiums, and form references
|
|
10341
10693
|
- coverage type labels
|
|
10342
10694
|
|
|
10343
10695
|
Rules:
|
|
10344
10696
|
- Every returned value must include sourceNodeIds or sourceSpanIds from the provided nodes.
|
|
10345
10697
|
- If a value is not directly supported, omit it.
|
|
10346
10698
|
- Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
|
|
10699
|
+
- Treat an endorsement as one coverage unit when it contains a schedule. Do not split an endorsement schedule into generic rows like "Aggregate Limit".
|
|
10700
|
+
- 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.
|
|
10701
|
+
- Use coverageOrigin: "endorsement" for endorsement units and "core" for declarations/core policy coverage units.
|
|
10347
10702
|
- Do not copy entire policy wording into fields.
|
|
10348
10703
|
|
|
10349
10704
|
Deterministic baseline:
|
|
@@ -10459,11 +10814,18 @@ function materializeDocument(params) {
|
|
|
10459
10814
|
limit: coverage.limit,
|
|
10460
10815
|
deductible: coverage.deductible,
|
|
10461
10816
|
premium: coverage.premium,
|
|
10817
|
+
retroactiveDate: coverage.retroactiveDate,
|
|
10462
10818
|
formNumber: coverage.formNumber,
|
|
10463
10819
|
sectionRef: coverage.sectionRef,
|
|
10820
|
+
coverageOrigin: coverage.coverageOrigin,
|
|
10821
|
+
endorsementNumber: coverage.endorsementNumber,
|
|
10822
|
+
limits: coverage.limits,
|
|
10464
10823
|
sourceSpanIds: coverage.sourceSpanIds,
|
|
10465
10824
|
documentNodeId: coverage.sourceNodeIds[0],
|
|
10466
|
-
originalContent: [
|
|
10825
|
+
originalContent: [
|
|
10826
|
+
coverage.name,
|
|
10827
|
+
...coverage.limits?.length ? coverage.limits.map((term) => `${term.label}: ${term.value}`) : [coverage.limit, coverage.deductible, coverage.premium]
|
|
10828
|
+
].filter(Boolean).join(" | ")
|
|
10467
10829
|
}));
|
|
10468
10830
|
const documentOutline = sourceTreeToOutline(params.sourceTree);
|
|
10469
10831
|
const documentMetadata = {
|
|
@@ -15589,6 +15951,7 @@ export {
|
|
|
15589
15951
|
MissingInfoQuestionSchema,
|
|
15590
15952
|
NamedInsuredSchema,
|
|
15591
15953
|
OperationalCoverageLineSchema,
|
|
15954
|
+
OperationalCoverageTermSchema,
|
|
15592
15955
|
OperationalEndorsementSupportSchema,
|
|
15593
15956
|
OperationalPartySchema,
|
|
15594
15957
|
PERSONAL_AUTO_USAGES,
|