@claritylabs/cl-sdk 3.1.19 → 3.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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-q8LQXen9.d.mts → index-DUBsVEev.d.mts} +1 -1
- package/dist/{index-q8LQXen9.d.ts → index-DUBsVEev.d.ts} +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +214 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +214 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -9761,6 +9761,12 @@ function endorsementDescription(title, node) {
|
|
|
9761
9761
|
title
|
|
9762
9762
|
);
|
|
9763
9763
|
}
|
|
9764
|
+
function endorsementTitleKey(node) {
|
|
9765
|
+
const title = endorsementTitle(sourceNodeText(node));
|
|
9766
|
+
if (title) return title.toLowerCase();
|
|
9767
|
+
const fallback = cleanText(node.title, "");
|
|
9768
|
+
return fallback ? fallback.toLowerCase() : void 0;
|
|
9769
|
+
}
|
|
9764
9770
|
function nodePageEnd2(node) {
|
|
9765
9771
|
return node.pageEnd ?? node.pageStart;
|
|
9766
9772
|
}
|
|
@@ -10682,7 +10688,76 @@ function applyEndorsementGrouping(sourceTree) {
|
|
|
10682
10688
|
(node) => endorsementGroupChildIds.has(node.id) ? { ...node, parentId: groupId, order: node.order + 1e-3 } : node
|
|
10683
10689
|
);
|
|
10684
10690
|
}
|
|
10685
|
-
return normalizeSemanticHierarchy(nextTree);
|
|
10691
|
+
return collapseNestedDuplicateEndorsements(normalizeSemanticHierarchy(nextTree));
|
|
10692
|
+
}
|
|
10693
|
+
function nearestEndorsementAncestor(node, byId) {
|
|
10694
|
+
let parentId = node.parentId;
|
|
10695
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10696
|
+
while (parentId) {
|
|
10697
|
+
if (seen.has(parentId)) return void 0;
|
|
10698
|
+
seen.add(parentId);
|
|
10699
|
+
const parent = byId.get(parentId);
|
|
10700
|
+
if (!parent) return void 0;
|
|
10701
|
+
if (parent.kind === "endorsement") return parent;
|
|
10702
|
+
parentId = parent.parentId;
|
|
10703
|
+
}
|
|
10704
|
+
return void 0;
|
|
10705
|
+
}
|
|
10706
|
+
function collapseNestedDuplicateEndorsements(sourceTree) {
|
|
10707
|
+
const byId = new Map(sourceTree.map((node) => [node.id, node]));
|
|
10708
|
+
const replacementById = /* @__PURE__ */ new Map();
|
|
10709
|
+
const duplicateEvidenceByTarget = /* @__PURE__ */ new Map();
|
|
10710
|
+
for (const node of sourceTree) {
|
|
10711
|
+
if (node.kind !== "endorsement") continue;
|
|
10712
|
+
const ancestor = nearestEndorsementAncestor(node, byId);
|
|
10713
|
+
if (!ancestor) continue;
|
|
10714
|
+
if (endorsementTitleKey(node) !== endorsementTitleKey(ancestor)) continue;
|
|
10715
|
+
replacementById.set(node.id, ancestor.id);
|
|
10716
|
+
duplicateEvidenceByTarget.set(ancestor.id, [
|
|
10717
|
+
...duplicateEvidenceByTarget.get(ancestor.id) ?? [],
|
|
10718
|
+
node
|
|
10719
|
+
]);
|
|
10720
|
+
}
|
|
10721
|
+
if (replacementById.size === 0) return sourceTree;
|
|
10722
|
+
const replacementParent = (parentId) => {
|
|
10723
|
+
let next = parentId;
|
|
10724
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10725
|
+
while (next && replacementById.has(next) && !seen.has(next)) {
|
|
10726
|
+
seen.add(next);
|
|
10727
|
+
next = replacementById.get(next);
|
|
10728
|
+
}
|
|
10729
|
+
return next;
|
|
10730
|
+
};
|
|
10731
|
+
const updated = sourceTree.filter((node) => !replacementById.has(node.id)).map((node) => {
|
|
10732
|
+
const evidence = duplicateEvidenceByTarget.get(node.id);
|
|
10733
|
+
const parentId = replacementParent(node.parentId);
|
|
10734
|
+
if (!evidence?.length) {
|
|
10735
|
+
return parentId === node.parentId ? node : {
|
|
10736
|
+
...node,
|
|
10737
|
+
parentId,
|
|
10738
|
+
metadata: {
|
|
10739
|
+
...node.metadata,
|
|
10740
|
+
organizerRepair: "collapse_duplicate_endorsement_wrapper"
|
|
10741
|
+
}
|
|
10742
|
+
};
|
|
10743
|
+
}
|
|
10744
|
+
const evidenceNodes = [node, ...evidence];
|
|
10745
|
+
const pageStarts = evidenceNodes.map((item) => item.pageStart).filter((page) => typeof page === "number");
|
|
10746
|
+
const pageEnds = evidenceNodes.map((item) => item.pageEnd ?? item.pageStart).filter((page) => typeof page === "number");
|
|
10747
|
+
return {
|
|
10748
|
+
...node,
|
|
10749
|
+
parentId,
|
|
10750
|
+
sourceSpanIds: [...new Set(evidenceNodes.flatMap((item) => item.sourceSpanIds))],
|
|
10751
|
+
pageStart: pageStarts.length ? Math.min(...pageStarts) : node.pageStart,
|
|
10752
|
+
pageEnd: pageEnds.length ? Math.max(...pageEnds) : node.pageEnd,
|
|
10753
|
+
bbox: evidenceNodes.flatMap((item) => item.bbox ?? []).slice(0, 12),
|
|
10754
|
+
metadata: {
|
|
10755
|
+
...node.metadata,
|
|
10756
|
+
organizerRepair: "collapse_duplicate_endorsement_wrapper"
|
|
10757
|
+
}
|
|
10758
|
+
};
|
|
10759
|
+
});
|
|
10760
|
+
return normalizeDocumentSourceTreePaths(normalizeContainerEvidenceFromChildren(updated));
|
|
10686
10761
|
}
|
|
10687
10762
|
function compactNode2(node, maxText = 700) {
|
|
10688
10763
|
return {
|
|
@@ -10881,9 +10956,13 @@ Rules:
|
|
|
10881
10956
|
- Every returned value must include sourceNodeIds or sourceSpanIds from the provided nodes.
|
|
10882
10957
|
- If a value is not directly supported, omit it.
|
|
10883
10958
|
- Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
|
|
10959
|
+
- Keep each coverage unit tied to one evidence scope: a declaration/core schedule row, a core policy form section, or one specific endorsement schedule. Do not merge declaration facts and endorsement schedule facts into the same coverage unit, even when they use the same coverage name.
|
|
10960
|
+
- If the declarations schedule and an endorsement schedule both list Network Security, Social Engineering Fraud, Regulatory Proceedings, or another same-named coverage, return separate coverage units for each supported source scope.
|
|
10961
|
+
- Use the declaration coverage name for declaration/core schedule rows. Use the endorsement title or endorsement schedule coverage name for endorsement rows, and include formNumber and endorsementNumber when source-backed.
|
|
10884
10962
|
- For life, critical illness, disability, and long-term care policies, keep named benefit units and benefit subconditions as operational facts even when they do not have dollar limits. Examples include death benefit, disability benefit, total disability, catastrophic disability, return of premium, waiver, and conversion options. Put subcondition details in coverages[].limits with kind "other" when they belong under a broader benefit.
|
|
10885
10963
|
- Treat an endorsement as one coverage unit when it contains a schedule. Do not split an endorsement schedule into generic rows like "Aggregate Limit".
|
|
10886
10964
|
- 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.
|
|
10965
|
+
- Extract coinsurance, participation percentage, or insurer/named-insured split terms as coverages[].limits entries with kind "other" when they are part of a coverage schedule.
|
|
10887
10966
|
- Use coverageOrigin: "endorsement" for endorsement units and "core" for declarations/core policy coverage units.
|
|
10888
10967
|
- Do not copy entire policy wording into fields.
|
|
10889
10968
|
- Extract facts directly from source nodes. There is no deterministic fact baseline.
|
|
@@ -11141,6 +11220,26 @@ function findCellByVisualPosition(sourceCell, targetCells) {
|
|
|
11141
11220
|
);
|
|
11142
11221
|
return positioned[0]?.cell;
|
|
11143
11222
|
}
|
|
11223
|
+
function isDateLikeColumn(label) {
|
|
11224
|
+
return /\b(?:date|effective|expiration|retroactive)\b/i.test(cleanText(label, ""));
|
|
11225
|
+
}
|
|
11226
|
+
function containsDateValue(text) {
|
|
11227
|
+
return /\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b/.test(text) || /\b(?:jan|feb|mar|apr|may|jun|jul|aug|sep|sept|oct|nov|dec)[a-z]*\.?\s+\d{1,2},?\s+\d{2,4}\b/i.test(text);
|
|
11228
|
+
}
|
|
11229
|
+
function looksLikePolicyProse(text) {
|
|
11230
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
11231
|
+
if (words.length < 8) return false;
|
|
11232
|
+
return /\b(?:are|is|will|shall|must|may|includes?|included|reduce|subject|payment|terms?|conditions?|provided|pursuant)\b/i.test(text);
|
|
11233
|
+
}
|
|
11234
|
+
function shouldMergeVisualContinuation(params) {
|
|
11235
|
+
if (startsNewVisualTableItem(params.sourceCells)) return false;
|
|
11236
|
+
const targetLabel = params.targetCell?.title;
|
|
11237
|
+
if (isDateLikeColumn(targetLabel) && !containsDateValue(params.sourceText)) return false;
|
|
11238
|
+
if (looksLikePolicyProse(params.sourceText) && !/\b(?:description|coverage|remarks?|notes?)\b/i.test(cleanText(targetLabel, ""))) {
|
|
11239
|
+
return false;
|
|
11240
|
+
}
|
|
11241
|
+
return true;
|
|
11242
|
+
}
|
|
11144
11243
|
function columnLabelStartIndex(rows) {
|
|
11145
11244
|
const headerIndex = rows.findIndex(
|
|
11146
11245
|
({ row, cells }) => isSourceTreeHeaderRow(row) && cells.length > 1
|
|
@@ -11290,6 +11389,7 @@ function applyVisualTableRepair(sourceTree, repair) {
|
|
|
11290
11389
|
targetColumnIndex: continuation.targetColumnIndex,
|
|
11291
11390
|
targetColumnLabel: continuation.targetColumnLabel
|
|
11292
11391
|
});
|
|
11392
|
+
if (!shouldMergeVisualContinuation({ sourceText, sourceCells, targetCell })) continue;
|
|
11293
11393
|
const sourceNodes = [sourceRow, ...sourceCells];
|
|
11294
11394
|
const sourceSpanIds = sourceSpanIdsForNodes(sourceNodes);
|
|
11295
11395
|
let mergedIntoCells = false;
|
|
@@ -11392,7 +11492,7 @@ async function runVisualTableRepair(params) {
|
|
|
11392
11492
|
const repairResults = await Promise.all(candidates.map(async (candidate, index) => {
|
|
11393
11493
|
const label = `source_tree_visual_table_repair_p${candidate.page}`;
|
|
11394
11494
|
try {
|
|
11395
|
-
const budget = params.resolveBudget("
|
|
11495
|
+
const budget = params.resolveBudget("extraction_visual_table_repair", 1800);
|
|
11396
11496
|
const maxTokens = Math.min(budget.maxTokens, 2400);
|
|
11397
11497
|
const startedAt = Date.now();
|
|
11398
11498
|
const response = await safeGenerateObject(
|
|
@@ -11401,7 +11501,7 @@ async function runVisualTableRepair(params) {
|
|
|
11401
11501
|
prompt: buildVisualTableRepairPrompt(candidate),
|
|
11402
11502
|
schema: SourceTreeVisualTableRepairSchema,
|
|
11403
11503
|
maxTokens,
|
|
11404
|
-
taskKind: "
|
|
11504
|
+
taskKind: "extraction_visual_table_repair",
|
|
11405
11505
|
budgetDiagnostics: { ...budget, maxTokens },
|
|
11406
11506
|
trace: {
|
|
11407
11507
|
label,
|
|
@@ -11442,7 +11542,7 @@ async function runVisualTableRepair(params) {
|
|
|
11442
11542
|
continue;
|
|
11443
11543
|
}
|
|
11444
11544
|
params.trackUsage(result.usage, {
|
|
11445
|
-
taskKind: "
|
|
11545
|
+
taskKind: "extraction_visual_table_repair",
|
|
11446
11546
|
label: result.label,
|
|
11447
11547
|
maxTokens: result.maxTokens,
|
|
11448
11548
|
durationMs: result.durationMs
|
|
@@ -11676,6 +11776,105 @@ function materializeDocument(params) {
|
|
|
11676
11776
|
retroactiveDate: valueOf(profile, "retroactiveDate")
|
|
11677
11777
|
};
|
|
11678
11778
|
}
|
|
11779
|
+
function coverageCleanupGroups(profile) {
|
|
11780
|
+
const groups = [];
|
|
11781
|
+
const coreIndexes = [];
|
|
11782
|
+
const endorsementIndexes = [];
|
|
11783
|
+
const unclassifiedIndexes = [];
|
|
11784
|
+
profile.coverages.forEach((coverage, coverageIndex) => {
|
|
11785
|
+
if (coverage.coverageOrigin === "core") {
|
|
11786
|
+
coreIndexes.push(coverageIndex);
|
|
11787
|
+
} else if (coverage.coverageOrigin === "endorsement") {
|
|
11788
|
+
endorsementIndexes.push(coverageIndex);
|
|
11789
|
+
} else {
|
|
11790
|
+
unclassifiedIndexes.push(coverageIndex);
|
|
11791
|
+
}
|
|
11792
|
+
});
|
|
11793
|
+
if (coreIndexes.length) {
|
|
11794
|
+
groups.push({
|
|
11795
|
+
id: "policy",
|
|
11796
|
+
label: "Coverage schedule cleanup: policy schedules",
|
|
11797
|
+
coverageIndexes: coreIndexes
|
|
11798
|
+
});
|
|
11799
|
+
}
|
|
11800
|
+
if (endorsementIndexes.length) {
|
|
11801
|
+
groups.push({
|
|
11802
|
+
id: "endorsements",
|
|
11803
|
+
label: "Coverage schedule cleanup: endorsement schedules",
|
|
11804
|
+
coverageIndexes: endorsementIndexes
|
|
11805
|
+
});
|
|
11806
|
+
}
|
|
11807
|
+
if (unclassifiedIndexes.length) {
|
|
11808
|
+
groups.push({
|
|
11809
|
+
id: "source_backed",
|
|
11810
|
+
label: "Coverage schedule cleanup: source-backed schedules",
|
|
11811
|
+
coverageIndexes: unclassifiedIndexes
|
|
11812
|
+
});
|
|
11813
|
+
}
|
|
11814
|
+
return groups.length > 1 ? groups : [{
|
|
11815
|
+
id: "all",
|
|
11816
|
+
label: "Coverage schedule cleanup"
|
|
11817
|
+
}];
|
|
11818
|
+
}
|
|
11819
|
+
async function cleanupOperationalCoverageSchedules(params) {
|
|
11820
|
+
const groups = coverageCleanupGroups(params.operationalProfile);
|
|
11821
|
+
const validNodeIds = new Set(params.sourceTree.map((node) => node.id));
|
|
11822
|
+
const validSpanIds = new Set(params.sourceSpans.map((span) => span.id));
|
|
11823
|
+
const results = await Promise.all(groups.map(async (group, groupIndex) => {
|
|
11824
|
+
const budget = params.resolveBudget("extraction_coverage_cleanup", 4096);
|
|
11825
|
+
const startedAt = Date.now();
|
|
11826
|
+
const response = await safeGenerateObject(
|
|
11827
|
+
params.generateObject,
|
|
11828
|
+
{
|
|
11829
|
+
prompt: buildOperationalProfileCleanupPrompt(
|
|
11830
|
+
params.sourceTree,
|
|
11831
|
+
params.operationalProfile,
|
|
11832
|
+
{ coverageIndexes: group.coverageIndexes, label: group.label }
|
|
11833
|
+
),
|
|
11834
|
+
schema: OperationalProfileCleanupSchema,
|
|
11835
|
+
maxTokens: budget.maxTokens,
|
|
11836
|
+
taskKind: "extraction_coverage_cleanup",
|
|
11837
|
+
budgetDiagnostics: budget,
|
|
11838
|
+
providerOptions: params.providerOptions,
|
|
11839
|
+
trace: {
|
|
11840
|
+
phase: "coverage_cleanup",
|
|
11841
|
+
label: group.label,
|
|
11842
|
+
itemCount: group.coverageIndexes?.length ?? params.operationalProfile.coverages.length,
|
|
11843
|
+
coverageGroup: group.id,
|
|
11844
|
+
batchIndex: groups.length > 1 ? groupIndex + 1 : void 0,
|
|
11845
|
+
batchCount: groups.length > 1 ? groups.length : void 0,
|
|
11846
|
+
sourceBacked: true
|
|
11847
|
+
}
|
|
11848
|
+
},
|
|
11849
|
+
{
|
|
11850
|
+
fallback: { coverageDecisions: [], warnings: [] },
|
|
11851
|
+
maxRetries: 0,
|
|
11852
|
+
log: params.log,
|
|
11853
|
+
retry: false
|
|
11854
|
+
}
|
|
11855
|
+
);
|
|
11856
|
+
params.trackUsage(response.usage, {
|
|
11857
|
+
taskKind: "extraction_coverage_cleanup",
|
|
11858
|
+
label: group.id === "all" ? "coverage_cleanup" : `coverage_cleanup_${group.id}`,
|
|
11859
|
+
maxTokens: budget.maxTokens,
|
|
11860
|
+
durationMs: Date.now() - startedAt
|
|
11861
|
+
});
|
|
11862
|
+
return response.object;
|
|
11863
|
+
}));
|
|
11864
|
+
const cleanup = {
|
|
11865
|
+
coverageDecisions: results.flatMap((result) => result.coverageDecisions ?? []),
|
|
11866
|
+
warnings: results.flatMap((result) => result.warnings ?? [])
|
|
11867
|
+
};
|
|
11868
|
+
return {
|
|
11869
|
+
operationalProfile: applyOperationalProfileCleanup(
|
|
11870
|
+
params.operationalProfile,
|
|
11871
|
+
cleanup,
|
|
11872
|
+
validNodeIds,
|
|
11873
|
+
validSpanIds
|
|
11874
|
+
),
|
|
11875
|
+
warnings: cleanup.warnings
|
|
11876
|
+
};
|
|
11877
|
+
}
|
|
11679
11878
|
async function runSourceTreeExtraction(params) {
|
|
11680
11879
|
const sourceSpans = normalizeSourceSpans(params.sourceSpans);
|
|
11681
11880
|
const formHints = normalizeFormHints(params.formInventory?.forms, sourceSpans);
|
|
@@ -11838,45 +12037,18 @@ async function runSourceTreeExtraction(params) {
|
|
|
11838
12037
|
}
|
|
11839
12038
|
if (operationalProfile.coverages.length > 0) {
|
|
11840
12039
|
try {
|
|
11841
|
-
const
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
const startedAt = Date.now();
|
|
11845
|
-
const response = await safeGenerateObject(
|
|
11846
|
-
params.generateObject,
|
|
11847
|
-
{
|
|
11848
|
-
prompt: buildOperationalProfileCleanupPrompt(sourceTree, operationalProfile),
|
|
11849
|
-
schema: OperationalProfileCleanupSchema,
|
|
11850
|
-
maxTokens: budget.maxTokens,
|
|
11851
|
-
taskKind: "extraction_coverage_cleanup",
|
|
11852
|
-
budgetDiagnostics: budget,
|
|
11853
|
-
providerOptions: params.providerOptions,
|
|
11854
|
-
trace: {
|
|
11855
|
-
phase: "coverage_cleanup",
|
|
11856
|
-
label: "Coverage cleanup",
|
|
11857
|
-
itemCount: operationalProfile.coverages.length,
|
|
11858
|
-
sourceBacked: true
|
|
11859
|
-
}
|
|
11860
|
-
},
|
|
11861
|
-
{
|
|
11862
|
-
fallback: { coverageDecisions: [], warnings: [] },
|
|
11863
|
-
maxRetries: 0,
|
|
11864
|
-
log: params.log,
|
|
11865
|
-
retry: false
|
|
11866
|
-
}
|
|
11867
|
-
);
|
|
11868
|
-
localTrack(response.usage, {
|
|
11869
|
-
taskKind: "extraction_coverage_cleanup",
|
|
11870
|
-
label: "coverage_cleanup",
|
|
11871
|
-
maxTokens: budget.maxTokens,
|
|
11872
|
-
durationMs: Date.now() - startedAt
|
|
11873
|
-
});
|
|
11874
|
-
operationalProfile = applyOperationalProfileCleanup(
|
|
12040
|
+
const cleanup = await cleanupOperationalCoverageSchedules({
|
|
12041
|
+
sourceTree,
|
|
12042
|
+
sourceSpans,
|
|
11875
12043
|
operationalProfile,
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
12044
|
+
generateObject: params.generateObject,
|
|
12045
|
+
providerOptions: params.providerOptions,
|
|
12046
|
+
resolveBudget: params.resolveBudget,
|
|
12047
|
+
trackUsage: localTrack,
|
|
12048
|
+
log: params.log
|
|
12049
|
+
});
|
|
12050
|
+
operationalProfile = cleanup.operationalProfile;
|
|
12051
|
+
warnings.push(...cleanup.warnings);
|
|
11880
12052
|
} catch (error) {
|
|
11881
12053
|
warnings.push(`Operational profile cleanup pass failed; uncleaned profile used (${error instanceof Error ? error.message : String(error)})`);
|
|
11882
12054
|
}
|