@claritylabs/cl-sdk 3.1.18 → 3.1.19

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.d.mts CHANGED
@@ -4,7 +4,11 @@ import * as zod from 'zod';
4
4
  import { ZodTypeAny, z, ZodSchema } from 'zod';
5
5
  import { PDFDocument } from 'pdf-lib';
6
6
 
7
- declare function withRetry<T>(fn: () => Promise<T>, log?: LogFn): Promise<T>;
7
+ interface RetryOptions {
8
+ maxRetries?: number;
9
+ baseDelayMs?: number;
10
+ }
11
+ declare function withRetry<T>(fn: () => Promise<T>, log?: LogFn, options?: RetryOptions): Promise<T>;
8
12
 
9
13
  /**
10
14
  * Concurrency limiter — returns a function that wraps async tasks
@@ -31,6 +35,8 @@ interface SafeGenerateOptions<T> {
31
35
  onError?: (error: unknown, attempt: number) => void;
32
36
  /** Logger for pipeline status messages. */
33
37
  log?: LogFn;
38
+ /** Controls retryable provider-error backoff around the host callback. Use false when the host already owns fallback. */
39
+ retry?: RetryOptions | false;
34
40
  }
35
41
  interface SafeGenerateParams {
36
42
  prompt: string;
@@ -44,7 +50,7 @@ interface SafeGenerateParams {
44
50
  /**
45
51
  * Wraps a `generateObject` call with two layers of resilience:
46
52
  *
47
- * 1. Inner: `withRetry` handles 429 / rate-limit errors with exponential backoff
53
+ * 1. Inner: `withRetry` handles retryable provider errors with exponential backoff unless disabled.
48
54
  * 2. Outer: catches all other errors (schema validation, malformed JSON, transient API errors)
49
55
  * and retries up to `maxRetries` times. If all retries fail, returns `fallback` (if provided)
50
56
  * or re-throws.
package/dist/index.d.ts CHANGED
@@ -4,7 +4,11 @@ import * as zod from 'zod';
4
4
  import { ZodTypeAny, z, ZodSchema } from 'zod';
5
5
  import { PDFDocument } from 'pdf-lib';
6
6
 
7
- declare function withRetry<T>(fn: () => Promise<T>, log?: LogFn): Promise<T>;
7
+ interface RetryOptions {
8
+ maxRetries?: number;
9
+ baseDelayMs?: number;
10
+ }
11
+ declare function withRetry<T>(fn: () => Promise<T>, log?: LogFn, options?: RetryOptions): Promise<T>;
8
12
 
9
13
  /**
10
14
  * Concurrency limiter — returns a function that wraps async tasks
@@ -31,6 +35,8 @@ interface SafeGenerateOptions<T> {
31
35
  onError?: (error: unknown, attempt: number) => void;
32
36
  /** Logger for pipeline status messages. */
33
37
  log?: LogFn;
38
+ /** Controls retryable provider-error backoff around the host callback. Use false when the host already owns fallback. */
39
+ retry?: RetryOptions | false;
34
40
  }
35
41
  interface SafeGenerateParams {
36
42
  prompt: string;
@@ -44,7 +50,7 @@ interface SafeGenerateParams {
44
50
  /**
45
51
  * Wraps a `generateObject` call with two layers of resilience:
46
52
  *
47
- * 1. Inner: `withRetry` handles 429 / rate-limit errors with exponential backoff
53
+ * 1. Inner: `withRetry` handles retryable provider errors with exponential backoff unless disabled.
48
54
  * 2. Outer: catches all other errors (schema validation, malformed JSON, transient API errors)
49
55
  * and retries up to `maxRetries` times. If all retries fail, returns `fallback` (if provided)
50
56
  * or re-throws.
package/dist/index.js CHANGED
@@ -396,17 +396,19 @@ function isRetryableError(error) {
396
396
  }
397
397
  return false;
398
398
  }
399
- async function withRetry(fn, log) {
399
+ async function withRetry(fn, log, options) {
400
+ const maxRetries = options?.maxRetries ?? MAX_RETRIES;
401
+ const baseDelayMs = options?.baseDelayMs ?? BASE_DELAY_MS;
400
402
  for (let attempt = 0; ; attempt++) {
401
403
  try {
402
404
  return await fn();
403
405
  } catch (error) {
404
- if (!isRetryableError(error) || attempt >= MAX_RETRIES) {
406
+ if (!isRetryableError(error) || attempt >= maxRetries) {
405
407
  throw error;
406
408
  }
407
409
  const jitter = Math.random() * 1e3;
408
- const delay = BASE_DELAY_MS * Math.pow(2, attempt) + jitter;
409
- await log?.(`Retryable error, retrying in ${(delay / 1e3).toFixed(1)}s (attempt ${attempt + 1}/${MAX_RETRIES})...`);
410
+ const delay = baseDelayMs * Math.pow(2, attempt) + jitter;
411
+ await log?.(`Retryable error, retrying in ${(delay / 1e3).toFixed(1)}s (attempt ${attempt + 1}/${maxRetries})...`);
410
412
  await new Promise((resolve) => setTimeout(resolve, delay));
411
413
  }
412
414
  }
@@ -533,10 +535,8 @@ async function safeGenerateObject(generateObject, params, options) {
533
535
  const strictParams = { ...params, schema: toStrictSchema(params.schema) };
534
536
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
535
537
  try {
536
- const result = await withRetry(
537
- () => generateObject(strictParams),
538
- options?.log
539
- );
538
+ const generate = () => generateObject(strictParams);
539
+ const result = options?.retry === false ? await generate() : await withRetry(generate, options?.log, options?.retry);
540
540
  return {
541
541
  ...result,
542
542
  object: params.schema.parse(sanitizeNulls(result.object))
@@ -11782,7 +11782,9 @@ async function runVisualTableRepair(params) {
11782
11782
  },
11783
11783
  {
11784
11784
  fallback: { tables: [], warnings: [] },
11785
- log: params.log
11785
+ maxRetries: 0,
11786
+ log: params.log,
11787
+ retry: false
11786
11788
  }
11787
11789
  );
11788
11790
  return {
@@ -11913,32 +11915,6 @@ var NORMALIZED_COMPATIBILITY_FIELDS = /* @__PURE__ */ new Set([
11913
11915
  "insurer",
11914
11916
  "broker"
11915
11917
  ]);
11916
- function coverageBelongsToEndorsementCleanupChunk(coverage) {
11917
- return coverage.coverageOrigin === "endorsement" || Boolean(coverage.endorsementNumber);
11918
- }
11919
- function coverageCleanupChunks(profile) {
11920
- const basePolicy = [];
11921
- const endorsements = [];
11922
- profile.coverages.forEach((coverage, coverageIndex) => {
11923
- if (coverageBelongsToEndorsementCleanupChunk(coverage)) {
11924
- endorsements.push(coverageIndex);
11925
- } else {
11926
- basePolicy.push(coverageIndex);
11927
- }
11928
- });
11929
- return [
11930
- basePolicy.length ? {
11931
- group: "base_policy",
11932
- label: "Coverage cleanup: base policy",
11933
- coverageIndexes: basePolicy
11934
- } : void 0,
11935
- endorsements.length ? {
11936
- group: "endorsements",
11937
- label: "Coverage cleanup: endorsements",
11938
- coverageIndexes: endorsements
11939
- } : void 0
11940
- ].filter((chunk) => Boolean(chunk));
11941
- }
11942
11918
  function valueOf(profile, key) {
11943
11919
  const value = profile[key];
11944
11920
  if (!value || typeof value !== "object" || Array.isArray(value) || !("value" in value)) return void 0;
@@ -12117,7 +12093,9 @@ async function runSourceTreeExtraction(params) {
12117
12093
  },
12118
12094
  {
12119
12095
  fallback: { labels: [], groups: [] },
12120
- log: params.log
12096
+ maxRetries: 0,
12097
+ log: params.log,
12098
+ retry: false
12121
12099
  }
12122
12100
  );
12123
12101
  return {
@@ -12162,7 +12140,9 @@ async function runSourceTreeExtraction(params) {
12162
12140
  },
12163
12141
  {
12164
12142
  fallback: { labels: [], groups: [] },
12165
- log: params.log
12143
+ maxRetries: 0,
12144
+ log: params.log,
12145
+ retry: false
12166
12146
  }
12167
12147
  );
12168
12148
  localTrack(response.usage, {
@@ -12204,7 +12184,9 @@ async function runSourceTreeExtraction(params) {
12204
12184
  },
12205
12185
  {
12206
12186
  fallback: emptyProfile,
12207
- log: params.log
12187
+ maxRetries: 0,
12188
+ log: params.log,
12189
+ retry: false
12208
12190
  }
12209
12191
  );
12210
12192
  localTrack(response.usage, {
@@ -12226,64 +12208,40 @@ async function runSourceTreeExtraction(params) {
12226
12208
  try {
12227
12209
  const validNodeIds = new Set(sourceTree.map((node) => node.id));
12228
12210
  const validSpanIds = new Set(sourceSpans.map((span) => span.id));
12229
- const chunks = coverageCleanupChunks(operationalProfile);
12230
- if (chunks.length > 1) {
12231
- await params.log?.(`Operational profile coverage cleanup reviewing ${chunks.length} coverage groups in parallel`);
12232
- }
12233
- const cleanupResults = await Promise.all(chunks.map(async (chunk, batchIndex) => {
12234
- const budget = params.resolveBudget("extraction_coverage_cleanup", 4096);
12235
- const startedAt = Date.now();
12236
- const response = await safeGenerateObject(
12237
- params.generateObject,
12238
- {
12239
- prompt: buildOperationalProfileCleanupPrompt(sourceTree, operationalProfile, {
12240
- coverageIndexes: chunk.coverageIndexes,
12241
- label: chunk.label
12242
- }),
12243
- schema: OperationalProfileCleanupSchema,
12244
- maxTokens: budget.maxTokens,
12245
- taskKind: "extraction_coverage_cleanup",
12246
- budgetDiagnostics: budget,
12247
- providerOptions: params.providerOptions,
12248
- trace: {
12249
- phase: "coverage_cleanup",
12250
- label: chunk.label,
12251
- batchIndex: batchIndex + 1,
12252
- batchCount: chunks.length,
12253
- coverageGroup: chunk.group,
12254
- itemCount: chunk.coverageIndexes.length,
12255
- sourceBacked: true
12256
- }
12257
- },
12258
- {
12259
- fallback: { coverageDecisions: [], warnings: [] },
12260
- maxRetries: 0,
12261
- log: params.log
12262
- }
12263
- );
12264
- return {
12265
- batchIndex,
12266
- chunk,
12267
- budget,
12268
- durationMs: Date.now() - startedAt,
12269
- usage: response.usage,
12270
- cleanup: response.object
12271
- };
12272
- }));
12273
- const cleanup = { coverageDecisions: [], warnings: [] };
12274
- for (const result of cleanupResults.sort((left, right) => left.batchIndex - right.batchIndex)) {
12275
- localTrack(result.usage, {
12211
+ const budget = params.resolveBudget("extraction_coverage_cleanup", 4096);
12212
+ const startedAt = Date.now();
12213
+ const response = await safeGenerateObject(
12214
+ params.generateObject,
12215
+ {
12216
+ prompt: buildOperationalProfileCleanupPrompt(sourceTree, operationalProfile),
12217
+ schema: OperationalProfileCleanupSchema,
12218
+ maxTokens: budget.maxTokens,
12276
12219
  taskKind: "extraction_coverage_cleanup",
12277
- label: result.chunk.label,
12278
- maxTokens: result.budget.maxTokens,
12279
- durationMs: result.durationMs
12280
- });
12281
- cleanup.coverageDecisions.push(...result.cleanup.coverageDecisions);
12282
- cleanup.warnings.push(...result.cleanup.warnings);
12283
- }
12220
+ budgetDiagnostics: budget,
12221
+ providerOptions: params.providerOptions,
12222
+ trace: {
12223
+ phase: "coverage_cleanup",
12224
+ label: "Coverage cleanup",
12225
+ itemCount: operationalProfile.coverages.length,
12226
+ sourceBacked: true
12227
+ }
12228
+ },
12229
+ {
12230
+ fallback: { coverageDecisions: [], warnings: [] },
12231
+ maxRetries: 0,
12232
+ log: params.log,
12233
+ retry: false
12234
+ }
12235
+ );
12236
+ localTrack(response.usage, {
12237
+ taskKind: "extraction_coverage_cleanup",
12238
+ label: "coverage_cleanup",
12239
+ maxTokens: budget.maxTokens,
12240
+ durationMs: Date.now() - startedAt
12241
+ });
12284
12242
  operationalProfile = applyOperationalProfileCleanup(
12285
12243
  operationalProfile,
12286
- cleanup,
12244
+ response.object,
12287
12245
  validNodeIds,
12288
12246
  validSpanIds
12289
12247
  );
@@ -12681,7 +12639,9 @@ ${sourceText}`;
12681
12639
  },
12682
12640
  {
12683
12641
  fallback: { forms: [] },
12642
+ maxRetries: 0,
12684
12643
  log,
12644
+ retry: false,
12685
12645
  onError: (err, attempt) => log?.(`Form inventory attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`)
12686
12646
  }
12687
12647
  );