@claritylabs/cl-sdk 3.0.1 → 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.mjs CHANGED
@@ -8890,6 +8890,8 @@ var ORGANIZABLE_KINDS = [
8890
8890
  "schedule",
8891
8891
  "clause"
8892
8892
  ];
8893
+ var ORGANIZATION_TOP_LEVEL_BATCH_SIZE = 80;
8894
+ var ORGANIZATION_CHILD_CONTEXT_LIMIT = 4;
8893
8895
  var SourceTreeOrganizationSchema = z41.object({
8894
8896
  labels: z41.array(z41.object({
8895
8897
  nodeId: z41.string(),
@@ -8909,20 +8911,20 @@ var SourceTreeOrganizationSchema = z41.object({
8909
8911
  ]).optional(),
8910
8912
  title: z41.string().optional(),
8911
8913
  description: z41.string().optional()
8912
- })).default([]),
8914
+ })),
8913
8915
  groups: z41.array(z41.object({
8914
8916
  kind: z41.enum(ORGANIZABLE_KINDS),
8915
8917
  title: z41.string(),
8916
8918
  description: z41.string().optional(),
8917
8919
  childNodeIds: z41.array(z41.string()).min(1)
8918
- })).default([])
8920
+ }))
8919
8921
  });
8920
8922
  var SourceBackedValueForPromptSchema = z41.object({
8921
8923
  value: z41.string(),
8922
8924
  normalizedValue: z41.string().optional(),
8923
8925
  confidence: z41.enum(["low", "medium", "high"]).optional(),
8924
- sourceNodeIds: z41.array(z41.string()).default([]),
8925
- sourceSpanIds: z41.array(z41.string()).default([])
8926
+ sourceNodeIds: z41.array(z41.string()),
8927
+ sourceSpanIds: z41.array(z41.string())
8926
8928
  });
