@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.mjs CHANGED
@@ -9101,9 +9101,21 @@ function looksLikeEndorsementStart(node) {
9101
9101
  if (/^endorsement\s+(?:no\.?|number|#)\s*[A-Z0-9][A-Z0-9.-]*\b/i.test(start)) return true;
9102
9102
  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);
9103
9103
  }
9104
+ function looksLikeEndorsementContinuation(node) {
9105
+ if (looksLikeEndorsementStart(node)) return false;
9106
+ const title = cleanText(node.title, "");
9107
+ const text = sourceNodeText(node);
9108
+ return /\bendorsement\b/i.test(text) || /\bcontinuation\b/i.test(title) || /\ball\s+other\s+terms\s+and\s+conditions\b/i.test(text);
9109
+ }
9104
9110
  function endorsementStartTitle(node) {
9105
9111
  return looksLikeEndorsementStart(node) ? endorsementTitle(sourceNodeText(node)) : void 0;
9106
9112
  }
9113
+ function endorsementDescription(title, node) {
9114
+ return cleanText(
9115
+ [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0].filter(Boolean).join(" | "),
9116
+ title
9117
+ );
9118
+ }
9107
9119
  function semanticGroupNodeId(documentId, kind, title, childNodeIds) {
9108
9120
  return [
9109
9121
  documentId.replace(/[^a-zA-Z0-9_.:-]/g, "_"),
@@ -9175,7 +9187,7 @@ function applySemanticPageGrouping(sourceTree) {
9175
9187
  ...node,
9176
9188
  kind: "endorsement",
9177
9189
  title: endorsement,
9178
- description: cleanText([endorsement, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "), endorsement),
9190
+ description: endorsementDescription(endorsement, node),
9179
9191
  metadata: { ...node.metadata, organizerRepair: "semantic_page_grouping" }
9180
9192
  };
9181
9193
  }
@@ -9261,6 +9273,124 @@ function endorsementGroupNodeId(documentId, parentId) {
9261
9273
  parentId?.replace(/[^a-zA-Z0-9_.:-]/g, "_").slice(0, 48) ?? "root"
9262
9274
  ].join(":");
9263
9275
  }
9276
+ function isPolicyFormNode(node) {
9277
+ return node.title === "Policy Form" && (node.kind === "form" || node.kind === "page_group");
9278
+ }
9279
+ function isDeclarationsNode(node) {
9280
+ return node.kind === "page_group" && node.title === "Declarations";
9281
+ }
9282
+ function normalizePolicyFormStructure(sourceTree) {
9283
+ let nextTree = sourceTree;
9284
+ const byParent = nodesByParent(nextTree);
9285
+ const nodesToRemove = /* @__PURE__ */ new Set();
9286
+ for (const form of nextTree.filter((node) => node.kind === "form" && node.title === "Policy Form")) {
9287
+ const children = byParent.get(form.id) ?? [];
9288
+ const declarationsChildren = children.filter(isDeclarationsNode);
9289
+ const nestedPolicyForm = children.find((child) => child.id !== form.id && isPolicyFormNode(child));
9290
+ if (declarationsChildren.length === 0 && !nestedPolicyForm) continue;
9291
+ const declarationIds = new Set(declarationsChildren.map((child) => child.id));
9292
+ nextTree = nextTree.map((node) => {
9293
+ if (declarationIds.has(node.id)) {
9294
+ return {
9295
+ ...node,
9296
+ parentId: form.parentId,
9297
+ metadata: {
9298
+ ...node.metadata,
9299
+ organizerRepair: "promote_declarations_from_policy_form"
9300
+ }
9301
+ };
9302
+ }
9303
+ if (nestedPolicyForm && node.parentId === nestedPolicyForm.id) {
9304
+ return {
9305
+ ...node,
9306
+ parentId: form.id,
9307
+ metadata: {
9308
+ ...node.metadata,
9309
+ organizerRepair: "collapse_nested_policy_form"
9310
+ }
9311
+ };
9312
+ }
9313
+ return node;
9314
+ });
9315
+ if (nestedPolicyForm) nodesToRemove.add(nestedPolicyForm.id);
9316
+ }
9317
+ if (nodesToRemove.size > 0) {
9318
+ nextTree = nextTree.filter((node) => !nodesToRemove.has(node.id));
9319
+ }
9320
+ return nextTree;
9321
+ }
9322
+ function nestEndorsementContinuationPages(sourceTree) {
9323
+ const byParent = nodesByParent(sourceTree);
9324
+ const continuationParentById = /* @__PURE__ */ new Map();
9325
+ for (const group of sourceTree.filter(isEndorsementGroup)) {
9326
+ const children = byParent.get(group.id) ?? [];
9327
+ let currentEndorsement;
9328
+ for (const child of children) {
9329
+ if (child.kind === "endorsement" && endorsementStartTitle(child)) {
9330
+ currentEndorsement = child;
9331
+ continue;
9332
+ }
9333
+ if (!currentEndorsement || child.kind !== "page") continue;
9334
+ continuationParentById.set(child.id, currentEndorsement.id);
9335
+ }
9336
+ }
9337
+ if (continuationParentById.size === 0) return sourceTree;
9338
+ return sourceTree.map((node) => {
9339
+ const parentId = continuationParentById.get(node.id);
9340
+ if (!parentId) return node;
9341
+ return {
9342
+ ...node,
9343
+ parentId,
9344
+ metadata: {
9345
+ ...node.metadata,
9346
+ organizerRepair: "nest_endorsement_continuation"
9347
+ }
9348
+ };
9349
+ });
9350
+ }
9351
+ function nodeDepth(node) {
9352
+ return node.path ? node.path.split("/").filter(Boolean).length : 0;
9353
+ }
9354
+ function shouldUseOwnEvidenceForContainer(node) {
9355
+ return node.kind === "endorsement" || node.kind === "page" || node.kind === "table" || node.kind === "table_row" || node.kind === "table_cell" || node.kind === "text";
9356
+ }
9357
+ function normalizeContainerEvidenceFromChildren(sourceTree) {
9358
+ const byParent = nodesByParent(sourceTree);
9359
+ const byId = new Map(sourceTree.map((node) => [node.id, node]));
9360
+ const sorted = [...sourceTree].sort((left, right) => nodeDepth(right) - nodeDepth(left));
9361
+ for (const originalNode of sorted) {
9362
+ const children = (byParent.get(originalNode.id) ?? []).map((child) => byId.get(child.id)).filter((child) => Boolean(child));
9363
+ if (children.length === 0) continue;
9364
+ const currentNode = byId.get(originalNode.id) ?? originalNode;
9365
+ const evidenceNodes = shouldUseOwnEvidenceForContainer(currentNode) ? [currentNode, ...children] : children;
9366
+ const pageStarts = evidenceNodes.map((node) => node.pageStart).filter((page) => typeof page === "number");
9367
+ const pageEnds = evidenceNodes.map((node) => node.pageEnd ?? node.pageStart).filter((page) => typeof page === "number");
9368
+ const sourceSpanIds = [...new Set(evidenceNodes.flatMap((node) => node.sourceSpanIds))];
9369
+ const bbox = evidenceNodes.flatMap((node) => node.bbox ?? []).slice(0, 12);
9370
+ const childText = children.map((child) => child.textExcerpt ?? child.description).filter(Boolean).join("\n\n").slice(0, 1600);
9371
+ byId.set(currentNode.id, {
9372
+ ...currentNode,
9373
+ sourceSpanIds,
9374
+ pageStart: pageStarts.length ? Math.min(...pageStarts) : currentNode.pageStart,
9375
+ pageEnd: pageEnds.length ? Math.max(...pageEnds) : currentNode.pageEnd,
9376
+ bbox,
9377
+ order: Math.min(currentNode.order, ...children.map((child) => child.order)),
9378
+ textExcerpt: shouldUseOwnEvidenceForContainer(currentNode) ? currentNode.textExcerpt : childText || currentNode.textExcerpt
9379
+ });
9380
+ }
9381
+ return sourceTree.map((node) => byId.get(node.id) ?? node);
9382
+ }
9383
+ function normalizeSemanticHierarchy(sourceTree) {
9384
+ return normalizeDocumentSourceTreePaths(
9385
+ normalizeContainerEvidenceFromChildren(
9386
+ nestEndorsementContinuationPages(
9387
+ normalizePolicyFormStructure(
9388
+ normalizeDocumentSourceTreePaths(sourceTree)
9389
+ )
9390
+ )
9391
+ )
9392
+ );
9393
+ }
9264
9394
  function applyEndorsementGrouping(sourceTree) {
9265
9395
  const relabeledTree = sourceTree.map((node) => {
9266
9396
  if (node.kind === "document" || isEndorsementGroup(node)) return node;
@@ -9281,10 +9411,7 @@ function applyEndorsementGrouping(sourceTree) {
9281
9411
  ...node,
9282
9412
  kind: "endorsement",
9283
9413
  title,
9284
- description: cleanText(
9285
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9286
- title
9287
- ),
9414
+ description: endorsementDescription(title, node),
9288
9415
  metadata: {
9289
9416
  ...node.metadata,
9290
9417
  organizerRepair: "normalize_endorsement_grouping"
@@ -9321,10 +9448,7 @@ function applyEndorsementGrouping(sourceTree) {
9321
9448
  ...node,
9322
9449
  kind: "endorsement",
9323
9450
  title,
9324
- description: cleanText(
9325
- [title, "endorsement", node.pageStart ? `page ${node.pageStart}` : void 0, node.textExcerpt].filter(Boolean).join(" | "),
9326
- title
9327
- ),
9451
+ description: endorsementDescription(title, node),
9328
9452
  metadata: {
9329
9453
  ...node.metadata,
9330
9454
  organizerRepair: "normalize_endorsement_grouping"
@@ -9335,9 +9459,21 @@ function applyEndorsementGrouping(sourceTree) {
9335
9459
  if (endorsementGroupIds.has(parentId ?? "")) continue;
9336
9460
  const endorsementChildren = children.filter((child) => child.kind === "endorsement" && !isEndorsementGroup(child));
9337
9461
  if (endorsementChildren.length < 2) continue;
9462
+ const endorsementGroupChildren = [];
9463
+ let hasSeenEndorsementStart = false;
9464
+ for (const child of children) {
9465
+ if (child.kind === "endorsement" && !isEndorsementGroup(child)) {
9466
+ hasSeenEndorsementStart = true;
9467
+ endorsementGroupChildren.push(child);
9468
+ continue;
9469
+ }
9470
+ if (hasSeenEndorsementStart && child.kind === "page" && looksLikeEndorsementContinuation(child)) {
9471
+ endorsementGroupChildren.push(child);
9472
+ }
9473
+ }
9338
9474
  const documentId = endorsementChildren[0].documentId;
9339
- const pageStarts = endorsementChildren.map((child) => child.pageStart).filter((page) => typeof page === "number");
9340
- const pageEnds = endorsementChildren.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
9475
+ const pageStarts = endorsementGroupChildren.map((child) => child.pageStart).filter((page) => typeof page === "number");
9476
+ const pageEnds = endorsementGroupChildren.map((child) => child.pageEnd ?? child.pageStart).filter((page) => typeof page === "number");
9341
9477
  const order = Math.min(...endorsementChildren.map((child) => child.order));
9342
9478
  const existingGroup = groupsByParent.get(parentId);
9343
9479
  const groupId = existingGroup?.id ?? endorsementGroupNodeId(documentId, parentId);
@@ -9352,12 +9488,12 @@ function applyEndorsementGrouping(sourceTree) {
9352
9488
  sourceSpanIds: [],
9353
9489
  pageStart: pageStarts.length ? Math.min(...pageStarts) : void 0,
9354
9490
  pageEnd: pageEnds.length ? Math.max(...pageEnds) : void 0,
9355
- bbox: endorsementChildren.flatMap((child) => child.bbox ?? []).slice(0, 12),
9491
+ bbox: endorsementGroupChildren.flatMap((child) => child.bbox ?? []).slice(0, 12),
9356
9492
  order,
9357
9493
  path: "",
9358
9494
  metadata: { sourceTreeVersion: "v3", organizer: "endorsement_grouping" }
9359
9495
  };
9360
- const childSpanIds = [...new Set(endorsementChildren.flatMap((child) => child.sourceSpanIds))];
9496
+ const childSpanIds = [...new Set(endorsementGroupChildren.flatMap((child) => child.sourceSpanIds))];
9361
9497
  const normalizedGroup = {
9362
9498
  ...groupNode,
9363
9499
  sourceSpanIds: groupNode.sourceSpanIds.length ? groupNode.sourceSpanIds : childSpanIds,
@@ -9368,11 +9504,12 @@ function applyEndorsementGrouping(sourceTree) {
9368
9504
  groupsByParent.set(parentId, normalizedGroup);
9369
9505
  if (!existingGroup) nextTree.push(normalizedGroup);
9370
9506
  else nextTree = nextTree.map((node) => node.id === normalizedGroup.id ? normalizedGroup : node);
9507
+ const endorsementGroupChildIds = new Set(endorsementGroupChildren.map((child) => child.id));
9371
9508
  nextTree = nextTree.map(
9372
- (node) => endorsementChildren.some((child) => child.id === node.id) ? { ...node, parentId: groupId, order: node.order + 1e-3 } : node
9509
+ (node) => endorsementGroupChildIds.has(node.id) ? { ...node, parentId: groupId, order: node.order + 1e-3 } : node
9373
9510
  );
9374
9511
  }
9375
- return normalizeDocumentSourceTreePaths(nextTree);
9512
+ return normalizeSemanticHierarchy(nextTree);
9376
9513
  }
9377
9514
  function compactNode(node, maxText = 700) {
9378
9515
  return {
@@ -9756,7 +9893,7 @@ async function runSourceTreeExtraction(params) {
9756
9893
  maxTokens: budget.maxTokens,
9757
9894
  taskKind: "extraction_operational_profile",
9758
9895
  budgetDiagnostics: budget,
9759
- providerOptions: { ...params.providerOptions, sourceSpans, sourceTree }
9896
+ providerOptions: params.providerOptions
9760
9897
  },
9761
9898
  {
9762
9899
  fallback: deterministicProfile,