@claritylabs/cl-sdk 3.1.6 → 3.1.8
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 +3 -3
- package/dist/application.d.mts +1 -1
- package/dist/application.d.ts +1 -1
- package/dist/application.js.map +1 -1
- package/dist/application.mjs.map +1 -1
- package/dist/{index-C-jIqJru.d.mts → index-CTxWtbqE.d.mts} +2 -2
- package/dist/{index-C-jIqJru.d.ts → index-CTxWtbqE.d.ts} +2 -2
- package/dist/index.d.mts +3 -9
- package/dist/index.d.ts +3 -9
- package/dist/index.js +241 -907
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +241 -905
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2986,878 +2986,6 @@ function buildDocumentSourceTree(sourceSpans, documentId) {
|
|
|
2986
2986
|
return normalizeDocumentSourceTreePaths(groupPageContentByTitles([...nodes.values()]));
|
|
2987
2987
|
}
|
|
2988
2988
|
|
|
2989
|
-
// src/source/operational-profile.ts
|
|
2990
|
-
function normalizeWhitespace3(value) {
|
|
2991
|
-
return value.replace(/\s+/g, " ").trim();
|
|
2992
|
-
}
|
|
2993
|
-
function cleanValue(value) {
|
|
2994
|
-
if (!value) return void 0;
|
|
2995
|
-
return normalizeWhitespace3(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
|
|
2996
|
-
}
|
|
2997
|
-
function cleanCoverageLabel(value) {
|
|
2998
|
-
return cleanValue(value)?.replace(/^column\s+\d+\s*:\s*/i, "");
|
|
2999
|
-
}
|
|
3000
|
-
function moneyValue(value) {
|
|
3001
|
-
const clean = cleanValue(value);
|
|
3002
|
-
if (!clean) return void 0;
|
|
3003
|
-
if (/^\$/.test(clean)) return clean;
|
|
3004
|
-
if (/^\d{1,3}(?:,\d{3})*(?:\.\d{2})?$/.test(clean)) return `$${clean}`;
|
|
3005
|
-
return clean;
|
|
3006
|
-
}
|
|
3007
|
-
function premiumValue(value) {
|
|
3008
|
-
const clean = cleanValue(value);
|
|
3009
|
-
if (!clean) return void 0;
|
|
3010
|
-
if (/\$[A-Z0-9]/i.test(clean)) return clean;
|
|
3011
|
-
if (/\b(?:CAD|USD)\b/i.test(clean) && /(?:\d|X{2,})/i.test(clean)) return clean;
|
|
3012
|
-
if (/^\d{1,3}(?:,\d{3})+\.\d{2}$/.test(clean) || /^\d+\.\d{2}$/.test(clean)) return `$${clean}`;
|
|
3013
|
-
if (/^X{2,}(?:,X{3})*(?:\.X{2})$/i.test(clean)) return clean;
|
|
3014
|
-
return void 0;
|
|
3015
|
-
}
|
|
3016
|
-
function nodeText(node) {
|
|
3017
|
-
return normalizeWhitespace3([
|
|
3018
|
-
node.title,
|
|
3019
|
-
node.description,
|
|
3020
|
-
node.textExcerpt
|
|
3021
|
-
].filter(Boolean).join(" "));
|
|
3022
|
-
}
|
|
3023
|
-
function valueFromNode(node, value, confidence = "medium") {
|
|
3024
|
-
return {
|
|
3025
|
-
value,
|
|
3026
|
-
confidence,
|
|
3027
|
-
sourceNodeIds: [node.id],
|
|
3028
|
-
sourceSpanIds: node.sourceSpanIds
|
|
3029
|
-
};
|
|
3030
|
-
}
|
|
3031
|
-
function valueFromNodes(nodes, value, confidence = "medium", normalizedValue) {
|
|
3032
|
-
return {
|
|
3033
|
-
value,
|
|
3034
|
-
...normalizedValue ? { normalizedValue } : {},
|
|
3035
|
-
confidence,
|
|
3036
|
-
...sourceIds(nodes)
|
|
3037
|
-
};
|
|
3038
|
-
}
|
|
3039
|
-
function firstMatch(nodes, patterns) {
|
|
3040
|
-
for (const node of nodes) {
|
|
3041
|
-
const text = nodeText(node);
|
|
3042
|
-
for (const pattern of patterns) {
|
|
3043
|
-
const match = text.match(pattern);
|
|
3044
|
-
const value = cleanValue(match?.[1]);
|
|
3045
|
-
if (value) return valueFromNode(node, value, "high");
|
|
3046
|
-
}
|
|
3047
|
-
}
|
|
3048
|
-
return void 0;
|
|
3049
|
-
}
|
|
3050
|
-
var POLICY_NUMBER_PATTERNS = [
|
|
3051
|
-
/\bpolicy\s*(?:number|no\.?|#)\s*:?\s*([A-Z0-9][A-Z0-9,.-]{4,}[A-Z0-9])/i,
|
|
3052
|
-
/\bpolicy\s*[:#]\s*([A-Z0-9][A-Z0-9,.-]{4,}[A-Z0-9])/i
|
|
3053
|
-
];
|
|
3054
|
-
function policyNumberEvidenceScore(node) {
|
|
3055
|
-
const text = normalizeWhitespace3([node.path, nodeText(node)].filter(Boolean).join(" ")).toLowerCase();
|
|
3056
|
-
let score = 0;
|
|
3057
|
-
if (/\b(policy\s+summary|declarations?|declaration\s+page|schedule)\b/.test(text)) score += 80;
|
|
3058
|
-
if (/\b(plan|policy\s+date|insured\s+person|named\s+insured|insurance\s+amount|benefit\s+amount)\b/.test(text)) score += 35;
|
|
3059
|
-
if (node.kind === "table_row" || node.kind === "table_cell" || node.kind === "text") score += 20;
|
|
3060
|
-
if (node.kind === "page") score += 10;
|
|
3061
|
-
if (typeof node.pageStart === "number" && node.pageStart > 1 && node.pageStart <= 10) score += 20;
|
|
3062
|
-
if (typeof node.pageStart === "number" && node.pageStart === 1) score -= 30;
|
|
3063
|
-
if (/\b(notices?\s+and\s+jacket|policy\s+jacket|front\s+matter|table\s+of\s+contents)\b/.test(text)) score -= 70;
|
|
3064
|
-
if (node.kind === "page_group" || node.kind === "form") score -= 30;
|
|
3065
|
-
return score;
|
|
3066
|
-
}
|
|
3067
|
-
function policyNumberFromNodes(nodes) {
|
|
3068
|
-
const candidates = nodes.slice(0, 120).flatMap((node) => {
|
|
3069
|
-
const text = nodeText(node);
|
|
3070
|
-
for (const pattern of POLICY_NUMBER_PATTERNS) {
|
|
3071
|
-
const value = cleanValue(text.match(pattern)?.[1]);
|
|
3072
|
-
if (value) return [{ node, value, score: policyNumberEvidenceScore(node) }];
|
|
3073
|
-
}
|
|
3074
|
-
return [];
|
|
3075
|
-
}).sort(
|
|
3076
|
-
(left, right) => right.score - left.score || (left.node.pageStart ?? Number.MAX_SAFE_INTEGER) - (right.node.pageStart ?? Number.MAX_SAFE_INTEGER) || left.node.order - right.node.order
|
|
3077
|
-
);
|
|
3078
|
-
const candidate = candidates[0];
|
|
3079
|
-
return candidate ? valueFromNode(candidate.node, candidate.value, "high") : void 0;
|
|
3080
|
-
}
|
|
3081
|
-
function compactFactNodes(nodes) {
|
|
3082
|
-
return nodes.filter((node) => {
|
|
3083
|
-
if (node.kind === "document" || node.kind === "page_group" || node.kind === "form") return false;
|
|
3084
|
-
const text = nodeText(node);
|
|
3085
|
-
if (text.length > 900) return false;
|
|
3086
|
-
if (/\b(table of contents|provided solely for your convenience|not to be construed|actual policy issued)\b/i.test(text)) return false;
|
|
3087
|
-
return node.kind === "text" || node.kind === "table_row" || node.kind === "table_cell" || node.kind === "page";
|
|
3088
|
-
});
|
|
3089
|
-
}
|
|
3090
|
-
function firstCleanMatch(nodes, patterns, clean) {
|
|
3091
|
-
for (const node of compactFactNodes(nodes)) {
|
|
3092
|
-
const text = nodeText(node);
|
|
3093
|
-
for (const pattern of patterns) {
|
|
3094
|
-
const raw = cleanValue(text.match(pattern)?.[1]);
|
|
3095
|
-
if (!raw) continue;
|
|
3096
|
-
const value = clean(raw);
|
|
3097
|
-
if (value) return valueFromNode(node, value, "high");
|
|
3098
|
-
}
|
|
3099
|
-
}
|
|
3100
|
-
return void 0;
|
|
3101
|
-
}
|
|
3102
|
-
function cleanNamedInsured(value) {
|
|
3103
|
-
const clean = cleanValue(value.replace(/\bborn\s+on\b.*$/i, "").replace(/\bage\s+nearest\b.*$/i, "").replace(/\bbeneficiary\b.*$/i, ""));
|
|
3104
|
-
if (!clean || clean.length > 160) return void 0;
|
|
3105
|
-
if (!/[A-Za-z0-9]/.test(clean)) return void 0;
|
|
3106
|
-
if (/^(person|persons)\b/i.test(clean)) return void 0;
|
|
3107
|
-
if (/^(insurance amount|benefit amount|policy number|policy date|owner|beneficiary|premium|coverage|risk classification)\b/i.test(clean)) {
|
|
3108
|
-
return void 0;
|
|
3109
|
-
}
|
|
3110
|
-
if (/\b(table of contents|policy wording|provided solely|convenience|not to be construed|actual policy issued)\b/i.test(clean)) {
|
|
3111
|
-
return void 0;
|
|
3112
|
-
}
|
|
3113
|
-
return clean;
|
|
3114
|
-
}
|
|
3115
|
-
var PARTY_LABEL_PATTERNS = {
|
|
3116
|
-
namedInsured: /^(?:item\s*\d+[.)]?\s*)?(?:named insured(?:\s+and\s+address)?|insured name)$/i,
|
|
3117
|
-
insurer: /^(?:carrier|insurer|security)$/i,
|
|
3118
|
-
broker: /^(?:broker(?:\s+of\s+record)?|producer|agent)$/i
|
|
3119
|
-
};
|
|
3120
|
-
function partyLabelKind(value) {
|
|
3121
|
-
const clean = cleanValue(value.replace(/^\s*column\s+\d+\s*:\s*/i, ""));
|
|
3122
|
-
if (!clean) return void 0;
|
|
3123
|
-
if (PARTY_LABEL_PATTERNS.namedInsured.test(clean)) return "namedInsured";
|
|
3124
|
-
if (PARTY_LABEL_PATTERNS.insurer.test(clean)) return "insurer";
|
|
3125
|
-
if (PARTY_LABEL_PATTERNS.broker.test(clean)) return "broker";
|
|
3126
|
-
return void 0;
|
|
3127
|
-
}
|
|
3128
|
-
function isRejectedPartyValue(value) {
|
|
3129
|
-
const clean = normalizeWhitespace3(value);
|
|
3130
|
-
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);
|
|
3131
|
-
}
|
|
3132
|
-
function identityWithoutAddress(value) {
|
|
3133
|
-
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, ""));
|
|
3134
|
-
if (!clean) return void 0;
|
|
3135
|
-
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];
|
|
3136
|
-
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];
|
|
3137
|
-
return cleanValue(beforeStreet ?? beforeCityState ?? clean);
|
|
3138
|
-
}
|
|
3139
|
-
function cleanPartyIdentity(value, clean) {
|
|
3140
|
-
const raw = cleanValue(value);
|
|
3141
|
-
if (!raw || isRejectedPartyValue(raw)) return void 0;
|
|
3142
|
-
const identity = identityWithoutAddress(raw);
|
|
3143
|
-
const cleaned = identity ? clean(identity) : void 0;
|
|
3144
|
-
if (!cleaned || isRejectedPartyValue(cleaned)) return void 0;
|
|
3145
|
-
return {
|
|
3146
|
-
value: cleaned,
|
|
3147
|
-
...cleaned !== raw ? { normalizedValue: cleaned } : {}
|
|
3148
|
-
};
|
|
3149
|
-
}
|
|
3150
|
-
function partyFromTableRows(nodes, wanted, clean) {
|
|
3151
|
-
const children = childMap(nodes);
|
|
3152
|
-
for (const row of compactFactNodes(nodes).filter((node) => node.kind === "table_row")) {
|
|
3153
|
-
const cells = cellRows(row, children);
|
|
3154
|
-
for (const [index, cell] of cells.entries()) {
|
|
3155
|
-
const labelKind = partyLabelKind(cell.value) ?? partyLabelKind(cell.label);
|
|
3156
|
-
if (labelKind !== wanted) continue;
|
|
3157
|
-
const valueCell = cells.slice(index + 1).find((candidate) => !partyLabelKind(candidate.value) && !partyLabelKind(candidate.label));
|
|
3158
|
-
if (!valueCell) continue;
|
|
3159
|
-
const cleaned = cleanPartyIdentity(valueCell.value, clean);
|
|
3160
|
-
if (cleaned) return valueFromNodes([row, valueCell.node], cleaned.value, "high", cleaned.normalizedValue);
|
|
3161
|
-
}
|
|
3162
|
-
const parts = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row)).split(/\s+\|\s+|\t/).map(cleanValue).filter((part) => Boolean(part));
|
|
3163
|
-
for (const [index, part] of parts.entries()) {
|
|
3164
|
-
const labelKind = partyLabelKind(part);
|
|
3165
|
-
if (labelKind !== wanted) continue;
|
|
3166
|
-
const cleaned = cleanPartyIdentity(parts[index + 1] ?? "", clean);
|
|
3167
|
-
if (cleaned) return valueFromNodes([row], cleaned.value, "high", cleaned.normalizedValue);
|
|
3168
|
-
}
|
|
3169
|
-
}
|
|
3170
|
-
return void 0;
|
|
3171
|
-
}
|
|
3172
|
-
function namedInsuredFromNodes(nodes) {
|
|
3173
|
-
return partyFromTableRows(nodes, "namedInsured", cleanNamedInsured) ?? firstCleanMatch(nodes, [
|
|
3174
|
-
/\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,
|
|
3175
|
-
/\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,
|
|
3176
|
-
/\b(?:applicant|policyholder)\s*:?\s*(.+?)(?=\s+(?:coverage|policy number|insurer|carrier|premium|effective|expiration)\b|[|;\n]|$)/i
|
|
3177
|
-
], cleanNamedInsured);
|
|
3178
|
-
}
|
|
3179
|
-
function cleanInsurer(value) {
|
|
3180
|
-
const clean = cleanValue(value);
|
|
3181
|
-
if (!clean || clean.length > 140) return void 0;
|
|
3182
|
-
if (/^(mean|means|we|us|our|the|a|an|agrees?|shall|will)\b/i.test(clean)) return void 0;
|
|
3183
|
-
if (/\b(table of contents|policy wording|provided solely|convenience)\b/i.test(clean)) return void 0;
|
|
3184
|
-
const known = clean.match(/\b(Sun Life Assurance Company of Canada|Manulife|The Manufacturers Life Insurance Company)\b/i)?.[1];
|
|
3185
|
-
return known ?? clean;
|
|
3186
|
-
}
|
|
3187
|
-
function insurerFromNodes(nodes) {
|
|
3188
|
-
const tableValue = partyFromTableRows(nodes, "insurer", cleanInsurer);
|
|
3189
|
-
if (tableValue) return tableValue;
|
|
3190
|
-
for (const node of compactFactNodes(nodes)) {
|
|
3191
|
-
const text = nodeText(node);
|
|
3192
|
-
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] ?? "");
|
|
3193
|
-
if (value) return valueFromNode(node, value, "high");
|
|
3194
|
-
}
|
|
3195
|
-
return firstCleanMatch(nodes, [
|
|
3196
|
-
/\bunderwritten by\s+([^|;\n.]{3,160})/i,
|
|
3197
|
-
/\b(?:insurer|carrier|company|security)\s*:?\s*([^|;\n]{3,120})/i,
|
|
3198
|
-
/\b(Sun Life Assurance Company of Canada|Manulife|The Manufacturers Life Insurance Company)\b/i
|
|
3199
|
-
], cleanInsurer);
|
|
3200
|
-
}
|
|
3201
|
-
function inferPolicyTypes(nodes) {
|
|
3202
|
-
const text = nodes.slice(0, 40).map(nodeText).join(" ").toLowerCase();
|
|
3203
|
-
const types = [];
|
|
3204
|
-
const add = (pattern, type) => {
|
|
3205
|
-
if (pattern.test(text) && !types.includes(type)) types.push(type);
|
|
3206
|
-
};
|
|
3207
|
-
add(/\b(life insurance|permanent life|term life|whole life|universal life|sun permanent life|sun par protector|manulife par|vitality\s*plus|death benefit)\b/i, "life");
|
|
3208
|
-
add(/\b(critical illness|critical illness insurance|covered critical illness|partial benefit payout)\b/i, "critical_illness");
|
|
3209
|
-
add(/\b(disability benefit|total disability|catastrophic disability|disability waiver|waiver of premium disability)\b/i, "disability");
|
|
3210
|
-
add(/\b(long[-\s]?term care|long term care conversion)\b/i, "long_term_care");
|
|
3211
|
-
add(/\b(cyber|network security|privacy liability|data breach)\b/i, "cyber");
|
|
3212
|
-
add(/\b(professional liability|errors?\s*&?\s*omissions|e&o)\b/i, "professional_liability");
|
|
3213
|
-
add(/\b(commercial general liability|general liability|cgl)\b/i, "general_liability");
|
|
3214
|
-
add(/\b(umbrella|excess liability)\b/i, "umbrella");
|
|
3215
|
-
add(/\b(workers'? compensation|employers'? liability)\b/i, "workers_comp");
|
|
3216
|
-
add(/\b(commercial auto|business auto|automobile liability)\b/i, "commercial_auto");
|
|
3217
|
-
add(/\b(commercial property|property coverage|building coverage)\b/i, "commercial_property");
|
|
3218
|
-
return types.length ? types : ["other"];
|
|
3219
|
-
}
|
|
3220
|
-
function inferDocumentType(nodes) {
|
|
3221
|
-
const text = nodes.slice(0, 25).map(nodeText).join(" ").toLowerCase();
|
|
3222
|
-
if (/\b(quote|proposal|quotation|indication)\b/.test(text) && !/\bpolicy number\b/.test(text)) {
|
|
3223
|
-
return "quote";
|
|
3224
|
-
}
|
|
3225
|
-
return "policy";
|
|
3226
|
-
}
|
|
3227
|
-
function coverageNameFromRow(text) {
|
|
3228
|
-
const labelled = text.match(/\b(coverage part|coverage|line)\s*:?\s*([^|;$]{3,80})/i);
|
|
3229
|
-
if (labelled) {
|
|
3230
|
-
const value = cleanCoverageLabel(labelled[2]);
|
|
3231
|
-
if (!value) return void 0;
|
|
3232
|
-
return /^coverage part$/i.test(labelled[1]) ? `Coverage Part ${value}` : value;
|
|
3233
|
-
}
|
|
3234
|
-
const parts = text.split(/\s+\|\s+| {2,}|\t/).map(cleanCoverageLabel).filter(Boolean);
|
|
3235
|
-
const first = parts.find(
|
|
3236
|
-
(part) => !/^(limit|limits?|deductible|premium|amount|basis|rate|retroactive|aggregate|each occurrence)$/i.test(part) && !/^\$?[\d,]+/.test(part)
|
|
3237
|
-
);
|
|
3238
|
-
return cleanCoverageLabel(first);
|
|
3239
|
-
}
|
|
3240
|
-
function isDeclarationLimitLabel(value) {
|
|
3241
|
-
const label = normalizeLabel(value);
|
|
3242
|
-
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);
|
|
3243
|
-
}
|
|
3244
|
-
function declarationCoverageNameFromRow(row, children) {
|
|
3245
|
-
const cells = cellRows(row, children);
|
|
3246
|
-
const candidates = [
|
|
3247
|
-
row.title,
|
|
3248
|
-
...cells.flatMap((cell) => [cell.label, cell.value])
|
|
3249
|
-
];
|
|
3250
|
-
if (!candidates.some(isDeclarationLimitLabel)) return void 0;
|
|
3251
|
-
return candidates.some((candidate) => /\blimits?\s+of\s+liability\b/i.test(candidate ?? "")) ? "Limits of Liability" : "Policy Limits";
|
|
3252
|
-
}
|
|
3253
|
-
function limitFromText(text) {
|
|
3254
|
-
return moneyValue(
|
|
3255
|
-
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]
|
|
3256
|
-
);
|
|
3257
|
-
}
|
|
3258
|
-
function deductibleFromText(text) {
|
|
3259
|
-
return moneyValue(text.match(/\b(?:deductible|retention|sir)\s*:?\s*(\$?\d[\d,]*(?:\.\d{2})?)/i)?.[1]);
|
|
3260
|
-
}
|
|
3261
|
-
function premiumFromText(text) {
|
|
3262
|
-
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]);
|
|
3263
|
-
}
|
|
3264
|
-
function premiumFromNodes(nodes) {
|
|
3265
|
-
for (const node of compactFactNodes(nodes)) {
|
|
3266
|
-
const value = premiumFromText(nodeText(node));
|
|
3267
|
-
if (value) return valueFromNode(node, value, "high");
|
|
3268
|
-
}
|
|
3269
|
-
return void 0;
|
|
3270
|
-
}
|
|
3271
|
-
function moneyAmount(value) {
|
|
3272
|
-
const clean = cleanValue(value);
|
|
3273
|
-
if (!clean) return void 0;
|
|
3274
|
-
const currency = clean.match(/\$\s*([0-9][0-9,]*(?:\.\d+)?)/);
|
|
3275
|
-
const percent = clean.match(/\b([0-9][0-9,]*(?:\.\d+)?)\s*%/);
|
|
3276
|
-
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;
|
|
3277
|
-
const match = currency ?? percent ?? explicitNumeric;
|
|
3278
|
-
if (!match) return void 0;
|
|
3279
|
-
const amount = Number(match[1].replace(/,/g, ""));
|
|
3280
|
-
return Number.isFinite(amount) ? amount : void 0;
|
|
3281
|
-
}
|
|
3282
|
-
function normalizeLabel(value) {
|
|
3283
|
-
return normalizeWhitespace3(value ?? "").toLowerCase();
|
|
3284
|
-
}
|
|
3285
|
-
function isGenericColumnLabel(value) {
|
|
3286
|
-
return /^column\s+\d+$/i.test(cleanValue(value) ?? "");
|
|
3287
|
-
}
|
|
3288
|
-
function isHeaderRow(row) {
|
|
3289
|
-
return row.metadata?.isHeader === true || row.metadata?.isHeader === "true";
|
|
3290
|
-
}
|
|
3291
|
-
var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
|
|
3292
|
-
"each_claim_limit",
|
|
3293
|
-
"each_occurrence_limit",
|
|
3294
|
-
"each_loss_limit",
|
|
3295
|
-
"aggregate_limit",
|
|
3296
|
-
"sublimit",
|
|
3297
|
-
"retention",
|
|
3298
|
-
"deductible",
|
|
3299
|
-
"retroactive_date",
|
|
3300
|
-
"premium",
|
|
3301
|
-
"other"
|
|
3302
|
-
]);
|
|
3303
|
-
function termKind(label, value) {
|
|
3304
|
-
const text = normalizeLabel(`${label} ${value}`);
|
|
3305
|
-
if (/\bretroactive\b/.test(text)) return "retroactive_date";
|
|
3306
|
-
if (/\b(self[-\s]?insured retention|retention|sir)\b/.test(text)) return "retention";
|
|
3307
|
-
if (/\bdeductible\b/.test(text)) return "deductible";
|
|
3308
|
-
if (/\bpremium\b/.test(text)) return "premium";
|
|
3309
|
-
if (/\bsub[-\s]?limit\b/.test(text)) return "sublimit";
|
|
3310
|
-
if (/\baggregate\b/.test(text)) return "aggregate_limit";
|
|
3311
|
-
if (/\beach\s+proceeding|per\s+proceeding\b/.test(text)) return "sublimit";
|
|
3312
|
-
if (/\beach\s+claim|per\s+claim\b/.test(text)) return "each_claim_limit";
|
|
3313
|
-
if (/\beach\s+occurrence|per\s+occurrence\b/.test(text)) return "each_occurrence_limit";
|
|
3314
|
-
if (/\beach\s+loss|per\s+loss\b/.test(text)) return "each_loss_limit";
|
|
3315
|
-
if (/\blimit\b/.test(text)) return "other";
|
|
3316
|
-
return "other";
|
|
3317
|
-
}
|
|
3318
|
-
function normalizeTermKind(value, label, termValue) {
|
|
3319
|
-
return typeof value === "string" && OPERATIONAL_COVERAGE_TERM_KINDS.has(value) ? value : termKind(label, termValue);
|
|
3320
|
-
}
|
|
3321
|
-
function isValueCell(label, value) {
|
|
3322
|
-
const normalizedLabel = normalizeLabel(label);
|
|
3323
|
-
const normalizedValue = normalizeLabel(value);
|
|
3324
|
-
if (!value || normalizedValue === "\u2014") return false;
|
|
3325
|
-
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)) {
|
|
3326
|
-
return false;
|
|
3327
|
-
}
|
|
3328
|
-
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);
|
|
3329
|
-
}
|
|
3330
|
-
function isCoverageTermLabel(value) {
|
|
3331
|
-
const label = normalizeLabel(value);
|
|
3332
|
-
return /\b(limit|aggregate|retention|deductible|sir|retroactive|premium|amount|sub[-\s]?limit)\b/.test(label);
|
|
3333
|
-
}
|
|
3334
|
-
function isNameCell(label, value) {
|
|
3335
|
-
const normalizedLabel = normalizeLabel(label);
|
|
3336
|
-
const normalizedValue = normalizeLabel(value);
|
|
3337
|
-
if (!value || moneyAmount(value) !== void 0) return false;
|
|
3338
|
-
if (/^item\s+\d+[.)]?\s*limits?\s+of\s+liability\b/.test(normalizedValue)) return false;
|
|
3339
|
-
if (/\b(coverage|coverage part|insuring agreement|description|item|name)\b/.test(normalizedLabel)) {
|
|
3340
|
-
return true;
|
|
3341
|
-
}
|
|
3342
|
-
if (/\b(sub[-\s]?limit|aggregate(?:\s+policy)?\s+limit|limit\s+of\s+liability)\b/.test(normalizedLabel) && /\b[a-z][a-z0-9&/ -]{2,}\b/.test(normalizedValue) && !/\bcoverage\s+part\s+[a-z]\)?$/.test(normalizedValue)) {
|
|
3343
|
-
return true;
|
|
3344
|
-
}
|
|
3345
|
-
if (/^column\s+1$/.test(normalizedLabel) && !/^(item\s+\d+|nwc-|iso-|cg |il |form\b|page\b)/i.test(normalizedValue)) {
|
|
3346
|
-
return true;
|
|
3347
|
-
}
|
|
3348
|
-
if (/^column\s+\d+$/.test(normalizedLabel) && /\b(coverage|sub[-\s]?limit|liability|expense|part\s+[a-z])\b/.test(normalizedValue)) {
|
|
3349
|
-
return true;
|
|
3350
|
-
}
|
|
3351
|
-
return false;
|
|
3352
|
-
}
|
|
3353
|
-
function childMap(nodes) {
|
|
3354
|
-
const children = /* @__PURE__ */ new Map();
|
|
3355
|
-
for (const node of nodes) {
|
|
3356
|
-
const group = children.get(node.parentId) ?? [];
|
|
3357
|
-
group.push(node);
|
|
3358
|
-
children.set(node.parentId, group);
|
|
3359
|
-
}
|
|
3360
|
-
for (const group of children.values()) group.sort((left, right) => left.order - right.order);
|
|
3361
|
-
return children;
|
|
3362
|
-
}
|
|
3363
|
-
function rawCellRows(row, children) {
|
|
3364
|
-
return (children.get(row.id) ?? []).filter((child) => child.kind === "table_cell").map((cell) => ({
|
|
3365
|
-
label: cleanValue(cell.title) ?? "Value",
|
|
3366
|
-
value: cleanValue(cell.textExcerpt ?? cell.description ?? cell.title) ?? "",
|
|
3367
|
-
node: cell
|
|
3368
|
-
})).filter((cell) => cell.value);
|
|
3369
|
-
}
|
|
3370
|
-
function headerLabelsForRow(row, children) {
|
|
3371
|
-
if (!row.parentId) return [];
|
|
3372
|
-
const labels = [];
|
|
3373
|
-
const siblingRows = (children.get(row.parentId) ?? []).filter((candidate) => candidate.kind === "table_row" && candidate.order < row.order).sort((left, right) => left.order - right.order);
|
|
3374
|
-
for (const sibling of siblingRows) {
|
|
3375
|
-
if (!isHeaderRow(sibling)) continue;
|
|
3376
|
-
for (const [index, cell] of rawCellRows(sibling, children).entries()) {
|
|
3377
|
-
const label = cleanValue(cell.value) ?? cleanValue(cell.label);
|
|
3378
|
-
if (label && !isGenericColumnLabel(label)) labels[index] = label;
|
|
3379
|
-
}
|
|
3380
|
-
}
|
|
3381
|
-
return labels;
|
|
3382
|
-
}
|
|
3383
|
-
function cellRows(row, children, headerLabels = []) {
|
|
3384
|
-
return rawCellRows(row, children).map((cell, index) => ({
|
|
3385
|
-
...cell,
|
|
3386
|
-
label: isGenericColumnLabel(cell.label) && headerLabels[index] ? headerLabels[index] : cell.label
|
|
3387
|
-
}));
|
|
3388
|
-
}
|
|
3389
|
-
function directChildren(parent, children) {
|
|
3390
|
-
return children.get(parent.id) ?? [];
|
|
3391
|
-
}
|
|
3392
|
-
function descendants(parent, children) {
|
|
3393
|
-
const stack = [...directChildren(parent, children)];
|
|
3394
|
-
const result = [];
|
|
3395
|
-
while (stack.length > 0) {
|
|
3396
|
-
const node = stack.shift();
|
|
3397
|
-
result.push(node);
|
|
3398
|
-
stack.unshift(...directChildren(node, children));
|
|
3399
|
-
}
|
|
3400
|
-
return result;
|
|
3401
|
-
}
|
|
3402
|
-
function ancestry(node, byId) {
|
|
3403
|
-
const result = [];
|
|
3404
|
-
let current = node.parentId ? byId.get(node.parentId) : void 0;
|
|
3405
|
-
while (current) {
|
|
3406
|
-
result.push(current);
|
|
3407
|
-
current = current.parentId ? byId.get(current.parentId) : void 0;
|
|
3408
|
-
}
|
|
3409
|
-
return result;
|
|
3410
|
-
}
|
|
3411
|
-
function endorsementAncestor(node, byId) {
|
|
3412
|
-
return ancestry(node, byId).find((ancestor) => ancestor.kind === "endorsement");
|
|
3413
|
-
}
|
|
3414
|
-
function endorsementNumberFrom(value) {
|
|
3415
|
-
return cleanValue(value?.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)/i)?.[1]);
|
|
3416
|
-
}
|
|
3417
|
-
function endorsementNameFrom(node) {
|
|
3418
|
-
const candidates = [node.title, node.textExcerpt, node.description, nodeText(node)].filter(Boolean);
|
|
3419
|
-
for (const candidate of candidates) {
|
|
3420
|
-
const match = candidate.match(/\bendorsement\s+no\.?\s*([0-9A-Z-]+)\s*[—-]\s*(.{3,140}?)(?=\s+This\s+endorsement\b|\.|$)/i);
|
|
3421
|
-
if (match) return cleanValue(`Endorsement No. ${match[1]} - ${match[2]}`) ?? node.title;
|
|
3422
|
-
}
|
|
3423
|
-
return node.title;
|
|
3424
|
-
}
|
|
3425
|
-
function sourceIds(nodes) {
|
|
3426
|
-
return {
|
|
3427
|
-
sourceNodeIds: [...new Set(nodes.map((node) => node.id))],
|
|
3428
|
-
sourceSpanIds: [...new Set(nodes.flatMap((node) => node.sourceSpanIds))]
|
|
3429
|
-
};
|
|
3430
|
-
}
|
|
3431
|
-
function termFromCell(params) {
|
|
3432
|
-
const value = cleanCoverageTermValue(params.value);
|
|
3433
|
-
if (!value) return void 0;
|
|
3434
|
-
if (isRejectedCoverageTermValue(params.label, value)) return void 0;
|
|
3435
|
-
const nodes = [params.row, params.cell].filter((node) => Boolean(node));
|
|
3436
|
-
const kind = termKind(params.label, value);
|
|
3437
|
-
const amount = moneyAmount(value);
|
|
3438
|
-
return {
|
|
3439
|
-
kind,
|
|
3440
|
-
label: params.label,
|
|
3441
|
-
value,
|
|
3442
|
-
...amount !== void 0 && kind !== "retroactive_date" ? { amount } : {},
|
|
3443
|
-
...params.appliesTo ? { appliesTo: params.appliesTo } : {},
|
|
3444
|
-
...sourceIds(nodes)
|
|
3445
|
-
};
|
|
3446
|
-
}
|
|
3447
|
-
function cleanCoverageTermValue(value) {
|
|
3448
|
-
return cleanValue(value)?.replace(/\s+\/\s*$/, "").trim();
|
|
3449
|
-
}
|
|
3450
|
-
function isRejectedCoverageTermValue(label, value) {
|
|
3451
|
-
if (/\bshown\s+in\s+item\s*\d+\b/i.test(value) && moneyAmount(value) === void 0) return true;
|
|
3452
|
-
if (/\b(does not afford coverage|doesn't afford coverage|no coverage|remains excluded|is excluded|are excluded|shall not cover|will not cover)\b/i.test(value) && moneyAmount(value) === void 0) {
|
|
3453
|
-
return true;
|
|
3454
|
-
}
|
|
3455
|
-
if (/^for:\s*\(\d+\)/i.test(label) && moneyAmount(value) === void 0) return true;
|
|
3456
|
-
if (value.length > 80 && /\b(exclusion|excluded|shall not|will not|does not|failure to)\b/i.test(value) && moneyAmount(value) === void 0) return true;
|
|
3457
|
-
return false;
|
|
3458
|
-
}
|
|
3459
|
-
function termsFromRow(row, children) {
|
|
3460
|
-
const cells = cellRows(row, children, headerLabelsForRow(row, children));
|
|
3461
|
-
if (cells.length > 0) {
|
|
3462
|
-
const pairedTerms = [];
|
|
3463
|
-
const pairedIndexes = /* @__PURE__ */ new Set();
|
|
3464
|
-
for (const [index, cell] of cells.entries()) {
|
|
3465
|
-
const next = cells[index + 1];
|
|
3466
|
-
if (!next) continue;
|
|
3467
|
-
if (!isGenericColumnLabel(cell.label) && isNameCell(cell.label, cell.value)) continue;
|
|
3468
|
-
if (!isCoverageTermLabel(cell.value)) continue;
|
|
3469
|
-
if (isCoverageTermLabel(next.value) && moneyAmount(next.value) === void 0) continue;
|
|
3470
|
-
const term = termFromCell({ row, cell: next.node, label: cell.value, value: next.value });
|
|
3471
|
-
if (term) {
|
|
3472
|
-
pairedTerms.push(term);
|
|
3473
|
-
pairedIndexes.add(index);
|
|
3474
|
-
pairedIndexes.add(index + 1);
|
|
3475
|
-
}
|
|
3476
|
-
}
|
|
3477
|
-
const valueTerms = cells.filter((_, index) => !pairedIndexes.has(index)).filter((cell) => isValueCell(cell.label, cell.value)).map((cell) => termFromCell({ row, cell: cell.node, label: cell.label, value: cell.value })).filter((term) => Boolean(term));
|
|
3478
|
-
return [...pairedTerms, ...valueTerms];
|
|
3479
|
-
}
|
|
3480
|
-
const text = normalizeWhitespace3(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
3481
|
-
const terms = [];
|
|
3482
|
-
for (const part of text.split(/\s+\|\s+/)) {
|
|
3483
|
-
const match = part.match(/^([^:]{2,80}):\s*(.+)$/);
|
|
3484
|
-
if (!match) continue;
|
|
3485
|
-
if (!isValueCell(match[1], match[2])) continue;
|
|
3486
|
-
const term = termFromCell({ row, label: cleanValue(match[1]) ?? "Value", value: match[2] });
|
|
3487
|
-
if (term) terms.push(term);
|
|
3488
|
-
}
|
|
3489
|
-
if (terms.length === 0) {
|
|
3490
|
-
const limit = limitFromText(text);
|
|
3491
|
-
if (limit) {
|
|
3492
|
-
const term = termFromCell({ row, label: "Limit", value: limit });
|
|
3493
|
-
if (term) terms.push(term);
|
|
3494
|
-
}
|
|
3495
|
-
const deductible = deductibleFromText(text);
|
|
3496
|
-
if (deductible) {
|
|
3497
|
-
const term = termFromCell({ row, label: "Deductible", value: deductible });
|
|
3498
|
-
if (term) terms.push(term);
|
|
3499
|
-
}
|
|
3500
|
-
}
|
|
3501
|
-
return terms;
|
|
3502
|
-
}
|
|
3503
|
-
function nameFromRow(row, children) {
|
|
3504
|
-
const cells = cellRows(row, children, headerLabelsForRow(row, children));
|
|
3505
|
-
const named = cells.find((cell) => isNameCell(cell.label, cell.value));
|
|
3506
|
-
if (named) return cleanValue(named.value);
|
|
3507
|
-
const declarationName = declarationCoverageNameFromRow(row, children);
|
|
3508
|
-
if (declarationName) return declarationName;
|
|
3509
|
-
return coverageNameFromRow(row.textExcerpt ?? row.description ?? nodeText(row));
|
|
3510
|
-
}
|
|
3511
|
-
function legacyLimit(terms) {
|
|
3512
|
-
return terms.find(
|
|
3513
|
-
(term) => ["each_claim_limit", "each_occurrence_limit", "each_loss_limit", "aggregate_limit", "sublimit", "other"].includes(term.kind)
|
|
3514
|
-
)?.value;
|
|
3515
|
-
}
|
|
3516
|
-
function legacyDeductible(terms) {
|
|
3517
|
-
return terms.find((term) => term.kind === "deductible" || term.kind === "retention")?.value;
|
|
3518
|
-
}
|
|
3519
|
-
function legacyPremium(terms) {
|
|
3520
|
-
return terms.find((term) => term.kind === "premium")?.value;
|
|
3521
|
-
}
|
|
3522
|
-
function retroDate(terms) {
|
|
3523
|
-
return terms.find((term) => term.kind === "retroactive_date")?.value;
|
|
3524
|
-
}
|
|
3525
|
-
function hasCoverageLimitTerm(terms) {
|
|
3526
|
-
return terms.some(
|
|
3527
|
-
(term) => ["each_claim_limit", "each_occurrence_limit", "each_loss_limit", "aggregate_limit", "sublimit"].includes(term.kind) || term.kind === "other" && /\blimit\b/i.test(term.label) && moneyAmount(term.value) !== void 0
|
|
3528
|
-
);
|
|
3529
|
-
}
|
|
3530
|
-
function isOperationalCoverageRow(coverage) {
|
|
3531
|
-
const name = normalizeLabel(coverage.name);
|
|
3532
|
-
if (!hasCoverageLimitTerm(coverage.limits)) return false;
|
|
3533
|
-
if (/^(item\s+\d+|option:|annual policy premium|total premium|premium and payment)\b/i.test(coverage.name)) return false;
|
|
3534
|
-
if (/^coverage part\s+s\b/i.test(coverage.name)) return false;
|
|
3535
|
-
if (/^(nwc|iso|cg|il|acord)[-\s]?[a-z0-9]/i.test(coverage.name)) return false;
|
|
3536
|
-
if (/\b(forms?|endorsements?|premium|payment|terrorism risk insurance act|tria|erp option|bilateral discovery)\b/i.test(name)) return false;
|
|
3537
|
-
if (/\b(incurred in excess|shall erode|subject to|combined defense expenses)\b/i.test(name)) return false;
|
|
3538
|
-
if (coverage.name.split(/\s+/).length > 16 && !/\b(coverage|liability|sub[-\s]?limit|aggregate|each\s+(claim|loss|occurrence)|limit)\b/i.test(coverage.name)) {
|
|
3539
|
-
return false;
|
|
3540
|
-
}
|
|
3541
|
-
return /\b(coverage|coverage part|liability|sub[-\s]?limit|aggregate|each\s+(claim|loss|occurrence|proceeding)|bricking|cyber|privacy|media|regulatory|defense|fraud|social engineering|ai\/ml|errors?\s*&?\s*omissions|technology)\b/i.test(coverage.name);
|
|
3542
|
-
}
|
|
3543
|
-
function uniqueTerms(terms) {
|
|
3544
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3545
|
-
const result = [];
|
|
3546
|
-
for (const term of terms) {
|
|
3547
|
-
const key = [term.kind, term.label.toLowerCase(), term.value.toLowerCase(), term.appliesTo ?? ""].join("|");
|
|
3548
|
-
if (seen.has(key)) continue;
|
|
3549
|
-
seen.add(key);
|
|
3550
|
-
result.push(term);
|
|
3551
|
-
}
|
|
3552
|
-
return result;
|
|
3553
|
-
}
|
|
3554
|
-
function coverageFromTableRow(row, children, byId) {
|
|
3555
|
-
if (isHeaderRow(row)) return void 0;
|
|
3556
|
-
const name = nameFromRow(row, children);
|
|
3557
|
-
const terms = uniqueTerms(termsFromRow(row, children));
|
|
3558
|
-
if (!name || terms.length === 0) return void 0;
|
|
3559
|
-
const ids = sourceIds([row, ...directChildren(row, children)]);
|
|
3560
|
-
const endorsement = endorsementAncestor(row, byId);
|
|
3561
|
-
return {
|
|
3562
|
-
name,
|
|
3563
|
-
limit: legacyLimit(terms),
|
|
3564
|
-
deductible: legacyDeductible(terms),
|
|
3565
|
-
premium: legacyPremium(terms),
|
|
3566
|
-
retroactiveDate: retroDate(terms),
|
|
3567
|
-
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3568
|
-
sectionRef: endorsement?.title,
|
|
3569
|
-
coverageOrigin: endorsement ? "endorsement" : "core",
|
|
3570
|
-
endorsementNumber: endorsementNumberFrom(endorsement?.title),
|
|
3571
|
-
limits: terms,
|
|
3572
|
-
...ids
|
|
3573
|
-
};
|
|
3574
|
-
}
|
|
3575
|
-
function coverageFromEndorsement(endorsement, children) {
|
|
3576
|
-
const rows = descendants(endorsement, children).filter((node) => node.kind === "table_row");
|
|
3577
|
-
const terms = uniqueTerms(rows.flatMap(
|
|
3578
|
-
(row) => termsFromRow(row, children).map((term) => {
|
|
3579
|
-
const appliesTo = nameFromRow(row, children);
|
|
3580
|
-
return appliesTo && term.label !== appliesTo ? { ...term, appliesTo } : term;
|
|
3581
|
-
})
|
|
3582
|
-
));
|
|
3583
|
-
if (terms.length === 0) return void 0;
|
|
3584
|
-
const ids = sourceIds([endorsement, ...rows, ...rows.flatMap((row) => directChildren(row, children))]);
|
|
3585
|
-
const name = endorsementNameFrom(endorsement);
|
|
3586
|
-
return {
|
|
3587
|
-
name,
|
|
3588
|
-
limit: legacyLimit(terms),
|
|
3589
|
-
deductible: legacyDeductible(terms),
|
|
3590
|
-
premium: legacyPremium(terms),
|
|
3591
|
-
retroactiveDate: retroDate(terms),
|
|
3592
|
-
formNumber: typeof endorsement.metadata?.formNumber === "string" ? endorsement.metadata.formNumber : void 0,
|
|
3593
|
-
sectionRef: name,
|
|
3594
|
-
coverageOrigin: "endorsement",
|
|
3595
|
-
endorsementNumber: endorsementNumberFrom(name),
|
|
3596
|
-
limits: terms,
|
|
3597
|
-
...ids
|
|
3598
|
-
};
|
|
3599
|
-
}
|
|
3600
|
-
function hasDescendantEndorsementWithTableRows(endorsement, children) {
|
|
3601
|
-
return descendants(endorsement, children).some(
|
|
3602
|
-
(node) => node.kind === "endorsement" && descendants(node, children).some((descendant) => descendant.kind === "table_row")
|
|
3603
|
-
);
|
|
3604
|
-
}
|
|
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
|
-
if (hasDescendantEndorsementWithTableRows(endorsement, children)) continue;
|
|
3612
|
-
const coverage = coverageFromEndorsement(endorsement, children);
|
|
3613
|
-
if (!coverage) continue;
|
|
3614
|
-
const key = [coverage.name.toLowerCase(), coverage.sourceNodeIds.join(",")].join("|");
|
|
3615
|
-
if (seen.has(key)) continue;
|
|
3616
|
-
seen.add(key);
|
|
3617
|
-
coverages.push(coverage);
|
|
3618
|
-
}
|
|
3619
|
-
const rows = nodes.filter((node) => {
|
|
3620
|
-
const text = nodeText(node);
|
|
3621
|
-
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);
|
|
3622
|
-
});
|
|
3623
|
-
for (const row of rows) {
|
|
3624
|
-
if (endorsementAncestor(row, byId)) continue;
|
|
3625
|
-
const structured = row.kind === "table_row" ? coverageFromTableRow(row, children, byId) : void 0;
|
|
3626
|
-
if (structured) {
|
|
3627
|
-
if (!isOperationalCoverageRow(structured)) continue;
|
|
3628
|
-
const key2 = [
|
|
3629
|
-
structured.name.toLowerCase(),
|
|
3630
|
-
structured.limits.map((term) => `${term.kind}:${term.value}`).join(","),
|
|
3631
|
-
structured.sourceNodeIds.join(",")
|
|
3632
|
-
].join("|");
|
|
3633
|
-
if (seen.has(key2)) continue;
|
|
3634
|
-
seen.add(key2);
|
|
3635
|
-
coverages.push(structured);
|
|
3636
|
-
if (coverages.length >= 60) break;
|
|
3637
|
-
continue;
|
|
3638
|
-
}
|
|
3639
|
-
const text = nodeText(row);
|
|
3640
|
-
const name = coverageNameFromRow(text);
|
|
3641
|
-
const limit = limitFromText(text);
|
|
3642
|
-
const deductible = deductibleFromText(text);
|
|
3643
|
-
const premium = premiumFromText(text);
|
|
3644
|
-
if (!name || !limit && !deductible && !premium) continue;
|
|
3645
|
-
if (!isOperationalCoverageRow({
|
|
3646
|
-
name,
|
|
3647
|
-
limit,
|
|
3648
|
-
deductible,
|
|
3649
|
-
premium,
|
|
3650
|
-
coverageOrigin: "core",
|
|
3651
|
-
limits: [
|
|
3652
|
-
...limit ? [{ kind: "other", label: "Limit", value: limit, sourceNodeIds: [row.id], sourceSpanIds: row.sourceSpanIds }] : [],
|
|
3653
|
-
...deductible ? [{ kind: "deductible", label: "Deductible", value: deductible, sourceNodeIds: [row.id], sourceSpanIds: row.sourceSpanIds }] : [],
|
|
3654
|
-
...premium ? [{ kind: "premium", label: "Premium", value: premium, sourceNodeIds: [row.id], sourceSpanIds: row.sourceSpanIds }] : []
|
|
3655
|
-
],
|
|
3656
|
-
sourceNodeIds: [row.id],
|
|
3657
|
-
sourceSpanIds: row.sourceSpanIds
|
|
3658
|
-
})) continue;
|
|
3659
|
-
const key = [name.toLowerCase(), limit, deductible, premium].join("|");
|
|
3660
|
-
if (seen.has(key)) continue;
|
|
3661
|
-
seen.add(key);
|
|
3662
|
-
coverages.push({
|
|
3663
|
-
name,
|
|
3664
|
-
limit,
|
|
3665
|
-
deductible,
|
|
3666
|
-
premium,
|
|
3667
|
-
formNumber: typeof row.metadata?.formNumber === "string" ? row.metadata.formNumber : void 0,
|
|
3668
|
-
coverageOrigin: "core",
|
|
3669
|
-
limits: [],
|
|
3670
|
-
sourceNodeIds: [row.id],
|
|
3671
|
-
sourceSpanIds: row.sourceSpanIds
|
|
3672
|
-
});
|
|
3673
|
-
if (coverages.length >= 60) break;
|
|
3674
|
-
}
|
|
3675
|
-
return coverages;
|
|
3676
|
-
}
|
|
3677
|
-
function buildParties(profile) {
|
|
3678
|
-
const parties = [];
|
|
3679
|
-
if (profile.namedInsured) {
|
|
3680
|
-
parties.push({
|
|
3681
|
-
role: "named_insured",
|
|
3682
|
-
name: profile.namedInsured.normalizedValue ?? profile.namedInsured.value,
|
|
3683
|
-
sourceNodeIds: profile.namedInsured.sourceNodeIds,
|
|
3684
|
-
sourceSpanIds: profile.namedInsured.sourceSpanIds
|
|
3685
|
-
});
|
|
3686
|
-
}
|
|
3687
|
-
if (profile.insurer) {
|
|
3688
|
-
parties.push({
|
|
3689
|
-
role: "insurer",
|
|
3690
|
-
name: profile.insurer.normalizedValue ?? profile.insurer.value,
|
|
3691
|
-
sourceNodeIds: profile.insurer.sourceNodeIds,
|
|
3692
|
-
sourceSpanIds: profile.insurer.sourceSpanIds
|
|
3693
|
-
});
|
|
3694
|
-
}
|
|
3695
|
-
if (profile.broker) {
|
|
3696
|
-
parties.push({
|
|
3697
|
-
role: "broker",
|
|
3698
|
-
name: profile.broker.normalizedValue ?? profile.broker.value,
|
|
3699
|
-
sourceNodeIds: profile.broker.sourceNodeIds,
|
|
3700
|
-
sourceSpanIds: profile.broker.sourceSpanIds
|
|
3701
|
-
});
|
|
3702
|
-
}
|
|
3703
|
-
return parties;
|
|
3704
|
-
}
|
|
3705
|
-
function buildEndorsementSupport(nodes) {
|
|
3706
|
-
const support = [];
|
|
3707
|
-
for (const node of nodes) {
|
|
3708
|
-
const text = nodeText(node);
|
|
3709
|
-
const add = (kind, status) => {
|
|
3710
|
-
if (support.some((item) => item.kind === kind && item.status === status && item.sourceNodeIds.includes(node.id))) {
|
|
3711
|
-
return;
|
|
3712
|
-
}
|
|
3713
|
-
support.push({
|
|
3714
|
-
kind,
|
|
3715
|
-
status,
|
|
3716
|
-
summary: node.textExcerpt ?? node.description,
|
|
3717
|
-
sourceNodeIds: [node.id],
|
|
3718
|
-
sourceSpanIds: node.sourceSpanIds
|
|
3719
|
-
});
|
|
3720
|
-
};
|
|
3721
|
-
if (/additional insured/i.test(text)) add("additional_insured", /not included|requires endorsement|only by endorsement/i.test(text) ? "requires_review" : "supported");
|
|
3722
|
-
if (/waiver of subrogation|subrogation.*waived/i.test(text)) add("waiver_of_subrogation", /not included|requires endorsement|only by endorsement/i.test(text) ? "requires_review" : "supported");
|
|
3723
|
-
if (/primary.*non[-\s]?contributory|non[-\s]?contributory/i.test(text)) add("primary_non_contributory", /not included|requires endorsement|only by endorsement/i.test(text) ? "requires_review" : "supported");
|
|
3724
|
-
if (/loss payee|mortgagee/i.test(text)) add(/mortgagee/i.test(text) ? "mortgagee" : "loss_payee", "supported");
|
|
3725
|
-
if (support.length >= 20) break;
|
|
3726
|
-
}
|
|
3727
|
-
return support;
|
|
3728
|
-
}
|
|
3729
|
-
function buildDeterministicOperationalProfile(params) {
|
|
3730
|
-
const nodes = params.sourceTree.filter((node) => node.kind !== "document");
|
|
3731
|
-
const partial = {
|
|
3732
|
-
documentType: inferDocumentType(nodes),
|
|
3733
|
-
policyTypes: inferPolicyTypes(nodes),
|
|
3734
|
-
policyNumber: policyNumberFromNodes(nodes),
|
|
3735
|
-
namedInsured: namedInsuredFromNodes(nodes),
|
|
3736
|
-
insurer: insurerFromNodes(nodes),
|
|
3737
|
-
broker: firstMatch(nodes, [
|
|
3738
|
-
/\b(?:broker|producer|agent)\s*:?\s*([^|;\n]{3,120})/i
|
|
3739
|
-
]),
|
|
3740
|
-
effectiveDate: firstMatch(nodes, [
|
|
3741
|
-
/\b(?:effective date|policy period from|from)\s*:?\s*([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})/i,
|
|
3742
|
-
/\b([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})\s+(?:to|through|-)\s+[0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4}/i
|
|
3743
|
-
]),
|
|
3744
|
-
expirationDate: firstMatch(nodes, [
|
|
3745
|
-
/\b(?:expiration date|expiry date|expires|to)\s*:?\s*([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})/i,
|
|
3746
|
-
/\b[0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4}\s+(?:to|through|-)\s+([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4})/i
|
|
3747
|
-
]),
|
|
3748
|
-
retroactiveDate: firstMatch(nodes, [
|
|
3749
|
-
/\bretroactive date\s*:?\s*([0-9]{1,2}[/-][0-9]{1,2}[/-][0-9]{2,4}|full prior acts|none)/i
|
|
3750
|
-
]),
|
|
3751
|
-
premium: premiumFromNodes(nodes)
|
|
3752
|
-
};
|
|
3753
|
-
const coverages = buildCoverages(nodes);
|
|
3754
|
-
const coverageTypes = [...new Set(coverages.map((coverage) => coverage.name))];
|
|
3755
|
-
const sourceNodeIds = [.../* @__PURE__ */ new Set([
|
|
3756
|
-
...Object.values(partial).flatMap(
|
|
3757
|
-
(value) => value && typeof value === "object" && "sourceNodeIds" in value ? value.sourceNodeIds : []
|
|
3758
|
-
),
|
|
3759
|
-
...coverages.flatMap((coverage) => coverage.sourceNodeIds)
|
|
3760
|
-
])];
|
|
3761
|
-
const sourceSpanIds = [.../* @__PURE__ */ new Set([
|
|
3762
|
-
...Object.values(partial).flatMap(
|
|
3763
|
-
(value) => value && typeof value === "object" && "sourceSpanIds" in value ? value.sourceSpanIds : []
|
|
3764
|
-
),
|
|
3765
|
-
...coverages.flatMap((coverage) => coverage.sourceSpanIds)
|
|
3766
|
-
])];
|
|
3767
|
-
return PolicyOperationalProfileSchema.parse({
|
|
3768
|
-
...partial,
|
|
3769
|
-
coverageTypes,
|
|
3770
|
-
coverages,
|
|
3771
|
-
parties: buildParties(partial),
|
|
3772
|
-
endorsementSupport: buildEndorsementSupport(nodes),
|
|
3773
|
-
sourceNodeIds,
|
|
3774
|
-
sourceSpanIds,
|
|
3775
|
-
warnings: [
|
|
3776
|
-
...coverages.length === 0 ? ["No source-backed coverage schedule rows were identified deterministically."] : [],
|
|
3777
|
-
...!partial.policyNumber ? ["No source-backed policy number was identified deterministically."] : [],
|
|
3778
|
-
...!partial.namedInsured ? ["No source-backed named insured was identified deterministically."] : []
|
|
3779
|
-
]
|
|
3780
|
-
});
|
|
3781
|
-
}
|
|
3782
|
-
function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
|
|
3783
|
-
const keepIds = (ids, valid) => Array.isArray(ids) ? ids.filter((id) => typeof id === "string" && valid.has(id)) : [];
|
|
3784
|
-
const mergeValue = (fallback, next) => {
|
|
3785
|
-
if (!next || typeof next !== "object" || Array.isArray(next)) return fallback;
|
|
3786
|
-
const record = next;
|
|
3787
|
-
const value = typeof record.value === "string" ? cleanValue(record.value) : void 0;
|
|
3788
|
-
if (!value) return fallback;
|
|
3789
|
-
const sourceNodeIds = keepIds(record.sourceNodeIds, validNodeIds);
|
|
3790
|
-
const sourceSpanIds = keepIds(record.sourceSpanIds, validSpanIds);
|
|
3791
|
-
if (sourceNodeIds.length === 0 && sourceSpanIds.length === 0) return fallback;
|
|
3792
|
-
return {
|
|
3793
|
-
value,
|
|
3794
|
-
normalizedValue: typeof record.normalizedValue === "string" ? record.normalizedValue : fallback?.normalizedValue,
|
|
3795
|
-
confidence: record.confidence === "high" || record.confidence === "low" || record.confidence === "medium" ? record.confidence : "medium",
|
|
3796
|
-
sourceNodeIds,
|
|
3797
|
-
sourceSpanIds
|
|
3798
|
-
};
|
|
3799
|
-
};
|
|
3800
|
-
const coverages = base.coverages.length > 0 ? base.coverages : Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
|
|
3801
|
-
const record = coverage;
|
|
3802
|
-
const name = typeof record.name === "string" ? cleanValue(record.name) : void 0;
|
|
3803
|
-
const sourceNodeIds = keepIds(record.sourceNodeIds, validNodeIds);
|
|
3804
|
-
const sourceSpanIds = keepIds(record.sourceSpanIds, validSpanIds);
|
|
3805
|
-
const limits = Array.isArray(record.limits) ? record.limits.filter(
|
|
3806
|
-
(term) => Boolean(term) && typeof term === "object" && !Array.isArray(term)
|
|
3807
|
-
).flatMap((term) => {
|
|
3808
|
-
const label = typeof term.label === "string" ? cleanValue(term.label) : void 0;
|
|
3809
|
-
const value = typeof term.value === "string" ? cleanValue(term.value) : void 0;
|
|
3810
|
-
const sourceNodeIds2 = keepIds(term.sourceNodeIds, validNodeIds);
|
|
3811
|
-
const sourceSpanIds2 = keepIds(term.sourceSpanIds, validSpanIds);
|
|
3812
|
-
if (!label || !value || sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return [];
|
|
3813
|
-
return [{
|
|
3814
|
-
kind: normalizeTermKind(term.kind, label, value),
|
|
3815
|
-
label,
|
|
3816
|
-
value,
|
|
3817
|
-
amount: typeof term.amount === "number" && Number.isFinite(term.amount) ? term.amount : void 0,
|
|
3818
|
-
appliesTo: typeof term.appliesTo === "string" ? term.appliesTo : void 0,
|
|
3819
|
-
sourceNodeIds: sourceNodeIds2,
|
|
3820
|
-
sourceSpanIds: sourceSpanIds2
|
|
3821
|
-
}];
|
|
3822
|
-
}) : [];
|
|
3823
|
-
return {
|
|
3824
|
-
name,
|
|
3825
|
-
coverageCode: typeof record.coverageCode === "string" ? cleanValue(record.coverageCode) : void 0,
|
|
3826
|
-
limit: typeof record.limit === "string" ? cleanValue(record.limit) : void 0,
|
|
3827
|
-
deductible: typeof record.deductible === "string" ? cleanValue(record.deductible) : void 0,
|
|
3828
|
-
premium: typeof record.premium === "string" ? cleanValue(record.premium) : void 0,
|
|
3829
|
-
retroactiveDate: typeof record.retroactiveDate === "string" ? cleanValue(record.retroactiveDate) : void 0,
|
|
3830
|
-
formNumber: typeof record.formNumber === "string" ? cleanValue(record.formNumber) : void 0,
|
|
3831
|
-
sectionRef: typeof record.sectionRef === "string" ? cleanValue(record.sectionRef) : void 0,
|
|
3832
|
-
coverageOrigin: record.coverageOrigin === "core" || record.coverageOrigin === "endorsement" ? record.coverageOrigin : void 0,
|
|
3833
|
-
endorsementNumber: typeof record.endorsementNumber === "string" ? cleanValue(record.endorsementNumber) : void 0,
|
|
3834
|
-
limits,
|
|
3835
|
-
sourceNodeIds,
|
|
3836
|
-
sourceSpanIds
|
|
3837
|
-
};
|
|
3838
|
-
}).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
|
|
3839
|
-
return PolicyOperationalProfileSchema.parse({
|
|
3840
|
-
...base,
|
|
3841
|
-
documentType: candidate.documentType === "quote" ? "quote" : candidate.documentType === "policy" ? "policy" : base.documentType,
|
|
3842
|
-
policyTypes: Array.isArray(candidate.policyTypes) && candidate.policyTypes.length > 0 ? candidate.policyTypes : base.policyTypes,
|
|
3843
|
-
policyNumber: mergeValue(base.policyNumber, candidate.policyNumber),
|
|
3844
|
-
namedInsured: mergeValue(base.namedInsured, candidate.namedInsured),
|
|
3845
|
-
insurer: mergeValue(base.insurer, candidate.insurer),
|
|
3846
|
-
broker: mergeValue(base.broker, candidate.broker),
|
|
3847
|
-
effectiveDate: mergeValue(base.effectiveDate, candidate.effectiveDate),
|
|
3848
|
-
expirationDate: mergeValue(base.expirationDate, candidate.expirationDate),
|
|
3849
|
-
retroactiveDate: mergeValue(base.retroactiveDate, candidate.retroactiveDate),
|
|
3850
|
-
premium: mergeValue(base.premium, candidate.premium),
|
|
3851
|
-
coverageTypes: Array.isArray(candidate.coverageTypes) && candidate.coverageTypes.length > 0 ? candidate.coverageTypes : base.coverageTypes,
|
|
3852
|
-
coverages,
|
|
3853
|
-
parties: base.parties,
|
|
3854
|
-
endorsementSupport: base.endorsementSupport,
|
|
3855
|
-
sourceNodeIds: [.../* @__PURE__ */ new Set([...base.sourceNodeIds, ...keepIds(candidate.sourceNodeIds, validNodeIds)])],
|
|
3856
|
-
sourceSpanIds: [.../* @__PURE__ */ new Set([...base.sourceSpanIds, ...keepIds(candidate.sourceSpanIds, validSpanIds)])],
|
|
3857
|
-
warnings: base.warnings
|
|
3858
|
-
});
|
|
3859
|
-
}
|
|
3860
|
-
|
|
3861
2989
|
// src/extraction/pdf.ts
|
|
3862
2990
|
import {
|
|
3863
2991
|
PDFDocument,
|
|
@@ -9778,6 +8906,199 @@ function groundExtractionMemoryWithSourceSpans(memory, sourceSpans) {
|
|
|
9778
8906
|
// src/extraction/source-tree-extractor.ts
|
|
9779
8907
|
import { z as z42 } from "zod";
|
|
9780
8908
|
|
|
8909
|
+
// src/source/operational-profile.ts
|
|
8910
|
+
function normalizeWhitespace3(value) {
|
|
8911
|
+
return value.replace(/\s+/g, " ").trim();
|
|
8912
|
+
}
|
|
8913
|
+
function cleanValue(value) {
|
|
8914
|
+
if (!value) return void 0;
|
|
8915
|
+
return normalizeWhitespace3(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
|
|
8916
|
+
}
|
|
8917
|
+
var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
|
|
8918
|
+
"each_claim_limit",
|
|
8919
|
+
"each_occurrence_limit",
|
|
8920
|
+
"each_loss_limit",
|
|
8921
|
+
"aggregate_limit",
|
|
8922
|
+
"sublimit",
|
|
8923
|
+
"retention",
|
|
8924
|
+
"deductible",
|
|
8925
|
+
"retroactive_date",
|
|
8926
|
+
"premium",
|
|
8927
|
+
"other"
|
|
8928
|
+
]);
|
|
8929
|
+
function normalizeTermKind(value) {
|
|
8930
|
+
return typeof value === "string" && OPERATIONAL_COVERAGE_TERM_KINDS.has(value) ? value : "other";
|
|
8931
|
+
}
|
|
8932
|
+
function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
|
|
8933
|
+
const keepIds = (ids, valid) => Array.isArray(ids) ? ids.filter((id) => typeof id === "string" && valid.has(id)) : [];
|
|
8934
|
+
const mergeValue = (fallback, next) => {
|
|
8935
|
+
if (!next || typeof next !== "object" || Array.isArray(next)) return fallback;
|
|
8936
|
+
const record = next;
|
|
8937
|
+
const value = typeof record.value === "string" ? cleanValue(record.value) : void 0;
|
|
8938
|
+
if (!value) return fallback;
|
|
8939
|
+
const sourceNodeIds2 = keepIds(record.sourceNodeIds, validNodeIds);
|
|
8940
|
+
const sourceSpanIds2 = keepIds(record.sourceSpanIds, validSpanIds);
|
|
8941
|
+
if (sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return fallback;
|
|
8942
|
+
return {
|
|
8943
|
+
value,
|
|
8944
|
+
normalizedValue: typeof record.normalizedValue === "string" ? record.normalizedValue : fallback?.normalizedValue,
|
|
8945
|
+
confidence: record.confidence === "high" || record.confidence === "low" || record.confidence === "medium" ? record.confidence : "medium",
|
|
8946
|
+
sourceNodeIds: sourceNodeIds2,
|
|
8947
|
+
sourceSpanIds: sourceSpanIds2
|
|
8948
|
+
};
|
|
8949
|
+
};
|
|
8950
|
+
const policyNumber = mergeValue(base.policyNumber, candidate.policyNumber);
|
|
8951
|
+
const namedInsured = mergeValue(base.namedInsured, candidate.namedInsured);
|
|
8952
|
+
const insurer = mergeValue(base.insurer, candidate.insurer);
|
|
8953
|
+
const broker = mergeValue(base.broker, candidate.broker);
|
|
8954
|
+
const effectiveDate = mergeValue(base.effectiveDate, candidate.effectiveDate);
|
|
8955
|
+
const expirationDate = mergeValue(base.expirationDate, candidate.expirationDate);
|
|
8956
|
+
const retroactiveDate = mergeValue(base.retroactiveDate, candidate.retroactiveDate);
|
|
8957
|
+
const premium = mergeValue(base.premium, candidate.premium);
|
|
8958
|
+
const sourceValues = [
|
|
8959
|
+
policyNumber,
|
|
8960
|
+
namedInsured,
|
|
8961
|
+
insurer,
|
|
8962
|
+
broker,
|
|
8963
|
+
effectiveDate,
|
|
8964
|
+
expirationDate,
|
|
8965
|
+
retroactiveDate,
|
|
8966
|
+
premium
|
|
8967
|
+
].filter((value) => Boolean(value));
|
|
8968
|
+
const coverages = base.coverages.length > 0 ? base.coverages : Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
|
|
8969
|
+
const record = coverage;
|
|
8970
|
+
const name = typeof record.name === "string" ? cleanValue(record.name) : void 0;
|
|
8971
|
+
const limits = Array.isArray(record.limits) ? record.limits.filter(
|
|
8972
|
+
(term) => Boolean(term) && typeof term === "object" && !Array.isArray(term)
|
|
8973
|
+
).flatMap((term) => {
|
|
8974
|
+
const label = typeof term.label === "string" ? cleanValue(term.label) : void 0;
|
|
8975
|
+
const value = typeof term.value === "string" ? cleanValue(term.value) : void 0;
|
|
8976
|
+
const sourceNodeIds3 = keepIds(term.sourceNodeIds, validNodeIds);
|
|
8977
|
+
const sourceSpanIds3 = keepIds(term.sourceSpanIds, validSpanIds);
|
|
8978
|
+
if (!label || !value || sourceNodeIds3.length === 0 && sourceSpanIds3.length === 0) return [];
|
|
8979
|
+
return [{
|
|
8980
|
+
kind: normalizeTermKind(term.kind),
|
|
8981
|
+
label,
|
|
8982
|
+
value,
|
|
8983
|
+
amount: typeof term.amount === "number" && Number.isFinite(term.amount) ? term.amount : void 0,
|
|
8984
|
+
appliesTo: typeof term.appliesTo === "string" ? term.appliesTo : void 0,
|
|
8985
|
+
sourceNodeIds: sourceNodeIds3,
|
|
8986
|
+
sourceSpanIds: sourceSpanIds3
|
|
8987
|
+
}];
|
|
8988
|
+
}) : [];
|
|
8989
|
+
const sourceNodeIds2 = [.../* @__PURE__ */ new Set([
|
|
8990
|
+
...keepIds(record.sourceNodeIds, validNodeIds),
|
|
8991
|
+
...limits.flatMap((term) => term.sourceNodeIds)
|
|
8992
|
+
])];
|
|
8993
|
+
const sourceSpanIds2 = [.../* @__PURE__ */ new Set([
|
|
8994
|
+
...keepIds(record.sourceSpanIds, validSpanIds),
|
|
8995
|
+
...limits.flatMap((term) => term.sourceSpanIds)
|
|
8996
|
+
])];
|
|
8997
|
+
return {
|
|
8998
|
+
name,
|
|
8999
|
+
coverageCode: typeof record.coverageCode === "string" ? cleanValue(record.coverageCode) : void 0,
|
|
9000
|
+
limit: typeof record.limit === "string" ? cleanValue(record.limit) : void 0,
|
|
9001
|
+
deductible: typeof record.deductible === "string" ? cleanValue(record.deductible) : void 0,
|
|
9002
|
+
premium: typeof record.premium === "string" ? cleanValue(record.premium) : void 0,
|
|
9003
|
+
retroactiveDate: typeof record.retroactiveDate === "string" ? cleanValue(record.retroactiveDate) : void 0,
|
|
9004
|
+
formNumber: typeof record.formNumber === "string" ? cleanValue(record.formNumber) : void 0,
|
|
9005
|
+
sectionRef: typeof record.sectionRef === "string" ? cleanValue(record.sectionRef) : void 0,
|
|
9006
|
+
coverageOrigin: record.coverageOrigin === "core" || record.coverageOrigin === "endorsement" ? record.coverageOrigin : void 0,
|
|
9007
|
+
endorsementNumber: typeof record.endorsementNumber === "string" ? cleanValue(record.endorsementNumber) : void 0,
|
|
9008
|
+
limits,
|
|
9009
|
+
sourceNodeIds: sourceNodeIds2,
|
|
9010
|
+
sourceSpanIds: sourceSpanIds2
|
|
9011
|
+
};
|
|
9012
|
+
}).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
|
|
9013
|
+
const sourceBackedParty = (role, value) => value ? {
|
|
9014
|
+
role,
|
|
9015
|
+
name: value.normalizedValue ?? value.value,
|
|
9016
|
+
sourceNodeIds: value.sourceNodeIds,
|
|
9017
|
+
sourceSpanIds: value.sourceSpanIds
|
|
9018
|
+
} : void 0;
|
|
9019
|
+
const candidateParties = Array.isArray(candidate.parties) ? candidate.parties.flatMap((party) => {
|
|
9020
|
+
if (!party || typeof party !== "object" || Array.isArray(party)) return [];
|
|
9021
|
+
const record = party;
|
|
9022
|
+
const role = typeof record.role === "string" ? cleanValue(record.role) : void 0;
|
|
9023
|
+
const name = typeof record.name === "string" ? cleanValue(record.name) : void 0;
|
|
9024
|
+
const sourceNodeIds2 = keepIds(record.sourceNodeIds, validNodeIds);
|
|
9025
|
+
const sourceSpanIds2 = keepIds(record.sourceSpanIds, validSpanIds);
|
|
9026
|
+
if (!role || !name || sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return [];
|
|
9027
|
+
return [{ role, name, sourceNodeIds: sourceNodeIds2, sourceSpanIds: sourceSpanIds2 }];
|
|
9028
|
+
}) : [];
|
|
9029
|
+
const parties = [
|
|
9030
|
+
...base.parties,
|
|
9031
|
+
...candidateParties,
|
|
9032
|
+
sourceBackedParty("named_insured", namedInsured),
|
|
9033
|
+
sourceBackedParty("insurer", insurer),
|
|
9034
|
+
sourceBackedParty("broker", broker)
|
|
9035
|
+
].filter((party) => Boolean(party)).filter(
|
|
9036
|
+
(party, index, rows) => rows.findIndex(
|
|
9037
|
+
(other) => other.role === party.role && other.name === party.name && other.sourceNodeIds.join(",") === party.sourceNodeIds.join(",") && other.sourceSpanIds.join(",") === party.sourceSpanIds.join(",")
|
|
9038
|
+
) === index
|
|
9039
|
+
);
|
|
9040
|
+
const endorsementSupport = [
|
|
9041
|
+
...base.endorsementSupport,
|
|
9042
|
+
...Array.isArray(candidate.endorsementSupport) ? candidate.endorsementSupport.flatMap((row) => {
|
|
9043
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) return [];
|
|
9044
|
+
const record = row;
|
|
9045
|
+
const kind = typeof record.kind === "string" ? cleanValue(record.kind) : void 0;
|
|
9046
|
+
const summary = typeof record.summary === "string" ? cleanValue(record.summary) : void 0;
|
|
9047
|
+
const status = record.status === "supported" || record.status === "excluded" || record.status === "requires_review" ? record.status : void 0;
|
|
9048
|
+
const sourceNodeIds2 = keepIds(record.sourceNodeIds, validNodeIds);
|
|
9049
|
+
const sourceSpanIds2 = keepIds(record.sourceSpanIds, validSpanIds);
|
|
9050
|
+
if (!kind || !summary || !status || sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return [];
|
|
9051
|
+
return [{ kind, status, summary, sourceNodeIds: sourceNodeIds2, sourceSpanIds: sourceSpanIds2 }];
|
|
9052
|
+
}) : []
|
|
9053
|
+
].filter(
|
|
9054
|
+
(row, index, rows) => rows.findIndex(
|
|
9055
|
+
(other) => other.kind === row.kind && other.status === row.status && other.summary === row.summary && other.sourceNodeIds.join(",") === row.sourceNodeIds.join(",") && other.sourceSpanIds.join(",") === row.sourceSpanIds.join(",")
|
|
9056
|
+
) === index
|
|
9057
|
+
);
|
|
9058
|
+
const sourceNodeIds = [.../* @__PURE__ */ new Set([
|
|
9059
|
+
...base.sourceNodeIds,
|
|
9060
|
+
...keepIds(candidate.sourceNodeIds, validNodeIds),
|
|
9061
|
+
...sourceValues.flatMap((value) => value.sourceNodeIds),
|
|
9062
|
+
...coverages.flatMap((coverage) => coverage.sourceNodeIds),
|
|
9063
|
+
...coverages.flatMap((coverage) => coverage.limits.flatMap((term) => term.sourceNodeIds)),
|
|
9064
|
+
...parties.flatMap((party) => party.sourceNodeIds),
|
|
9065
|
+
...endorsementSupport.flatMap((row) => row.sourceNodeIds)
|
|
9066
|
+
])];
|
|
9067
|
+
const sourceSpanIds = [.../* @__PURE__ */ new Set([
|
|
9068
|
+
...base.sourceSpanIds,
|
|
9069
|
+
...keepIds(candidate.sourceSpanIds, validSpanIds),
|
|
9070
|
+
...sourceValues.flatMap((value) => value.sourceSpanIds),
|
|
9071
|
+
...coverages.flatMap((coverage) => coverage.sourceSpanIds),
|
|
9072
|
+
...coverages.flatMap((coverage) => coverage.limits.flatMap((term) => term.sourceSpanIds)),
|
|
9073
|
+
...parties.flatMap((party) => party.sourceSpanIds),
|
|
9074
|
+
...endorsementSupport.flatMap((row) => row.sourceSpanIds)
|
|
9075
|
+
])];
|
|
9076
|
+
const warnings = [
|
|
9077
|
+
...base.warnings,
|
|
9078
|
+
...Array.isArray(candidate.warnings) ? candidate.warnings.filter((warning) => typeof warning === "string" && warning.trim().length > 0) : []
|
|
9079
|
+
];
|
|
9080
|
+
return PolicyOperationalProfileSchema.parse({
|
|
9081
|
+
...base,
|
|
9082
|
+
documentType: candidate.documentType === "quote" ? "quote" : candidate.documentType === "policy" ? "policy" : base.documentType,
|
|
9083
|
+
policyTypes: Array.isArray(candidate.policyTypes) && candidate.policyTypes.length > 0 ? candidate.policyTypes : base.policyTypes,
|
|
9084
|
+
policyNumber,
|
|
9085
|
+
namedInsured,
|
|
9086
|
+
insurer,
|
|
9087
|
+
broker,
|
|
9088
|
+
effectiveDate,
|
|
9089
|
+
expirationDate,
|
|
9090
|
+
retroactiveDate,
|
|
9091
|
+
premium,
|
|
9092
|
+
coverageTypes: Array.isArray(candidate.coverageTypes) && candidate.coverageTypes.length > 0 ? candidate.coverageTypes : base.coverageTypes,
|
|
9093
|
+
coverages,
|
|
9094
|
+
parties,
|
|
9095
|
+
endorsementSupport,
|
|
9096
|
+
sourceNodeIds,
|
|
9097
|
+
sourceSpanIds,
|
|
9098
|
+
warnings: [...new Set(warnings)]
|
|
9099
|
+
});
|
|
9100
|
+
}
|
|
9101
|
+
|
|
9781
9102
|
// src/extraction/operational-profile-cleanup.ts
|
|
9782
9103
|
import { z as z41 } from "zod";
|
|
9783
9104
|
var OPERATIONAL_COVERAGE_TERM_KINDS2 = [
|
|
@@ -11014,8 +10335,8 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
11014
10335
|
const current = updates.get(child.id) ?? child;
|
|
11015
10336
|
const heading = sectionHeadingTitle(current, container);
|
|
11016
10337
|
if (heading) {
|
|
11017
|
-
const
|
|
11018
|
-
const hasOwnContent =
|
|
10338
|
+
const descendants = byParent.get(child.id) ?? [];
|
|
10339
|
+
const hasOwnContent = descendants.some((descendant) => descendant.kind !== "table_row" && descendant.kind !== "table_cell");
|
|
11019
10340
|
let hasFollowingContent = false;
|
|
11020
10341
|
for (const nextChild of directPageChildren.slice(index + 1)) {
|
|
11021
10342
|
const next = updates.get(nextChild.id) ?? nextChild;
|
|
@@ -11033,7 +10354,7 @@ function applyTitleSectionHierarchy(sourceTree) {
|
|
|
11033
10354
|
parentId: container.id,
|
|
11034
10355
|
kind: sectionKindForTitle(heading),
|
|
11035
10356
|
title: heading,
|
|
11036
|
-
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...
|
|
10357
|
+
description: descriptionWithPages(cleanText([heading, "section"].join(" "), heading), [current, ...descendants]),
|
|
11037
10358
|
metadata: {
|
|
11038
10359
|
...current.metadata,
|
|
11039
10360
|
organizer: "title_section",
|
|
@@ -11357,8 +10678,32 @@ ${JSON.stringify(nodes, null, 2)}
|
|
|
11357
10678
|
|
|
11358
10679
|
Return JSON with labels and groups only.`;
|
|
11359
10680
|
}
|
|
11360
|
-
function
|
|
11361
|
-
|
|
10681
|
+
function operationalProfilePromptNodes(sourceTree) {
|
|
10682
|
+
return sourceTree.filter((node) => node.kind !== "document").filter((node) => {
|
|
10683
|
+
if (["page_group", "form", "endorsement", "schedule", "table", "table_row", "table_cell"].includes(node.kind)) {
|
|
10684
|
+
return true;
|
|
10685
|
+
}
|
|
10686
|
+
const text = [node.title, node.path, node.description, node.textExcerpt].filter(Boolean).join(" ");
|
|
10687
|
+
return /\b(policy\s*(number|period)|named insured|insurer|carrier|broker|producer|premium|coverage|limit|liability|deductible|retention|retroactive|aggregate|sublimit|sub-limit|endorsement)\b/i.test(text);
|
|
10688
|
+
}).slice(0, 420);
|
|
10689
|
+
}
|
|
10690
|
+
function emptyOperationalProfile() {
|
|
10691
|
+
return {
|
|
10692
|
+
documentType: "policy",
|
|
10693
|
+
policyTypes: ["other"],
|
|
10694
|
+
coverageTypes: [],
|
|
10695
|
+
coverages: [],
|
|
10696
|
+
parties: [],
|
|
10697
|
+
endorsementSupport: [],
|
|
10698
|
+
sourceNodeIds: [],
|
|
10699
|
+
sourceSpanIds: [],
|
|
10700
|
+
warnings: []
|
|
10701
|
+
};
|
|
10702
|
+
}
|
|
10703
|
+
function buildOperationalProfilePrompt(sourceTree) {
|
|
10704
|
+
const nodes = operationalProfilePromptNodes(sourceTree).map(
|
|
10705
|
+
(node) => compactNode2(node, node.kind === "page" || node.kind === "endorsement" ? 900 : 700)
|
|
10706
|
+
);
|
|
11362
10707
|
return `Extract a source-backed operational profile for an insurance policy or quote.
|
|
11363
10708
|
|
|
11364
10709
|
Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
|
|
@@ -11375,9 +10720,7 @@ Rules:
|
|
|
11375
10720
|
- 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.
|
|
11376
10721
|
- Use coverageOrigin: "endorsement" for endorsement units and "core" for declarations/core policy coverage units.
|
|
11377
10722
|
- Do not copy entire policy wording into fields.
|
|
11378
|
-
|
|
11379
|
-
Deterministic baseline:
|
|
11380
|
-
${JSON.stringify(fallback, null, 2)}
|
|
10723
|
+
- Extract facts directly from source nodes. There is no deterministic fact baseline.
|
|
11381
10724
|
|
|
11382
10725
|
Source nodes:
|
|
11383
10726
|
${JSON.stringify(nodes, null, 2)}
|
|
@@ -11387,7 +10730,6 @@ Return JSON for the operational profile.`;
|
|
|
11387
10730
|
var VISUAL_TABLE_REPAIR_MAX_TABLES = 4;
|
|
11388
10731
|
var VISUAL_TABLE_REPAIR_MAX_ROWS = 28;
|
|
11389
10732
|
var VISUAL_TABLE_REPAIR_MAX_CELLS = 140;
|
|
11390
|
-
var VISUAL_TABLE_REPAIR_KEYWORDS = /\b(coverage|limit|limits?|deductible|retroactive|premium|tax|fee|sublimit|sub-limit|aggregate|claim|occurrence|retention|declarations?)\b/i;
|
|
11391
10733
|
function isSourceTreeHeaderRow(row) {
|
|
11392
10734
|
return row.metadata?.isHeader === true || row.metadata?.isHeader === "true";
|
|
11393
10735
|
}
|
|
@@ -11433,13 +10775,11 @@ function primaryHeaderColumnCount(rows) {
|
|
|
11433
10775
|
if (header) return header.cells.length;
|
|
11434
10776
|
return Math.max(0, ...rows.map(({ cells }) => cells.length));
|
|
11435
10777
|
}
|
|
11436
|
-
function
|
|
10778
|
+
function visualTableRepairScore(candidate) {
|
|
11437
10779
|
const rows = candidate.rows;
|
|
11438
|
-
if (rows.length < 3) return
|
|
11439
|
-
const tableText = rows.map(({ row, cells }) => tableRowTextForPrompt(row, cells)).join(" ");
|
|
11440
|
-
if (!VISUAL_TABLE_REPAIR_KEYWORDS.test(tableText)) return false;
|
|
10780
|
+
if (rows.length < 3) return 0;
|
|
11441
10781
|
const headerCount = primaryHeaderColumnCount(rows);
|
|
11442
|
-
if (headerCount < 2) return
|
|
10782
|
+
if (headerCount < 2) return 0;
|
|
11443
10783
|
const firstHeaderIndex = rows.findIndex(({ row, cells }) => isSourceTreeHeaderRow(row) && cells.length > 1);
|
|
11444
10784
|
const repeatedHeader = firstHeaderIndex >= 0 && rows.some(({ row }, index) => index > firstHeaderIndex && isSourceTreeHeaderRow(row));
|
|
11445
10785
|
const shortContinuation = rows.some(
|
|
@@ -11451,7 +10791,7 @@ function shouldRepairVisualTable(candidate) {
|
|
|
11451
10791
|
const danglingSlash = rows.some(
|
|
11452
10792
|
({ row, cells }) => !isSourceTreeHeaderRow(row) && /\/\s*$/.test(tableRowTextForPrompt(row, cells))
|
|
11453
10793
|
);
|
|
11454
|
-
return repeatedHeader
|
|
10794
|
+
return (repeatedHeader ? 4 : 0) + (danglingSlash ? 3 : 0) + (shortContinuation ? 3 : 0) + (genericDataLabels ? 2 : 0);
|
|
11455
10795
|
}
|
|
11456
10796
|
function visualTableCandidates(sourceTree) {
|
|
11457
10797
|
const byParent = nodesByParent(sourceTree);
|
|
@@ -11459,9 +10799,9 @@ function visualTableCandidates(sourceTree) {
|
|
|
11459
10799
|
table,
|
|
11460
10800
|
page: table.pageStart,
|
|
11461
10801
|
rows: tableRowsWithCells(table, byParent)
|
|
11462
|
-
})).filter(
|
|
11463
|
-
(left, right) => left.page - right.page || left.table.order - right.table.order || left.table.id.localeCompare(right.table.id)
|
|
11464
|
-
).slice(0, VISUAL_TABLE_REPAIR_MAX_TABLES);
|
|
10802
|
+
})).map((candidate) => ({ ...candidate, repairScore: visualTableRepairScore(candidate) })).filter((candidate) => candidate.repairScore > 0).sort(
|
|
10803
|
+
(left, right) => right.repairScore - left.repairScore || left.page - right.page || left.table.order - right.table.order || left.table.id.localeCompare(right.table.id)
|
|
10804
|
+
).slice(0, VISUAL_TABLE_REPAIR_MAX_TABLES).map(({ repairScore: _repairScore, ...candidate }) => candidate);
|
|
11465
10805
|
}
|
|
11466
10806
|
function compactVisualTableCandidate(candidate) {
|
|
11467
10807
|
let cellCount = 0;
|
|
@@ -12019,11 +11359,8 @@ async function runSourceTreeExtraction(params) {
|
|
|
12019
11359
|
});
|
|
12020
11360
|
sourceTree = visualTableRepair.sourceTree;
|
|
12021
11361
|
warnings.push(...visualTableRepair.warnings);
|
|
12022
|
-
const
|
|
12023
|
-
|
|
12024
|
-
sourceSpans
|
|
12025
|
-
});
|
|
12026
|
-
let operationalProfile = deterministicProfile;
|
|
11362
|
+
const emptyProfile = emptyOperationalProfile();
|
|
11363
|
+
let operationalProfile = emptyProfile;
|
|
12027
11364
|
try {
|
|
12028
11365
|
const validNodeIds = new Set(sourceTree.map((node) => node.id));
|
|
12029
11366
|
const validSpanIds = new Set(sourceSpans.map((span) => span.id));
|
|
@@ -12032,7 +11369,7 @@ async function runSourceTreeExtraction(params) {
|
|
|
12032
11369
|
const response = await safeGenerateObject(
|
|
12033
11370
|
params.generateObject,
|
|
12034
11371
|
{
|
|
12035
|
-
prompt: buildOperationalProfilePrompt(sourceTree
|
|
11372
|
+
prompt: buildOperationalProfilePrompt(sourceTree),
|
|
12036
11373
|
schema: OperationalProfilePromptSchema,
|
|
12037
11374
|
maxTokens: budget.maxTokens,
|
|
12038
11375
|
taskKind: "extraction_operational_profile",
|
|
@@ -12040,7 +11377,7 @@ async function runSourceTreeExtraction(params) {
|
|
|
12040
11377
|
providerOptions: params.providerOptions
|
|
12041
11378
|
},
|
|
12042
11379
|
{
|
|
12043
|
-
fallback:
|
|
11380
|
+
fallback: emptyProfile,
|
|
12044
11381
|
log: params.log
|
|
12045
11382
|
}
|
|
12046
11383
|
);
|
|
@@ -12051,19 +11388,19 @@ async function runSourceTreeExtraction(params) {
|
|
|
12051
11388
|
durationMs: Date.now() - startedAt
|
|
12052
11389
|
});
|
|
12053
11390
|
operationalProfile = mergeOperationalProfile(
|
|
12054
|
-
|
|
11391
|
+
emptyProfile,
|
|
12055
11392
|
response.object,
|
|
12056
11393
|
validNodeIds,
|
|
12057
11394
|
validSpanIds
|
|
12058
11395
|
);
|
|
12059
11396
|
} catch (error) {
|
|
12060
|
-
warnings.push(`Operational profile model pass failed;
|
|
11397
|
+
warnings.push(`Operational profile model pass failed; coverage rows omitted (${error instanceof Error ? error.message : String(error)})`);
|
|
12061
11398
|
}
|
|
12062
11399
|
if (operationalProfile.coverages.length > 0) {
|
|
12063
11400
|
try {
|
|
12064
11401
|
const validNodeIds = new Set(sourceTree.map((node) => node.id));
|
|
12065
11402
|
const validSpanIds = new Set(sourceSpans.map((span) => span.id));
|
|
12066
|
-
const budget = params.resolveBudget("
|
|
11403
|
+
const budget = params.resolveBudget("extraction_coverage_cleanup", 4096);
|
|
12067
11404
|
const startedAt = Date.now();
|
|
12068
11405
|
const response = await safeGenerateObject(
|
|
12069
11406
|
params.generateObject,
|
|
@@ -12071,9 +11408,10 @@ async function runSourceTreeExtraction(params) {
|
|
|
12071
11408
|
prompt: buildOperationalProfileCleanupPrompt(sourceTree, operationalProfile),
|
|
12072
11409
|
schema: OperationalProfileCleanupSchema,
|
|
12073
11410
|
maxTokens: budget.maxTokens,
|
|
12074
|
-
taskKind: "
|
|
11411
|
+
taskKind: "extraction_coverage_cleanup",
|
|
12075
11412
|
budgetDiagnostics: budget,
|
|
12076
|
-
providerOptions: params.providerOptions
|
|
11413
|
+
providerOptions: params.providerOptions,
|
|
11414
|
+
trace: { phase: "coverage_cleanup", sourceBacked: true }
|
|
12077
11415
|
},
|
|
12078
11416
|
{
|
|
12079
11417
|
fallback: { coverageDecisions: [], warnings: [] },
|
|
@@ -12081,7 +11419,7 @@ async function runSourceTreeExtraction(params) {
|
|
|
12081
11419
|
}
|
|
12082
11420
|
);
|
|
12083
11421
|
localTrack(response.usage, {
|
|
12084
|
-
taskKind: "
|
|
11422
|
+
taskKind: "extraction_coverage_cleanup",
|
|
12085
11423
|
label: "operational_profile_cleanup",
|
|
12086
11424
|
maxTokens: budget.maxTokens,
|
|
12087
11425
|
durationMs: Date.now() - startedAt
|
|
@@ -17609,7 +16947,6 @@ export {
|
|
|
17609
16947
|
buildConfirmationSummaryPrompt,
|
|
17610
16948
|
buildConversationMemoryGuidance,
|
|
17611
16949
|
buildCoverageGapPrompt,
|
|
17612
|
-
buildDeterministicOperationalProfile,
|
|
17613
16950
|
buildDoclingProviderOptions,
|
|
17614
16951
|
buildDocumentSourceTree,
|
|
17615
16952
|
buildFieldExplanationPrompt,
|
|
@@ -17666,7 +17003,6 @@ export {
|
|
|
17666
17003
|
getTemplate,
|
|
17667
17004
|
isDoclingExtractionInput,
|
|
17668
17005
|
isFileReference,
|
|
17669
|
-
mergeOperationalProfile,
|
|
17670
17006
|
mergeQuestionAnswers,
|
|
17671
17007
|
mergeSourceSpans,
|
|
17672
17008
|
normalizeApplicationQuestionGraph,
|