@claritylabs/cl-sdk 3.0.9 → 3.0.11

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
@@ -3017,14 +3017,24 @@ function normalizeDocumentSourceTreePaths(nodes) {
3017
3017
  group.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
3018
3018
  }
3019
3019
  const result = [];
3020
- const visit = (node, path) => {
3021
- const next = { ...node, path };
3020
+ const visited = /* @__PURE__ */ new Set();
3021
+ const visit = (node, path, ancestors, parentId) => {
3022
+ if (visited.has(node.id) || ancestors.has(node.id)) return;
3023
+ visited.add(node.id);
3024
+ const next = { ...node, parentId, path };
3022
3025
  result.push(next);
3023
3026
  const children = byParent.get(node.id) ?? [];
3024
- children.forEach((child, index) => visit(child, `${path}.${index + 1}`));
3027
+ const nextAncestors = new Set(ancestors);
3028
+ nextAncestors.add(node.id);
3029
+ children.forEach((child, index) => visit(child, `${path}.${index + 1}`, nextAncestors, node.id));
3025
3030
  };
3026
3031
  const roots = byParent.get(void 0) ?? [];
3027
- roots.forEach((root, index) => visit(root, String(index + 1)));
3032
+ roots.forEach((root, index) => visit(root, String(index + 1), /* @__PURE__ */ new Set(), void 0));
3033
+ for (const node of nodes) {
3034
+ if (!visited.has(node.id)) {
3035
+ visit(node, String(result.length + 1), /* @__PURE__ */ new Set(), void 0);
3036
+ }
3037
+ }
3028
3038
  return result;
3029
3039
  }
