@claritylabs/cl-sdk 3.0.11 → 3.0.12
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 +211 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +211 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2957,7 +2957,7 @@ function normalizeNodeKind(span) {
|
|
|
2957
2957
|
if (unit === "table_cell") return "table_cell";
|
|
2958
2958
|
if (unit === "key_value") return "schedule";
|
|
2959
2959
|
if (unit === "section") return "section";
|
|
2960
|
-
if (element === "
|
|
2960
|
+
if (element === "section_candidate") {
|
|
2961
2961
|
const text = span.text.toLowerCase();
|
|
2962
2962
|
if (/endorsement/.test(text)) return "endorsement";
|
|
2963
2963
|
if (/schedule|declarations?/.test(text)) return "schedule";
|
|
@@ -2993,6 +2993,90 @@ function makeNode(params) {
|
|
|
2993
2993
|
metadata: params.metadata
|
|
2994
2994
|
};
|
|
2995
2995
|
}
|
|
2996
|
+
function metadataString(metadata, key) {
|
|
2997
|
+
const value = metadata?.[key];
|
|
2998
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
2999
|
+
}
|
|
3000
|
+
function isTitleContentNode(node) {
|
|
3001
|
+
if (node.kind !== "text") return false;
|
|
3002
|
+
return metadataString(node.metadata, "elementType") === "title" || metadataString(node.metadata, "sourceUnit") === "title";
|
|
3003
|
+
}
|
|
3004
|
+
function nodePageEnd(node) {
|
|
3005
|
+
return node.pageEnd ?? node.pageStart;
|
|
3006
|
+
}
|
|
3007
|
+
function groupPageContentByTitles(nodes) {
|
|
3008
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
3009
|
+
for (const node of nodes) {
|
|
3010
|
+
const children = byParent.get(node.parentId) ?? [];
|
|
3011
|
+
children.push(node);
|
|
3012
|
+
byParent.set(node.parentId, children);
|
|
3013
|
+
}
|
|
3014
|
+
for (const children of byParent.values()) {
|
|
3015
|
+
children.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
|
|
3016
|
+
}
|
|
3017
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
3018
|
+
for (const pageNode of nodes.filter((node) => node.kind === "page")) {
|
|
3019
|
+
const children = (byParent.get(pageNode.id) ?? []).filter((child) => child.kind !== "table_row" && child.kind !== "table_cell");
|
|
3020
|
+
let activeTitle;
|
|
3021
|
+
let activeContent = [];
|
|
3022
|
+
const flush = () => {
|
|
3023
|
+
if (!activeTitle || activeContent.length === 0) {
|
|
3024
|
+
activeTitle = void 0;
|
|
3025
|
+
activeContent = [];
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
3028
|
+
const contentNodes = activeContent.map((node) => byId.get(node.id) ?? node).filter((node) => node.parentId === pageNode.id);
|
|
3029
|
+
if (contentNodes.length === 0) {
|
|
3030
|
+
activeTitle = void 0;
|
|
3031
|
+
activeContent = [];
|
|
3032
|
+
return;
|
|
3033
|
+
}
|
|
3034
|
+
const evidenceNodes = [activeTitle, ...contentNodes];
|
|
3035
|
+
const title = truncate(activeTitle.textExcerpt ?? activeTitle.title, 120);
|
|
3036
|
+
const pageStarts = evidenceNodes.map((node) => node.pageStart).filter((page) => typeof page === "number");
|
|
3037
|
+
const pageEnds = evidenceNodes.map(nodePageEnd).filter((page) => typeof page === "number");
|
|
3038
|
+
const sourceSpanIds = [...new Set(evidenceNodes.flatMap((node) => node.sourceSpanIds))];
|
|
3039
|
+
const bbox = evidenceNodes.flatMap((node) => node.bbox ?? []).slice(0, 12);
|
|
3040
|
+
byId.set(activeTitle.id, {
|
|
3041
|
+
...activeTitle,
|
|
3042
|
+
kind: "section",
|
|
3043
|
+
title,
|
|
3044
|
+
description: nodeTextDescription({
|
|
3045
|
+
kind: "section",
|
|
3046
|
+
title,
|
|
3047
|
+
text: evidenceNodes.map((node) => node.textExcerpt).filter(Boolean).join("\n\n"),
|
|
3048
|
+
page: activeTitle.pageStart
|
|
3049
|
+
}),
|
|
3050
|
+
textExcerpt: evidenceNodes.map((node) => node.textExcerpt).filter(Boolean).join("\n\n").slice(0, 1600),
|
|
3051
|
+
sourceSpanIds,
|
|
3052
|
+
pageStart: pageStarts.length ? Math.min(...pageStarts) : activeTitle.pageStart,
|
|
3053
|
+
pageEnd: pageEnds.length ? Math.max(...pageEnds) : activeTitle.pageEnd,
|
|
3054
|
+
bbox,
|
|
3055
|
+
metadata: {
|
|
3056
|
+
...activeTitle.metadata,
|
|
3057
|
+
sourceTreeVersion: "v3",
|
|
3058
|
+
organizer: "title_block"
|
|
3059
|
+
}
|
|
3060
|
+
});
|
|
3061
|
+
for (const node of contentNodes) {
|
|
3062
|
+
byId.set(node.id, { ...node, parentId: activeTitle.id });
|
|
3063
|
+
}
|
|
3064
|
+
activeTitle = void 0;
|
|
3065
|
+
activeContent = [];
|
|
3066
|
+
};
|
|
3067
|
+
for (const child of children) {
|
|
3068
|
+
if (isTitleContentNode(child)) {
|
|
3069
|
+
flush();
|
|
3070
|
+
activeTitle = child;
|
|
3071
|
+
activeContent = [];
|
|
3072
|
+
continue;
|
|
3073
|
+
}
|
|
3074
|
+
if (activeTitle) activeContent.push(child);
|
|
3075
|
+
}
|
|
3076
|
+
flush();
|
|
3077
|
+
}
|
|
3078
|
+
return nodes.map((node) => byId.get(node.id) ?? node);
|
|
3079
|
+
}
|
|
2996
3080
|
function sortSpans(left, right) {
|
|
2997
3081
|
const leftPage = pageStart(left) ?? 0;
|
|
2998
3082
|
const rightPage = pageStart(right) ?? 0;
|
|
@@ -3168,7 +3252,7 @@ function buildDocumentSourceTree(sourceSpans, documentId) {
|
|
|
3168
3252
|
}
|
|
3169
3253
|
addStandaloneSpanNode(span, pageParentId);
|
|
3170
3254
|
}
|
|
3171
|
-
return normalizeDocumentSourceTreePaths([...nodes.values()]);
|
|
3255
|
+
return normalizeDocumentSourceTreePaths(groupPageContentByTitles([...nodes.values()]));
|
|
3172
3256
|
}
|
|
3173
3257
|
|
|
3174
3258
|
// src/source/operational-profile.ts
|
|
@@ -9356,9 +9440,9 @@ var ORGANIZABLE_KINDS = [
|
|
|
9356
9440
|
"clause"
|
|
9357
9441
|
];
|
|
9358
9442
|
var ORGANIZATION_TOP_LEVEL_BATCH_SIZE = 80;
|
|
9359
|
-
var ORGANIZATION_CHILD_CONTEXT_LIMIT = 4;
|
|
9360
9443
|
var ORGANIZER_MAX_SOURCE_SPANS = 400;
|
|
9361
9444
|
var ORGANIZER_MAX_TOP_LEVEL_NODES = 18;
|
|
9445
|
+
var OUTLINE_CLEANUP_MAX_TOP_LEVEL_NODES = 80;
|
|
9362
9446
|
var SourceTreeOrganizationSchema = import_zod41.z.object({
|
|
9363
9447
|
labels: import_zod41.z.array(import_zod41.z.object({
|
|
9364
9448
|
nodeId: import_zod41.z.string(),
|
|
@@ -9475,6 +9559,22 @@ function endorsementDescription(title, node) {
|
|
|
9475
9559
|
title
|
|
9476
9560
|
);
|
|
9477
9561
|
}
|
|
9562
|
+
function nodePageEnd2(node) {
|
|
9563
|
+
return node.pageEnd ?? node.pageStart;
|
|
9564
|
+
}
|
|
9565
|
+
function pageRangeForNodes(nodes) {
|
|
9566
|
+
const pageStarts = nodes.map((node) => node.pageStart).filter((page) => typeof page === "number");
|
|
9567
|
+
const pageEnds = nodes.map(nodePageEnd2).filter((page) => typeof page === "number");
|
|
9568
|
+
if (pageStarts.length === 0 || pageEnds.length === 0) return void 0;
|
|
9569
|
+
const start = Math.min(...pageStarts);
|
|
9570
|
+
const end = Math.max(...pageEnds);
|
|
9571
|
+
return start === end ? `page ${start}` : `pages ${start}-${end}`;
|
|
9572
|
+
}
|
|
9573
|
+
function descriptionWithPages(description, nodes) {
|
|
9574
|
+
const range = pageRangeForNodes(nodes);
|
|
9575
|
+
if (!range || new RegExp(`\\b${range.replace("-", "\\-")}\\b`, "i").test(description)) return description;
|
|
9576
|
+
return `${description}; ${range}`;
|
|
9577
|
+
}
|
|
9478
9578
|
function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
|
|
9479
9579
|
return [
|
|
9480
9580
|
documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
|
|
@@ -9485,7 +9585,12 @@ function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
|
|
|
9485
9585
|
].join(":");
|
|
9486
9586
|
}
|
|
9487
9587
|
function looksLikeDeclarationsStart(node) {
|
|
9488
|
-
|
|
9588
|
+
const title = cleanText(node.title, "");
|
|
9589
|
+
const text = sourceNodeText(node);
|
|
9590
|
+
if (/\b(important notice|privacy notice|ofac advisory|terrorism risk insurance act|how to report a claim)\b/i.test(text)) {
|
|
9591
|
+
return false;
|
|
9592
|
+
}
|
|
9593
|
+
return /^declarations?$/i.test(title) || /\bdeclarations?\s+(page|schedule|section)\b/i.test(text) || /^declarations?\b/i.test(cleanText(node.textExcerpt, ""));
|
|
9489
9594
|
}
|
|
9490
9595
|
function looksLikeDeclarationsContinuation(node) {
|
|
9491
9596
|
const text = sourceNodeText(node);
|
|
@@ -9520,7 +9625,7 @@ function groupAdjacentChildren(params) {
|
|
|
9520
9625
|
parentId,
|
|
9521
9626
|
kind: params.kind,
|
|
9522
9627
|
title: params.title,
|
|
9523
|
-
description: params.description,
|
|
9628
|
+
description: descriptionWithPages(params.description, children),
|
|
9524
9629
|
textExcerpt: children.map((child) => child.textExcerpt ?? child.description).filter(Boolean).join("\n\n").slice(0, 1600),
|
|
9525
9630
|
sourceSpanIds,
|
|
9526
9631
|
pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
|
|
@@ -9573,6 +9678,22 @@ function applySemanticPageGrouping(sourceTree) {
|
|
|
9573
9678
|
const children = (nodesByParent(relabeled).get(rootId) ?? []).filter((node) => node.kind !== "document").sort((left, right) => left.order - right.order);
|
|
9574
9679
|
let nextTree = relabeled;
|
|
9575
9680
|
const declarationsStartIndex = children.findIndex(looksLikeDeclarationsStart);
|
|
9681
|
+
const firstCoreIndex = children.findIndex(
|
|
9682
|
+
(child) => looksLikeDeclarationsStart(child) || looksLikePolicyFormStart(child) || looksLikeEndorsementStart(child)
|
|
9683
|
+
);
|
|
9684
|
+
const frontMatterBoundary = declarationsStartIndex >= 0 ? declarationsStartIndex : firstCoreIndex;
|
|
9685
|
+
if (frontMatterBoundary > 0) {
|
|
9686
|
+
const frontMatterIds = children.slice(0, frontMatterBoundary).map((child) => child.id);
|
|
9687
|
+
nextTree = groupAdjacentChildren({
|
|
9688
|
+
sourceTree: nextTree,
|
|
9689
|
+
children,
|
|
9690
|
+
childIds: frontMatterIds,
|
|
9691
|
+
kind: "page_group",
|
|
9692
|
+
title: "Notices and Jacket",
|
|
9693
|
+
description: "Policy jacket, notices, and administrative pages grouped by source order",
|
|
9694
|
+
organizer: "semantic_front_matter_grouping"
|
|
9695
|
+
});
|
|
9696
|
+
}
|
|
9576
9697
|
if (declarationsStartIndex >= 0) {
|
|
9577
9698
|
const declarationIds = [];
|
|
9578
9699
|
for (let index = declarationsStartIndex; index < children.length; index += 1) {
|
|
@@ -9741,17 +9862,19 @@ function normalizeContainerEvidenceFromChildren(sourceTree) {
|
|
|
9741
9862
|
return sourceTree.map((node) => byId.get(node.id) ?? node);
|
|
9742
9863
|
}
|
|
9743
9864
|
function normalizeSemanticHierarchy(sourceTree) {
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
normalizePolicyFormStructure(
|
|
9748
|
-
normalizeDocumentSourceTreePaths(sourceTree)
|
|
9749
|
-
)
|
|
9750
|
-
)
|
|
9865
|
+
const normalized = normalizeDocumentSourceTreePaths(
|
|
9866
|
+
normalizePolicyFormStructure(
|
|
9867
|
+
normalizeDocumentSourceTreePaths(sourceTree)
|
|
9751
9868
|
)
|
|
9752
9869
|
);
|
|
9870
|
+
const nested = normalizeDocumentSourceTreePaths(nestEndorsementContinuationPages(normalized));
|
|
9871
|
+
const withEvidence = normalizeContainerEvidenceFromChildren(nested);
|
|
9872
|
+
return normalizeDocumentSourceTreePaths(
|
|
9873
|
+
normalizeContainerEvidenceFromChildren(withEvidence)
|
|
9874
|
+
);
|
|
9753
9875
|
}
|
|
9754
9876
|
function applyEndorsementGrouping(sourceTree) {
|
|
9877
|
+
const rootId = sourceTreeRootId(sourceTree);
|
|
9755
9878
|
const relabeledTree = sourceTree.map((node) => {
|
|
9756
9879
|
if (node.kind === "document" || isEndorsementGroup(node)) return node;
|
|
9757
9880
|
const title = endorsementStartTitle(node);
|
|
@@ -9789,7 +9912,7 @@ function applyEndorsementGrouping(sourceTree) {
|
|
|
9789
9912
|
...node,
|
|
9790
9913
|
kind: "page_group",
|
|
9791
9914
|
title: "Endorsements",
|
|
9792
|
-
description: cleanText(node.description, "Endorsement forms grouped by source order"),
|
|
9915
|
+
description: descriptionWithPages(cleanText(node.description, "Endorsement forms grouped by source order"), byParent.get(node.id) ?? [node]),
|
|
9793
9916
|
metadata: {
|
|
9794
9917
|
...node.metadata,
|
|
9795
9918
|
sourceTreeVersion: "v3",
|
|
@@ -9816,9 +9939,10 @@ function applyEndorsementGrouping(sourceTree) {
|
|
|
9816
9939
|
};
|
|
9817
9940
|
});
|
|
9818
9941
|
for (const [parentId, children] of byParent) {
|
|
9942
|
+
if (parentId !== rootId) continue;
|
|
9819
9943
|
if (endorsementGroupIds.has(parentId ?? "")) continue;
|
|
9820
9944
|
const endorsementChildren = children.filter((child) => child.kind === "endorsement" && !isEndorsementGroup(child));
|
|
9821
|
-
if (endorsementChildren.length <
|
|
9945
|
+
if (endorsementChildren.length < 1) continue;
|
|
9822
9946
|
const endorsementGroupChildren = [];
|
|
9823
9947
|
let hasSeenEndorsementStart = false;
|
|
9824
9948
|
for (const child of children) {
|
|
@@ -9831,6 +9955,7 @@ function applyEndorsementGrouping(sourceTree) {
|
|
|
9831
9955
|
endorsementGroupChildren.push(child);
|
|
9832
9956
|
}
|
|
9833
9957
|
}
|
|
9958
|
+
if (endorsementGroupChildren.length < 1) continue;
|
|
9834
9959
|
const documentId = endorsementChildren[0].documentId;
|
|
9835
9960
|
const pageStarts = endorsementGroupChildren.map((child) => child.pageStart).filter((page) => typeof page === "number");
|
|
9836
9961
|
const pageEnds = endorsementGroupChildren.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
|
|
@@ -9843,7 +9968,7 @@ function applyEndorsementGrouping(sourceTree) {
|
|
|
9843
9968
|
parentId,
|
|
9844
9969
|
kind: "page_group",
|
|
9845
9970
|
title: "Endorsements",
|
|
9846
|
-
description: "Endorsement forms grouped by source order",
|
|
9971
|
+
description: descriptionWithPages("Endorsement forms grouped by source order", endorsementGroupChildren),
|
|
9847
9972
|
textExcerpt: void 0,
|
|
9848
9973
|
sourceSpanIds: [],
|
|
9849
9974
|
pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
|
|
@@ -9854,11 +9979,13 @@ function applyEndorsementGrouping(sourceTree) {
|
|
|
9854
9979
|
metadata: { sourceTreeVersion: "v3", organizer: "endorsement_grouping" }
|
|
9855
9980
|
};
|
|
9856
9981
|
const childSpanIds = [...new Set(endorsementGroupChildren.flatMap((child) => child.sourceSpanIds))];
|
|
9982
|
+
const childPageStart = pageStarts.length ? Math.min(...pageStarts) : void 0;
|
|
9983
|
+
const childPageEnd = pageEnds.length ? Math.max(...pageEnds) : void 0;
|
|
9857
9984
|
const normalizedGroup = {
|
|
9858
9985
|
...groupNode,
|
|
9859
9986
|
sourceSpanIds: groupNode.sourceSpanIds.length ? groupNode.sourceSpanIds : childSpanIds,
|
|
9860
|
-
pageStart: groupNode.pageStart
|
|
9861
|
-
pageEnd: groupNode.pageEnd
|
|
9987
|
+
pageStart: childPageStart === void 0 ? groupNode.pageStart : groupNode.pageStart === void 0 ? childPageStart : Math.min(groupNode.pageStart, childPageStart),
|
|
9988
|
+
pageEnd: childPageEnd === void 0 ? groupNode.pageEnd : groupNode.pageEnd === void 0 ? childPageEnd : Math.max(groupNode.pageEnd, childPageEnd),
|
|
9862
9989
|
order
|
|
9863
9990
|
};
|
|
9864
9991
|
groupsByParent.set(parentId, normalizedGroup);
|
|
@@ -9934,10 +10061,6 @@ function organizationBatches(sourceTree) {
|
|
|
9934
10061
|
const candidates = /* @__PURE__ */ new Map();
|
|
9935
10062
|
for (const node of topLevelBatch) {
|
|
9936
10063
|
candidates.set(node.id, node);
|
|
9937
|
-
const childContext = (byParent.get(node.id) ?? []).filter((child) => child.kind !== "text" && child.kind !== "table_cell").slice(0, ORGANIZATION_CHILD_CONTEXT_LIMIT);
|
|
9938
|
-
for (const child of childContext) {
|
|
9939
|
-
candidates.set(child.id, child);
|
|
9940
|
-
}
|
|
9941
10064
|
}
|
|
9942
10065
|
batches.push({
|
|
9943
10066
|
label: `top-level nodes ${index + 1}-${index + topLevelBatch.length} of ${topLevelNodes.length}`,
|
|
@@ -9988,6 +10111,41 @@ Rules:
|
|
|
9988
10111
|
Source nodes:
|
|
9989
10112
|
${JSON.stringify(nodes, null, 2)}
|
|
9990
10113
|
|
|
10114
|
+
Return JSON with labels and groups only.`;
|
|
10115
|
+
}
|
|
10116
|
+
function shouldRunOutlineCleanup(sourceTree) {
|
|
10117
|
+
const topLevel = rootChildren(sourceTree);
|
|
10118
|
+
if (topLevel.length === 0 || topLevel.length > OUTLINE_CLEANUP_MAX_TOP_LEVEL_NODES) return false;
|
|
10119
|
+
const genericPages = topLevel.filter((node) => node.kind === "page" && /^Page\s+\d+$/i.test(node.title));
|
|
10120
|
+
const hasDeclarations = topLevel.some((node) => node.title === "Declarations");
|
|
10121
|
+
const hasPolicyForm = topLevel.some((node) => node.title === "Policy Form");
|
|
10122
|
+
const hasEndorsements = topLevel.some((node) => node.title === "Endorsements");
|
|
10123
|
+
return genericPages.length > 0 || topLevel.length > 6 || !hasDeclarations || !hasPolicyForm || !hasEndorsements;
|
|
10124
|
+
}
|
|
10125
|
+
function buildOutlineCleanupPrompt(sourceTree) {
|
|
10126
|
+
const topLevel = rootChildren(sourceTree).slice(0, OUTLINE_CLEANUP_MAX_TOP_LEVEL_NODES);
|
|
10127
|
+
const nodes = topLevel.map((node) => compactNode(node, 900));
|
|
10128
|
+
return `You clean a top-level source outline for an insurance policy.
|
|
10129
|
+
|
|
10130
|
+
Expected product-facing order:
|
|
10131
|
+
1. Optional front matter: policy jacket, important notices, privacy notices, OFAC notices, TRIA/terrorism notices, marketing/admin pages, signatures, countersignatures, or other pages that are not the declarations, policy wording, or endorsements.
|
|
10132
|
+
2. Declarations: declarations page(s), schedules, named insured/policy period/premium rows, coverage limit schedules, forms-and-endorsements schedules.
|
|
10133
|
+
3. Policy Form: the main policy wording, insuring agreements, definitions, exclusions, conditions, claim provisions, and general policy terms.
|
|
10134
|
+
4. Endorsements: one generic "Endorsements" page_group containing each separately numbered endorsement as its own child.
|
|
10135
|
+
|
|
10136
|
+
Rules:
|
|
10137
|
+
- Use only node IDs from this top-level list: ${JSON.stringify(topLevel.map((node) => node.id))}
|
|
10138
|
+
- Group only adjacent top-level nodes.
|
|
10139
|
+
- Do not invent text, pages, source spans, limits, or policy facts.
|
|
10140
|
+
- Do not merge individually numbered endorsements into one endorsement node; use the generic "Endorsements" parent for the series.
|
|
10141
|
+
- Use canonical terse titles: "Notices and Jacket", "Declarations", "Policy Form", "Endorsements", or the printed endorsement number.
|
|
10142
|
+
- Keep page_group descriptions short and include the page range when pages are known, for example "Declarations pages 6-8".
|
|
10143
|
+
- If a page is an OFAC, privacy, terrorism/TRIA, claim-reporting notice, signature page, or jacket, do not label it as declarations or policy form.
|
|
10144
|
+
- If the existing deterministic outline is already correct, return empty labels and groups.
|
|
10145
|
+
|
|
10146
|
+
Top-level source nodes:
|
|
10147
|
+
${JSON.stringify(nodes, null, 2)}
|
|
10148
|
+
|
|
9991
10149
|
Return JSON with labels and groups only.`;
|
|
9992
10150
|
}
|
|
9993
10151
|
function buildOperationalProfilePrompt(sourceTree, fallback) {
|
|
@@ -10042,7 +10200,7 @@ function applyOrganization(sourceTree, organization) {
|
|
|
10042
10200
|
if (!children.every((child) => child.parentId === parentId)) continue;
|
|
10043
10201
|
const documentId = children[0].documentId;
|
|
10044
10202
|
const title = simplifyOrganizerTitle(group.title, group.title, group.kind);
|
|
10045
|
-
const description = cleanText(group.description, title);
|
|
10203
|
+
const description = descriptionWithPages(cleanText(group.description, title), children);
|
|
10046
10204
|
const id = groupNodeId(documentId, { ...group, title });
|
|
10047
10205
|
if (byId.has(id)) continue;
|
|
10048
10206
|
const sourceSpanIds = [...new Set(children.flatMap((child) => child.sourceSpanIds))];
|
|
@@ -10233,8 +10391,7 @@ async function runSourceTreeExtraction(params) {
|
|
|
10233
10391
|
schema: SourceTreeOrganizationSchema,
|
|
10234
10392
|
maxTokens: budget.maxTokens,
|
|
10235
10393
|
taskKind: "extraction_source_tree",
|
|
10236
|
-
budgetDiagnostics: budget
|
|
10237
|
-
providerOptions: params.providerOptions
|
|
10394
|
+
budgetDiagnostics: budget
|
|
10238
10395
|
},
|
|
10239
10396
|
{
|
|
10240
10397
|
fallback: { labels: [], groups: [] },
|
|
@@ -10256,6 +10413,36 @@ async function runSourceTreeExtraction(params) {
|
|
|
10256
10413
|
} else {
|
|
10257
10414
|
await params.log?.("Deterministic source tree ready; skipped model organizer");
|
|
10258
10415
|
}
|
|
10416
|
+
if (shouldRunOutlineCleanup(sourceTree)) {
|
|
10417
|
+
try {
|
|
10418
|
+
const budget = params.resolveBudget("extraction_source_tree", 1600);
|
|
10419
|
+
const maxTokens = Math.min(budget.maxTokens, 1600);
|
|
10420
|
+
const startedAt = Date.now();
|
|
10421
|
+
const response = await safeGenerateObject(
|
|
10422
|
+
params.generateObject,
|
|
10423
|
+
{
|
|
10424
|
+
prompt: buildOutlineCleanupPrompt(sourceTree),
|
|
10425
|
+
schema: SourceTreeOrganizationSchema,
|
|
10426
|
+
maxTokens,
|
|
10427
|
+
taskKind: "extraction_source_tree",
|
|
10428
|
+
budgetDiagnostics: { ...budget, maxTokens }
|
|
10429
|
+
},
|
|
10430
|
+
{
|
|
10431
|
+
fallback: { labels: [], groups: [] },
|
|
10432
|
+
log: params.log
|
|
10433
|
+
}
|
|
10434
|
+
);
|
|
10435
|
+
localTrack(response.usage, {
|
|
10436
|
+
taskKind: "extraction_source_tree",
|
|
10437
|
+
label: "source_tree_outline_cleanup",
|
|
10438
|
+
maxTokens,
|
|
10439
|
+
durationMs: Date.now() - startedAt
|
|
10440
|
+
});
|
|
10441
|
+
sourceTree = applyOrganization(sourceTree, response.object);
|
|
10442
|
+
} catch (error) {
|
|
10443
|
+
warnings.push(`Source-tree outline cleanup failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
|
|
10444
|
+
}
|
|
10445
|
+
}
|
|
10259
10446
|
const deterministicProfile = buildDeterministicOperationalProfile({
|
|
10260
10447
|
sourceTree,
|
|
10261
10448
|
sourceSpans
|