@claritylabs/cl-sdk 3.0.2 → 3.0.3
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 +107 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +107 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9236,6 +9236,8 @@ var ORGANIZABLE_KINDS = [
|
|
|
9236
9236
|
"schedule",
|
|
9237
9237
|
"clause"
|
|
9238
9238
|
];
|
|
9239
|
+
var ORGANIZATION_TOP_LEVEL_BATCH_SIZE = 80;
|
|
9240
|
+
var ORGANIZATION_CHILD_CONTEXT_LIMIT = 4;
|
|
9239
9241
|
var SourceTreeOrganizationSchema = import_zod41.z.object({
|
|
9240
9242
|
labels: import_zod41.z.array(import_zod41.z.object({
|
|
9241
9243
|
nodeId: import_zod41.z.string(),
|
|
@@ -9300,7 +9302,7 @@ function cleanText(value, fallback) {
|
|
|
9300
9302
|
const text = value?.replace(/\s+/g, " ").trim();
|
|
9301
9303
|
return text || fallback;
|
|
9302
9304
|
}
|
|
9303
|
-
function compactNode(node) {
|
|
9305
|
+
function compactNode(node, maxText = 700) {
|
|
9304
9306
|
return {
|
|
9305
9307
|
id: node.id,
|
|
9306
9308
|
kind: node.kind,
|
|
@@ -9309,20 +9311,89 @@ function compactNode(node) {
|
|
|
9309
9311
|
pageStart: node.pageStart,
|
|
9310
9312
|
pageEnd: node.pageEnd,
|
|
9311
9313
|
sourceSpanIds: node.sourceSpanIds.slice(0, 8),
|
|
9312
|
-
text: (node.textExcerpt ?? node.description).slice(0,
|
|
9314
|
+
text: (node.textExcerpt ?? node.description).slice(0, maxText)
|
|
9313
9315
|
};
|
|
9314
9316
|
}
|
|
9315
|
-
function
|
|
9316
|
-
const
|
|
9317
|
+
function nodesByParent(sourceTree) {
|
|
9318
|
+
const byParent = /* @__PURE__ */ new Map();
|
|
9319
|
+
for (const node of sourceTree) {
|
|
9320
|
+
const children = byParent.get(node.parentId) ?? [];
|
|
9321
|
+
children.push(node);
|
|
9322
|
+
byParent.set(node.parentId, children);
|
|
9323
|
+
}
|
|
9324
|
+
for (const children of byParent.values()) {
|
|
9325
|
+
children.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
|
|
9326
|
+
}
|
|
9327
|
+
return byParent;
|
|
9328
|
+
}
|
|
9329
|
+
function sourceTreeRootId(sourceTree) {
|
|
9330
|
+
return sourceTree.find((node) => node.kind === "document")?.id;
|
|
9331
|
+
}
|
|
9332
|
+
function organizationBatches(sourceTree) {
|
|
9333
|
+
const byParent = nodesByParent(sourceTree);
|
|
9334
|
+
const rootId = sourceTreeRootId(sourceTree);
|
|
9335
|
+
const topLevelNodes = (byParent.get(rootId) ?? []).filter((node) => node.kind !== "document");
|
|
9336
|
+
if (topLevelNodes.length === 0) {
|
|
9337
|
+
const nodes = sourceTree.filter((node) => node.kind !== "document").slice(0, 240);
|
|
9338
|
+
return [{
|
|
9339
|
+
label: "fallback node prefix because no document root children were found",
|
|
9340
|
+
topLevelNodeIds: nodes.map((node) => node.id),
|
|
9341
|
+
nodes
|
|
9342
|
+
}];
|
|
9343
|
+
}
|
|
9344
|
+
const batches = [];
|
|
9345
|
+
for (let index = 0; index < topLevelNodes.length; index += ORGANIZATION_TOP_LEVEL_BATCH_SIZE) {
|
|
9346
|
+
const topLevelBatch = topLevelNodes.slice(index, index + ORGANIZATION_TOP_LEVEL_BATCH_SIZE);
|
|
9347
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
9348
|
+
for (const node of topLevelBatch) {
|
|
9349
|
+
candidates.set(node.id, node);
|
|
9350
|
+
const childContext = (byParent.get(node.id) ?? []).filter((child) => child.kind !== "text" && child.kind !== "table_cell").slice(0, ORGANIZATION_CHILD_CONTEXT_LIMIT);
|
|
9351
|
+
for (const child of childContext) {
|
|
9352
|
+
candidates.set(child.id, child);
|
|
9353
|
+
}
|
|
9354
|
+
}
|
|
9355
|
+
batches.push({
|
|
9356
|
+
label: `top-level nodes ${index + 1}-${index + topLevelBatch.length} of ${topLevelNodes.length}`,
|
|
9357
|
+
topLevelNodeIds: topLevelBatch.map((node) => node.id),
|
|
9358
|
+
nodes: [...candidates.values()]
|
|
9359
|
+
});
|
|
9360
|
+
}
|
|
9361
|
+
return batches;
|
|
9362
|
+
}
|
|
9363
|
+
function mergeOrganizationResults(results) {
|
|
9364
|
+
const labels = /* @__PURE__ */ new Map();
|
|
9365
|
+
const groups = /* @__PURE__ */ new Map();
|
|
9366
|
+
for (const result of results) {
|
|
9367
|
+
for (const label of result.labels) {
|
|
9368
|
+
labels.set(label.nodeId, { ...labels.get(label.nodeId), ...label });
|
|
9369
|
+
}
|
|
9370
|
+
for (const group of result.groups) {
|
|
9371
|
+
const key = `${group.kind}:${group.childNodeIds.join("|")}`;
|
|
9372
|
+
groups.set(key, group);
|
|
9373
|
+
}
|
|
9374
|
+
}
|
|
9375
|
+
return {
|
|
9376
|
+
labels: [...labels.values()],
|
|
9377
|
+
groups: [...groups.values()]
|
|
9378
|
+
};
|
|
9379
|
+
}
|
|
9380
|
+
function buildOrganizationPrompt(batch) {
|
|
9381
|
+
const nodes = batch.nodes.map((node) => compactNode(node, node.kind === "page" ? 900 : 320));
|
|
9317
9382
|
return `You organize an insurance document source tree.
|
|
9318
9383
|
|
|
9384
|
+
Scope:
|
|
9385
|
+
- ${batch.label}
|
|
9386
|
+
- The provided list is a bounded extraction-time batch. It is not necessarily the whole document.
|
|
9387
|
+
- Top-level page/form candidates in this batch: ${JSON.stringify(batch.topLevelNodeIds)}
|
|
9388
|
+
|
|
9319
9389
|
Rules:
|
|
9320
9390
|
- Use only node IDs from the provided list.
|
|
9321
9391
|
- Do not invent text, page numbers, source spans, limits, or policy facts.
|
|
9322
|
-
- 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.
|
|
9392
|
+
- 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.
|
|
9323
9393
|
- Add concise, human-readable titles to generic text, table, row, and cell nodes when the text makes their role clear.
|
|
9324
9394
|
- Groups must list existing childNodeIds only.
|
|
9325
9395
|
- Keep descriptions short and useful for search.
|
|
9396
|
+
- Prefer the document's own form titles, endorsement titles, schedules, declarations headings, and page order over keyword-only guessing.
|
|
9326
9397
|
|
|
9327
9398
|
Source nodes:
|
|
9328
9399
|
${JSON.stringify(nodes, null, 2)}
|
|
@@ -9362,8 +9433,9 @@ function groupNodeId(documentId, group) {
|
|
|
9362
9433
|
}
|
|
9363
9434
|
function applyOrganization(sourceTree, organization) {
|
|
9364
9435
|
const byId = new Map(sourceTree.map((node) => [node.id, node]));
|
|
9436
|
+
const labels = new Map(organization.labels.map((label) => [label.nodeId, label]));
|
|
9365
9437
|
let nextTree = sourceTree.map((node) => {
|
|
9366
|
-
const label =
|
|
9438
|
+
const label = labels.get(node.id);
|
|
9367
9439
|
if (!label) return node;
|
|
9368
9440
|
return {
|
|
9369
9441
|
...node,
|
|
@@ -9372,7 +9444,7 @@ function applyOrganization(sourceTree, organization) {
|
|
|
9372
9444
|
description: cleanText(label.description, node.description)
|
|
9373
9445
|
};
|
|
9374
9446
|
});
|
|
9375
|
-
for (const group of organization.groups
|
|
9447
|
+
for (const group of organization.groups) {
|
|
9376
9448
|
const children = group.childNodeIds.map((id2) => byId.get(id2)).filter((node2) => Boolean(node2));
|
|
9377
9449
|
if (children.length === 0) continue;
|
|
9378
9450
|
const parentId = children[0].parentId;
|
|
@@ -9554,30 +9626,35 @@ async function runSourceTreeExtraction(params) {
|
|
|
9554
9626
|
params.trackUsage(usage, report);
|
|
9555
9627
|
};
|
|
9556
9628
|
try {
|
|
9557
|
-
const
|
|
9558
|
-
const
|
|
9559
|
-
const
|
|
9560
|
-
params.
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
|
|
9629
|
+
const organizations = [];
|
|
9630
|
+
const batches = organizationBatches(sourceTree);
|
|
9631
|
+
for (const [batchIndex, batch] of batches.entries()) {
|
|
9632
|
+
const budget = params.resolveBudget("extraction_source_tree", 4096);
|
|
9633
|
+
const startedAt = Date.now();
|
|
9634
|
+
const response = await safeGenerateObject(
|
|
9635
|
+
params.generateObject,
|
|
9636
|
+
{
|
|
9637
|
+
prompt: buildOrganizationPrompt(batch),
|
|
9638
|
+
schema: SourceTreeOrganizationSchema,
|
|
9639
|
+
maxTokens: budget.maxTokens,
|
|
9640
|
+
taskKind: "extraction_source_tree",
|
|
9641
|
+
budgetDiagnostics: budget,
|
|
9642
|
+
providerOptions: { ...params.providerOptions, sourceSpans: params.sourceSpans }
|
|
9643
|
+
},
|
|
9644
|
+
{
|
|
9645
|
+
fallback: { labels: [], groups: [] },
|
|
9646
|
+
log: params.log
|
|
9647
|
+
}
|
|
9648
|
+
);
|
|
9649
|
+
localTrack(response.usage, {
|
|
9565
9650
|
taskKind: "extraction_source_tree",
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
);
|
|
9574
|
-
localTrack(response.usage, {
|
|
9575
|
-
taskKind: "extraction_source_tree",
|
|
9576
|
-
label: "source_tree_organizer",
|
|
9577
|
-
maxTokens: budget.maxTokens,
|
|
9578
|
-
durationMs: Date.now() - startedAt
|
|
9579
|
-
});
|
|
9580
|
-
sourceTree = applyOrganization(sourceTree, response.object);
|
|
9651
|
+
label: batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer",
|
|
9652
|
+
maxTokens: budget.maxTokens,
|
|
9653
|
+
durationMs: Date.now() - startedAt
|
|
9654
|
+
});
|
|
9655
|
+
organizations.push(response.object);
|
|
9656
|
+
}
|
|
9657
|
+
sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
|
|
9581
9658
|
} catch (error) {
|
|
9582
9659
|
warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
|
|
9583
9660
|
}
|