@claritylabs/cl-sdk 3.2.11 → 3.2.12

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
@@ -182,6 +182,7 @@ __export(src_exports, {
182
182
  POLICY_SECTION_TYPES: () => POLICY_SECTION_TYPES,
183
183
  POLICY_TERM_TYPES: () => POLICY_TERM_TYPES,
184
184
  POLICY_TYPES: () => POLICY_TYPES,
185
+ POLICY_TYPES_FROM_COVERAGES_WARNING: () => POLICY_TYPES_FROM_COVERAGES_WARNING,
185
186
  ParsedAnswerSchema: () => ParsedAnswerSchema,
186
187
  PaymentInstallmentSchema: () => PaymentInstallmentSchema,
187
188
  PaymentPlanSchema: () => PaymentPlanSchema,
@@ -337,6 +338,7 @@ __export(src_exports, {
337
338
  getNextApplicationQuestions: () => getNextApplicationQuestions,
338
339
  getPdfPageCount: () => getPdfPageCount,
339
340
  getTemplate: () => getTemplate,
341
+ inferPolicyTypesFromOperationalCoverages: () => inferPolicyTypesFromOperationalCoverages,
340
342
  isDoclingExtractionInput: () => isDoclingExtractionInput,
341
343
  isFileReference: () => isFileReference,
342
344
  mergeQuestionAnswers: () => mergeQuestionAnswers,
@@ -345,6 +347,7 @@ __export(src_exports, {
345
347
  normalizeDoclingDocument: () => normalizeDoclingDocument,
346
348
  normalizeDocumentSourceTreePaths: () => normalizeDocumentSourceTreePaths,
347
349
  normalizeForMatch: () => normalizeForMatch,
350
+ normalizeOperationalPolicyTypes: () => normalizeOperationalPolicyTypes,
348
351
  normalizeSourceSpans: () => normalizeSourceSpans,
349
352
  orderSourceEvidence: () => orderSourceEvidence,
350
353
  overlayTextOnPdf: () => overlayTextOnPdf,
@@ -355,6 +358,7 @@ __export(src_exports, {
355
358
  processReply: () => processReply,
356
359
  proposeContextWrites: () => proposeContextWrites,
357
360
  resolveModelBudget: () => resolveModelBudget,
361
+ resolveOperationalProfilePolicyTypes: () => resolveOperationalProfilePolicyTypes,
358
362
  safeGenerateObject: () => safeGenerateObject,
359
363
  sanitizeNulls: () => sanitizeNulls,
360
364
  scoreCaseProposal: () => scoreCaseProposal,
@@ -710,6 +714,10 @@ var PolicyTypeSchema = import_zod2.z.enum([
710
714
  "watercraft",
711
715
  "recreational_vehicle",
712
716
  "farm_ranch",
717
+ "life",
718
+ "critical_illness",
719
+ "disability",
720
+ "long_term_care",
713
721
  "pet",
714
722
  "travel",
715
723
  "identity_theft",
@@ -2515,6 +2523,179 @@ var PolicyOperationalProfileSchema = import_zod20.z.object({
2515
2523
  warnings: import_zod20.z.array(import_zod20.z.string()).default([])
2516
2524
  });
2517
2525
 
2526
+ // src/source/policy-types.ts
2527
+ var POLICY_TYPE_KEYS = new Set(POLICY_TYPES);
2528
+ var POLICY_TYPE_ALIASES = {
2529
+ "general liability": "general_liability",
2530
+ "commercial general liability": "general_liability",
2531
+ cgl: "general_liability",
2532
+ "commercial property": "commercial_property",
2533
+ property: "property",
2534
+ "property insurance": "commercial_property",
2535
+ "commercial auto": "commercial_auto",
2536
+ "commercial automobile": "commercial_auto",
2537
+ "business auto": "commercial_auto",
2538
+ "business automobile": "commercial_auto",
2539
+ "auto physical damage": "commercial_auto",
2540
+ "automobile physical damage": "commercial_auto",
2541
+ "hired non owned auto": "non_owned_auto",
2542
+ "hired non-owned auto": "non_owned_auto",
2543
+ "non owned auto": "non_owned_auto",
2544
+ "non-owned auto": "non_owned_auto",
2545
+ "workers comp": "workers_comp",
2546
+ "workers compensation": "workers_comp",
2547
+ "workers' compensation": "workers_comp",
2548
+ umbrella: "umbrella",
2549
+ "excess liability": "excess_liability",
2550
+ "professional liability": "professional_liability",
2551
+ "errors and omissions": "professional_liability",
2552
+ "e&o": "professional_liability",
2553
+ cyber: "cyber",
2554
+ "cyber liability": "cyber",
2555
+ "network security": "cyber",
2556
+ "privacy liability": "cyber",
2557
+ epli: "epli",
2558
+ "employment practices liability": "epli",
2559
+ "directors and officers": "directors_officers",
2560
+ "directors & officers": "directors_officers",
2561
+ "d&o": "directors_officers",
2562
+ "fiduciary liability insurance": "fiduciary_liability",
2563
+ "crime insurance": "crime_fidelity",
2564
+ "fidelity bond": "crime_fidelity",
2565
+ "inland marine insurance": "inland_marine",
2566
+ "motor truck cargo": "inland_marine",
2567
+ "motor truck cargo legal liability": "inland_marine",
2568
+ "builders risk insurance": "builders_risk",
2569
+ "pollution liability": "environmental",
2570
+ "premises pollution liability": "environmental",
2571
+ "environmental liability": "environmental",
2572
+ "ocean marine insurance": "ocean_marine",
2573
+ "surety bond": "surety",
2574
+ "product liability insurance": "product_liability",
2575
+ "life insurance": "life",
2576
+ "permanent life": "life",
2577
+ "term life": "life",
2578
+ "whole life": "life",
2579
+ "universal life": "life",
2580
+ "critical illness": "critical_illness",
2581
+ "critical illness insurance": "critical_illness",
2582
+ "disability insurance": "disability",
2583
+ "long term care": "long_term_care",
2584
+ "long-term care": "long_term_care"
2585
+ };
2586
+ var POLICY_TYPE_TEXT_PATTERNS = [
2587
+ { type: "general_liability", pattern: /\b(?:commercial\s+)?general\s+liability\b|\bcgl\b/i },
2588
+ { type: "commercial_property", pattern: /\bcommercial\s+property\b|\bproperty\s+insurance\b/i },
2589
+ { type: "commercial_auto", pattern: /\bcommercial\s+auto(?:mobile)?\b|\bbusiness\s+auto(?:mobile)?\b|\bauto(?:mobile)?\s+physical\s+damage\b/i },
2590
+ { type: "non_owned_auto", pattern: /\b(?:hired\s+(?:and\s+)?)?non[-\s]?owned\s+auto\b/i },
2591
+ { type: "workers_comp", pattern: /\bworkers['’]?\s+comp(?:ensation)?\b/i },
2592
+ { type: "umbrella", pattern: /\bcommercial\s+umbrella\b|\bumbrella\s+liability\b/i },
2593
+ { type: "excess_liability", pattern: /\bexcess\s+liability\b/i },
2594
+ { type: "professional_liability", pattern: /\bprofessional\s+liability\b|\berrors?\s*(?:and|&)\s*omissions?\b|\be&o\b/i },
2595
+ { type: "cyber", pattern: /\bcyber\b|\bnetwork\s+security\b|\bprivacy\s+liability\b/i },
2596
+ { type: "epli", pattern: /\bemployment\s+practices?\s+liability\b|\bepli\b/i },
2597
+ { type: "directors_officers", pattern: /\bdirectors?\s*(?:and|&)\s*officers?\b|\bd&o\b/i },
2598
+ { type: "fiduciary_liability", pattern: /\bfiduciary\s+liability\b/i },
2599
+ { type: "crime_fidelity", pattern: /\bcrime\b|\bfidelity\b/i },
2600
+ { type: "inland_marine", pattern: /\binland\s+marine\b|\bmotor\s+truck\s+cargo\b|\bcargo\s+legal\s+liability\b/i },
2601
+ { type: "builders_risk", pattern: /\bbuilders?\s+risk\b/i },
2602
+ { type: "environmental", pattern: /\bpollution\s+liability\b|\benvironmental\s+liability\b/i },
2603
+ { type: "ocean_marine", pattern: /\bocean\s+marine\b/i },
2604
+ { type: "surety", pattern: /\bsurety\b/i },
2605
+ { type: "product_liability", pattern: /\bproduct\s+liability\b|\bproducts?\s+completed\s+operations\b/i },
2606
+ { type: "bop", pattern: /\bbusiness\s*owners?\s+policy\b|\bbop\b/i },
2607
+ { type: "homeowners_ho3", pattern: /\bhomeowners?\s*(?:ho[-\s]?3)?\b/i },
2608
+ { type: "homeowners_ho5", pattern: /\bho[-\s]?5\b/i },
2609
+ { type: "renters_ho4", pattern: /\brenters?\b|\bho[-\s]?4\b/i },
2610
+ { type: "condo_ho6", pattern: /\bcondo(?:minium)?\b|\bho[-\s]?6\b/i },
2611
+ { type: "dwelling_fire", pattern: /\bdwelling\s+fire\b/i },
2612
+ { type: "personal_auto", pattern: /\bpersonal\s+auto\b/i },
2613
+ { type: "personal_umbrella", pattern: /\bpersonal\s+umbrella\b/i },
2614
+ { type: "flood_private", pattern: /\bflood\b/i },
2615
+ { type: "earthquake", pattern: /\bearthquake\b/i },
2616
+ { type: "personal_inland_marine", pattern: /\bpersonal\s+(?:articles|inland\s+marine)\b/i },
2617
+ { type: "watercraft", pattern: /\bwatercraft\b|\bboat\s+insurance\b/i },
2618
+ { type: "recreational_vehicle", pattern: /\brecreational\s+vehicle\b|\brv\s+insurance\b/i },
2619
+ { type: "farm_ranch", pattern: /\bfarm\b|\branch\b/i },
2620
+ { type: "life", pattern: /\blife\s+insurance\b|\bterm\s+life\b|\bwhole\s+life\b|\buniversal\s+life\b/i },
2621
+ { type: "critical_illness", pattern: /\bcritical\s+illness\b/i },
2622
+ { type: "disability", pattern: /\bdisability\s+insurance\b|\btotal\s+disability\b/i },
2623
+ { type: "long_term_care", pattern: /\blong[-\s]?term\s+care\b/i },
2624
+ { type: "pet", pattern: /\bpet\s+insurance\b/i },
2625
+ { type: "travel", pattern: /\btravel\s+insurance\b/i },
2626
+ { type: "identity_theft", pattern: /\bidentity\s+theft\b/i },
2627
+ { type: "title", pattern: /\btitle\s+insurance\b/i }
2628
+ ];
2629
+ var POLICY_TYPES_FROM_COVERAGES_WARNING = "Policy types augmented from extracted coverage labels.";
2630
+ function normalizeWhitespace(value) {
2631
+ return value.replace(/\s+/g, " ").trim();
2632
+ }
2633
+ function normalizeOperationalPolicyTypes(values) {
2634
+ const types = Array.isArray(values) ? values.filter((value) => typeof value === "string") : [];
2635
+ const controlled = types.map((type) => type.trim().toLowerCase().replace(/\s+/g, " ")).map((type) => POLICY_TYPE_ALIASES[type] ?? type.replace(/[\s-]+/g, "_")).filter((type) => POLICY_TYPE_KEYS.has(type));
2636
+ const unique = [...new Set(controlled)].slice(0, 6);
2637
+ return unique.length ? unique : ["other"];
2638
+ }
2639
+ function hasSpecificPolicyType(types) {
2640
+ return types.some((type) => type !== "other");
2641
+ }
2642
+ function policyTypesFromText(value) {
2643
+ const text = normalizeWhitespace(value ?? "");
2644
+ if (!text) return [];
2645
+ const aliasType = POLICY_TYPE_ALIASES[text.toLowerCase()];
2646
+ if (aliasType && POLICY_TYPE_KEYS.has(aliasType)) return [aliasType];
2647
+ return POLICY_TYPE_TEXT_PATTERNS.filter(({ pattern }) => pattern.test(text)).map(({ type }) => type).filter((type) => POLICY_TYPE_KEYS.has(type));
2648
+ }
2649
+ function inferPolicyTypesFromOperationalCoverages(coverages) {
2650
+ const inferred = [];
2651
+ for (const coverage of coverages) {
2652
+ const limits = coverage.limits ?? [];
2653
+ const text = [
2654
+ coverage.coverageCode,
2655
+ coverage.formNumber,
2656
+ coverage.name,
2657
+ ...limits.flatMap((term) => [term.appliesTo, term.label])
2658
+ ].filter((value) => typeof value === "string" && value.trim().length > 0);
2659
+ for (const value of text) {
2660
+ for (const type of policyTypesFromText(value)) {
2661
+ if (!inferred.includes(type)) inferred.push(type);
2662
+ }
2663
+ }
2664
+ }
2665
+ return inferred.slice(0, 6);
2666
+ }
2667
+ function mergePolicyTypes(base, additions) {
2668
+ const merged = [
2669
+ ...base.filter((type) => type !== "other"),
2670
+ ...additions.filter((type) => type !== "other")
2671
+ ];
2672
+ const unique = [...new Set(merged)].slice(0, 6);
2673
+ return unique.length ? unique : base;
2674
+ }
2675
+ function resolveOperationalProfilePolicyTypes(params) {
2676
+ const inferred = inferPolicyTypesFromOperationalCoverages(params.coverages ?? []);
2677
+ const controlled = normalizeOperationalPolicyTypes(params.profileTypes);
2678
+ if (hasSpecificPolicyType(controlled)) {
2679
+ const policyTypes = mergePolicyTypes(controlled, inferred);
2680
+ return {
2681
+ policyTypes,
2682
+ source: policyTypes.length > controlled.filter((type) => type !== "other").length ? "profile_augmented" : "profile"
2683
+ };
2684
+ }
2685
+ const existingControlled = normalizeOperationalPolicyTypes(params.existingTypes);
2686
+ if (hasSpecificPolicyType(existingControlled)) {
2687
+ const policyTypes = mergePolicyTypes(existingControlled, inferred);
2688
+ return {
2689
+ policyTypes,
2690
+ source: policyTypes.length > existingControlled.filter((type) => type !== "other").length ? "existing_augmented" : "existing"
2691
+ };
2692
+ }
2693
+ if (inferred.length > 0) {
2694
+ return { policyTypes: inferred, source: "inferred" };
2695
+ }
2696
+ return { policyTypes: controlled, source: "profile" };
2697
+ }
2698
+
2518
2699
  // src/source/ids.ts
2519
2700
  function normalizeText(text) {
2520
2701
  return text.replace(/\s+/g, " ").trim();
@@ -2581,14 +2762,14 @@ function orderSourceEvidence(evidence) {
2581
2762
  }
2582
2763
 
2583
2764
  // src/source/extraction.ts
2584
- function normalizeWhitespace(value) {
2765
+ function normalizeWhitespace2(value) {
2585
2766
  return value.replace(/\s+/g, " ").trim();
2586
2767
  }
2587
2768
  function sanitizeIdPart(value) {
2588
2769
  return value.replace(/[^a-zA-Z0-9_.:-]/g, "_");
2589
2770
  }
2590
2771
  function buildSourceSpan(input, localIndex = 0) {
2591
- const text = normalizeWhitespace(input.text);
2772
+ const text = normalizeWhitespace2(input.text);
2592
2773
  const textHash = sourceSpanTextHash(text);
2593
2774
  const pagePart = input.pageStart ?? "na";
2594
2775
  const id = [
@@ -2623,7 +2804,7 @@ function buildSourceSpan(input, localIndex = 0) {
2623
2804
  });
2624
2805
  }
2625
2806
  function buildPageSourceSpans(pages) {
2626
- return pages.filter((page) => normalizeWhitespace(page.text).length > 0).map(
2807
+ return pages.filter((page) => normalizeWhitespace2(page.text).length > 0).map(
2627
2808
  (page, index) => buildSourceSpan(
2628
2809
  {
2629
2810
  documentId: page.documentId,
@@ -2674,7 +2855,7 @@ function buildSectionSourceSpans(pages, options = {}) {
2674
2855
  function buildTextSourceSpans(input, options = {}) {
2675
2856
  const maxChars = options.maxChars ?? 4e3;
2676
2857
  const overlapChars = Math.min(options.overlapChars ?? 0, Math.max(0, maxChars - 1));
2677
- const text = normalizeWhitespace(input.text);
2858
+ const text = normalizeWhitespace2(input.text);
2678
2859
  if (!text) return [];
2679
2860
  const spans = [];
2680
2861
  let cursor = 0;
@@ -2749,7 +2930,7 @@ function spanPage(span) {
2749
2930
  }
2750
2931
  function normalizeSourceSpanText(span) {
2751
2932
  const unit = sourceUnit(span);
2752
- const text = normalizeWhitespace(span.text);
2933
+ const text = normalizeWhitespace2(span.text);
2753
2934
  if (!text) return void 0;
2754
2935
  if (isDiscardableBoilerplate(text, unit)) return void 0;
2755
2936
  const cleanedText = cleanBoilerplateLines(text);
@@ -2761,7 +2942,7 @@ function normalizeSourceSpanText(span) {
2761
2942
  });
2762
2943
  }
2763
2944
  function isDiscardableBoilerplate(text, unit) {
2764
- const cleaned = normalizeWhitespace(text.replace(/\bColumn\s+\d+:\s*/gi, ""));
2945
+ const cleaned = normalizeWhitespace2(text.replace(/\bColumn\s+\d+:\s*/gi, ""));
2765
2946
  if (/^SPECIMEN POLICY\s+[-—]\s+FOR TESTING ONLY$/i.test(cleaned)) return true;
2766
2947
  if (/^Page\s+\d+\s+of\s+\d+$/i.test(cleaned)) return true;
2767
2948
  if (/^[A-Z]{2,}(?:-[A-Z0-9]{2,})+\s+\d{2}\s+\d{2}$/i.test(cleaned)) return true;
@@ -2770,24 +2951,24 @@ function isDiscardableBoilerplate(text, unit) {
2770
2951
  return false;
2771
2952
  }
2772
2953
  function isBoilerplateLine(line) {
2773
- const cleaned = normalizeWhitespace(line.replace(/\bColumn\s+\d+:\s*/gi, ""));
2954
+ const cleaned = normalizeWhitespace2(line.replace(/\bColumn\s+\d+:\s*/gi, ""));
2774
2955
  return isDiscardableBoilerplate(cleaned) || /^THIS IS A CLAIMS-MADE AND REPORTED POLICY\.? PLEASE READ IT CAREFULLY\.?$/i.test(cleaned);
2775
2956
  }
2776
2957
  function removedBoilerplateLines(text) {
2777
- return text.split(/\s{2,}|\r?\n/).map(normalizeWhitespace).filter((line) => line && isBoilerplateLine(line));
2958
+ return text.split(/\s{2,}|\r?\n/).map(normalizeWhitespace2).filter((line) => line && isBoilerplateLine(line));
2778
2959
  }
2779
2960
  function cleanBoilerplateLines(text) {
2780
2961
  const withoutInlineBoilerplate = text.replace(/\b(?:Column\s+\d+:\s*)?[A-Z]{2,}(?:-[A-Z0-9]{2,})+\s+\d{2}\s+\d{2}\s+(?:\|\s*)?(?:Column\s+\d+:\s*)?Page\s+\d+\s+of\s+\d+\b/gi, " ").replace(/\bSPECIMEN POLICY\s+[-—]\s+FOR TESTING ONLY\b/gi, " ").replace(/\bPage\s+\d+\s+of\s+\d+\b/gi, " ");
2781
2962
  const lines = withoutInlineBoilerplate.split(/\r?\n/);
2782
- const filtered = lines.map(normalizeWhitespace).filter((line) => line && !isBoilerplateLine(line));
2783
- return normalizeWhitespace(filtered.join(" "));
2963
+ const filtered = lines.map(normalizeWhitespace2).filter((line) => line && !isBoilerplateLine(line));
2964
+ return normalizeWhitespace2(filtered.join(" "));
2784
2965
  }
2785
2966
  function shouldMergeTextSpan(left, right) {
2786
2967
  if (sourceUnit(left) !== "text" || sourceUnit(right) !== "text") return false;
2787
2968
  if (spanPage(left) !== spanPage(right)) return false;
2788
2969
  if (left.metadata?.elementType === "title" || right.metadata?.elementType === "title") return false;
2789
- const leftText = normalizeWhitespace(left.text);
2790
- const rightText = normalizeWhitespace(right.text);
2970
+ const leftText = normalizeWhitespace2(left.text);
2971
+ const rightText = normalizeWhitespace2(right.text);
2791
2972
  if (!leftText || !rightText) return false;
2792
2973
  if (/[:.;!?)]$/.test(leftText)) return false;
2793
2974
  if (/^(?:[A-Z][A-Z0-9 &/(),.-]{8,}|Item\s+\d+|Section\s+\d+|Part\s+[A-Z]\b)/.test(rightText)) return false;
@@ -2808,7 +2989,7 @@ function mergeTextRuns(spans) {
2808
2989
  return result;
2809
2990
  }
2810
2991
  function mergeTextSpanPair(left, right) {
2811
- const text = normalizeWhitespace(`${left.text} ${right.text}`);
2992
+ const text = normalizeWhitespace2(`${left.text} ${right.text}`);
2812
2993
  const merged = retextSpan(left, text, {
2813
2994
  mergedSourceSpanIds: [left.metadata?.mergedSourceSpanIds, left.id, right.id, right.metadata?.mergedSourceSpanIds].filter(Boolean).join(","),
2814
2995
  sourceSpanNormalization: "merged_text_run"
@@ -2860,7 +3041,7 @@ function splitPageIntoSections(text, headingPattern, minSectionChars) {
2860
3041
  if (current) sections.push(current);
2861
3042
  const suffix = match[1]?.trim();
2862
3043
  current = {
2863
- title: normalizeWhitespace(suffix ? `${line}` : line).slice(0, 120),
3044
+ title: normalizeWhitespace2(suffix ? `${line}` : line).slice(0, 120),
2864
3045
  lines: [line]
2865
3046
  };
2866
3047
  continue;
@@ -2870,7 +3051,7 @@ function splitPageIntoSections(text, headingPattern, minSectionChars) {
2870
3051
  if (current) sections.push(current);
2871
3052
  return sections.map((section) => ({
2872
3053
  title: section.title,
2873
- text: normalizeWhitespace(section.lines.join("\n"))
3054
+ text: normalizeWhitespace2(section.lines.join("\n"))
2874
3055
  })).filter((section) => section.text.length >= minSectionChars);
2875
3056
  }
2876
3057
  function inferFormNumber(text) {
@@ -2971,14 +3152,14 @@ function matchesFilters(span, filters) {
2971
3152
  }
2972
3153
 
2973
3154
  // src/source/tree.ts
2974
- function normalizeWhitespace2(value) {
3155
+ function normalizeWhitespace3(value) {
2975
3156
  return value.replace(/\s+/g, " ").trim();
2976
3157
  }
2977
3158
  function sanitizeIdPart2(value) {
2978
3159
  return value.replace(/[^a-zA-Z0-9_.:-]/g, "_");
2979
3160
  }
2980
3161
  function truncate(value, maxChars) {
2981
- const text = normalizeWhitespace2(value);
3162
+ const text = normalizeWhitespace3(value);
2982
3163
  return text.length > maxChars ? `${text.slice(0, maxChars).trimEnd()}...` : text;
2983
3164
  }
2984
3165
  function pageStart(span) {
@@ -3072,7 +3253,7 @@ function isTitleContentNode(node) {
3072
3253
  if (node.kind !== "text") return false;
3073
3254
  const isMarkedTitle = metadataString(node.metadata, "elementType") === "title" || metadataString(node.metadata, "sourceUnit") === "title";
3074
3255
  if (!isMarkedTitle) return false;
3075
- const text = normalizeWhitespace2(node.textExcerpt ?? node.title);
3256
+ const text = normalizeWhitespace3(node.textExcerpt ?? node.title);
3076
3257
  if (!text || text.length > 140) return false;
3077
3258
  const words = text.split(/\s+/);
3078
3259
  if (words.length > 14) return false;
@@ -3747,12 +3928,12 @@ function shouldFailQualityGate(mode, status) {
3747
3928
  var import_zod22 = require("zod");
3748
3929
 
3749
3930
  // src/source/operational-profile.ts
3750
- function normalizeWhitespace3(value) {
3931
+ function normalizeWhitespace4(value) {
3751
3932
  return value.replace(/\s+/g, " ").trim();
3752
3933
  }
3753
3934
  function cleanValue(value) {
3754
3935
  if (!value) return void 0;
3755
- return normalizeWhitespace3(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
3936
+ return normalizeWhitespace4(value.replace(/^[\s:;#-]+|[\s;,.]+$/g, ""));
3756
3937
  }
3757
3938
  var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
3758
3939
  "each_claim_limit",
@@ -3834,6 +4015,7 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3834
4015
  ...keepIds(record.sourceSpanIds, validSpanIds),
3835
4016
  ...limits.flatMap((term) => term.sourceSpanIds)
3836
4017
  ])];
4018
+ if (!name || sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return void 0;
3837
4019
  return {
3838
4020
  name,
3839
4021
  coverageCode: typeof record.coverageCode === "string" ? cleanValue(record.coverageCode) : void 0,
@@ -3848,7 +4030,7 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3848
4030
  sourceNodeIds: sourceNodeIds2,
3849
4031
  sourceSpanIds: sourceSpanIds2
3850
4032
  };
3851
- }).filter((coverage) => coverage.name && (coverage.sourceNodeIds.length > 0 || coverage.sourceSpanIds.length > 0)) : base.coverages;
4033
+ }).filter((coverage) => Boolean(coverage)) : base.coverages;
3852
4034
  const sourceBackedParty = (role, value) => value ? {
3853
4035
  role,
3854
4036
  name: value.normalizedValue ?? value.value,
@@ -3916,10 +4098,18 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3916
4098
  ...base.warnings,
3917
4099
  ...Array.isArray(candidate.warnings) ? candidate.warnings.filter((warning) => typeof warning === "string" && warning.trim().length > 0) : []
3918
4100
  ];
4101
+ const resolvedPolicyTypes = resolveOperationalProfilePolicyTypes({
4102
+ profileTypes: candidate.policyTypes,
4103
+ existingTypes: base.policyTypes,
4104
+ coverages
4105
+ });
4106
+ if (resolvedPolicyTypes.source === "profile_augmented" || resolvedPolicyTypes.source === "existing_augmented" || resolvedPolicyTypes.source === "inferred") {
4107
+ warnings.push(POLICY_TYPES_FROM_COVERAGES_WARNING);
4108
+ }
3919
4109
  return PolicyOperationalProfileSchema.parse({
3920
4110
  ...base,
3921
4111
  documentType: candidate.documentType === "policy" ? "policy" : base.documentType,
3922
- policyTypes: Array.isArray(candidate.policyTypes) && candidate.policyTypes.length > 0 ? candidate.policyTypes : base.policyTypes,
4112
+ policyTypes: resolvedPolicyTypes.policyTypes,
3923
4113
  policyNumber,
3924
4114
  namedInsured,
3925
4115
  insurer,
@@ -12989,6 +13179,7 @@ function getTemplate(policyType) {
12989
13179
  POLICY_SECTION_TYPES,
12990
13180
  POLICY_TERM_TYPES,
12991
13181
  POLICY_TYPES,
13182
+ POLICY_TYPES_FROM_COVERAGES_WARNING,
12992
13183
  ParsedAnswerSchema,
12993
13184
  PaymentInstallmentSchema,
12994
13185
  PaymentPlanSchema,
@@ -13144,6 +13335,7 @@ function getTemplate(policyType) {
13144
13335
  getNextApplicationQuestions,
13145
13336
  getPdfPageCount,
13146
13337
  getTemplate,
13338
+ inferPolicyTypesFromOperationalCoverages,
13147
13339
  isDoclingExtractionInput,
13148
13340
  isFileReference,
13149
13341
  mergeQuestionAnswers,
@@ -13152,6 +13344,7 @@ function getTemplate(policyType) {
13152
13344
  normalizeDoclingDocument,
13153
13345
  normalizeDocumentSourceTreePaths,
13154
13346
  normalizeForMatch,
13347
+ normalizeOperationalPolicyTypes,
13155
13348
  normalizeSourceSpans,
13156
13349
  orderSourceEvidence,
13157
13350
  overlayTextOnPdf,
@@ -13162,6 +13355,7 @@ function getTemplate(policyType) {
13162
13355
  processReply,
13163
13356
  proposeContextWrites,
13164
13357
  resolveModelBudget,
13358
+ resolveOperationalProfilePolicyTypes,
13165
13359
  safeGenerateObject,
13166
13360
  sanitizeNulls,
13167
13361
  scoreCaseProposal,