8927
8929
  var OperationalProfilePromptSchema = z41.object({
8928
8930
  documentType: z41.enum(["policy", "quote"]).optional(),
@@ -8944,8 +8946,8 @@ var OperationalProfilePromptSchema = z41.object({
8944
8946
  premium: z41.string().optional(),
8945
8947
  formNumber: z41.string().optional(),
8946
8948
  sectionRef: z41.string().optional(),
8947
- sourceNodeIds: z41.array(z41.string()).default([]),
8948
- sourceSpanIds: z41.array(z41.string()).default([])
8949
+ sourceNodeIds: z41.array(z41.string()),
8950
+ sourceSpanIds: z41.array(z41.string())
8949
8951
  })).optional(),
8950
8952
  sourceNodeIds: z41.array(z41.string()).optional(),
8951
8953
  sourceSpanIds: z41.array(z41.string()).optional()
@@ -8954,7 +8956,7 @@ function cleanText(value, fallback) {
8954
8956
  const text = value?.replace(/\s+/g, " ").trim();
8955
8957
  return text || fallback;
8956
8958
  }
8957
- function compactNode(node) {
8959
+ function compactNode(node, maxText = 700) {
8958
8960
  return {
8959
8961
  id: node.id,
8960
8962
  kind: node.kind,
@@ -8963,19 +8965,89 @@ function compactNode(node) {
8963
8965
  pageStart: node.pageStart,
8964
8966
  pageEnd: node.pageEnd,
8965
8967
  sourceSpanIds: node.sourceSpanIds.slice(0, 8),
8966
- text: (node.textExcerpt ?? node.description).slice(0, 700)
8968
+ text: (node.textExcerpt ?? node.description).slice(0, maxText)
8969
+ };
8970
+ }
8971
+ function nodesByParent(sourceTree) {
8972
+ const byParent = /* @__PURE__ */ new Map();
8973
+ for (const node of sourceTree) {
8974
+ const children = byParent.get(node.parentId) ?? [];
8975
+ children.push(node);
8976
+ byParent.set(node.parentId, children);
8977
+ }
8978
+ for (const children of byParent.values()) {
8979
+ children.sort((left, right) => left.order - right.order || left.id.localeCompare(right.id));
8980
+ }
8981
+ return byParent;
8982
+ }
8983
+ function sourceTreeRootId(sourceTree) {
8984
+ return sourceTree.find((node) => node.kind === "document")?.id;
8985
+ }
8986
+ function organizationBatches(sourceTree) {
8987
+ const byParent = nodesByParent(sourceTree);
8988
+ const rootId = sourceTreeRootId(sourceTree);
8989
+ const topLevelNodes = (byParent.get(rootId) ?? []).filter((node) => node.kind !== "document");
8990
+ if (topLevelNodes.length === 0) {
8991
+ const nodes = sourceTree.filter((node) => node.kind !== "document").slice(0, 240);
8992
+ return [{
8993
+ label: "fallback node prefix because no document root children were found",
8994
+ topLevelNodeIds: nodes.map((node) => node.id),
8995
+ nodes
8996
+ }];
8997
+ }
8998
+ const batches = [];
8999
+ for (let index = 0; index < topLevelNodes.length; index += ORGANIZATION_TOP_LEVEL_BATCH_SIZE) {
9000
+ const topLevelBatch = topLevelNodes.slice(index, index + ORGANIZATION_TOP_LEVEL_BATCH_SIZE);
9001
+ const candidates = /* @__PURE__ */ new Map();
9002
+ for (const node of topLevelBatch) {
9003
+ candidates.set(node.id, node);
9004
+ const childContext = (byParent.get(node.id) ?? []).filter((child) => child.kind !== "text" && child.kind !== "table_cell").slice(0, ORGANIZATION_CHILD_CONTEXT_LIMIT);
9005
+ for (const child of childContext) {
9006
+ candidates.set(child.id, child);
9007
+ }
9008
+ }
9009
+ batches.push({
9010
+ label: `top-level nodes ${index + 1}-${index + topLevelBatch.length} of ${topLevelNodes.length}`,
9011
+ topLevelNodeIds: topLevelBatch.map((node) => node.id),
9012
+ nodes: [...candidates.values()]
9013
+ });
9014
+ }
9015
+ return batches;
9016
+ }
9017
+ function mergeOrganizationResults(results) {
9018
+ const labels = /* @__PURE__ */ new Map();
9019
+ const groups = /* @__PURE__ */ new Map();
9020
+ for (const result of results) {
9021
+ for (const label of result.labels) {
9022
+ labels.set(label.nodeId, { ...labels.get(label.nodeId), ...label });
9023
+ }
9024
+ for (const group of result.groups) {
9025
+ const key = `${group.kind}:${group.childNodeIds.join("|")}`;
9026
+ groups.set(key, group);
9027
+ }
9028
+ }
9029
+ return {
9030
+ labels: [...labels.values()],
9031
+ groups: [...groups.values()]
8967
9032
  };
8968
9033
  }
8969
- function buildOrganizationPrompt(sourceTree) {
8970
- const nodes = sourceTree.filter((node) => node.kind !== "table_cell").slice(0, 180).map(compactNode);
9034
+ function buildOrganizationPrompt(batch) {
9035
+ const nodes = batch.nodes.map((node) => compactNode(node, node.kind === "page" ? 900 : 320));
8971
9036
  return `You organize an insurance document source tree.
8972
9037
 
9038
+ Scope:
9039
+ - ${batch.label}
9040
+ - The provided list is a bounded extraction-time batch. It is not necessarily the whole document.
9041
+ - Top-level page/form candidates in this batch: ${JSON.stringify(batch.topLevelNodeIds)}
9042
+
8973
9043
  Rules:
8974
9044
  - Use only node IDs from the provided list.
8975
9045
  - Do not invent text, page numbers, source spans, limits, or policy facts.
8976
- - 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.
9046
+ - 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.
9047
+ - Add concise, human-readable titles to generic text, table, row, and cell nodes when the text makes their role clear.
8977
9048
  - Groups must list existing childNodeIds only.
8978
9049
  - Keep descriptions short and useful for search.
9050
+ - Prefer the document's own form titles, endorsement titles, schedules, declarations headings, and page order over keyword-only guessing.
8979
9051
 
8980
9052
  Source nodes:
8981
9053
  ${JSON.stringify(nodes, null, 2)}
@@ -9015,8 +9087,9 @@ function groupNodeId(documentId, group) {
9015
9087
  }
9016
9088
  function applyOrganization(sourceTree, organization) {
9017
9089
  const byId = new Map(sourceTree.map((node) => [node.id, node]));
9090
+ const labels = new Map(organization.labels.map((label) => [label.nodeId, label]));
9018
9091
  let nextTree = sourceTree.map((node) => {
9019
- const label = organization.labels.find((item) => item.nodeId === node.id);
9092
+ const label = labels.get(node.id);
9020
9093
  if (!label) return node;
9021
9094
  return {
9022
9095
  ...node,
@@ -9025,7 +9098,7 @@ function applyOrganization(sourceTree, organization) {
9025
9098
  description: cleanText(label.description, node.description)
9026
9099
  };
9027
9100
  });
9028
- for (const group of organization.groups.slice(0, 40)) {
9101
+ for (const group of organization.groups) {
9029
9102
  const children = group.childNodeIds.map((id2) => byId.get(id2)).filter((node2) => Boolean(node2));
9030
9103
  if (children.length === 0) continue;
9031
9104
  const parentId = children[0].parentId;
@@ -9083,6 +9156,7 @@ function sourceTreeToOutline(sourceTree) {
9083
9156
  sourceSpanIds: node.sourceSpanIds,
9084
9157
  sourceTextHash: node.sourceSpanIds.join(":") || void 0,
9085
9158
  interpretationLabels: [node.kind],
9159
+ metadata: node.metadata,
9086
9160
  children: (byParent.get(node.id) ?? []).map(visit)
9087
9161
  });
9088
9162
  return (byParent.get(root?.id) ?? []).map(visit);
@@ -9206,30 +9280,35 @@ async function runSourceTreeExtraction(params) {
9206
9280
  params.trackUsage(usage, report);
9207
9281
  };
9208
9282
  try {
9209
- const budget = params.resolveBudget("extraction_source_tree", 4096);
9210
- const startedAt = Date.now();
9211
- const response = await safeGenerateObject(
9212
- params.generateObject,
9213
- {
9214
- prompt: buildOrganizationPrompt(sourceTree),
9215
- schema: SourceTreeOrganizationSchema,
9216
- maxTokens: budget.maxTokens,
9283
+ const organizations = [];
9284
+ const batches = organizationBatches(sourceTree);
9285
+ for (const [batchIndex, batch] of batches.entries()) {
9286
+ const budget = params.resolveBudget("extraction_source_tree", 4096);
9287
+ const startedAt = Date.now();
9288
+ const response = await safeGenerateObject(
9289
+ params.generateObject,
9290
+ {
9291
+ prompt: buildOrganizationPrompt(batch),
9292
+ schema: SourceTreeOrganizationSchema,
9293
+ maxTokens: budget.maxTokens,
9294
+ taskKind: "extraction_source_tree",
9295
+ budgetDiagnostics: budget,
9296
+ providerOptions: { ...params.providerOptions, sourceSpans: params.sourceSpans }
9297
+ },
9298
+ {
9299
+ fallback: { labels: [], groups: [] },
9300
+ log: params.log
9301
+ }
9302
+ );
9303
+ localTrack(response.usage, {
9217
9304
  taskKind: "extraction_source_tree",
9218
- budgetDiagnostics: budget,
9219
- providerOptions: { ...params.providerOptions, sourceSpans: params.sourceSpans }
9220
- },
9221
- {
9222
- fallback: { labels: [], groups: [] },
9223
- log: params.log
9224
- }
9225
- );
9226
- localTrack(response.usage, {
9227
- taskKind: "extraction_source_tree",
9228
- label: "source_tree_organizer",
9229
- maxTokens: budget.maxTokens,
9230
- durationMs: Date.now() - startedAt
9231
- });
9232
- sourceTree = applyOrganization(sourceTree, response.object);
9305
+ label: batches.length > 1 ? `source_tree_organizer_${batchIndex + 1}` : "source_tree_organizer",
9306
+ maxTokens: budget.maxTokens,
9307
+ durationMs: Date.now() - startedAt
9308
+ });
9309
+ organizations.push(response.object);
9310
+ }
9311
+ sourceTree = applyOrganization(sourceTree, mergeOrganizationResults(organizations));
9233
9312
  } catch (error) {
9234
9313
  warnings.push(`Source-tree organizer failed; deterministic tree used (${error instanceof Error ? error.message : String(error)})`);
9235
9314
  }