@claritylabs/cl-sdk 3.0.8 → 3.0.10

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
@@ -9448,9 +9448,21 @@ function looksLikeEndorsementStart(node) {
9448
9448
  if (/^endorsement\s+(?:no\.?|number|#)\s*[A-Z0-9][A-Z0-9.-]*\b/i.test(start)) return true;
9449
9449
  return /^endorsement\s+(?:no\.?|number|#)\s*[A-Z0-9][A-Z0-9.-]*\b/i.test(title) && /\bthis endorsement changes the policy\b/i.test(body);
9450
9450
  }
9451
+ function looksLikeEndorsementContinuation(node) {
9452
+ if (looksLikeEndorsementStart(node)) return false;
9453
+ const title = cleanText(node.title, "");
9454
+ const text = sourceNodeText(node);
9455
+ return /\bendorsement\b/i.test(text) || /\bcontinuation\b/i.test(title) || /\ball\s+other\s+terms\s+and\s+conditions\b/i.test(text);
9456
+ }
9451
9457
  function endorsementStartTitle(node) {
9452
9458
  return looksLikeEndorsementStart(node) ? endorsementTitle(sourceNodeText(node)) : void 0;
9453
9459
  }
9460
+ function endorsementDescription(title, node) {
9461
+ return cleanText(
9462
+ [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0].filter(Boolean).join(" | "),
9463
+ title
9464
+ );
9465
+ }
9454
9466
  function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
9455
9467
  return [
9456
9468
  documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
@@ -9522,7 +9534,7 @@ function applySemanticPageGrouping(sourceTree) {
9522
9534
  ...node,
9523
9535
  kind: "endorsement",
9524
9536
  title: endorsement,
9525
- description: cleanText([endorsement, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "), endorsement),
9537
+ description: endorsementDescription(endorsement, node),
9526
9538
  metadata: { ...node.metadata, organizerRepair: "semantic_page_grouping" }
9527
9539
  };
9528
9540
  }
@@ -9608,6 +9620,124 @@ function endorsementGroupNodeId(documentId, parentId) {
9608
9620
  parentId?.replace(/[^a-zA-Z0-9_.:-]/g, "_").slice(0, 48) ?? "root"
9609
9621
  ].join(":");
9610
9622
  }
9623
+ function isPolicyFormNode(node) {
9624
+ return node.title === "Policy Form" && (node.kind === "form" || node.kind === "page_group");
9625
+ }
9626
+ function isDeclarationsNode(node) {
9627
+ return node.kind === "page_group" && node.title === "Declarations";
9628
+ }
9629
+ function normalizePolicyFormStructure(sourceTree) {
9630
+ let nextTree = sourceTree;
9631
+ const byParent = nodesByParent(nextTree);
9632
+ const nodesToRemove = /* @__PURE__ */ new Set();
9633
+ for (const form of nextTree.filter((node) => node.kind === "form" && node.title === "Policy Form")) {
9634
+ const children = byParent.get(form.id) ?? [];
9635
+ const declarationsChildren = children.filter(isDeclarationsNode);
9636
+ const nestedPolicyForm = children.find((child) => child.id !== form.id && isPolicyFormNode(child));
9637
+ if (declarationsChildren.length === 0 && !nestedPolicyForm) continue;
9638
+ const declarationIds = new Set(declarationsChildren.map((child) => child.id));
9639
+ nextTree = nextTree.map((node) => {
9640
+ if (declarationIds.has(node.id)) {
9641
+ return {
9642
+ ...node,
9643
+ parentId: form.parentId,
9644
+ metadata: {
9645
+ ...node.metadata,
9646
+ organizerRepair: "promote_declarations_from_policy_form"
9647
+ }
9648
+ };
9649
+ }
9650
+ if (nestedPolicyForm && node.parentId === nestedPolicyForm.id) {
9651
+ return {
9652
+ ...node,
9653
+ parentId: form.id,
9654
+ metadata: {
9655
+ ...node.metadata,
9656
+ organizerRepair: "collapse_nested_policy_form"
9657
+ }
9658
+ };
9659
+ }
9660
+ return node;
9661
+ });
9662
+ if (nestedPolicyForm) nodesToRemove.add(nestedPolicyForm.id);
9663
+ }
9664
+ if (nodesToRemove.size > 0) {
9665
+ nextTree = nextTree.filter((node) => !nodesToRemove.has(node.id));
9666
+ }
9667
+ return nextTree;
9668
+ }
9669
+ function nestEndorsementContinuationPages(sourceTree) {
9670
+ const byParent = nodesByParent(sourceTree);
9671
+ const continuationParentById = /* @__PURE__ */ new Map();
9672
+ for (const group of sourceTree.filter(isEndorsementGroup)) {
9673
+ const children = byParent.get(group.id) ?? [];
9674
+ let currentEndorsement;
9675
+ for (const child of children) {
9676
+ if (child.kind === "endorsement" && endorsementStartTitle(child)) {
9677
+ currentEndorsement = child;
9678
+ continue;
9679
+ }
9680
+ if (!currentEndorsement || child.kind !== "page") continue;
9681
+ continuationParentById.set(child.id, currentEndorsement.id);
9682
+ }
9683
+ }
9684
+ if (continuationParentById.size === 0) return sourceTree;
9685
+ return sourceTree.map((node) => {
9686
+ const parentId = continuationParentById.get(node.id);
9687
+ if (!parentId) return node;
9688
+ return {
9689
+ ...node,
9690
+ parentId,
9691
+ metadata: {
9692
+ ...node.metadata,
9693
+ organizerRepair: "nest_endorsement_continuation"
9694
+ }
9695
+ };
9696
+ });
9697
+ }
9698
+ function nodeDepth(node) {
9699
+ return node.path ? node.path.split("/").filter(Boolean).length : 0;
9700
+ }
9701
+ function shouldUseOwnEvidenceForContainer(node) {
9702
+ return node.kind === "endorsement" || node.kind === "page" || node.kind === "table" || node.kind === "table_row" || node.kind === "table_cell" || node.kind === "text";
9703
+ }
9704
+ function normalizeContainerEvidenceFromChildren(sourceTree) {
9705
+ const byParent = nodesByParent(sourceTree);
9706
+ const byId = new Map(sourceTree.map((node) => [node.id, node]));
9707
+ const sorted = [...sourceTree].sort((left, right) => nodeDepth(right) - nodeDepth(left));
9708
+ for (const originalNode of sorted) {
9709
+ const children = (byParent.get(originalNode.id) ?? []).map((child) => byId.get(child.id)).filter((child) => Boolean(child));
9710
+ if (children.length === 0) continue;
9711
+ const currentNode = byId.get(originalNode.id) ?? originalNode;
9712
+ const evidenceNodes = shouldUseOwnEvidenceForContainer(currentNode) ? [currentNode, ...children] : children;
9713
+ const pageStarts = evidenceNodes.map((node) => node.pageStart).filter((page) => typeof page === "number");
9714
+ const pageEnds = evidenceNodes.map((node) => node.pageEnd ?? node.pageStart).filter((page) => typeof page === "number");
9715
+ const sourceSpanIds = [...new Set(evidenceNodes.flatMap((node) => node.sourceSpanIds))];
9716
+ const bbox = evidenceNodes.flatMap((node) => node.bbox ?? []).slice(0, 12);
9717
+ const childText = children.map((child) => child.textExcerpt ?? child.description).filter(Boolean).join("\n\n").slice(0, 1600);
9718
+ byId.set(currentNode.id, {
9719
+ ...currentNode,
9720
+ sourceSpanIds,
9721
+ pageStart: pageStarts.length ? Math.min(...pageStarts) : currentNode.pageStart,
9722
+ pageEnd: pageEnds.length ? Math.max(...pageEnds) : currentNode.pageEnd,
9723
+ bbox,
9724
+ order: Math.min(currentNode.order, ...children.map((child) => child.order)),
9725
+ textExcerpt: shouldUseOwnEvidenceForContainer(currentNode) ? currentNode.textExcerpt : childText || currentNode.textExcerpt
9726
+ });
9727
+ }
9728
+ return sourceTree.map((node) => byId.get(node.id) ?? node);
9729
+ }
9730
+ function normalizeSemanticHierarchy(sourceTree) {
9731
+ return normalizeDocumentSourceTreePaths(
9732
+ normalizeContainerEvidenceFromChildren(
9733
+ nestEndorsementContinuationPages(
9734
+ normalizePolicyFormStructure(
9735
+ normalizeDocumentSourceTreePaths(sourceTree)
9736
+ )
9737
+ )
9738
+ )
9739
+ );
9740
+ }
9611
9741
  function applyEndorsementGrouping(sourceTree) {
9612
9742
  const relabeledTree = sourceTree.map((node) => {
9613
9743
  if (node.kind === "document" || isEndorsementGroup(node)) return node;
@@ -9628,10 +9758,7 @@ function applyEndorsementGrouping(sourceTree) {
9628
9758
  ...node,
9629
9759
  kind: "endorsement",
9630
9760
  title,
9631
- description: cleanText(
9632
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9633
- title
9634
- ),
9761
+ description: endorsementDescription(title, node),
9635
9762
  metadata: {
9636
9763
  ...node.metadata,
9637
9764
  organizerRepair: "normalize_endorsement_grouping"
@@ -9668,10 +9795,7 @@ function applyEndorsementGrouping(sourceTree) {
9668
9795
  ...node,
9669
9796
  kind: "endorsement",
9670
9797
  title,
9671
- description: cleanText(
9672
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9673
- title
9674
- ),
9798
+ description: endorsementDescription(title, node),
9675
9799
  metadata: {
9676
9800
  ...node.metadata,
9677
9801
  organizerRepair: "normalize_endorsement_grouping"
@@ -9682,9 +9806,21 @@ function applyEndorsementGrouping(sourceTree) {
9682
9806
  if (endorsementGroupIds.has(parentId ?? "")) continue;
9683
9807
  const endorsementChildren = children.filter((child) => child.kind === "endorsement" && !isEndorsementGroup(child));
9684
9808
  if (endorsementChildren.length < 2) continue;
9809
+ const endorsementGroupChildren = [];
9810
+ let hasSeenEndorsementStart = false;
9811
+ for (const child of children) {
9812
+ if (child.kind === "endorsement" && !isEndorsementGroup(child)) {
9813
+ hasSeenEndorsementStart = true;
9814
+ endorsementGroupChildren.push(child);
9815
+ continue;
9816
+ }
9817
+ if (hasSeenEndorsementStart && child.kind === "page" && looksLikeEndorsementContinuation(child)) {
9818
+ endorsementGroupChildren.push(child);
9819
+ }
9820
+ }
9685
9821
  const documentId = endorsementChildren[0].documentId;
9686
- const pageStarts = endorsementChildren.map((child) => child.pageStart).filter((page) => typeof page === "number");
9687
- const pageEnds = endorsementChildren.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
9822
+ const pageStarts = endorsementGroupChildren.map((child) => child.pageStart).filter((page) => typeof page === "number");
9823
+ const pageEnds = endorsementGroupChildren.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
9688
9824
  const order = Math.min(...endorsementChildren.map((child) => child.order));
9689
9825
  const existingGroup = groupsByParent.get(parentId);
9690
9826
  const groupId = existingGroup?.id ?? endorsementGroupNodeId(documentId, parentId);
@@ -9699,12 +9835,12 @@ function applyEndorsementGrouping(sourceTree) {
9699
9835
  sourceSpanIds: [],
9700
9836
  pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
9701
9837
  pageEnd: pageEnds.length ? Math.max(...pageEnds) : void 0,
9702
- bbox: endorsementChildren.flatMap((child) => child.bbox ?? []).slice(0, 12),
9838
+ bbox: endorsementGroupChildren.flatMap((child) => child.bbox ?? []).slice(0, 12),
9703
9839
  order,
9704
9840
  path: "",
9705
9841
  metadata: { sourceTreeVersion: "v3", organizer: "endorsement_grouping" }
9706
9842
  };
9707
- const childSpanIds = [...new Set(endorsementChildren.flatMap((child) => child.sourceSpanIds))];
9843
+ const childSpanIds = [...new Set(endorsementGroupChildren.flatMap((child) => child.sourceSpanIds))];
9708
9844
  const normalizedGroup = {
9709
9845
  ...groupNode,
9710
9846
  sourceSpanIds: groupNode.sourceSpanIds.length ? groupNode.sourceSpanIds : childSpanIds,
@@ -9715,11 +9851,12 @@ function applyEndorsementGrouping(sourceTree) {
9715
9851
  groupsByParent.set(parentId, normalizedGroup);
9716
9852
  if (!existingGroup) nextTree.push(normalizedGroup);
9717
9853
  else nextTree = nextTree.map((node) => node.id === normalizedGroup.id ? normalizedGroup : node);
9854
+ const endorsementGroupChildIds = new Set(endorsementGroupChildren.map((child) => child.id));
9718
9855
  nextTree = nextTree.map(
9719
- (node) => endorsementChildren.some((child) => child.id === node.id) ? { ...node, parentId: groupId, order: node.order + 1e-3 } : node
9856
+ (node) => endorsementGroupChildIds.has(node.id) ? { ...node, parentId: groupId, order: node.order + 1e-3 } : node
9720
9857
  );
9721
9858
  }
9722
- return normalizeDocumentSourceTreePaths(nextTree);
9859
+ return normalizeSemanticHierarchy(nextTree);
9723
9860
  }
9724
9861
  function compactNode(node, maxText = 700) {
9725
9862
  return {
@@ -10103,7 +10240,7 @@ async function runSourceTreeExtraction(params) {
10103
10240
  maxTokens: budget.maxTokens,
10104
10241
  taskKind: "extraction_operational_profile",
10105
10242
  budgetDiagnostics: budget,
10106
- providerOptions: { ...params.providerOptions, sourceSpans, sourceTree }
10243
+ providerOptions: params.providerOptions
10107
10244
  },
10108
10245
  {
10109
10246
  fallback: deterministicProfile,