@claritylabs/cl-sdk 4.2.0 → 4.3.0

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
@@ -1060,7 +1060,8 @@ var InsurerInfoSchema = z9.object({
1060
1060
  amBestRating: z9.string().optional(),
1061
1061
  amBestNumber: z9.string().optional(),
1062
1062
  admittedStatus: AdmittedStatusSchema.optional(),
1063
- stateOfDomicile: z9.string().optional()
1063
+ stateOfDomicile: z9.string().optional(),
1064
+ address: AddressSchema.optional()
1064
1065
  }).merge(SourceProvenanceSchema);
1065
1066
  var ProducerInfoSchema = z9.object({
1066
1067
  agencyName: z9.string(),
@@ -2432,6 +2433,7 @@ var OperationalCoverageLineSchema = z21.object({
2432
2433
  var OperationalPartySchema = z21.object({
2433
2434
  role: z21.string(),
2434
2435
  name: z21.string(),
2436
+ address: OperationalAddressSchema.optional(),
2435
2437
  sourceNodeIds: z21.array(z21.string().min(1)).default([]),
2436
2438
  sourceSpanIds: z21.array(z21.string().min(1)).default([])
2437
2439
  });
@@ -2469,6 +2471,7 @@ var PolicyOperationalProfileSchema = z21.preprocess(
2469
2471
  expirationDate: SourceBackedValueSchema.optional(),
2470
2472
  retroactiveDate: SourceBackedValueSchema.optional(),
2471
2473
  premium: SourceBackedValueSchema.optional(),
2474
+ operationsDescription: SourceBackedValueSchema.optional(),
2472
2475
  declarationFacts: z21.array(OperationalDeclarationFactSchema).default([]),
2473
2476
  coverages: z21.array(OperationalCoverageLineSchema).default([]),
2474
2477
  parties: z21.array(OperationalPartySchema).default([]),
@@ -3847,6 +3850,34 @@ function cleanCoverageLineOfBusiness(value) {
3847
3850
  function normalizedFactValue(value) {
3848
3851
  return value.toLowerCase().replace(/&/g, " and ").replace(/[.,#]/g, " ").replace(/\s+/g, " ").trim();
3849
3852
  }
3853
+ var OPERATIONAL_ADDRESS_FIELDS = [
3854
+ "street1",
3855
+ "street2",
3856
+ "city",
3857
+ "state",
3858
+ "zip",
3859
+ "country",
3860
+ "formatted"
3861
+ ];
3862
+ function normalizeOperationalAddress(value) {
3863
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
3864
+ const record = value;
3865
+ const address = Object.fromEntries(
3866
+ OPERATIONAL_ADDRESS_FIELDS.flatMap((field) => {
3867
+ const cleaned = typeof record[field] === "string" ? cleanValue(record[field]) : void 0;
3868
+ return cleaned ? [[field, cleaned]] : [];
3869
+ })
3870
+ );
3871
+ return Object.keys(address).length > 0 ? address : void 0;
3872
+ }
3873
+ function normalizeOperationalPartyRole(value) {
3874
+ const normalized = value.toLowerCase().replace(/[\s-]+/g, "_");
3875
+ if (normalized === "namedinsured" || normalized === "insured") return "named_insured";
3876
+ if (normalized === "managing_general_agent") return "mga";
3877
+ if (normalized === "managing_general_underwriter") return "mga";
3878
+ if (normalized === "third_party_administrator") return "administrator";
3879
+ return normalized;
3880
+ }
3850
3881
  var OPERATIONAL_COVERAGE_TERM_KINDS = /* @__PURE__ */ new Set([
3851
3882
  "each_claim_limit",
3852
3883
  "each_occurrence_limit",
@@ -3945,6 +3976,7 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3945
3976
  const expirationDate = mergeValue(base.expirationDate, candidate.expirationDate);
3946
3977
  const retroactiveDate = mergeValue(base.retroactiveDate, candidate.retroactiveDate);
3947
3978
  const premium = mergeValue(base.premium, candidate.premium);
3979
+ const operationsDescription = mergeValue(base.operationsDescription, candidate.operationsDescription);
3948
3980
  const candidateDeclarationFacts = Array.isArray(candidate.declarationFacts) ? candidate.declarationFacts.map(mergeDeclarationFact).filter((fact) => Boolean(fact)) : [];
3949
3981
  const declarationFacts = [
3950
3982
  ...base.declarationFacts,
@@ -3969,7 +4001,8 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
3969
4001
  effectiveDate,
3970
4002
  expirationDate,
3971
4003
  retroactiveDate,
3972
- premium
4004
+ premium,
4005
+ operationsDescription
3973
4006
  ].filter((value) => Boolean(value));
3974
4007
  const coverages = base.coverages.length > 0 ? base.coverages : Array.isArray(candidate.coverages) ? candidate.coverages.map((coverage) => {
3975
4008
  const record = coverage;
@@ -4028,14 +4061,21 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
4028
4061
  const record = party;
4029
4062
  const role = typeof record.role === "string" ? cleanValue(record.role) : void 0;
4030
4063
  const name = typeof record.name === "string" ? cleanValue(record.name) : void 0;
4064
+ const address = normalizeOperationalAddress(record.address);
4031
4065
  const sourceNodeIds2 = keepIds(record.sourceNodeIds, validNodeIds);
4032
4066
  const sourceSpanIds2 = keepIds(record.sourceSpanIds, validSpanIds);
4033
4067
  if (!role || !name || sourceNodeIds2.length === 0 && sourceSpanIds2.length === 0) return [];
4034
- return [{ role, name, sourceNodeIds: sourceNodeIds2, sourceSpanIds: sourceSpanIds2 }];
4068
+ return [{
4069
+ role: normalizeOperationalPartyRole(role),
4070
+ name,
4071
+ address,
4072
+ sourceNodeIds: sourceNodeIds2,
4073
+ sourceSpanIds: sourceSpanIds2
4074
+ }];
4035
4075
  }) : [];
4036
4076
  const parties = [
4037
- ...base.parties,
4038
4077
  ...candidateParties,
4078
+ ...base.parties,
4039
4079
  sourceBackedParty("named_insured", namedInsured),
4040
4080
  sourceBackedParty("insurer", insurer),
4041
4081
  sourceBackedParty("broker", broker)
@@ -4109,6 +4149,7 @@ function mergeOperationalProfile(base, candidate, validNodeIds, validSpanIds) {
4109
4149
  expirationDate,
4110
4150
  retroactiveDate,
4111
4151
  premium,
4152
+ operationsDescription,
4112
4153
  declarationFacts,
4113
4154
  coverages: annotatedCoverages,
4114
4155
  parties,
@@ -4582,7 +4623,8 @@ function sourceIdsFromOperationalProfile(profile) {
4582
4623
  profile.effectiveDate,
4583
4624
  profile.expirationDate,
4584
4625
  profile.retroactiveDate,
4585
- profile.premium
4626
+ profile.premium,
4627
+ profile.operationsDescription
4586
4628
  ].filter(Boolean);
4587
4629
  return {
4588
4630
  sourceNodeIds: uniqueStrings([
@@ -4666,6 +4708,21 @@ var OperationalDeclarationFactForPromptSchema = z23.object({
4666
4708
  sourceNodeIds: z23.array(z23.string()),
4667
4709
  sourceSpanIds: z23.array(z23.string())
4668
4710
  });
4711
+ var OperationalPartyForPromptSchema = z23.object({
4712
+ role: z23.enum([
4713
+ "named_insured",
4714
+ "producer",
4715
+ "broker",
4716
+ "insurer",
4717
+ "carrier",
4718
+ "mga",
4719
+ "administrator"
4720
+ ]),
4721
+ name: z23.string(),
4722
+ address: OperationalAddressForPromptSchema.optional(),
4723
+ sourceNodeIds: z23.array(z23.string()),
4724
+ sourceSpanIds: z23.array(z23.string())
4725
+ });
4669
4726
  var OperationalProfilePromptSchema = z23.object({
4670
4727
  documentType: z23.enum(["policy", "quote"]).optional(),
4671
4728
  linesOfBusiness: z23.array(z23.string()).optional(),
@@ -4677,7 +4734,9 @@ var OperationalProfilePromptSchema = z23.object({
4677
4734
  expirationDate: SourceBackedValueForPromptSchema.optional(),
4678
4735
  retroactiveDate: SourceBackedValueForPromptSchema.optional(),
4679
4736
  premium: SourceBackedValueForPromptSchema.optional(),
4737
+ operationsDescription: SourceBackedValueForPromptSchema.optional(),
4680
4738
  declarationFacts: z23.array(OperationalDeclarationFactForPromptSchema).optional(),
4739
+ parties: z23.array(OperationalPartyForPromptSchema).optional(),
4681
4740
  coverages: z23.array(z23.object({
4682
4741
  name: z23.string(),
4683
4742
  lineOfBusiness: z23.string().optional(),
@@ -5589,6 +5648,9 @@ function operationalEvidenceScore(span) {
5589
5648
  if (span.metadata?.elementType === "title") score += 4;
5590
5649
  if (span.sourceUnit === "page") score -= 3;
5591
5650
  if (/\b(policy\s*(number|period|term)|effective date|expiration date|expiry date|named insured|insurer|carrier|security|broker|producer|premium|total due)\b/i.test(text)) score += 12;
5651
+ if (/\b(mailing address|business address|address|managing general (?:agent|underwriter)|mga|administrator|description of operations|operations description|nature of business|business description)\b/i.test(text)) score += 12;
5652
+ if (/\b\d{1,6}\s+[A-Z0-9][^\n,]{1,80}\b(?:street|st|avenue|ave|road|rd|boulevard|blvd|drive|dr|lane|ln|way|court|ct|highway|hwy)\b/i.test(text)) score += 10;
5653
+ if (/\b[A-Za-z][A-Za-z .'-]+,\s*[A-Z]{2}\s+\d{5}(?:-\d{4})?\b/.test(text)) score += 10;
5592
5654
  if (/\b(coverage part|limit(?:s)? of liability|deductible|retention|retroactive date|aggregate|sublimit|sub-limit|each claim|each loss|each occurrence|coinsurance)\b/i.test(text)) score += 14;
5593
5655
  if (/\bendorsement\s+(?:no\.?|number|#)?\s*[A-Z0-9]|forms? and endorsements?|attached at inception|schedule\b/i.test(text)) score += 8;
5594
5656
  if (/\bitem\s+\d+\.?\s*(?:named insured|policy number|policy period|renewal|form of business|coverage parts?|premium|extended reporting|producer|forms? and endorsements?)\b/i.test(text)) score += 10;
@@ -5608,10 +5670,13 @@ function isOperationalEvidenceAnchor(span) {
5608
5670
  const text = cleanText([span.text, span.formNumber].filter(Boolean).join(" "), "");
5609
5671
  if (!text) return false;
5610
5672
  if (sourceUnit3 === "page") {
5611
- return hasSubstantiveDeclarationsScheduleText(text) || /\b(declarations?|named insured|policy number|policy period|effective date|expiration date|premium|total due|producer)\b/i.test(text);
5673
+ return hasSubstantiveDeclarationsScheduleText(text) || /\b(declarations?|named insured|policy number|policy period|effective date|expiration date|premium|total due|producer|mailing address|mga|administrator|description of operations|nature of business|business description)\b/i.test(text);
5612
5674
  }
5613
5675
  if (/\bitem\s+\d+\.?\s*(?:named insured|policy number|policy period|renewal|form of business|coverage parts?|premium|extended reporting|producer|forms? and endorsements?)\b/i.test(text)) return true;
5614
5676
  if (/\b(policy\s*(number|period)|effective date|expiration date|expiry date|named insured|insurer|carrier|broker|producer|premium|total due)\b/i.test(text)) return true;
5677
+ if (/\b(mailing address|business address|address|managing general (?:agent|underwriter)|mga|administrator|description of operations|operations description|nature of business|business description)\b/i.test(text)) return true;
5678
+ if (/\b\d{1,6}\s+[A-Z0-9][^\n,]{1,80}\b(?:street|st|avenue|ave|road|rd|boulevard|blvd|drive|dr|lane|ln|way|court|ct|highway|hwy)\b/i.test(text)) return true;
5679
+ if (/\b[A-Za-z][A-Za-z .'-]+,\s*[A-Z]{2}\s+\d{5}(?:-\d{4})?\b/.test(text)) return true;
5615
5680
  if (/\b(coverage part|forms? and endorsements?|attached at inception|endorsement\s+(?:no\.?|number|#)?\s*[A-Z0-9])\b/i.test(text)) return true;
5616
5681
  if (/\$[\d,.]+|[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2,4}|[0-9]{1,2}\s+[A-Za-z]{3,9}\s+[0-9]{4}/.test(text)) return true;
5617
5682
  return false;
@@ -5629,6 +5694,7 @@ function operationalEvidencePages(sourceSpans) {
5629
5694
  if (/\bcoverage parts?,?\s+limits? of liability,?\s+deductibles?,?\s+and retroactive dates\b/i.test(text)) score += 24;
5630
5695
  if (/\b(policy\s*(number|period|term)|effective date|expiration date|expiry date|named insured|insurer|carrier|security)\b/i.test(text)) score += 12;
5631
5696
  if (/\b(premium|total due|tax|fee|producer|broker)\b/i.test(text)) score += 10;
5697
+ if (/\b(mailing address|business address|managing general (?:agent|underwriter)|mga|administrator|description of operations|operations description|nature of business|business description)\b/i.test(text)) score += 16;
5632
5698
  if (/\b(endorsement\s+(?:no\.?|number|#)?\s*[A-Z0-9]|attached at inception|forms? and endorsements?)\b/i.test(text)) score += 8;
5633
5699
  if (/\b(definitions?|exclusions?|conditions?|duties in the event|action against|cancellation by)\b/i.test(text)) score -= 12;
5634
5700
  if (score > 0) scores.set(page, (scores.get(page) ?? 0) + score);
@@ -5703,7 +5769,7 @@ function operationalProfilePromptNodes(sourceTree) {
5703
5769
  return true;
5704
5770
  }
5705
5771
  const text = [node.title, node.path, node.description, node.textExcerpt].filter(Boolean).join(" ");
5706
- return /\b(policy\s*(number|period)|named insured|insurer|carrier|broker|producer|premium|coverage|limit|liability|deductible|retention|retroactive|aggregate|sublimit|sub-limit|endorsement)\b/i.test(text);
5772
+ return /\b(policy\s*(number|period)|named insured|insurer|carrier|broker|producer|managing general (?:agent|underwriter)|mga|administrator|mailing address|description of operations|operations description|nature of business|business description|premium|coverage|limit|liability|deductible|retention|retroactive|aggregate|sublimit|sub-limit|endorsement)\b/i.test(text);
5707
5773
  }).slice(0, 420);
5708
5774
  }
5709
5775
  function emptyOperationalProfile() {
@@ -5727,7 +5793,8 @@ function buildOperationalProfilePrompt(sourceTree, sourceSpans) {
5727
5793
  return `Extract a source-backed operational profile for an insurance policy.
5728
5794
 
5729
5795
  Return only high-value operational facts needed for policy lists, Q&A, compliance, and certificate generation:
5730
- - policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium
5796
+ - policy number, named insured, insurer/carrier/security, broker/producer, policy period, retroactive date, premium, and the insured's description of operations
5797
+ - parties[] rows for named insured, producer/broker, insurer/carrier, and MGA/administrator identities and their mailing addresses
5731
5798
  - source-backed declarationFacts for named-insured identity details: named insured, mailing address, DBA, entity type, tax ID/FEIN, additional named insureds, and other durable declaration-page identity facts
5732
5799
  - coverage units with their own nested limit terms, deductibles/retentions, retroactive dates, premiums, and form references
5733
5800
  - coverage type labels
@@ -5739,6 +5806,9 @@ Rules:
5739
5806
  - If a value is not directly supported, omit it.
5740
5807
  - Prefer declarations, schedules, premium tables, and endorsement schedules over generic policy wording.
5741
5808
  - Put named-insured mailing address in declarationFacts[] with field "mailingAddress", valueKind "address", a user-facing value string, and structured address fields when present. Do not put producer, broker, insurer, mortgagee, loss-payee, or certificate-holder addresses in mailingAddress.
5809
+ - Put every source-backed policy party in parties[] using only these canonical roles: "named_insured", "producer", "broker", "insurer", "carrier", "mga", or "administrator". Keep producer/broker, insurer/carrier, and MGA/administrator addresses policy-scoped in parties[]; never represent them as the named-insured mailingAddress declaration fact.
5810
+ - When a party's address is present, return its available street1, street2, city, state, zip, country, and formatted parts under parties[].address. Partial addresses are allowed in parties[], but never guess a missing component. The party row must cite the source node or source span that supports both the identity and address.
5811
+ - Put the insured's directly stated business or operations description in operationsDescription. Do not synthesize it from coverages, industry inference, website research, or generic policy wording.
5742
5812
  - Put DBA or trade name in declarationFacts[] with field "dba"; entity/legal form in field "entityType"; FEIN/tax ID in field "taxId"; each additional named insured in field "additionalNamedInsured".
5743
5813
  - For effective, expiration, retroactive, and other date fields, return a normalized YYYY-MM-DD value when the source date is unambiguous, including month-name dates such as "20 Feb 2026". Do not emit fragmented date text such as "20 2 2026".
5744
5814
  - For broker/producer, extract the agency or company legal name, not the license role, credential, or type. In a block like "Bayshore Insurance Brokers, LLC" followed by "Surplus Lines Broker - CA License No. ...", broker.value must be "Bayshore Insurance Brokers, LLC"; the surplus-lines role and license number are not the broker name.
@@ -5808,13 +5878,6 @@ function valueOf(profile, key) {
5808
5878
  }
5809
5879
  return String(value.value);
5810
5880
  }
5811
- function provenanceOf(value) {
5812
- if (!value?.sourceSpanIds.length) return void 0;
5813
- return {
5814
- sourceSpanIds: value.sourceSpanIds,
5815
- ...value.sourceNodeIds[0] ? { documentNodeId: value.sourceNodeIds[0] } : {}
5816
- };
5817
- }
5818
5881
  function provenanceFromIds(sourceSpanIds, sourceNodeIds) {
5819
5882
  if (sourceSpanIds.length === 0) return void 0;
5820
5883
  return {
@@ -5822,6 +5885,33 @@ function provenanceFromIds(sourceSpanIds, sourceNodeIds) {
5822
5885
  ...sourceNodeIds[0] ? { documentNodeId: sourceNodeIds[0] } : {}
5823
5886
  };
5824
5887
  }
5888
+ function combinedProvenance(...values) {
5889
+ const sourceSpanIds = [...new Set(values.flatMap((value) => value?.sourceSpanIds ?? []))];
5890
+ const sourceNodeIds = [...new Set(values.flatMap((value) => value?.sourceNodeIds ?? []))];
5891
+ return provenanceFromIds(sourceSpanIds, sourceNodeIds);
5892
+ }
5893
+ function firstOperationalParty(profile, roles) {
5894
+ const candidates = roles.flatMap(
5895
+ (role) => profile.parties.filter((candidate) => candidate.role === role && candidate.name.trim())
5896
+ );
5897
+ return candidates.find((candidate) => candidate.address) ?? candidates[0];
5898
+ }
5899
+ function completeOperationalAddress(address) {
5900
+ if (!address?.street1 || !address.city || !address.state || !address.zip) return void 0;
5901
+ return {
5902
+ street1: address.street1,
5903
+ street2: address.street2,
5904
+ city: address.city,
5905
+ state: address.state,
5906
+ zip: address.zip,
5907
+ country: address.country
5908
+ };
5909
+ }
5910
+ function sourceBackedAddressFromParty(party) {
5911
+ const address = completeOperationalAddress(party?.address);
5912
+ const provenance = party ? provenanceFromIds(party.sourceSpanIds, party.sourceNodeIds) : void 0;
5913
+ return address && provenance ? { ...address, ...provenance } : void 0;
5914
+ }
5825
5915
  function declarationFactsByField(profile, field) {
5826
5916
  return profile.declarationFacts.filter((fact) => fact.field === field && fact.value.trim());
5827
5917
  }
@@ -5872,16 +5962,21 @@ function declarationFieldName(fact) {
5872
5962
  function materializeDocument(params) {
5873
5963
  const profile = params.operationalProfile;
5874
5964
  const policyNumber = valueOf(profile, "policyNumber") ?? "Unknown";
5875
- const insuredName = valueOf(profile, "namedInsured") ?? "Unknown";
5876
- const carrier = valueOf(profile, "insurer") ?? "Unknown";
5965
+ const namedInsuredParty = firstOperationalParty(profile, ["named_insured"]);
5966
+ const insurerParty = firstOperationalParty(profile, ["insurer", "carrier"]);
5967
+ const producerParty = firstOperationalParty(profile, ["producer", "broker"]);
5968
+ const insuredName = valueOf(profile, "namedInsured") ?? namedInsuredParty?.name ?? "Unknown";
5969
+ const carrier = valueOf(profile, "insurer") ?? insurerParty?.name ?? "Unknown";
5877
5970
  const effectiveDate = valueOf(profile, "effectiveDate") ?? "Unknown";
5878
5971
  const expirationDate = valueOf(profile, "expirationDate") ?? "Unknown";
5879
5972
  const premium = valueOf(profile, "premium");
5880
- const insurerProvenance = provenanceOf(profile.insurer);
5881
- const broker = valueOf(profile, "broker");
5882
- const brokerProvenance = provenanceOf(profile.broker);
5973
+ const insurerProvenance = combinedProvenance(profile.insurer, insurerParty);
5974
+ const insurerAddress = completeOperationalAddress(insurerParty?.address);
5975
+ const broker = valueOf(profile, "broker") ?? producerParty?.name;
5976
+ const brokerProvenance = combinedProvenance(profile.broker, producerParty);
5977
+ const producerAddress = completeOperationalAddress(producerParty?.address);
5883
5978
  const mailingAddressFact = firstDeclarationFact(profile, "mailingAddress");
5884
- const insuredAddress = sourceBackedAddressFromFact(mailingAddressFact);
5979
+ const insuredAddress = sourceBackedAddressFromParty(namedInsuredParty) ?? sourceBackedAddressFromFact(mailingAddressFact);
5885
5980
  const insuredDba = firstDeclarationFact(profile, "dba")?.value;
5886
5981
  const insuredEntityType = normalizedEntityType(firstDeclarationFact(profile, "entityType")?.value);
5887
5982
  const insuredFein = firstDeclarationFact(profile, "taxId")?.value;
@@ -5945,10 +6040,20 @@ function materializeDocument(params) {
5945
6040
  insuredEntityType,
5946
6041
  insuredFein,
5947
6042
  ...additionalNamedInsureds.length > 0 ? { additionalNamedInsureds } : {},
5948
- ...insurerProvenance ? { insurer: { legalName: carrier, ...insurerProvenance } } : {},
6043
+ ...insurerProvenance ? {
6044
+ insurer: {
6045
+ legalName: carrier,
6046
+ ...insurerAddress ? { address: insurerAddress } : {},
6047
+ ...insurerProvenance
6048
+ }
6049
+ } : {},
5949
6050
  ...broker && brokerProvenance ? {
5950
6051
  brokerAgency: broker,
5951
- producer: { agencyName: broker, ...brokerProvenance }
6052
+ producer: {
6053
+ agencyName: broker,
6054
+ ...producerAddress ? { address: producerAddress } : {},
6055
+ ...brokerProvenance
6056
+ }
5952
6057
  } : {},
5953
6058
  linesOfBusiness: profile.linesOfBusiness,
5954
6059
  formInventory: params.formInventory.filter((form) => typeof form.formNumber === "string" && form.formNumber.trim().length > 0).map((form) => ({