@claritylabs/cl-sdk 3.1.23 → 3.1.25

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 CHANGED
@@ -9748,46 +9748,6 @@ function applyOperationalProfileCleanup(profile, cleanup, validNodeIds, validSpa
9748
9748
  }
9749
9749
 
9750
9750
  // src/extraction/source-tree-extractor.ts
9751
- var ORGANIZABLE_KINDS = [
9752
- "page_group",
9753
- "form",
9754
- "endorsement",
9755
- "section",
9756
- "schedule",
9757
- "clause"
9758
- ];
9759
- var ORGANIZATION_TOP_LEVEL_BATCH_SIZE = 1;
9760
- var ORGANIZER_MAX_TOP_LEVEL_NODES = 120;
9761
- var ORGANIZER_MAX_BATCH_NODES = 80;
9762
- var OUTLINE_CLEANUP_MAX_TOP_LEVEL_NODES = 80;
9763
- var SourceTreeOrganizationSchema = import_zod42.z.object({
9764
- labels: import_zod42.z.array(import_zod42.z.object({
9765
- nodeId: import_zod42.z.string(),
9766
- kind: import_zod42.z.enum([
9767
- "document",
9768
- "page_group",
9769
- "page",
9770
- "form",
9771
- "endorsement",
9772
- "section",
9773
- "schedule",
9774
- "clause",
9775
- "table",
9776
- "table_row",
9777
- "table_cell",
9778
- "text"
9779
- ]).optional(),
9780
- title: import_zod42.z.string().optional(),
9781
- description: import_zod42.z.string().optional()
9782
- })),
9783
- groups: import_zod42.z.array(import_zod42.z.object({
9784
- kind: import_zod42.z.enum(ORGANIZABLE_KINDS),
9785
- title: import_zod42.z.string(),
9786
- description: import_zod42.z.string().optional(),
9787
- parentNodeId: import_zod42.z.string().optional(),
9788
- childNodeIds: import_zod42.z.array(import_zod42.z.string()).min(1)
9789
- }))
9790
- });
9791
9751
  var SourceBackedValueForPromptSchema = import_zod42.z.object({
9792
9752
  value: import_zod42.z.string(),
9793
9753
  normalizedValue: import_zod42.z.string().optional(),
@@ -9831,17 +9791,6 @@ var OperationalProfilePromptSchema = import_zod42.z.object({
9831
9791
  sourceNodeIds: import_zod42.z.array(import_zod42.z.string()).optional(),
9832
9792
  sourceSpanIds: import_zod42.z.array(import_zod42.z.string()).optional()
9833
9793
  });
9834
- function formatFormHintsForPrompt(forms) {
9835
- const usable = forms.filter((form) => typeof form.pageStart === "number" && typeof form.pageEnd === "number").slice(0, 120).map((form) => ({
9836
- title: form.title,
9837
- formType: form.formType,
9838
- formNumber: form.formNumber,
9839
- editionDate: form.editionDate,
9840
- pageStart: form.pageStart,
9841
- pageEnd: form.pageEnd
9842
- }));
9843
- return usable.length ? JSON.stringify(usable, null, 2) : "[]";
9844
- }
9845
9794
  function cleanText(value, fallback) {
9846
9795
  const text = value?.replace(/\s+/g, " ").trim();
9847
9796
  return text || fallback;
@@ -10384,15 +10333,6 @@ function applySemanticPageGrouping(sourceTree) {
10384
10333
  }
10385
10334
  return applyEndorsementGrouping(normalizeDocumentSourceTreePaths(nextTree));
10386
10335
  }
10387
- function rejectsOrganizerGroup(group, children) {
10388
- if (/^endorsements?\b/i.test(group.title) && group.kind !== "page_group") return true;
10389
- if (group.kind !== "endorsement") return false;
10390
- if (/^endorsements?\s+\d+\s*[–-]\s*\d+\b/i.test(group.title)) return true;
10391
- const childNumbers = new Set(
10392
- children.map((child) => endorsementReference([child.title, child.description, child.textExcerpt].filter(Boolean).join(" "))).filter((value) => Boolean(value))
10393
- );
10394
- return childNumbers.size > 1;
10395
- }
10396
10336
  function isEndorsementGroup(node) {
10397
10337
  return node.kind === "page_group" && /^endorsements?\b/i.test(node.title);
10398
10338
  }
@@ -10456,10 +10396,10 @@ function rootSemanticRank(node) {
10456
10396
  function normalizeRootSemanticOrder(sourceTree) {
10457
10397
  const rootId = sourceTreeRootId(sourceTree);
10458
10398
  if (!rootId) return sourceTree;
10459
- const rootChildren2 = (nodesByParent(sourceTree).get(rootId) ?? []).filter((node) => node.kind !== "document").sort(
10399
+ const rootChildren = (nodesByParent(sourceTree).get(rootId) ?? []).filter((node) => node.kind !== "document").sort(
10460
10400
  (left, right) => rootSemanticRank(left) - rootSemanticRank(right) || (left.pageStart ?? Number.MAX_SAFE_INTEGER) - (right.pageStart ?? Number.MAX_SAFE_INTEGER) || left.order - right.order || left.id.localeCompare(right.id)
10461
10401
  );
10462
- const orderById = new Map(rootChildren2.map((node, index) => [node.id, index + 1]));
10402
+ const orderById = new Map(rootChildren.map((node, index) => [node.id, index + 1]));
10463
10403
  return sourceTree.map((node) => {
10464
10404
  const order = orderById.get(node.id);
10465
10405
  return order === void 0 ? node : { ...node, order };
@@ -10929,174 +10869,6 @@ function nodesByParent(sourceTree) {
10929
10869
  function sourceTreeRootId(sourceTree) {
10930
10870
  return sourceTree.find((node) => node.kind === "document")?.id;
10931
10871
  }
10932
- function rootChildren(sourceTree) {
10933
- const byParent = nodesByParent(sourceTree);
10934
- const rootId = sourceTreeRootId(sourceTree);
10935
- return (byParent.get(rootId) ?? []).filter((node) => node.kind !== "document");
10936
- }
10937
- function shouldRunSourceTreeOrganizer(sourceTree, _sourceSpans) {
10938
- const topLevelCount = rootChildren(sourceTree).length;
10939
- if (topLevelCount > ORGANIZER_MAX_TOP_LEVEL_NODES) return false;
10940
- return true;
10941
- }
10942
- function organizationCandidateText(node) {
10943
- return [node.title, node.description, node.textExcerpt].filter(Boolean).join(" ");
10944
- }
10945
- function isHighSignalOrganizationNode(node) {
10946
- if (node.kind === "document") return false;
10947
- if (["page", "page_group", "form", "endorsement", "section", "schedule", "clause", "table"].includes(node.kind)) {
10948
- return true;
10949
- }
10950
- if (node.kind !== "text" && node.kind !== "table_cell" && node.kind !== "table_row") return false;
10951
- const text = organizationCandidateText(node);
10952
- return /\b(SECTION|PART|ARTICLE|SCHEDULE)\s+[IVXLCDM0-9]+/i.test(text) || /\bItem\s+\d+[\.:]/i.test(text) || /^[A-Z]\.\s+\S/.test(cleanText(node.textExcerpt ?? node.title, "")) || /\b(forms? and endorsements?|coverage parts?|limits? of liability|extended reporting period|producer|premium|aggregate|retroactive date|endorsement no\.?)\b/i.test(text);
10953
- }
10954
- function organizationBatchNodes(topLevelBatch, byParent) {
10955
- const nodes = /* @__PURE__ */ new Map();
10956
- const queue = [...topLevelBatch];
10957
- while (queue.length > 0 && nodes.size < ORGANIZER_MAX_BATCH_NODES) {
10958
- const node = queue.shift();
10959
- if (!node || nodes.has(node.id) || !isHighSignalOrganizationNode(node)) continue;
10960
- nodes.set(node.id, node);
10961
- for (const child of byParent.get(node.id) ?? []) {
10962
- if (nodes.size + queue.length >= ORGANIZER_MAX_BATCH_NODES) break;
10963
- if (isHighSignalOrganizationNode(child)) queue.push(child);
10964
- }
10965
- }
10966
- return [...nodes.values()];
10967
- }
10968
- function organizationBatches(sourceTree) {
10969
- const byParent = nodesByParent(sourceTree);
10970
- const rootId = sourceTreeRootId(sourceTree);
10971
- const topLevelNodes = (byParent.get(rootId) ?? []).filter((node) => node.kind !== "document");
10972
- if (topLevelNodes.length === 0) {
10973
- const nodes = sourceTree.filter((node) => node.kind !== "document").slice(0, ORGANIZER_MAX_BATCH_NODES);
10974
- return [{
10975
- label: "fallback node prefix because no document root children were found",
10976
- topLevelNodeIds: nodes.map((node) => node.id),
10977
- nodes
10978
- }];
10979
- }
10980
- const batches = [];
10981
- for (let index = 0; index < topLevelNodes.length; index += ORGANIZATION_TOP_LEVEL_BATCH_SIZE) {
10982
- const topLevelBatch = topLevelNodes.slice(index, index + ORGANIZATION_TOP_LEVEL_BATCH_SIZE);
10983
- batches.push({
10984
- label: `top-level nodes ${index + 1}-${index + topLevelBatch.length} of ${topLevelNodes.length}`,
10985
- topLevelNodeIds: topLevelBatch.map((node) => node.id),
10986
- nodes: organizationBatchNodes(topLevelBatch, byParent)
10987
- });
10988
- }
10989
- return batches;
10990
- }
10991
- function pageRangeOverlaps(leftStart, leftEnd, rightStart, rightEnd) {
10992
- if (leftStart === void 0 || rightStart === void 0) return true;
10993
- const leftLast = leftEnd ?? leftStart;
10994
- const rightLast = rightEnd ?? rightStart;
10995
- return leftStart <= rightLast && rightStart <= leftLast;
10996
- }
10997
- function formHintsForBatch(batch, formHints) {
10998
- const batchStart = batch.nodes.map((node) => node.pageStart).filter((page) => typeof page === "number").reduce((min, page) => min === void 0 ? page : Math.min(min, page), void 0);
10999
- const batchEnd = batch.nodes.map((node) => node.pageEnd ?? node.pageStart).filter((page) => typeof page === "number").reduce((max, page) => max === void 0 ? page : Math.max(max, page), void 0);
11000
- return formHints.filter((form) => pageRangeOverlaps(batchStart, batchEnd, form.pageStart, form.pageEnd)).slice(0, 24);
11001
- }
11002
- function mergeOrganizationResults(results) {
11003
- const labels = /* @__PURE__ */ new Map();
11004
- const groups = /* @__PURE__ */ new Map();
11005
- for (const result of results) {
11006
- for (const label of result.labels) {
11007
- labels.set(label.nodeId, { ...labels.get(label.nodeId), ...label });
11008
- }
11009
- for (const group of result.groups) {
11010
- const key = `${group.parentNodeId ?? ""}:${group.kind}:${group.childNodeIds.join("|")}`;
11011
- groups.set(key, group);
11012
- }
11013
- }
11014
- return {
11015
- labels: [...labels.values()],
11016
- groups: [...groups.values()]
11017
- };
11018
- }
11019
- function buildOrganizationPrompt(batch, formHints) {
11020
- const nodes = batch.nodes.map((node) => compactNode2(node, node.kind === "page" ? 520 : 260));
11021
- const localFormHints = formHintsForBatch(batch, formHints);
11022
- return `You organize an insurance document source tree.
11023
-
11024
- Scope:
11025
- - ${batch.label}
11026
- - The provided list is a bounded extraction-time batch. It is not necessarily the whole document.
11027
- - Top-level page/form candidates in this batch: ${JSON.stringify(batch.topLevelNodeIds)}
11028
-
11029
- Expected form inventory / page ranges:
11030
- ${formatFormHintsForPrompt(localFormHints)}
11031
-
11032
- Rules:
11033
- - Use only node IDs from the provided list.
11034
- - Do not invent text, page numbers, source spans, limits, or policy facts.
11035
- - You may relabel existing nodes and group adjacent sibling nodes from this batch only when they are clearly one continuous form, one declarations item, one policy section, one schedule, or one clause family.
11036
- - Treat the form inventory as a page-range hint for the expected order: front matter/notices, declarations, policy form, then endorsements.
11037
- - Prefer section hierarchy from printed title elements inside a form over page-by-page grouping.
11038
- - Printed section markers are hard hierarchy boundaries. If source text moves from "SECTION XI" to "SECTION XII", "Section 12", "PART III", or similar sequential headings, create a new sibling section at that marker even when the marker appears mid-page after prior section text.
11039
- - Declarations pages often use "Item 1.", "Item 2.", ... as the real section structure. Preserve each item as its own section or schedule under "Declarations"; do not bury item labels inside a single table when they mark new declaration fields.
11040
- - For declaration item tables, a table belongs only to the current item until the next "Item N" marker. Start a new declaration item section at the next marker, even if the parser presents the marker as a table row or cell.
11041
- - Keep forms-and-endorsements schedules attached to declarations when they appear as "Item 10", "Forms and Endorsements Attached at Inception", or a continuation page listing form numbers. Do not discard that page just because it also contains countersignature or authorized-representative language.
11042
- - Prefer sections/schedules over table grouping when a table-like node mixes structural labels such as "Item 7", "Item 8", "SECTION XII", "Producer", or "Forms and Endorsements" with values.
11043
- - Use group.parentNodeId only when the source clearly shows a child was nested under the wrong earlier section/table. Example: a "SECTION XII" marker nested below "SECTION XI" should be grouped with parentNodeId set to the Policy Form node so Section XII becomes a sibling of Section XI.
11044
- - Use group.parentNodeId to place "Item N" groups under the Declarations node when parser table structure would otherwise leave those items trapped inside one table.
11045
- - Group adjacent separately numbered endorsements under a single generic "Endorsements" page_group parent, with each individual endorsement preserved as its own child node.
11046
- - Never create rollup titles such as "Endorsements 1-3 (...)" or merge multiple endorsements into one endorsement node.
11047
- - Add concise, human-readable titles to generic text, table, row, and cell nodes when the text makes their role clear.
11048
- - 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.
11049
- - Groups must list existing childNodeIds only.
11050
- - Keep descriptions short and useful for search.
11051
- - Prefer the document's own form titles, endorsement titles, schedules, declarations headings, and page order over keyword-only guessing.
11052
-
11053
- Source nodes:
11054
- ${JSON.stringify(nodes, null, 2)}
11055
-
11056
- Return JSON with labels and groups only.`;
11057
- }
11058
- function shouldRunOutlineCleanup(sourceTree) {
11059
- const topLevel = rootChildren(sourceTree);
11060
- if (topLevel.length === 0 || topLevel.length > OUTLINE_CLEANUP_MAX_TOP_LEVEL_NODES) return false;
11061
- const genericPages = topLevel.filter((node) => node.kind === "page" && /^Page\s+\d+$/i.test(node.title));
11062
- const hasDeclarations = topLevel.some((node) => node.title === "Declarations");
11063
- const hasPolicyForm = topLevel.some((node) => node.title === "Policy Form");
11064
- const hasEndorsements = topLevel.some((node) => node.title === "Endorsements");
11065
- if (hasDeclarations && hasPolicyForm && hasEndorsements) return false;
11066
- return genericPages.length > 0 || topLevel.length > 6 || !hasDeclarations || !hasPolicyForm || !hasEndorsements;
11067
- }
11068
- function buildOutlineCleanupPrompt(sourceTree, formHints) {
11069
- const topLevel = rootChildren(sourceTree).slice(0, OUTLINE_CLEANUP_MAX_TOP_LEVEL_NODES);
11070
- const nodes = topLevel.map((node) => compactNode2(node, 900));
11071
- return `You clean a top-level source outline for an insurance policy.
11072
-
11073
- Expected product-facing order:
11074
- 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.
11075
- 2. Declarations: declarations page(s), schedules, itemized declaration fields, named insured/policy period/premium rows, coverage limit schedules, forms-and-endorsements schedules.
11076
- 3. Policy Form: the main policy wording, insuring agreements, definitions, exclusions, conditions, claim provisions, and general policy terms.
11077
- 4. Endorsements: one generic "Endorsements" page_group containing each separately numbered endorsement as its own child.
11078
-
11079
- Expected form inventory / page ranges:
11080
- ${formatFormHintsForPrompt(formHints)}
11081
-
11082
- Rules:
11083
- - Use only node IDs from this top-level list: ${JSON.stringify(topLevel.map((node) => node.id))}
11084
- - Group only adjacent top-level nodes.
11085
- - Do not invent text, pages, source spans, limits, or policy facts.
11086
- - Do not merge individually numbered endorsements into one endorsement node; use the generic "Endorsements" parent for the series.
11087
- - Use canonical terse titles: "Notices and Jacket", "Declarations", "Policy Form", "Endorsements", or the printed endorsement number.
11088
- - Keep page_group descriptions short and include the page range when pages are known, for example "Declarations pages 6-8".
11089
- - If a page is only an OFAC, privacy, terrorism/TRIA, claim-reporting notice, signature page, or jacket, do not label it as declarations or policy form.
11090
- - If a page contains declaration items, coverage schedules, premium rows, producer rows, or a forms-and-endorsements schedule, keep it in Declarations even if it also contains countersignature or authorized-representative text.
11091
- - If a policy-form page contains a later printed section marker such as "SECTION XII \u2014 EXTENDED REPORTING PERIOD", preserve that marker as the start of a new sibling section rather than a paragraph under the previous section.
11092
- - If the form inventory provides page ranges, keep groups aligned to those ranges unless the source node text clearly contradicts them.
11093
- - If the existing deterministic outline is already correct, return empty labels and groups.
11094
-
11095
- Top-level source nodes:
11096
- ${JSON.stringify(nodes, null, 2)}
11097
-
11098
- Return JSON with labels and groups only.`;
11099
- }
11100
10872
  function operationalProfilePromptNodes(sourceTree) {
11101
10873
  return sourceTree.filter((node) => node.kind !== "document").filter((node) => {
11102
10874
  if (["page_group", "form", "endorsement", "schedule", "table", "table_row", "table_cell"].includes(node.kind)) {
@@ -11152,147 +10924,6 @@ ${JSON.stringify(nodes, null, 2)}
11152
10924
 
11153
10925
  Return JSON for the operational profile.`;
11154
10926
  }
11155
- function tableCellValueText(cell) {
11156
- return cleanText(cell.textExcerpt ?? cell.description ?? "", "");
11157
- }
11158
- function tableRowTextFromCells(cells) {
11159
- const text = cells.map((cell) => {
11160
- const label = cleanText(cell.title, "");
11161
- const value = tableCellValueText(cell);
11162
- if (!value) return label;
11163
- if (!label || value.toLowerCase() === label.toLowerCase()) return value;
11164
- return `${label}: ${value}`;
11165
- }).filter(Boolean).join(" | ");
11166
- return text ? cleanText(text, text) : void 0;
11167
- }
11168
- function normalizeTableBoundaryDelimiters(value) {
11169
- const text = cleanText(value, "");
11170
- if (!text) return void 0;
11171
- const normalized = text.replace(/\s+\|\s+\|/g, " | ").replace(/\s+\/\s+\|/g, " |").replace(/\s+[|/]\s*$/g, "").replace(/\s{2,}/g, " ").trim();
11172
- return normalized || void 0;
11173
- }
11174
- function normalizeSourceTreeTableDisplayText(sourceTree) {
11175
- const byParent = nodesByParent(sourceTree);
11176
- const updates = /* @__PURE__ */ new Map();
11177
- const currentNode = (node) => updates.get(node.id) ?? node;
11178
- for (const node of sourceTree) {
11179
- if (node.kind !== "table_cell") continue;
11180
- const textExcerpt = normalizeTableBoundaryDelimiters(node.textExcerpt);
11181
- const textChanged = textExcerpt !== void 0 && textExcerpt !== node.textExcerpt;
11182
- const description = textChanged && textExcerpt ? normalizeTableBoundaryDelimiters([node.title, textExcerpt].filter(Boolean).join(" | ")) : normalizeTableBoundaryDelimiters(node.description);
11183
- if (textExcerpt === node.textExcerpt && description === node.description) continue;
11184
- updates.set(node.id, {
11185
- ...node,
11186
- ...textExcerpt !== void 0 ? { textExcerpt } : {},
11187
- ...description !== void 0 ? { description } : {}
11188
- });
11189
- }
11190
- for (const node of sourceTree) {
11191
- if (node.kind !== "table_row") continue;
11192
- const cells = (byParent.get(node.id) ?? []).filter((child) => child.kind === "table_cell").map(currentNode).sort(
11193
- (left, right) => tableCellColumnIndex(left, 0) - tableCellColumnIndex(right, 0) || left.order - right.order || left.id.localeCompare(right.id)
11194
- );
11195
- const textExcerpt = cells.length ? tableRowTextFromCells(cells) : normalizeTableBoundaryDelimiters(node.textExcerpt);
11196
- const textChanged = textExcerpt !== void 0 && textExcerpt !== node.textExcerpt;
11197
- const description = textChanged && textExcerpt ? normalizeTableBoundaryDelimiters([node.title, textExcerpt].filter(Boolean).join(" | ")) : normalizeTableBoundaryDelimiters(node.description);
11198
- if (textExcerpt === node.textExcerpt && description === node.description) continue;
11199
- updates.set(node.id, {
11200
- ...node,
11201
- ...textExcerpt !== void 0 ? { textExcerpt } : {},
11202
- ...description !== void 0 ? { description } : {}
11203
- });
11204
- }
11205
- if (updates.size === 0) return sourceTree;
11206
- return sourceTree.map((node) => updates.get(node.id) ?? node);
11207
- }
11208
- function tableCellColumnIndex(cell, fallbackIndex) {
11209
- const metadataIndex = cell.metadata?.columnIndex;
11210
- return typeof metadataIndex === "number" && Number.isInteger(metadataIndex) ? metadataIndex : fallbackIndex;
11211
- }
11212
- function groupNodeId(documentId, group) {
11213
- return [
11214
- documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
11215
- "source_node",
11216
- group.kind,
11217
- group.childNodeIds.join("_").replace(/[^a-zA-Z0-9_.:-]/g, "_").slice(0, 80)
11218
- ].join(":");
11219
- }
11220
- function isDescendantOf(nodeId2, ancestorId, byId) {
11221
- let parentId = nodeId2 ? byId.get(nodeId2)?.parentId : void 0;
11222
- const seen = /* @__PURE__ */ new Set();
11223
- while (parentId) {
11224
- if (parentId === ancestorId) return true;
11225
- if (seen.has(parentId)) return false;
11226
- seen.add(parentId);
11227
- parentId = byId.get(parentId)?.parentId;
11228
- }
11229
- return false;
11230
- }
11231
- function applyOrganization(sourceTree, organization) {
11232
- const byId = new Map(sourceTree.map((node) => [node.id, node]));
11233
- const labels = new Map(organization.labels.map((label) => [label.nodeId, label]));
11234
- let nextTree = sourceTree.map((node) => {
11235
- const label = labels.get(node.id);
11236
- if (!label) return node;
11237
- return {
11238
- ...node,
11239
- kind: label.kind ?? node.kind,
11240
- title: simplifyOrganizerTitle(label.title, node.title, label.kind ?? node.kind),
11241
- description: cleanText(label.description, node.description)
11242
- };
11243
- });
11244
- for (const group of organization.groups) {
11245
- const children = group.childNodeIds.map((id2) => byId.get(id2)).filter((node2) => Boolean(node2));
11246
- if (children.length === 0) continue;
11247
- if (rejectsOrganizerGroup(group, children)) continue;
11248
- const originalParentId = children[0].parentId;
11249
- const requestedParent = group.parentNodeId ? byId.get(group.parentNodeId) : void 0;
11250
- if (requestedParent && children.some((child) => child.id === requestedParent.id || isDescendantOf(requestedParent.id, child.id, byId))) {
11251
- continue;
11252
- }
11253
- if (requestedParent) {
11254
- if (!children.every((child) => child.parentId === requestedParent.id || hasAncestor(child, requestedParent.id, byId))) {
11255
- continue;
11256
- }
11257
- } else if (!children.every((child) => child.parentId === originalParentId)) {
11258
- continue;
11259
- }
11260
- const parentId = requestedParent?.id ?? originalParentId;
11261
- const documentId = children[0].documentId;
11262
- const title = simplifyOrganizerTitle(group.title, group.title, group.kind);
11263
- const description = descriptionWithPages(cleanText(group.description, title), children);
11264
- const id = groupNodeId(documentId, { ...group, title });
11265
- if (byId.has(id)) continue;
11266
- const sourceSpanIds = [...new Set(children.flatMap((child) => child.sourceSpanIds))];
11267
- const pageStarts = children.map((child) => child.pageStart).filter((page) => typeof page === "number");
11268
- const pageEnds = children.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
11269
- const order = Math.min(...children.map((child) => child.order));
11270
- const node = {
11271
- id,
11272
- documentId,
11273
- parentId,
11274
- kind: group.kind,
11275
- title,
11276
- description,
11277
- textExcerpt: children.map((child) => child.textExcerpt ?? child.description).filter(Boolean).join("\n\n").slice(0, 1600),
11278
- sourceSpanIds,
11279
- pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
11280
- pageEnd: pageEnds.length ? Math.max(...pageEnds) : void 0,
11281
- bbox: children.flatMap((child) => child.bbox ?? []).slice(0, 12),
11282
- order,
11283
- path: "",
11284
- metadata: { sourceTreeVersion: "v3", organizer: "llm_group" }
11285
- };
11286
- nextTree = [
11287
- ...nextTree.map(
11288
- (child) => group.childNodeIds.includes(child.id) ? { ...child, parentId: id, order: child.order + 1e-3 } : child
11289
- ),
11290
- node
11291
- ];
11292
- byId.set(id, node);
11293
- }
11294
- return applyEndorsementGrouping(normalizeDocumentSourceTreePaths(nextTree));
11295
- }
11296
10927
  function sourceTreeToOutline(sourceTree) {
11297
10928
  const byParent = /* @__PURE__ */ new Map();
11298
10929
  for (const node of sourceTree.filter((item) => item.kind !== "document")) {
@@ -11539,94 +11170,6 @@ async function runSourceTreeExtraction(params) {
11539
11170
  }
11540
11171
  params.trackUsage(usage, report);
11541
11172
  };
11542
- if (shouldRunSourceTreeOrganizer(sourceTree, sourceSpans)) {
11543
- try {
11544
- const batches = organizationBatches(sourceTree);
11545
- const organizationResults = await Promise.all(batches.map(async (batch, batchIndex) => {
11546
- const label = batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer";
11547
- const budget = params.resolveBudget("extraction_source_tree", 4096);
11548
- const startedAt = Date.now();
11549
- const response = await safeGenerateObject(
11550
- params.generateObject,
11551
- {
11552
- prompt: buildOrganizationPrompt(batch, formHints),
11553
- schema: SourceTreeOrganizationSchema,
11554
- maxTokens: budget.maxTokens,
11555
- taskKind: "extraction_source_tree",
11556
- budgetDiagnostics: budget,
11557
- trace: {
11558
- label,
11559
- batchIndex: batchIndex + 1,
11560
- batchCount: batches.length,
11561
- sourceBacked: true
11562
- }
11563
- },
11564
- {
11565
- fallback: { labels: [], groups: [] },
11566
- maxRetries: 0,
11567
- log: params.log,
11568
- retry: false
11569
- }
11570
- );
11571
- return {
11572
- batchIndex,
11573
- label,
11574
- budget,
11575
- durationMs: Date.now() - startedAt,
11576
- usage: response.usage,
11577
- organization: response.object
11578
- };
11579
- }));
11580
- const organizations = [];
11581
- for (const result of organizationResults.sort((left, right) => left.batchIndex - right.batchIndex)) {
11582
- localTrack(result.usage, {
11583
- taskKind: "extraction_source_tree",
11584
- label: result.label,
11585
- maxTokens: result.budget.maxTokens,
11586
- durationMs: result.durationMs
11587
- });
11588
- organizations.push(result.organization);
11589
- }
11590
- sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
11591
- } catch (error) {
11592
- warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
11593
- }
11594
- } else {
11595
- await params.log?.("Deterministic source tree ready; skipped model organizer");
11596
- }
11597
- if (shouldRunOutlineCleanup(sourceTree)) {
11598
- try {
11599
- const budget = params.resolveBudget("extraction_source_tree", 1600);
11600
- const maxTokens = Math.min(budget.maxTokens, 1600);
11601
- const startedAt = Date.now();
11602
- const response = await safeGenerateObject(
11603
- params.generateObject,
11604
- {
11605
- prompt: buildOutlineCleanupPrompt(sourceTree, formHints),
11606
- schema: SourceTreeOrganizationSchema,
11607
- maxTokens,
11608
- taskKind: "extraction_source_tree",
11609
- budgetDiagnostics: { ...budget, maxTokens }
11610
- },
11611
- {
11612
- fallback: { labels: [], groups: [] },
11613
- maxRetries: 0,
11614
- log: params.log,
11615
- retry: false
11616
- }
11617
- );
11618
- localTrack(response.usage, {
11619
- taskKind: "extraction_source_tree",
11620
- label: "source_tree_outline_cleanup",
11621
- maxTokens,
11622
- durationMs: Date.now() - startedAt
11623
- });
11624
- sourceTree = applyOrganization(sourceTree, response.object);
11625
- } catch (error) {
11626
- warnings.push(`Source-tree outline cleanup failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
11627
- }
11628
- }
11629
- sourceTree = normalizeSourceTreeTableDisplayText(sourceTree);
11630
11173
  const emptyProfile = emptyOperationalProfile();
11631
11174
  let operationalProfile = emptyProfile;
11632
11175
  try {