@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.mjs CHANGED
@@ -2662,14 +2662,24 @@ function normalizeDocumentSourceTreePaths(nodes) {
2662
2662
  group.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
2663
2663
  }
2664
2664
  const result = [];
2665
- const visit = (node, path) => {
2666
- const next = { ...node, path };
2665
+ const visited = /* @__PURE__ */ new Set();
2666
+ const visit = (node, path, ancestors, parentId) => {
2667
+ if (visited.has(node.id) || ancestors.has(node.id)) return;
2668
+ visited.add(node.id);
2669
+ const next = { ...node, parentId, path };
2667
2670
  result.push(next);
2668
2671
  const children = byParent.get(node.id) ?? [];
2669
- children.forEach((child, index) => visit(child, `${path}.${index + 1}`));
2672
+ const nextAncestors = new Set(ancestors);
2673
+ nextAncestors.add(node.id);
2674
+ children.forEach((child, index) => visit(child, `${path}.${index + 1}`, nextAncestors, node.id));
2670
2675
  };
2671
2676
  const roots = byParent.get(void 0) ?? [];
2672
- roots.forEach((root, index) => visit(root, String(index + 1)));
2677
+ roots.forEach((root, index) => visit(root, String(index + 1), /* @__PURE__ */ new Set(), void 0));
2678
+ for (const node of nodes) {
2679
+ if (!visited.has(node.id)) {
2680
+ visit(node, String(result.length + 1), /* @__PURE__ */ new Set(), void 0);
2681
+ }
2682
+ }
2673
2683
  return result;
2674
2684
  }