3030
3040
  function buildDocumentSourceTree(sourceSpans, documentId) {
@@ -9347,6 +9357,8 @@ var ORGANIZABLE_KINDS = [
9347
9357
  ];
9348
9358
  var ORGANIZATION_TOP_LEVEL_BATCH_SIZE = 80;
9349
9359
  var ORGANIZATION_CHILD_CONTEXT_LIMIT = 4;
9360
+ var ORGANIZER_MAX_SOURCE_SPANS = 400;
9361
+ var ORGANIZER_MAX_TOP_LEVEL_NODES = 18;
9350
9362
  var SourceTreeOrganizationSchema = import_zod41.z.object({
9351
9363
  labels: import_zod41.z.array(import_zod41.z.object({
9352
9364
  nodeId: import_zod41.z.string(),
@@ -9457,6 +9469,12 @@ function looksLikeEndorsementContinuation(node) {
9457
9469
  function endorsementStartTitle(node) {
9458
9470
  return looksLikeEndorsementStart(node) ? endorsementTitle(sourceNodeText(node)) : void 0;
9459
9471
  }
9472
+ function endorsementDescription(title, node) {
9473
+ return cleanText(
9474
+ [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0].filter(Boolean).join(" | "),
9475
+ title
9476
+ );
9477
+ }
9460
9478
  function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
9461
9479
  return [
9462
9480
  documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
@@ -9467,7 +9485,7 @@ function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
9467
9485
  ].join(":");
9468
9486
  }
9469
9487
  function looksLikeDeclarationsStart(node) {
9470
- return /\bdeclarations?\s+(page|schedule)\b/i.test(sourceNodeText(node));
9488
+ return /(^|\b)declarations?\b/i.test(sourceNodeText(node)) && !/\bforms?\s+and\s+endorsements?\b/i.test(sourceNodeText(node));
9471
9489
  }
9472
9490
  function looksLikeDeclarationsContinuation(node) {
9473
9491
  const text = sourceNodeText(node);
@@ -9475,7 +9493,8 @@ function looksLikeDeclarationsContinuation(node) {
9475
9493
  }
9476
9494
  function looksLikePolicyFormStart(node) {
9477
9495
  const text = sourceNodeText(node);
9478
- return /\bpolicy form\b/i.test(node.title) || /\btechnology errors?\s*&?\s*omissions\b/i.test(text) && /\bplease read this entire policy carefully\b/i.test(text) || /\bform\s+[A-Z]{2,}-[A-Z0-9-]+\s+\d{2}\s+\d{2}\b/i.test(text);
9496
+ const excerpt = cleanText(node.textExcerpt, "");
9497
+ return /\bpolicy form\b/i.test(node.title) || /^policy\s+form\b/i.test(excerpt) || /\btechnology errors?\s*&?\s*omissions\b/i.test(text) && /\bplease read this entire policy carefully\b/i.test(text) || /\bform\s+[A-Z]{2,}-[A-Z0-9-]+\s+\d{2}\s+\d{2}\b/i.test(text);
9479
9498
  }
9480
9499
  function looksLikePolicyFormContinuation(node) {
9481
9500
  const text = sourceNodeText(node);
@@ -9528,7 +9547,7 @@ function applySemanticPageGrouping(sourceTree) {
9528
9547
  ...node,
9529
9548
  kind: "endorsement",
9530
9549
  title: endorsement,
9531
- description: cleanText([endorsement, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "), endorsement),
9550
+ description: endorsementDescription(endorsement, node),
9532
9551
  metadata: { ...node.metadata, organizerRepair: "semantic_page_grouping" }
9533
9552
  };
9534
9553
  }
@@ -9752,10 +9771,7 @@ function applyEndorsementGrouping(sourceTree) {
9752
9771
  ...node,
9753
9772
  kind: "endorsement",
9754
9773
  title,
9755
- description: cleanText(
9756
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9757
- title
9758
- ),
9774
+ description: endorsementDescription(title, node),
9759
9775
  metadata: {
9760
9776
  ...node.metadata,
9761
9777
  organizerRepair: "normalize_endorsement_grouping"
@@ -9792,10 +9808,7 @@ function applyEndorsementGrouping(sourceTree) {
9792
9808
  ...node,
9793
9809
  kind: "endorsement",
9794
9810
  title,
9795
- description: cleanText(
9796
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9797
- title
9798
- ),
9811
+ description: endorsementDescription(title, node),
9799
9812
  metadata: {
9800
9813
  ...node.metadata,
9801
9814
  organizerRepair: "normalize_endorsement_grouping"
@@ -9885,6 +9898,24 @@ function nodesByParent(sourceTree) {
9885
9898
  function sourceTreeRootId(sourceTree) {
9886
9899
  return sourceTree.find((node) => node.kind === "document")?.id;
9887
9900
  }
9901
+ function rootChildren(sourceTree) {
9902
+ const byParent = nodesByParent(sourceTree);
9903
+ const rootId = sourceTreeRootId(sourceTree);
9904
+ return (byParent.get(rootId) ?? []).filter((node) => node.kind !== "document");
9905
+ }
9906
+ function hasDeterministicSemanticOutline(sourceTree) {
9907
+ const children = rootChildren(sourceTree);
9908
+ const semanticCount = children.filter(
9909
+ (node) => node.kind === "page_group" || node.kind === "form" || node.kind === "endorsement" || node.kind === "section" || node.kind === "schedule"
9910
+ ).length;
9911
+ return semanticCount >= 2 || children.some((node) => node.title === "Declarations") || children.some((node) => node.title === "Policy Form") || children.some((node) => node.title === "Endorsements");
9912
+ }
9913
+ function shouldRunSourceTreeOrganizer(sourceTree, sourceSpans) {
9914
+ const topLevelCount = rootChildren(sourceTree).length;
9915
+ if (sourceSpans.length > ORGANIZER_MAX_SOURCE_SPANS) return false;
9916
+ if (topLevelCount > ORGANIZER_MAX_TOP_LEVEL_NODES) return false;
9917
+ return !hasDeterministicSemanticOutline(sourceTree);
9918
+ }
9888
9919
  function organizationBatches(sourceTree) {
9889
9920
  const byParent = nodesByParent(sourceTree);
9890
9921
  const rootId = sourceTreeRootId(sourceTree);
@@ -10166,7 +10197,7 @@ function materializeDocument(params) {
10166
10197
  }
10167
10198
  async function runSourceTreeExtraction(params) {
10168
10199
  const sourceSpans = normalizeSourceSpans(params.sourceSpans);
10169
- let sourceTree = buildDocumentSourceTree(sourceSpans, params.id);
10200
+ let sourceTree = applySemanticPageGrouping(buildDocumentSourceTree(sourceSpans, params.id));
10170
10201
  const warnings = [];
10171
10202
  let modelCalls = 0;
10172
10203
  let callsWithUsage = 0;
@@ -10188,40 +10219,43 @@ async function runSourceTreeExtraction(params) {
10188
10219
  }
10189
10220
  params.trackUsage(usage, report);
10190
10221
  };
10191
- try {
10192
- const organizations = [];
10193
- const batches = organizationBatches(sourceTree);
10194
- for (const [batchIndex, batch] of batches.entries()) {
10195
- const budget = params.resolveBudget("extraction_source_tree", 4096);
10196
- const startedAt = Date.now();
10197
- const response = await safeGenerateObject(
10198
- params.generateObject,
10199
- {
10200
- prompt: buildOrganizationPrompt(batch),
10201
- schema: SourceTreeOrganizationSchema,
10202
- maxTokens: budget.maxTokens,
10222
+ if (shouldRunSourceTreeOrganizer(sourceTree, sourceSpans)) {
10223
+ try {
10224
+ const organizations = [];
10225
+ const batches = organizationBatches(sourceTree);
10226
+ for (const [batchIndex, batch] of batches.entries()) {
10227
+ const budget = params.resolveBudget("extraction_source_tree", 4096);
10228
+ const startedAt = Date.now();
10229
+ const response = await safeGenerateObject(
10230
+ params.generateObject,
10231
+ {
10232
+ prompt: buildOrganizationPrompt(batch),
10233
+ schema: SourceTreeOrganizationSchema,
10234
+ maxTokens: budget.maxTokens,
10235
+ taskKind: "extraction_source_tree",
10236
+ budgetDiagnostics: budget,
10237
+ providerOptions: params.providerOptions
10238
+ },
10239
+ {
10240
+ fallback: { labels: [], groups: [] },
10241
+ log: params.log
10242
+ }
10243
+ );
10244
+ localTrack(response.usage, {
10203
10245
  taskKind: "extraction_source_tree",
10204
- budgetDiagnostics: budget,
10205
- providerOptions: { ...params.providerOptions, sourceSpans }
10206
- },
10207
- {
10208
- fallback: { labels: [], groups: [] },
10209
- log: params.log
10210
- }
10211
- );
10212
- localTrack(response.usage, {
10213
- taskKind: "extraction_source_tree",
10214
- label: batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer",
10215
- maxTokens: budget.maxTokens,
10216
- durationMs: Date.now() - startedAt
10217
- });
10218
- organizations.push(response.object);
10246
+ label: batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer",
10247
+ maxTokens: budget.maxTokens,
10248
+ durationMs: Date.now() - startedAt
10249
+ });
10250
+ organizations.push(response.object);
10251
+ }
10252
+ sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
10253
+ } catch (error) {
10254
+ warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
10219
10255
  }
10220
- sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
10221
- } catch (error) {
10222
- warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
10256
+ } else {
10257
+ await params.log?.("Deterministic source tree ready; skipped model organizer");
10223
10258
  }
10224
- sourceTree = applySemanticPageGrouping(sourceTree);
10225
10259
  const deterministicProfile = buildDeterministicOperationalProfile({
10226
10260
  sourceTree,
10227
10261
  sourceSpans
@@ -10240,7 +10274,7 @@ async function runSourceTreeExtraction(params) {
10240
10274
  maxTokens: budget.maxTokens,
10241
10275
  taskKind: "extraction_operational_profile",
10242
10276
  budgetDiagnostics: budget,
10243
- providerOptions: { ...params.providerOptions, sourceSpans, sourceTree }
10277
+ providerOptions: params.providerOptions
10244
10278
  },
10245
10279
  {
10246
10280
  fallback: deterministicProfile,