@claritylabs/cl-sdk 3.0.4 → 3.0.6
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/index.js +157 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +157 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -9064,6 +9064,150 @@ function cleanText(value, fallback) {
|
|
|
9064
9064
|
const text = value?.replace(/\s+/g, " ").trim();
|
|
9065
9065
|
return text || fallback;
|
|
9066
9066
|
}
|
|
9067
|
+
function simplifyOrganizerTitle(value, fallback, kind) {
|
|
9068
|
+
const title = cleanText(value, fallback);
|
|
9069
|
+
if (/^declarations\b/i.test(title)) return "Declarations";
|
|
9070
|
+
if (/^policy\s+form\b/i.test(title)) return "Policy Form";
|
|
9071
|
+
if (/^definitions\b/i.test(title)) return "Definitions";
|
|
9072
|
+
if (kind === "page_group" && /^endorsements?\b/i.test(title)) return "Endorsements";
|
|
9073
|
+
const endorsementNumber = title.match(/^endorsement\s+(?:no\.?|number|#)?\s*([A-Z0-9][A-Z0-9.-]*)\b/i)?.[1];
|
|
9074
|
+
if (endorsementNumber) return `Endorsement No. ${endorsementNumber}`;
|
|
9075
|
+
if (kind === "endorsement" && /^endorsements?\s+\d+\s*[–-]\s*\d+\b/i.test(title)) {
|
|
9076
|
+
return title.replace(/[–—]/g, "-").replace(/\s*\(.*/, "").trim();
|
|
9077
|
+
}
|
|
9078
|
+
return title;
|
|
9079
|
+
}
|
|
9080
|
+
function endorsementReference(value) {
|
|
9081
|
+
return value?.match(/\bendorsement\s+(?:no\.?|number|#)?\s*([A-Z0-9][A-Z0-9.-]*)\b/i)?.[1]?.toUpperCase();
|
|
9082
|
+
}
|
|
9083
|
+
function endorsementTitle(value) {
|
|
9084
|
+
const text = cleanText(value, "");
|
|
9085
|
+
const number = text.match(/\bendorsement\s+(?:no\.?|number|#)\s*([A-Z0-9][A-Z0-9.-]*)\b/i)?.[1]?.toUpperCase();
|
|
9086
|
+
return number ? `Endorsement No. ${number}` : void 0;
|
|
9087
|
+
}
|
|
9088
|
+
function rejectsOrganizerGroup(group, children) {
|
|
9089
|
+
if (/^endorsements?\b/i.test(group.title) && group.kind !== "page_group") return true;
|
|
9090
|
+
if (group.kind !== "endorsement") return false;
|
|
9091
|
+
if (/^endorsements?\s+\d+\s*[–-]\s*\d+\b/i.test(group.title)) return true;
|
|
9092
|
+
const childNumbers = new Set(
|
|
9093
|
+
children.map((child) => endorsementReference([child.title, child.description, child.textExcerpt].filter(Boolean).join(" "))).filter((value) => Boolean(value))
|
|
9094
|
+
);
|
|
9095
|
+
return childNumbers.size > 1;
|
|
9096
|
+
}
|
|
9097
|
+
function isEndorsementGroup(node) {
|
|
9098
|
+
return node.kind === "page_group" && /^endorsements?\b/i.test(node.title);
|
|
9099
|
+
}
|
|
9100
|
+
function endorsementGroupNodeId(documentId, parentId) {
|
|
9101
|
+
return [
|
|
9102
|
+
documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
|
|
9103
|
+
"source_node",
|
|
9104
|
+
"page_group",
|
|
9105
|
+
"endorsements",
|
|
9106
|
+
parentId?.replace(/[^a-zA-Z0-9_.:-]/g, "_").slice(0, 48) ?? "root"
|
|
9107
|
+
].join(":");
|
|
9108
|
+
}
|
|
9109
|
+
function applyEndorsementGrouping(sourceTree) {
|
|
9110
|
+
const relabeledTree = sourceTree.map((node) => {
|
|
9111
|
+
if (node.kind === "document" || isEndorsementGroup(node) || node.kind === "endorsement") return node;
|
|
9112
|
+
const title = endorsementTitle([node.title, node.description, node.textExcerpt].filter(Boolean).join(" "));
|
|
9113
|
+
if (!title) return node;
|
|
9114
|
+
return {
|
|
9115
|
+
...node,
|
|
9116
|
+
kind: "endorsement",
|
|
9117
|
+
title,
|
|
9118
|
+
description: cleanText(
|
|
9119
|
+
[title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
|
|
9120
|
+
title
|
|
9121
|
+
),
|
|
9122
|
+
metadata: {
|
|
9123
|
+
...node.metadata,
|
|
9124
|
+
organizerRepair: "normalize_endorsement_grouping"
|
|
9125
|
+
}
|
|
9126
|
+
};
|
|
9127
|
+
});
|
|
9128
|
+
const byParent = nodesByParent(relabeledTree);
|
|
9129
|
+
const groupsByParent = /* @__PURE__ */ new Map();
|
|
9130
|
+
const endorsementGroupIds = new Set(
|
|
9131
|
+
relabeledTree.filter(isEndorsementGroup).map((node) => node.id)
|
|
9132
|
+
);
|
|
9133
|
+
let nextTree = relabeledTree.map((node) => {
|
|
9134
|
+
if (!isEndorsementGroup(node)) return node;
|
|
9135
|
+
const normalized = {
|
|
9136
|
+
...node,
|
|
9137
|
+
kind: "page_group",
|
|
9138
|
+
title: "Endorsements",
|
|
9139
|
+
description: cleanText(node.description, "Endorsement forms grouped by source order"),
|
|
9140
|
+
metadata: {
|
|
9141
|
+
...node.metadata,
|
|
9142
|
+
sourceTreeVersion: "v3",
|
|
9143
|
+
organizer: node.metadata?.organizer ?? "endorsement_grouping"
|
|
9144
|
+
}
|
|
9145
|
+
};
|
|
9146
|
+
groupsByParent.set(node.parentId, normalized);
|
|
9147
|
+
endorsementGroupIds.add(node.id);
|
|
9148
|
+
return normalized;
|
|
9149
|
+
});
|
|
9150
|
+
nextTree = nextTree.map((node) => {
|
|
9151
|
+
if (!endorsementGroupIds.has(node.parentId ?? "")) return node;
|
|
9152
|
+
const title = endorsementTitle([node.title, node.description, node.textExcerpt].filter(Boolean).join(" "));
|
|
9153
|
+
if (!title) return node;
|
|
9154
|
+
return {
|
|
9155
|
+
...node,
|
|
9156
|
+
kind: "endorsement",
|
|
9157
|
+
title,
|
|
9158
|
+
description: cleanText(
|
|
9159
|
+
[title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
|
|
9160
|
+
title
|
|
9161
|
+
),
|
|
9162
|
+
metadata: {
|
|
9163
|
+
...node.metadata,
|
|
9164
|
+
organizerRepair: "normalize_endorsement_grouping"
|
|
9165
|
+
}
|
|
9166
|
+
};
|
|
9167
|
+
});
|
|
9168
|
+
for (const [parentId, children] of byParent) {
|
|
9169
|
+
if (endorsementGroupIds.has(parentId ?? "")) continue;
|
|
9170
|
+
const endorsementChildren = children.filter((child) => child.kind === "endorsement" && !isEndorsementGroup(child));
|
|
9171
|
+
if (endorsementChildren.length < 2) continue;
|
|
9172
|
+
const documentId = endorsementChildren[0].documentId;
|
|
9173
|
+
const pageStarts = endorsementChildren.map((child) => child.pageStart).filter((page) => typeof page === "number");
|
|
9174
|
+
const pageEnds = endorsementChildren.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
|
|
9175
|
+
const order = Math.min(...endorsementChildren.map((child) => child.order));
|
|
9176
|
+
const existingGroup = groupsByParent.get(parentId);
|
|
9177
|
+
const groupId = existingGroup?.id ?? endorsementGroupNodeId(documentId, parentId);
|
|
9178
|
+
const groupNode = existingGroup ?? {
|
|
9179
|
+
id: groupId,
|
|
9180
|
+
documentId,
|
|
9181
|
+
parentId,
|
|
9182
|
+
kind: "page_group",
|
|
9183
|
+
title: "Endorsements",
|
|
9184
|
+
description: "Endorsement forms grouped by source order",
|
|
9185
|
+
textExcerpt: void 0,
|
|
9186
|
+
sourceSpanIds: [],
|
|
9187
|
+
pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
|
|
9188
|
+
pageEnd: pageEnds.length ? Math.max(...pageEnds) : void 0,
|
|
9189
|
+
bbox: endorsementChildren.flatMap((child) => child.bbox ?? []).slice(0, 12),
|
|
9190
|
+
order,
|
|
9191
|
+
path: "",
|
|
9192
|
+
metadata: { sourceTreeVersion: "v3", organizer: "endorsement_grouping" }
|
|
9193
|
+
};
|
|
9194
|
+
const childSpanIds = [...new Set(endorsementChildren.flatMap((child) => child.sourceSpanIds))];
|
|
9195
|
+
const normalizedGroup = {
|
|
9196
|
+
...groupNode,
|
|
9197
|
+
sourceSpanIds: groupNode.sourceSpanIds.length ? groupNode.sourceSpanIds : childSpanIds,
|
|
9198
|
+
pageStart: groupNode.pageStart ?? (pageStarts.length ? Math.min(...pageStarts) : void 0),
|
|
9199
|
+
pageEnd: groupNode.pageEnd ?? (pageEnds.length ? Math.max(...pageEnds) : void 0),
|
|
9200
|
+
order
|
|
9201
|
+
};
|
|
9202
|
+
groupsByParent.set(parentId, normalizedGroup);
|
|
9203
|
+
if (!existingGroup) nextTree.push(normalizedGroup);
|
|
9204
|
+
else nextTree = nextTree.map((node) => node.id === normalizedGroup.id ? normalizedGroup : node);
|
|
9205
|
+
nextTree = nextTree.map(
|
|
9206
|
+
(node) => endorsementChildren.some((child) => child.id === node.id) ? { ...node, parentId: groupId, order: node.order + 1e-3 } : node
|
|
9207
|
+
);
|
|
9208
|
+
}
|
|
9209
|
+
return normalizeDocumentSourceTreePaths(nextTree);
|
|
9210
|
+
}
|
|
9067
9211
|
function compactNode(node, maxText = 700) {
|
|
9068
9212
|
return {
|
|
9069
9213
|
id: node.id,
|
|
@@ -9151,8 +9295,11 @@ Scope:
|
|
|
9151
9295
|
Rules:
|
|
9152
9296
|
- Use only node IDs from the provided list.
|
|
9153
9297
|
- Do not invent text, page numbers, source spans, limits, or policy facts.
|
|
9154
|
-
- You may relabel existing nodes and group adjacent top-level/page nodes from this batch when they are clearly one form,
|
|
9298
|
+
- You may relabel existing nodes and group adjacent top-level/page nodes from this batch only when they are clearly one continuous form, one declarations set, one schedule, or one clause family.
|
|
9299
|
+
- Group adjacent separately numbered endorsements under a single generic "Endorsements" page_group parent, with each individual endorsement preserved as its own child node.
|
|
9300
|
+
- Never create rollup titles such as "Endorsements 1-3 (...)" or merge multiple endorsements into one endorsement node.
|
|
9155
9301
|
- Add concise, human-readable titles to generic text, table, row, and cell nodes when the text makes their role clear.
|
|
9302
|
+
- Keep organizer titles terse. Use the printed heading or a compact canonical title such as "Declarations", "Policy Form", "Definitions", or "Endorsement No. 3"; do not add parenthetical summaries.
|
|
9156
9303
|
- Groups must list existing childNodeIds only.
|
|
9157
9304
|
- Keep descriptions short and useful for search.
|
|
9158
9305
|
- Prefer the document's own form titles, endorsement titles, schedules, declarations headings, and page order over keyword-only guessing.
|
|
@@ -9202,17 +9349,20 @@ function applyOrganization(sourceTree, organization) {
|
|
|
9202
9349
|
return {
|
|
9203
9350
|
...node,
|
|
9204
9351
|
kind: label.kind ?? node.kind,
|
|
9205
|
-
title:
|
|
9352
|
+
title: simplifyOrganizerTitle(label.title, node.title, label.kind ?? node.kind),
|
|
9206
9353
|
description: cleanText(label.description, node.description)
|
|
9207
9354
|
};
|
|
9208
9355
|
});
|
|
9209
9356
|
for (const group of organization.groups) {
|
|
9210
9357
|
const children = group.childNodeIds.map((id2) => byId.get(id2)).filter((node2) => Boolean(node2));
|
|
9211
9358
|
if (children.length === 0) continue;
|
|
9359
|
+
if (rejectsOrganizerGroup(group, children)) continue;
|
|
9212
9360
|
const parentId = children[0].parentId;
|
|
9213
9361
|
if (!children.every((child) => child.parentId === parentId)) continue;
|
|
9214
9362
|
const documentId = children[0].documentId;
|
|
9215
|
-
const
|
|
9363
|
+
const title = simplifyOrganizerTitle(group.title, group.title, group.kind);
|
|
9364
|
+
const description = cleanText(group.description, title);
|
|
9365
|
+
const id = groupNodeId(documentId, { ...group, title });
|
|
9216
9366
|
if (byId.has(id)) continue;
|
|
9217
9367
|
const sourceSpanIds = [...new Set(children.flatMap((child) => child.sourceSpanIds))];
|
|
9218
9368
|
const pageStarts = children.map((child) => child.pageStart).filter((page) => typeof page === "number");
|
|
@@ -9223,8 +9373,8 @@ function applyOrganization(sourceTree, organization) {
|
|
|
9223
9373
|
documentId,
|
|
9224
9374
|
parentId,
|
|
9225
9375
|
kind: group.kind,
|
|
9226
|
-
title
|
|
9227
|
-
description
|
|
9376
|
+
title,
|
|
9377
|
+
description,
|
|
9228
9378
|
textExcerpt: children.map((child) => child.textExcerpt ?? child.description).filter(Boolean).join("\n\n").slice(0, 1600),
|
|
9229
9379
|
sourceSpanIds,
|
|
9230
9380
|
pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
|
|
@@ -9242,7 +9392,7 @@ function applyOrganization(sourceTree, organization) {
|
|
|
9242
9392
|
];
|
|
9243
9393
|
byId.set(id, node);
|
|
9244
9394
|
}
|
|
9245
|
-
return normalizeDocumentSourceTreePaths(nextTree);
|
|
9395
|
+
return applyEndorsementGrouping(normalizeDocumentSourceTreePaths(nextTree));
|
|
9246
9396
|
}
|
|
9247
9397
|
function sourceTreeToOutline(sourceTree) {
|
|
9248
9398
|
const byParent = /* @__PURE__ */ new Map();
|
|
@@ -9461,6 +9611,7 @@ async function runSourceTreeExtraction(params) {
|
|
|
9461
9611
|
} catch (error) {
|
|
9462
9612
|
warnings.push(`Operational profile model pass failed; deterministic profile used (${error instanceof Error ? error.message : String(error)})`);
|
|
9463
9613
|
}
|
|
9614
|
+
sourceTree = applyEndorsementGrouping(sourceTree);
|
|
9464
9615
|
const document = materializeDocument({
|
|
9465
9616
|
id: params.id,
|
|
9466
9617
|
sourceTree,
|