2675
2685
  function buildDocumentSourceTree(sourceSpans, documentId) {
@@ -9000,6 +9010,8 @@ var ORGANIZABLE_KINDS = [
9000
9010
  ];
9001
9011
  var ORGANIZATION_TOP_LEVEL_BATCH_SIZE = 80;
9002
9012
  var ORGANIZATION_CHILD_CONTEXT_LIMIT = 4;
9013
+ var ORGANIZER_MAX_SOURCE_SPANS = 400;
9014
+ var ORGANIZER_MAX_TOP_LEVEL_NODES = 18;
9003
9015
  var SourceTreeOrganizationSchema = z41.object({
9004
9016
  labels: z41.array(z41.object({
9005
9017
  nodeId: z41.string(),
@@ -9110,6 +9122,12 @@ function looksLikeEndorsementContinuation(node) {
9110
9122
  function endorsementStartTitle(node) {
9111
9123
  return looksLikeEndorsementStart(node) ? endorsementTitle(sourceNodeText(node)) : void 0;
9112
9124
  }
9125
+ function endorsementDescription(title, node) {
9126
+ return cleanText(
9127
+ [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0].filter(Boolean).join(" | "),
9128
+ title
9129
+ );
9130
+ }
9113
9131
  function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
9114
9132
  return [
9115
9133
  documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
@@ -9120,7 +9138,7 @@ function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
9120
9138
  ].join(":");
9121
9139
  }
9122
9140
  function looksLikeDeclarationsStart(node) {
9123
- return /\bdeclarations?\s+(page|schedule)\b/i.test(sourceNodeText(node));
9141
+ return /(^|\b)declarations?\b/i.test(sourceNodeText(node)) && !/\bforms?\s+and\s+endorsements?\b/i.test(sourceNodeText(node));
9124
9142
  }
9125
9143
  function looksLikeDeclarationsContinuation(node) {
9126
9144
  const text = sourceNodeText(node);
@@ -9128,7 +9146,8 @@ function looksLikeDeclarationsContinuation(node) {
9128
9146
  }
9129
9147
  function looksLikePolicyFormStart(node) {
9130
9148
  const text = sourceNodeText(node);
9131
- 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);
9149
+ const excerpt = cleanText(node.textExcerpt, "");
9150
+ 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);
9132
9151
  }
9133
9152
  function looksLikePolicyFormContinuation(node) {
9134
9153
  const text = sourceNodeText(node);
@@ -9181,7 +9200,7 @@ function applySemanticPageGrouping(sourceTree) {
9181
9200
  ...node,
9182
9201
  kind: "endorsement",
9183
9202
  title: endorsement,
9184
- description: cleanText([endorsement, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "), endorsement),
9203
+ description: endorsementDescription(endorsement, node),
9185
9204
  metadata: { ...node.metadata, organizerRepair: "semantic_page_grouping" }
9186
9205
  };
9187
9206
  }
@@ -9405,10 +9424,7 @@ function applyEndorsementGrouping(sourceTree) {
9405
9424
  ...node,
9406
9425
  kind: "endorsement",
9407
9426
  title,
9408
- description: cleanText(
9409
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9410
- title
9411
- ),
9427
+ description: endorsementDescription(title, node),
9412
9428
  metadata: {
9413
9429
  ...node.metadata,
9414
9430
  organizerRepair: "normalize_endorsement_grouping"
@@ -9445,10 +9461,7 @@ function applyEndorsementGrouping(sourceTree) {
9445
9461
  ...node,
9446
9462
  kind: "endorsement",
9447
9463
  title,
9448
- description: cleanText(
9449
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9450
- title
9451
- ),
9464
+ description: endorsementDescription(title, node),
9452
9465
  metadata: {
9453
9466
  ...node.metadata,
9454
9467
  organizerRepair: "normalize_endorsement_grouping"
@@ -9538,6 +9551,24 @@ function nodesByParent(sourceTree) {
9538
9551
  function sourceTreeRootId(sourceTree) {
9539
9552
  return sourceTree.find((node) => node.kind === "document")?.id;
9540
9553
  }
9554
+ function rootChildren(sourceTree) {
9555
+ const byParent = nodesByParent(sourceTree);
9556
+ const rootId = sourceTreeRootId(sourceTree);
9557
+ return (byParent.get(rootId) ?? []).filter((node) => node.kind !== "document");
9558
+ }
9559
+ function hasDeterministicSemanticOutline(sourceTree) {
9560
+ const children = rootChildren(sourceTree);
9561
+ const semanticCount = children.filter(
9562
+ (node) => node.kind === "page_group" || node.kind === "form" || node.kind === "endorsement" || node.kind === "section" || node.kind === "schedule"
9563
+ ).length;
9564
+ return semanticCount >= 2 || children.some((node) => node.title === "Declarations") || children.some((node) => node.title === "Policy Form") || children.some((node) => node.title === "Endorsements");
9565
+ }
9566
+ function shouldRunSourceTreeOrganizer(sourceTree, sourceSpans) {
9567
+ const topLevelCount = rootChildren(sourceTree).length;
9568
+ if (sourceSpans.length > ORGANIZER_MAX_SOURCE_SPANS) return false;
9569
+ if (topLevelCount > ORGANIZER_MAX_TOP_LEVEL_NODES) return false;
9570
+ return !hasDeterministicSemanticOutline(sourceTree);
9571
+ }
9541
9572
  function organizationBatches(sourceTree) {
9542
9573
  const byParent = nodesByParent(sourceTree);
9543
9574
  const rootId = sourceTreeRootId(sourceTree);
@@ -9819,7 +9850,7 @@ function materializeDocument(params) {
9819
9850
  }
9820
9851
  async function runSourceTreeExtraction(params) {
9821
9852
  const sourceSpans = normalizeSourceSpans(params.sourceSpans);
9822
- let sourceTree = buildDocumentSourceTree(sourceSpans, params.id);
9853
+ let sourceTree = applySemanticPageGrouping(buildDocumentSourceTree(sourceSpans, params.id));
9823
9854
  const warnings = [];
9824
9855
  let modelCalls = 0;
9825
9856
  let callsWithUsage = 0;
@@ -9841,40 +9872,43 @@ async function runSourceTreeExtraction(params) {
9841
9872
  }
9842
9873
  params.trackUsage(usage, report);
9843
9874
  };
9844
- try {
9845
- const organizations = [];
9846
- const batches = organizationBatches(sourceTree);
9847
- for (const [batchIndex, batch] of batches.entries()) {
9848
- const budget = params.resolveBudget("extraction_source_tree", 4096);
9849
- const startedAt = Date.now();
9850
- const response = await safeGenerateObject(
9851
- params.generateObject,
9852
- {
9853
- prompt: buildOrganizationPrompt(batch),
9854
- schema: SourceTreeOrganizationSchema,
9855
- maxTokens: budget.maxTokens,
9875
+ if (shouldRunSourceTreeOrganizer(sourceTree, sourceSpans)) {
9876
+ try {
9877
+ const organizations = [];
9878
+ const batches = organizationBatches(sourceTree);
9879
+ for (const [batchIndex, batch] of batches.entries()) {
9880
+ const budget = params.resolveBudget("extraction_source_tree", 4096);
9881
+ const startedAt = Date.now();
9882
+ const response = await safeGenerateObject(
9883
+ params.generateObject,
9884
+ {
9885
+ prompt: buildOrganizationPrompt(batch),
9886
+ schema: SourceTreeOrganizationSchema,
9887
+ maxTokens: budget.maxTokens,
9888
+ taskKind: "extraction_source_tree",
9889
+ budgetDiagnostics: budget,
9890
+ providerOptions: params.providerOptions
9891
+ },
9892
+ {
9893
+ fallback: { labels: [], groups: [] },
9894
+ log: params.log
9895
+ }
9896
+ );
9897
+ localTrack(response.usage, {
9856
9898
  taskKind: "extraction_source_tree",
9857
- budgetDiagnostics: budget,
9858
- providerOptions: { ...params.providerOptions, sourceSpans }
9859
- },
9860
- {
9861
- fallback: { labels: [], groups: [] },
9862
- log: params.log
9863
- }
9864
- );
9865
- localTrack(response.usage, {
9866
- taskKind: "extraction_source_tree",
9867
- label: batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer",
9868
- maxTokens: budget.maxTokens,
9869
- durationMs: Date.now() - startedAt
9870
- });
9871
- organizations.push(response.object);
9899
+ label: batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer",
9900
+ maxTokens: budget.maxTokens,
9901
+ durationMs: Date.now() - startedAt
9902
+ });
9903
+ organizations.push(response.object);
9904
+ }
9905
+ sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
9906
+ } catch (error) {
9907
+ warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
9872
9908
  }
9873
- sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
9874
- } catch (error) {
9875
- warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
9909
+ } else {
9910
+ await params.log?.("Deterministic source tree ready; skipped model organizer");
9876
9911
  }
9877
- sourceTree = applySemanticPageGrouping(sourceTree);
9878
9912
  const deterministicProfile = buildDeterministicOperationalProfile({
9879
9913
  sourceTree,
9880
9914
  sourceSpans
@@ -9893,7 +9927,7 @@ async function runSourceTreeExtraction(params) {
9893
9927
  maxTokens: budget.maxTokens,
9894
9928
  taskKind: "extraction_operational_profile",
9895
9929
  budgetDiagnostics: budget,
9896
- providerOptions: { ...params.providerOptions, sourceSpans, sourceTree }
9930
+ providerOptions: params.providerOptions
9897
9931
  },
9898
9932
  {
9899
9933
  fallback: deterministicProfile,