@claritylabs/cl-sdk 3.0.2 → 3.0.4
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.d.mts +12 -11
- package/dist/index.d.ts +12 -11
- package/dist/index.js +230 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +229 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2301,9 +2301,117 @@ function chunkSourceSpans(spans, options = {}) {
|
|
|
2301
2301
|
flush();
|
|
2302
2302
|
return chunks;
|
|
2303
2303
|
}
|
|
2304
|
+
function normalizeSourceSpans(spans) {
|
|
2305
|
+
const droppedParentSpanIds = /* @__PURE__ */ new Set();
|
|
2306
|
+
const cleaned = [];
|
|
2307
|
+
for (const [index, span] of spans.entries()) {
|
|
2308
|
+
if (span.parentSpanId && droppedParentSpanIds.has(span.parentSpanId)) continue;
|
|
2309
|
+
const normalized = normalizeSourceSpanText(span);
|
|
2310
|
+
if (!normalized) {
|
|
2311
|
+
droppedParentSpanIds.add(span.id);
|
|
2312
|
+
continue;
|
|
2313
|
+
}
|
|
2314
|
+
cleaned.push({ ...normalized, __originalIndex: index });
|
|
2315
|
+
}
|
|
2316
|
+
return mergeTextRuns(cleaned).map(({ __originalIndex: _index, ...span }) => span);
|
|
2317
|
+
}
|
|
2304
2318
|
function sourceUnit(span) {
|
|
2305
2319
|
return span.sourceUnit ?? span.metadata?.sourceUnit;
|
|
2306
2320
|
}
|
|
2321
|
+
function spanPage(span) {
|
|
2322
|
+
return span.pageStart ?? span.location?.page ?? span.location?.startPage;
|
|
2323
|
+
}
|
|
2324
|
+
function normalizeSourceSpanText(span) {
|
|
2325
|
+
const unit = sourceUnit(span);
|
|
2326
|
+
const text = normalizeWhitespace(span.text);
|
|
2327
|
+
if (!text) return void 0;
|
|
2328
|
+
if (isDiscardableBoilerplate(text, unit)) return void 0;
|
|
2329
|
+
const cleanedText = cleanBoilerplateLines(text);
|
|
2330
|
+
if (!cleanedText) return void 0;
|
|
2331
|
+
if (cleanedText === text) return span;
|
|
2332
|
+
return retextSpan(span, cleanedText, {
|
|
2333
|
+
boilerplateRemoved: "true",
|
|
2334
|
+
removedBoilerplateText: removedBoilerplateLines(text).join(" | ").slice(0, 500)
|
|
2335
|
+
});
|
|
2336
|
+
}
|
|
2337
|
+
function isDiscardableBoilerplate(text, unit) {
|
|
2338
|
+
const cleaned = normalizeWhitespace(text.replace(/\bColumn\s+\d+:\s*/gi, ""));
|
|
2339
|
+
if (/^SPECIMEN POLICY\s+[-—]\s+FOR TESTING ONLY$/i.test(cleaned)) return true;
|
|
2340
|
+
if (/^Page\s+\d+\s+of\s+\d+$/i.test(cleaned)) return true;
|
|
2341
|
+
if (/^[A-Z]{2,}(?:-[A-Z0-9]{2,})+\s+\d{2}\s+\d{2}$/i.test(cleaned)) return true;
|
|
2342
|
+
if (/^[A-Z]{2,}(?:-[A-Z0-9]{2,})+\s+\d{2}\s+\d{2}\s*\|\s*Page\s+\d+\s+of\s+\d+$/i.test(cleaned)) return true;
|
|
2343
|
+
if (unit === "table_row" && /^[^|]{0,40}\|\s*Page\s+\d+\s+of\s+\d+$/i.test(cleaned)) return true;
|
|
2344
|
+
return false;
|
|
2345
|
+
}
|
|
2346
|
+
function isBoilerplateLine(line) {
|
|
2347
|
+
const cleaned = normalizeWhitespace(line.replace(/\bColumn\s+\d+:\s*/gi, ""));
|
|
2348
|
+
return isDiscardableBoilerplate(cleaned) || /^IMPORTANT NOTICE\s*[-—]\s*/i.test(cleaned) || /^THIS IS A CLAIMS-MADE AND REPORTED POLICY\.? PLEASE READ IT CAREFULLY\.?$/i.test(cleaned);
|
|
2349
|
+
}
|
|
2350
|
+
function removedBoilerplateLines(text) {
|
|
2351
|
+
return text.split(/\s{2,}|\r?\n/).map(normalizeWhitespace).filter((line) => line && isBoilerplateLine(line));
|
|
2352
|
+
}
|
|
2353
|
+
function cleanBoilerplateLines(text) {
|
|
2354
|
+
const withoutInlineBoilerplate = text.replace(/\b(?:Column\s+\d+:\s*)?[A-Z]{2,}(?:-[A-Z0-9]{2,})+\s+\d{2}\s+\d{2}\s+(?:\|\s*)?(?:Column\s+\d+:\s*)?Page\s+\d+\s+of\s+\d+\b/gi, " ").replace(/\bSPECIMEN POLICY\s+[-—]\s+FOR TESTING ONLY\b/gi, " ").replace(/\bPage\s+\d+\s+of\s+\d+\b/gi, " ");
|
|
2355
|
+
const lines = withoutInlineBoilerplate.split(/\r?\n/);
|
|
2356
|
+
const filtered = lines.map(normalizeWhitespace).filter((line) => line && !isBoilerplateLine(line));
|
|
2357
|
+
return normalizeWhitespace(filtered.join(" "));
|
|
2358
|
+
}
|
|
2359
|
+
function shouldMergeTextSpan(left, right) {
|
|
2360
|
+
if (sourceUnit(left) !== "text" || sourceUnit(right) !== "text") return false;
|
|
2361
|
+
if (spanPage(left) !== spanPage(right)) return false;
|
|
2362
|
+
if (left.metadata?.elementType === "title" || right.metadata?.elementType === "title") return false;
|
|
2363
|
+
const leftText = normalizeWhitespace(left.text);
|
|
2364
|
+
const rightText = normalizeWhitespace(right.text);
|
|
2365
|
+
if (!leftText || !rightText) return false;
|
|
2366
|
+
if (/[:.;!?)]$/.test(leftText)) return false;
|
|
2367
|
+
if (/^(?:[A-Z][A-Z0-9 &/(),.-]{8,}|Item\s+\d+|Section\s+\d+|Part\s+[A-Z]\b)/.test(rightText)) return false;
|
|
2368
|
+
return /^[a-z(]/.test(rightText) || /\b(?:a|an|and|any|as|at|by|for|from|in|into|may|must|of|or|that|the|this|to|with|within|you|your)$/i.test(leftText);
|
|
2369
|
+
}
|
|
2370
|
+
function mergeTextRuns(spans) {
|
|
2371
|
+
const result = [];
|
|
2372
|
+
let current;
|
|
2373
|
+
for (const span of spans) {
|
|
2374
|
+
if (current && shouldMergeTextSpan(current, span)) {
|
|
2375
|
+
current = mergeTextSpanPair(current, span);
|
|
2376
|
+
continue;
|
|
2377
|
+
}
|
|
2378
|
+
if (current) result.push(current);
|
|
2379
|
+
current = span;
|
|
2380
|
+
}
|
|
2381
|
+
if (current) result.push(current);
|
|
2382
|
+
return result;
|
|
2383
|
+
}
|
|
2384
|
+
function mergeTextSpanPair(left, right) {
|
|
2385
|
+
const text = normalizeWhitespace(`${left.text} ${right.text}`);
|
|
2386
|
+
const merged = retextSpan(left, text, {
|
|
2387
|
+
mergedSourceSpanIds: [left.metadata?.mergedSourceSpanIds, left.id, right.id, right.metadata?.mergedSourceSpanIds].filter(Boolean).join(","),
|
|
2388
|
+
sourceSpanNormalization: "merged_text_run"
|
|
2389
|
+
});
|
|
2390
|
+
return {
|
|
2391
|
+
...merged,
|
|
2392
|
+
bbox: [...left.bbox ?? [], ...right.bbox ?? []],
|
|
2393
|
+
pageEnd: right.pageEnd ?? left.pageEnd,
|
|
2394
|
+
location: {
|
|
2395
|
+
...left.location,
|
|
2396
|
+
endPage: right.location?.endPage ?? right.pageEnd ?? left.location?.endPage
|
|
2397
|
+
},
|
|
2398
|
+
__originalIndex: left.__originalIndex
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
function retextSpan(span, text, metadata) {
|
|
2402
|
+
const textHash = sourceSpanTextHash(text);
|
|
2403
|
+
return SourceSpanSchema.parse({
|
|
2404
|
+
...span,
|
|
2405
|
+
id: `${span.id.split(":").slice(0, -1).join(":")}:${textHash.slice(0, 12)}`,
|
|
2406
|
+
text,
|
|
2407
|
+
hash: textHash,
|
|
2408
|
+
textHash,
|
|
2409
|
+
metadata: {
|
|
2410
|
+
...span.metadata ?? {},
|
|
2411
|
+
...metadata
|
|
2412
|
+
}
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2307
2415
|
function filterChunkableSourceSpans(spans) {
|
|
2308
2416
|
const rowIds = new Set(
|
|
2309
2417
|
spans.filter((span) => sourceUnit(span) === "table_row").map((span) => span.id)
|
|
@@ -4060,14 +4168,14 @@ function stringArray(value) {
|
|
|
4060
4168
|
function sourceUnit4(span) {
|
|
4061
4169
|
return span.sourceUnit ?? span.metadata?.sourceUnit;
|
|
4062
4170
|
}
|
|
4063
|
-
function
|
|
4171
|
+
function spanPage2(span) {
|
|
4064
4172
|
return span.pageStart ?? span.location?.page ?? span.location?.startPage;
|
|
4065
4173
|
}
|
|
4066
4174
|
function spanPageEnd(span) {
|
|
4067
|
-
return span.pageEnd ?? span.location?.endPage ??
|
|
4175
|
+
return span.pageEnd ?? span.location?.endPage ?? spanPage2(span);
|
|
4068
4176
|
}
|
|
4069
4177
|
function sourceSpansForPage(sourceSpans, page) {
|
|
4070
|
-
return sourceSpans.filter((span) =>
|
|
4178
|
+
return sourceSpans.filter((span) => spanPage2(span) === page && sourceUnit4(span) === "page").map((span) => span.id);
|
|
4071
4179
|
}
|
|
4072
4180
|
function nodePageOverlaps(node, record) {
|
|
4073
4181
|
const recordStart = numberValue(record, "pageNumber", "pageStart", "resolvedFromPage");
|
|
@@ -4168,8 +4276,8 @@ function buildNodesFromSourceSpans(sourceSpans) {
|
|
|
4168
4276
|
const unit = sourceUnit4(span);
|
|
4169
4277
|
return unit === "section" || unit === "section_candidate" || unit === "page";
|
|
4170
4278
|
});
|
|
4171
|
-
return candidates.sort((left, right) => (
|
|
4172
|
-
const title = span.sectionId ?? span.formNumber ?? (sourceUnit4(span) === "page" &&
|
|
4279
|
+
return candidates.sort((left, right) => (spanPage2(left) ?? 0) - (spanPage2(right) ?? 0) || left.id.localeCompare(right.id)).map((span, index) => {
|
|
4280
|
+
const title = span.sectionId ?? span.formNumber ?? (sourceUnit4(span) === "page" && spanPage2(span) ? `Page ${spanPage2(span)}` : `Source unit ${index + 1}`);
|
|
4173
4281
|
return {
|
|
4174
4282
|
id: `source:${index}:${slugPart(span.id)}`,
|
|
4175
4283
|
title,
|
|
@@ -4177,7 +4285,7 @@ function buildNodesFromSourceSpans(sourceSpans) {
|
|
|
4177
4285
|
type: sourceUnit4(span),
|
|
4178
4286
|
label: sourceUnit4(span),
|
|
4179
4287
|
level: 1,
|
|
4180
|
-
pageStart:
|
|
4288
|
+
pageStart: spanPage2(span),
|
|
4181
4289
|
pageEnd: spanPageEnd(span),
|
|
4182
4290
|
formNumber: span.formNumber,
|
|
4183
4291
|
excerpt: span.text.slice(0, 500),
|
|
@@ -8890,6 +8998,8 @@ var ORGANIZABLE_KINDS = [
|
|
|
8890
8998
|
"schedule",
|
|
8891
8999
|
"clause"
|
|
8892
9000
|
];
|
|
9001
|
+
var ORGANIZATION_TOP_LEVEL_BATCH_SIZE = 80;
|
|
9002
|
+
var ORGANIZATION_CHILD_CONTEXT_LIMIT = 4;
|
|
8893
9003
|
var SourceTreeOrganizationSchema = z41.object({
|
|
8894
9004
|
labels: z41.array(z41.object({
|
|
8895
9005
|
nodeId: z41.string(),
|
|
@@ -8954,7 +9064,7 @@ function cleanText(value, fallback) {
|
|
|
8954
9064
|
const text = value?.replace(/\s+/g, " ").trim();
|
|
8955
9065
|
return text || fallback;
|
|
8956
9066
|
}
|
|
8957
|
-
function compactNode(node) {
|
|
9067
|
+
function compactNode(node, maxText = 700) {
|
|
8958
9068
|
return {
|
|
8959
9069
|
id: node.id,
|
|
8960
9070
|
kind: node.kind,
|
|
@@ -8963,20 +9073,89 @@ function compactNode(node) {
|
|
|
8963
9073
|
pageStart: node.pageStart,
|
|
8964
9074
|
pageEnd: node.pageEnd,
|
|
8965
9075
|
sourceSpanIds: node.sourceSpanIds.slice(0, 8),
|
|
8966
|
-
text: (node.textExcerpt ?? node.description).slice(0,
|
|
9076
|
+
text: (node.textExcerpt ?? node.description).slice(0, maxText)
|
|
8967
9077
|
};
|
|
8968
9078
|
}
|
|
8969
|
-
function
|
|
8970
|
-
const
|
|
9079
|
+
function nodesByParent(sourceTree) {
|
|
9080
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
9081
|
+
for (const node of sourceTree) {
|
|
9082
|
+
const children = byParent.get(node.parentId) ?? [];
|
|
9083
|
+
children.push(node);
|
|
9084
|
+
byParent.set(node.parentId, children);
|
|
9085
|
+
}
|
|
9086
|
+
for (const children of byParent.values()) {
|
|
9087
|
+
children.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
|
|
9088
|
+
}
|
|
9089
|
+
return byParent;
|
|
9090
|
+
}
|
|
9091
|
+
function sourceTreeRootId(sourceTree) {
|
|
9092
|
+
return sourceTree.find((node) => node.kind === "document")?.id;
|
|
9093
|
+
}
|
|
9094
|
+
function organizationBatches(sourceTree) {
|
|
9095
|
+
const byParent = nodesByParent(sourceTree);
|
|
9096
|
+
const rootId = sourceTreeRootId(sourceTree);
|
|
9097
|
+
const topLevelNodes = (byParent.get(rootId) ?? []).filter((node) => node.kind !== "document");
|
|
9098
|
+
if (topLevelNodes.length === 0) {
|
|
9099
|
+
const nodes = sourceTree.filter((node) => node.kind !== "document").slice(0, 240);
|
|
9100
|
+
return [{
|
|
9101
|
+
label: "fallback node prefix because no document root children were found",
|
|
9102
|
+
topLevelNodeIds: nodes.map((node) => node.id),
|
|
9103
|
+
nodes
|
|
9104
|
+
}];
|
|
9105
|
+
}
|
|
9106
|
+
const batches = [];
|
|
9107
|
+
for (let index = 0; index < topLevelNodes.length; index += ORGANIZATION_TOP_LEVEL_BATCH_SIZE) {
|
|
9108
|
+
const topLevelBatch = topLevelNodes.slice(index, index + ORGANIZATION_TOP_LEVEL_BATCH_SIZE);
|
|
9109
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
9110
|
+
for (const node of topLevelBatch) {
|
|
9111
|
+
candidates.set(node.id, node);
|
|
9112
|
+
const childContext = (byParent.get(node.id) ?? []).filter((child) => child.kind !== "text" && child.kind !== "table_cell").slice(0, ORGANIZATION_CHILD_CONTEXT_LIMIT);
|
|
9113
|
+
for (const child of childContext) {
|
|
9114
|
+
candidates.set(child.id, child);
|
|
9115
|
+
}
|
|
9116
|
+
}
|
|
9117
|
+
batches.push({
|
|
9118
|
+
label: `top-level nodes ${index + 1}-${index + topLevelBatch.length} of ${topLevelNodes.length}`,
|
|
9119
|
+
topLevelNodeIds: topLevelBatch.map((node) => node.id),
|
|
9120
|
+
nodes: [...candidates.values()]
|
|
9121
|
+
});
|
|
9122
|
+
}
|
|
9123
|
+
return batches;
|
|
9124
|
+
}
|
|
9125
|
+
function mergeOrganizationResults(results) {
|
|
9126
|
+
const labels = /* @__PURE__ */ new Map();
|
|
9127
|
+
const groups = /* @__PURE__ */ new Map();
|
|
9128
|
+
for (const result of results) {
|
|
9129
|
+
for (const label of result.labels) {
|
|
9130
|
+
labels.set(label.nodeId, { ...labels.get(label.nodeId), ...label });
|
|
9131
|
+
}
|
|
9132
|
+
for (const group of result.groups) {
|
|
9133
|
+
const key = `${group.kind}:${group.childNodeIds.join("|")}`;
|
|
9134
|
+
groups.set(key, group);
|
|
9135
|
+
}
|
|
9136
|
+
}
|
|
9137
|
+
return {
|
|
9138
|
+
labels: [...labels.values()],
|
|
9139
|
+
groups: [...groups.values()]
|
|
9140
|
+
};
|
|
9141
|
+
}
|
|
9142
|
+
function buildOrganizationPrompt(batch) {
|
|
9143
|
+
const nodes = batch.nodes.map((node) => compactNode(node, node.kind === "page" ? 900 : 320));
|
|
8971
9144
|
return `You organize an insurance document source tree.
|
|
8972
9145
|
|
|
9146
|
+
Scope:
|
|
9147
|
+
- ${batch.label}
|
|
9148
|
+
- The provided list is a bounded extraction-time batch. It is not necessarily the whole document.
|
|
9149
|
+
- Top-level page/form candidates in this batch: ${JSON.stringify(batch.topLevelNodeIds)}
|
|
9150
|
+
|
|
8973
9151
|
Rules:
|
|
8974
9152
|
- Use only node IDs from the provided list.
|
|
8975
9153
|
- Do not invent text, page numbers, source spans, limits, or policy facts.
|
|
8976
|
-
- You may relabel existing nodes and group adjacent top-level/page nodes when they are clearly one form, endorsement, declarations set, schedule, or clause family.
|
|
9154
|
+
- You may relabel existing nodes and group adjacent top-level/page nodes from this batch when they are clearly one form, endorsement, declarations set, schedule, or clause family.
|
|
8977
9155
|
- Add concise, human-readable titles to generic text, table, row, and cell nodes when the text makes their role clear.
|
|
8978
9156
|
- Groups must list existing childNodeIds only.
|
|
8979
9157
|
- Keep descriptions short and useful for search.
|
|
9158
|
+
- Prefer the document's own form titles, endorsement titles, schedules, declarations headings, and page order over keyword-only guessing.
|
|
8980
9159
|
|
|
8981
9160
|
Source nodes:
|
|
8982
9161
|
${JSON.stringify(nodes, null, 2)}
|
|
@@ -9016,8 +9195,9 @@ function groupNodeId(documentId, group) {
|
|
|
9016
9195
|
}
|
|
9017
9196
|
function applyOrganization(sourceTree, organization) {
|
|
9018
9197
|
const byId = new Map(sourceTree.map((node) => [node.id, node]));
|
|
9198
|
+
const labels = new Map(organization.labels.map((label) => [label.nodeId, label]));
|
|
9019
9199
|
let nextTree = sourceTree.map((node) => {
|
|
9020
|
-
const label =
|
|
9200
|
+
const label = labels.get(node.id);
|
|
9021
9201
|
if (!label) return node;
|
|
9022
9202
|
return {
|
|
9023
9203
|
...node,
|
|
@@ -9026,7 +9206,7 @@ function applyOrganization(sourceTree, organization) {
|
|
|
9026
9206
|
description: cleanText(label.description, node.description)
|
|
9027
9207
|
};
|
|
9028
9208
|
});
|
|
9029
|
-
for (const group of organization.groups
|
|
9209
|
+
for (const group of organization.groups) {
|
|
9030
9210
|
const children = group.childNodeIds.map((id2) => byId.get(id2)).filter((node2) => Boolean(node2));
|
|
9031
9211
|
if (children.length === 0) continue;
|
|
9032
9212
|
const parentId = children[0].parentId;
|
|
@@ -9185,7 +9365,8 @@ function materializeDocument(params) {
|
|
|
9185
9365
|
};
|
|
9186
9366
|
}
|
|
9187
9367
|
async function runSourceTreeExtraction(params) {
|
|
9188
|
-
|
|
9368
|
+
const sourceSpans = normalizeSourceSpans(params.sourceSpans);
|
|
9369
|
+
let sourceTree = buildDocumentSourceTree(sourceSpans, params.id);
|
|
9189
9370
|
const warnings = [];
|
|
9190
9371
|
let modelCalls = 0;
|
|
9191
9372
|
let callsWithUsage = 0;
|
|
@@ -9208,41 +9389,46 @@ async function runSourceTreeExtraction(params) {
|
|
|
9208
9389
|
params.trackUsage(usage, report);
|
|
9209
9390
|
};
|
|
9210
9391
|
try {
|
|
9211
|
-
const
|
|
9212
|
-
const
|
|
9213
|
-
const
|
|
9214
|
-
params.
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9392
|
+
const organizations = [];
|
|
9393
|
+
const batches = organizationBatches(sourceTree);
|
|
9394
|
+
for (const [batchIndex, batch] of batches.entries()) {
|
|
9395
|
+
const budget = params.resolveBudget("extraction_source_tree", 4096);
|
|
9396
|
+
const startedAt = Date.now();
|
|
9397
|
+
const response = await safeGenerateObject(
|
|
9398
|
+
params.generateObject,
|
|
9399
|
+
{
|
|
9400
|
+
prompt: buildOrganizationPrompt(batch),
|
|
9401
|
+
schema: SourceTreeOrganizationSchema,
|
|
9402
|
+
maxTokens: budget.maxTokens,
|
|
9403
|
+
taskKind: "extraction_source_tree",
|
|
9404
|
+
budgetDiagnostics: budget,
|
|
9405
|
+
providerOptions: { ...params.providerOptions, sourceSpans }
|
|
9406
|
+
},
|
|
9407
|
+
{
|
|
9408
|
+
fallback: { labels: [], groups: [] },
|
|
9409
|
+
log: params.log
|
|
9410
|
+
}
|
|
9411
|
+
);
|
|
9412
|
+
localTrack(response.usage, {
|
|
9219
9413
|
taskKind: "extraction_source_tree",
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
);
|
|
9228
|
-
localTrack(response.usage, {
|
|
9229
|
-
taskKind: "extraction_source_tree",
|
|
9230
|
-
label: "source_tree_organizer",
|
|
9231
|
-
maxTokens: budget.maxTokens,
|
|
9232
|
-
durationMs: Date.now() - startedAt
|
|
9233
|
-
});
|
|
9234
|
-
sourceTree = applyOrganization(sourceTree, response.object);
|
|
9414
|
+
label: batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer",
|
|
9415
|
+
maxTokens: budget.maxTokens,
|
|
9416
|
+
durationMs: Date.now() - startedAt
|
|
9417
|
+
});
|
|
9418
|
+
organizations.push(response.object);
|
|
9419
|
+
}
|
|
9420
|
+
sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
|
|
9235
9421
|
} catch (error) {
|
|
9236
9422
|
warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
|
|
9237
9423
|
}
|
|
9238
9424
|
const deterministicProfile = buildDeterministicOperationalProfile({
|
|
9239
9425
|
sourceTree,
|
|
9240
|
-
sourceSpans
|
|
9426
|
+
sourceSpans
|
|
9241
9427
|
});
|
|
9242
9428
|
let operationalProfile = deterministicProfile;
|
|
9243
9429
|
try {
|
|
9244
9430
|
const validNodeIds = new Set(sourceTree.map((node) => node.id));
|
|
9245
|
-
const validSpanIds = new Set(
|
|
9431
|
+
const validSpanIds = new Set(sourceSpans.map((span) => span.id));
|
|
9246
9432
|
const budget = params.resolveBudget("extraction_operational_profile", 8192);
|
|
9247
9433
|
const startedAt = Date.now();
|
|
9248
9434
|
const response = await safeGenerateObject(
|
|
@@ -9253,7 +9439,7 @@ async function runSourceTreeExtraction(params) {
|
|
|
9253
9439
|
maxTokens: budget.maxTokens,
|
|
9254
9440
|
taskKind: "extraction_operational_profile",
|
|
9255
9441
|
budgetDiagnostics: budget,
|
|
9256
|
-
providerOptions: { ...params.providerOptions, sourceSpans
|
|
9442
|
+
providerOptions: { ...params.providerOptions, sourceSpans, sourceTree }
|
|
9257
9443
|
},
|
|
9258
9444
|
{
|
|
9259
9445
|
fallback: deterministicProfile,
|
|
@@ -9282,8 +9468,8 @@ async function runSourceTreeExtraction(params) {
|
|
|
9282
9468
|
});
|
|
9283
9469
|
return {
|
|
9284
9470
|
sourceTree,
|
|
9285
|
-
sourceSpans
|
|
9286
|
-
sourceChunks: chunkSourceSpans(
|
|
9471
|
+
sourceSpans,
|
|
9472
|
+
sourceChunks: chunkSourceSpans(sourceSpans),
|
|
9287
9473
|
operationalProfile,
|
|
9288
9474
|
document,
|
|
9289
9475
|
chunks: [],
|
|
@@ -14297,6 +14483,7 @@ export {
|
|
|
14297
14483
|
normalizeDoclingDocument,
|
|
14298
14484
|
normalizeDocumentSourceTreePaths,
|
|
14299
14485
|
normalizeForMatch,
|
|
14486
|
+
normalizeSourceSpans,
|
|
14300
14487
|
orderSourceEvidence,
|
|
14301
14488
|
overlayTextOnPdf,
|
|
14302
14489
|
pLimit,
|