@claritylabs/cl-sdk 0.10.2 → 0.11.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/README.md +1 -1
- package/dist/index.d.mts +41 -18
- package/dist/index.d.ts +41 -18
- package/dist/index.js +795 -317
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +795 -317
- package/dist/index.mjs.map +1 -1
- package/dist/storage-sqlite.d.mts +18 -8
- package/dist/storage-sqlite.d.ts +18 -8
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -540,6 +540,7 @@ var CoverageValueTypeSchema = z4.enum([
|
|
|
540
540
|
var CoverageSchema = z4.object({
|
|
541
541
|
name: z4.string(),
|
|
542
542
|
limit: z4.string(),
|
|
543
|
+
limitType: LimitTypeSchema.optional(),
|
|
543
544
|
limitValueType: CoverageValueTypeSchema.optional(),
|
|
544
545
|
deductible: z4.string().optional(),
|
|
545
546
|
deductibleValueType: CoverageValueTypeSchema.optional(),
|
|
@@ -1574,6 +1575,358 @@ async function runExtractor(params) {
|
|
|
1574
1575
|
};
|
|
1575
1576
|
}
|
|
1576
1577
|
|
|
1578
|
+
// src/extraction/promote.ts
|
|
1579
|
+
function getDeclarationFields(doc) {
|
|
1580
|
+
const decl = doc.declarations;
|
|
1581
|
+
return Array.isArray(decl?.fields) ? decl.fields : [];
|
|
1582
|
+
}
|
|
1583
|
+
function fieldMatches(fieldName, patterns) {
|
|
1584
|
+
const lower = fieldName.toLowerCase().replace(/[\s_-]/g, "");
|
|
1585
|
+
return patterns.some((p) => lower === p.toLowerCase().replace(/[\s_-]/g, ""));
|
|
1586
|
+
}
|
|
1587
|
+
function findFieldValue(fields, patterns) {
|
|
1588
|
+
const match = fields.find((f) => fieldMatches(f.field, patterns));
|
|
1589
|
+
return match?.value;
|
|
1590
|
+
}
|
|
1591
|
+
function promoteCarrierFields(doc) {
|
|
1592
|
+
const raw = doc;
|
|
1593
|
+
if (!raw.carrierNaicNumber && raw.naicNumber) {
|
|
1594
|
+
raw.carrierNaicNumber = raw.naicNumber;
|
|
1595
|
+
}
|
|
1596
|
+
if (!raw.carrierAmBestRating && raw.amBestRating) {
|
|
1597
|
+
raw.carrierAmBestRating = raw.amBestRating;
|
|
1598
|
+
}
|
|
1599
|
+
if (!raw.carrierAdmittedStatus && raw.admittedStatus) {
|
|
1600
|
+
raw.carrierAdmittedStatus = raw.admittedStatus;
|
|
1601
|
+
}
|
|
1602
|
+
delete raw.naicNumber;
|
|
1603
|
+
delete raw.amBestRating;
|
|
1604
|
+
delete raw.admittedStatus;
|
|
1605
|
+
if (!raw.insurer && raw.carrierLegalName) {
|
|
1606
|
+
raw.insurer = {
|
|
1607
|
+
legalName: raw.carrierLegalName,
|
|
1608
|
+
...raw.carrierNaicNumber ? { naicNumber: raw.carrierNaicNumber } : {},
|
|
1609
|
+
...raw.carrierAmBestRating ? { amBestRating: raw.carrierAmBestRating } : {},
|
|
1610
|
+
...raw.carrierAdmittedStatus ? { admittedStatus: raw.carrierAdmittedStatus } : {}
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
var BROKER_NAME_PATTERNS = [
|
|
1615
|
+
"brokerName",
|
|
1616
|
+
"broker",
|
|
1617
|
+
"agentName",
|
|
1618
|
+
"agent",
|
|
1619
|
+
"producerName",
|
|
1620
|
+
"producerAgency",
|
|
1621
|
+
"agencyName",
|
|
1622
|
+
"brokerAgency"
|
|
1623
|
+
];
|
|
1624
|
+
var BROKER_CONTACT_PATTERNS = [
|
|
1625
|
+
"brokerContactName",
|
|
1626
|
+
"brokerContact",
|
|
1627
|
+
"agentContactName",
|
|
1628
|
+
"producerContactName",
|
|
1629
|
+
"producerContact"
|
|
1630
|
+
];
|
|
1631
|
+
var BROKER_LICENSE_PATTERNS = [
|
|
1632
|
+
"brokerLicenseNumber",
|
|
1633
|
+
"brokerNumber",
|
|
1634
|
+
"agentLicenseNumber",
|
|
1635
|
+
"producerLicenseNumber",
|
|
1636
|
+
"producerNumber",
|
|
1637
|
+
"agentNumber"
|
|
1638
|
+
];
|
|
1639
|
+
var BROKER_PHONE_PATTERNS = ["brokerPhone", "agentPhone", "producerPhone"];
|
|
1640
|
+
var BROKER_EMAIL_PATTERNS = ["brokerEmail", "agentEmail", "producerEmail"];
|
|
1641
|
+
var BROKER_ADDRESS_PATTERNS = ["brokerAddress", "agentAddress", "producerAddress"];
|
|
1642
|
+
function promoteBroker(doc) {
|
|
1643
|
+
const raw = doc;
|
|
1644
|
+
const fields = getDeclarationFields(doc);
|
|
1645
|
+
const brokerAgency = raw.brokerAgency || findFieldValue(fields, BROKER_NAME_PATTERNS);
|
|
1646
|
+
const brokerContact = raw.brokerContactName || findFieldValue(fields, BROKER_CONTACT_PATTERNS);
|
|
1647
|
+
const brokerLicense = raw.brokerLicenseNumber || findFieldValue(fields, BROKER_LICENSE_PATTERNS);
|
|
1648
|
+
const brokerPhone = findFieldValue(fields, BROKER_PHONE_PATTERNS);
|
|
1649
|
+
const brokerEmail = findFieldValue(fields, BROKER_EMAIL_PATTERNS);
|
|
1650
|
+
const brokerAddress = findFieldValue(fields, BROKER_ADDRESS_PATTERNS);
|
|
1651
|
+
if (brokerAgency) raw.brokerAgency = brokerAgency;
|
|
1652
|
+
if (brokerContact) raw.brokerContactName = brokerContact;
|
|
1653
|
+
if (brokerLicense) raw.brokerLicenseNumber = brokerLicense;
|
|
1654
|
+
if (!raw.producer && brokerAgency) {
|
|
1655
|
+
raw.producer = {
|
|
1656
|
+
agencyName: brokerAgency,
|
|
1657
|
+
...brokerContact ? { contactName: brokerContact } : {},
|
|
1658
|
+
...brokerLicense ? { licenseNumber: brokerLicense } : {},
|
|
1659
|
+
...brokerPhone ? { phone: brokerPhone } : {},
|
|
1660
|
+
...brokerEmail ? { email: brokerEmail } : {},
|
|
1661
|
+
...brokerAddress ? { address: { street1: brokerAddress } } : {}
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
var LOSS_PAYEE_NAME_PATTERNS = [
|
|
1666
|
+
"lossPayeeName",
|
|
1667
|
+
"lossPayee",
|
|
1668
|
+
"lossPayeeHolder"
|
|
1669
|
+
];
|
|
1670
|
+
var LOSS_PAYEE_ADDRESS_PATTERNS = ["lossPayeeAddress"];
|
|
1671
|
+
var MORTGAGE_HOLDER_NAME_PATTERNS = [
|
|
1672
|
+
"mortgagee",
|
|
1673
|
+
"mortgageHolder",
|
|
1674
|
+
"mortgageHolderName",
|
|
1675
|
+
"mortgageeName",
|
|
1676
|
+
"lienholder",
|
|
1677
|
+
"lienholderName"
|
|
1678
|
+
];
|
|
1679
|
+
var MORTGAGE_HOLDER_ADDRESS_PATTERNS = [
|
|
1680
|
+
"mortgageeAddress",
|
|
1681
|
+
"mortgageHolderAddress",
|
|
1682
|
+
"lienholderAddress"
|
|
1683
|
+
];
|
|
1684
|
+
function promoteLossPayees(doc) {
|
|
1685
|
+
const raw = doc;
|
|
1686
|
+
const fields = getDeclarationFields(doc);
|
|
1687
|
+
if (!raw.lossPayees || Array.isArray(raw.lossPayees) && raw.lossPayees.length === 0) {
|
|
1688
|
+
const name = findFieldValue(fields, LOSS_PAYEE_NAME_PATTERNS);
|
|
1689
|
+
if (name) {
|
|
1690
|
+
const address = findFieldValue(fields, LOSS_PAYEE_ADDRESS_PATTERNS);
|
|
1691
|
+
raw.lossPayees = [{
|
|
1692
|
+
name,
|
|
1693
|
+
role: "loss_payee",
|
|
1694
|
+
...address ? { address: { street1: address } } : {}
|
|
1695
|
+
}];
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
if (!raw.mortgageHolders || Array.isArray(raw.mortgageHolders) && raw.mortgageHolders.length === 0) {
|
|
1699
|
+
const name = findFieldValue(fields, MORTGAGE_HOLDER_NAME_PATTERNS);
|
|
1700
|
+
if (name) {
|
|
1701
|
+
const address = findFieldValue(fields, MORTGAGE_HOLDER_ADDRESS_PATTERNS);
|
|
1702
|
+
raw.mortgageHolders = [{
|
|
1703
|
+
name,
|
|
1704
|
+
role: "mortgage_holder",
|
|
1705
|
+
...address ? { address: { street1: address } } : {}
|
|
1706
|
+
}];
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
function promoteLocations(doc) {
|
|
1711
|
+
const raw = doc;
|
|
1712
|
+
if (Array.isArray(raw.locations) && raw.locations.length > 0) return;
|
|
1713
|
+
const fields = getDeclarationFields(doc);
|
|
1714
|
+
if (fields.length === 0) return;
|
|
1715
|
+
const locationGroups = /* @__PURE__ */ new Map();
|
|
1716
|
+
for (const f of fields) {
|
|
1717
|
+
const lower = f.field.toLowerCase().replace(/[\s_-]/g, "");
|
|
1718
|
+
if (lower.includes("locationnumber") || lower.includes("locnumber") || lower.includes("locno")) {
|
|
1719
|
+
const key = f.value;
|
|
1720
|
+
if (!locationGroups.has(key)) locationGroups.set(key, /* @__PURE__ */ new Map());
|
|
1721
|
+
locationGroups.get(key).set("number", f.value);
|
|
1722
|
+
continue;
|
|
1723
|
+
}
|
|
1724
|
+
if (lower.includes("buildingnumber") || lower.includes("bldgnumber") || lower.includes("bldgno")) {
|
|
1725
|
+
const lastKey2 = [...locationGroups.keys()].pop();
|
|
1726
|
+
if (lastKey2) locationGroups.get(lastKey2).set("buildingNumber", f.value);
|
|
1727
|
+
continue;
|
|
1728
|
+
}
|
|
1729
|
+
const section = (f.section ?? "").toLowerCase();
|
|
1730
|
+
const isLocationField = section.includes("location") || section.includes("building") || section.includes("premises") || section.includes("schedule of locations");
|
|
1731
|
+
if (!isLocationField) continue;
|
|
1732
|
+
if (locationGroups.size === 0) {
|
|
1733
|
+
locationGroups.set("1", /* @__PURE__ */ new Map([["number", "1"]]));
|
|
1734
|
+
}
|
|
1735
|
+
const lastKey = [...locationGroups.keys()].pop();
|
|
1736
|
+
const group = locationGroups.get(lastKey);
|
|
1737
|
+
if (lower.includes("construction") || lower.includes("constructiontype")) {
|
|
1738
|
+
group.set("constructionType", f.value);
|
|
1739
|
+
} else if (lower.includes("occupancy") || lower.includes("occupancytype")) {
|
|
1740
|
+
group.set("occupancy", f.value);
|
|
1741
|
+
} else if (lower.includes("yearbuilt")) {
|
|
1742
|
+
group.set("yearBuilt", f.value);
|
|
1743
|
+
} else if (lower.includes("squarefootage") || lower.includes("sqft") || lower.includes("area")) {
|
|
1744
|
+
group.set("squareFootage", f.value);
|
|
1745
|
+
} else if (lower.includes("protectionclass") || lower.includes("fireprotection")) {
|
|
1746
|
+
group.set("protectionClass", f.value);
|
|
1747
|
+
} else if (lower.includes("sprinkler")) {
|
|
1748
|
+
group.set("sprinklered", f.value);
|
|
1749
|
+
} else if (lower.includes("buildingvalue") || lower.includes("buildingamt") || lower.includes("buildingcoverage")) {
|
|
1750
|
+
group.set("buildingValue", f.value);
|
|
1751
|
+
} else if (lower.includes("contentsvalue") || lower.includes("contentsamt") || lower.includes("contentscoverage")) {
|
|
1752
|
+
group.set("contentsValue", f.value);
|
|
1753
|
+
} else if (lower.includes("businessincome") || lower.includes("bivalue") || lower.includes("businessincomevalue")) {
|
|
1754
|
+
group.set("businessIncomeValue", f.value);
|
|
1755
|
+
} else if (lower.includes("description") || lower.includes("buildingdescription") || lower.includes("locationdescription")) {
|
|
1756
|
+
group.set("description", f.value);
|
|
1757
|
+
} else if (lower.includes("address") || lower.includes("industryaddress") || lower.includes("locationaddress") || lower.includes("premisesaddress")) {
|
|
1758
|
+
group.set("address", f.value);
|
|
1759
|
+
} else if (lower.includes("alarm") || lower.includes("alarmtype")) {
|
|
1760
|
+
group.set("alarmType", f.value);
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
if (locationGroups.size === 0) return;
|
|
1764
|
+
const locations = [];
|
|
1765
|
+
for (const [, group] of locationGroups) {
|
|
1766
|
+
const num = parseInt(group.get("number") ?? "0", 10) || locations.length + 1;
|
|
1767
|
+
const addressStr = group.get("address");
|
|
1768
|
+
locations.push({
|
|
1769
|
+
number: num,
|
|
1770
|
+
address: addressStr ? { street1: addressStr } : { street1: "See declarations" },
|
|
1771
|
+
...group.get("description") ? { description: group.get("description") } : {},
|
|
1772
|
+
...group.get("constructionType") ? { constructionType: group.get("constructionType") } : {},
|
|
1773
|
+
...group.get("occupancy") ? { occupancy: group.get("occupancy") } : {},
|
|
1774
|
+
...group.get("yearBuilt") ? { yearBuilt: parseInt(group.get("yearBuilt"), 10) || void 0 } : {},
|
|
1775
|
+
...group.get("squareFootage") ? { squareFootage: parseInt(group.get("squareFootage").replace(/[^0-9]/g, ""), 10) || void 0 } : {},
|
|
1776
|
+
...group.get("protectionClass") ? { protectionClass: group.get("protectionClass") } : {},
|
|
1777
|
+
...group.get("sprinklered") ? { sprinklered: /yes|true/i.test(group.get("sprinklered")) } : {},
|
|
1778
|
+
...group.get("buildingValue") ? { buildingValue: group.get("buildingValue") } : {},
|
|
1779
|
+
...group.get("contentsValue") ? { contentsValue: group.get("contentsValue") } : {},
|
|
1780
|
+
...group.get("businessIncomeValue") ? { businessIncomeValue: group.get("businessIncomeValue") } : {},
|
|
1781
|
+
...group.get("alarmType") ? { alarmType: group.get("alarmType") } : {}
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
if (locations.length > 0) {
|
|
1785
|
+
raw.locations = locations;
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
function normalizeName(name) {
|
|
1789
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1790
|
+
}
|
|
1791
|
+
var LIMIT_COVERAGE_MAP = [
|
|
1792
|
+
// GL standard
|
|
1793
|
+
[["eachoccurrence", "peroccurrence", "occurrencecombined"], "perOccurrence"],
|
|
1794
|
+
[["generalaggregate"], "generalAggregate"],
|
|
1795
|
+
[["productscompletedoperationsaggregate", "productscompletedopsaggregate", "prodcompopsagg"], "productsCompletedOpsAggregate"],
|
|
1796
|
+
[["personaladvertisinginjury", "personaladvinjury", "pai"], "personalAdvertisingInjury"],
|
|
1797
|
+
[["firedamage", "firedamagelegalliability", "damagetorentedpremises", "damagetopremisesrentedtoyou"], "fireDamage"],
|
|
1798
|
+
[["medicalexpense", "medexp", "medicalexpenseanypersonanyperson", "medicalexpenseanyone"], "medicalExpense"],
|
|
1799
|
+
// Auto
|
|
1800
|
+
[["combinedsingle", "combinedsinglelimit", "csl"], "combinedSingleLimit"],
|
|
1801
|
+
[["bodilyinjuryperperson", "biperperson"], "bodilyInjuryPerPerson"],
|
|
1802
|
+
[["bodilyinjuryperaccident", "biperaccident"], "bodilyInjuryPerAccident"],
|
|
1803
|
+
[["propertydamage", "pdperaccident"], "propertyDamage"],
|
|
1804
|
+
// Umbrella/Excess
|
|
1805
|
+
[["umbrellaoccurrence", "eachoccurrenceumbrella", "excessoccurrence", "excesseachoccurrence"], "eachOccurrenceUmbrella"],
|
|
1806
|
+
[["umbrellaaggregate", "excessaggregate"], "umbrellaAggregate"],
|
|
1807
|
+
[["umbrella retention", "selfinsuredretention", "sir", "excessretention"], "umbrellaRetention"]
|
|
1808
|
+
];
|
|
1809
|
+
function synthesizeLimits(doc) {
|
|
1810
|
+
const raw = doc;
|
|
1811
|
+
if (raw.limits && typeof raw.limits === "object" && Object.keys(raw.limits).length > 0) return;
|
|
1812
|
+
const coverages = doc.coverages;
|
|
1813
|
+
if (!coverages || coverages.length === 0) return;
|
|
1814
|
+
const limits = {};
|
|
1815
|
+
for (const cov of coverages) {
|
|
1816
|
+
if (!cov.name || !cov.limit) continue;
|
|
1817
|
+
const normalized = normalizeName(cov.name);
|
|
1818
|
+
for (const [patterns, fieldName] of LIMIT_COVERAGE_MAP) {
|
|
1819
|
+
if (patterns.some((p) => normalized.includes(p) || p.includes(normalized))) {
|
|
1820
|
+
if (fieldName.includes("Aggregate") || fieldName.includes("aggregate")) {
|
|
1821
|
+
if (!cov.limitType || cov.limitType === "aggregate") {
|
|
1822
|
+
limits[fieldName] = cov.limit;
|
|
1823
|
+
}
|
|
1824
|
+
} else {
|
|
1825
|
+
if (!limits[fieldName]) {
|
|
1826
|
+
limits[fieldName] = cov.limit;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
break;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
const hasStatutory = coverages.some(
|
|
1834
|
+
(c) => c.limitType === "statutory" || normalizeName(c.name ?? "").includes("statutory")
|
|
1835
|
+
);
|
|
1836
|
+
if (hasStatutory) {
|
|
1837
|
+
limits.statutory = "true";
|
|
1838
|
+
}
|
|
1839
|
+
const elCoverages = coverages.filter(
|
|
1840
|
+
(c) => normalizeName(c.name ?? "").includes("employersliability")
|
|
1841
|
+
);
|
|
1842
|
+
if (elCoverages.length > 0) {
|
|
1843
|
+
const el = {};
|
|
1844
|
+
for (const c of elCoverages) {
|
|
1845
|
+
if (!c.limit) continue;
|
|
1846
|
+
const n = normalizeName(c.name ?? "");
|
|
1847
|
+
if (n.includes("accident") || n.includes("eachaccident")) el.eachAccident = c.limit;
|
|
1848
|
+
else if (n.includes("diseasepolicy") || n.includes("diseasepolicylimit")) el.diseasePolicyLimit = c.limit;
|
|
1849
|
+
else if (n.includes("diseaseemployee") || n.includes("diseaseeachemployee")) el.diseaseEachEmployee = c.limit;
|
|
1850
|
+
else if (!el.eachAccident) el.eachAccident = c.limit;
|
|
1851
|
+
}
|
|
1852
|
+
if (Object.keys(el).length > 0) {
|
|
1853
|
+
limits.employersLiability = el;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
if (Object.keys(limits).length > 0) {
|
|
1857
|
+
const result = { ...limits };
|
|
1858
|
+
if (result.statutory === "true") result.statutory = true;
|
|
1859
|
+
raw.limits = result;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
function synthesizeDeductibles(doc) {
|
|
1863
|
+
const raw = doc;
|
|
1864
|
+
if (raw.deductibles && typeof raw.deductibles === "object" && Object.keys(raw.deductibles).length > 0) return;
|
|
1865
|
+
const coverages = doc.coverages;
|
|
1866
|
+
if (!coverages || coverages.length === 0) return;
|
|
1867
|
+
const deductibleValues = coverages.filter((c) => c.deductible && c.deductible.trim() !== "" && c.deductible !== "N/A" && c.deductible !== "None").map((c) => c.deductible);
|
|
1868
|
+
if (deductibleValues.length === 0) return;
|
|
1869
|
+
const freq = /* @__PURE__ */ new Map();
|
|
1870
|
+
for (const d of deductibleValues) {
|
|
1871
|
+
freq.set(d, (freq.get(d) ?? 0) + 1);
|
|
1872
|
+
}
|
|
1873
|
+
let mostCommon = deductibleValues[0];
|
|
1874
|
+
let maxFreq = 0;
|
|
1875
|
+
for (const [val, count] of freq) {
|
|
1876
|
+
if (count > maxFreq) {
|
|
1877
|
+
mostCommon = val;
|
|
1878
|
+
maxFreq = count;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
const deductibles = {};
|
|
1882
|
+
const hasPerClaim = coverages.some(
|
|
1883
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("perclaim")
|
|
1884
|
+
);
|
|
1885
|
+
if (hasPerClaim) {
|
|
1886
|
+
deductibles.perClaim = mostCommon;
|
|
1887
|
+
} else {
|
|
1888
|
+
deductibles.perOccurrence = mostCommon;
|
|
1889
|
+
}
|
|
1890
|
+
const sirCoverage = coverages.find(
|
|
1891
|
+
(c) => c.deductible && (normalizeName(c.name ?? "").includes("selfinsuredretention") || normalizeName(c.name ?? "").includes("sir"))
|
|
1892
|
+
);
|
|
1893
|
+
if (sirCoverage?.deductible) {
|
|
1894
|
+
deductibles.selfInsuredRetention = sirCoverage.deductible;
|
|
1895
|
+
}
|
|
1896
|
+
const aggDed = coverages.find(
|
|
1897
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("aggregatedeductible")
|
|
1898
|
+
);
|
|
1899
|
+
if (aggDed?.deductible) {
|
|
1900
|
+
deductibles.aggregateDeductible = aggDed.deductible;
|
|
1901
|
+
}
|
|
1902
|
+
if (Object.keys(deductibles).length > 0) {
|
|
1903
|
+
raw.deductibles = deductibles;
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
var PREMIUM_PATTERNS = ["premium", "totalPremium", "annualPremium", "policyPremium", "basePremium"];
|
|
1907
|
+
var TOTAL_COST_PATTERNS = ["totalCost", "totalDue", "totalAmount", "totalPolicyPremium"];
|
|
1908
|
+
function promotePremium(doc) {
|
|
1909
|
+
const raw = doc;
|
|
1910
|
+
const fields = getDeclarationFields(doc);
|
|
1911
|
+
if (!raw.premium) {
|
|
1912
|
+
const premium = findFieldValue(fields, PREMIUM_PATTERNS);
|
|
1913
|
+
if (premium) raw.premium = premium;
|
|
1914
|
+
}
|
|
1915
|
+
if (!raw.totalCost) {
|
|
1916
|
+
const totalCost = findFieldValue(fields, TOTAL_COST_PATTERNS);
|
|
1917
|
+
if (totalCost) raw.totalCost = totalCost;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
function promoteExtractedFields(doc) {
|
|
1921
|
+
promoteCarrierFields(doc);
|
|
1922
|
+
promoteBroker(doc);
|
|
1923
|
+
promoteLossPayees(doc);
|
|
1924
|
+
promoteLocations(doc);
|
|
1925
|
+
synthesizeLimits(doc);
|
|
1926
|
+
synthesizeDeductibles(doc);
|
|
1927
|
+
promotePremium(doc);
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1577
1930
|
// src/extraction/assembler.ts
|
|
1578
1931
|
function assembleDocument(documentId, documentType, memory) {
|
|
1579
1932
|
const carrier = memory.get("carrier_info");
|
|
@@ -1597,6 +1950,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1597
1950
|
policyTypes: classify?.policyTypes,
|
|
1598
1951
|
...sanitizeNulls(carrier ?? {}),
|
|
1599
1952
|
...sanitizeNulls(insured ?? {}),
|
|
1953
|
+
// Map named_insured extractor's loss payees/mortgage holders to EndorsementParty shape
|
|
1954
|
+
...Array.isArray(insured?.lossPayees) && insured.lossPayees.length > 0 ? { lossPayees: insured.lossPayees.map((lp) => ({ ...lp, role: "loss_payee" })) } : {},
|
|
1955
|
+
...Array.isArray(insured?.mortgageHolders) && insured.mortgageHolders.length > 0 ? { mortgageHolders: insured.mortgageHolders.map((mh) => ({ ...mh, role: "mortgage_holder" })) } : {},
|
|
1600
1956
|
...sanitizeNulls(coverages ?? {}),
|
|
1601
1957
|
...sanitizeNulls(premium ?? {}),
|
|
1602
1958
|
...sanitizeNulls(supplementary ?? {}),
|
|
@@ -1608,8 +1964,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1608
1964
|
declarations: declarations ? sanitizeNulls(declarations) : void 0,
|
|
1609
1965
|
...sanitizeNulls(lossHistory ?? {})
|
|
1610
1966
|
};
|
|
1967
|
+
let doc;
|
|
1611
1968
|
if (documentType === "policy") {
|
|
1612
|
-
|
|
1969
|
+
doc = {
|
|
1613
1970
|
...base,
|
|
1614
1971
|
type: "policy",
|
|
1615
1972
|
policyNumber: carrier?.policyNumber ?? insured?.policyNumber ?? "Unknown",
|
|
@@ -1617,17 +1974,20 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1617
1974
|
expirationDate: carrier?.expirationDate,
|
|
1618
1975
|
policyTermType: carrier?.policyTermType
|
|
1619
1976
|
};
|
|
1977
|
+
} else {
|
|
1978
|
+
doc = {
|
|
1979
|
+
...base,
|
|
1980
|
+
type: "quote",
|
|
1981
|
+
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
1982
|
+
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
1983
|
+
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
1984
|
+
subjectivities: coverages?.subjectivities,
|
|
1985
|
+
underwritingConditions: coverages?.underwritingConditions,
|
|
1986
|
+
premiumBreakdown: premium?.premiumBreakdown
|
|
1987
|
+
};
|
|
1620
1988
|
}
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
type: "quote",
|
|
1624
|
-
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
1625
|
-
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
1626
|
-
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
1627
|
-
subjectivities: coverages?.subjectivities,
|
|
1628
|
-
underwritingConditions: coverages?.underwritingConditions,
|
|
1629
|
-
premiumBreakdown: premium?.premiumBreakdown
|
|
1630
|
-
};
|
|
1989
|
+
promoteExtractedFields(doc);
|
|
1990
|
+
return doc;
|
|
1631
1991
|
}
|
|
1632
1992
|
|
|
1633
1993
|
// src/prompts/coordinator/format.ts
|
|
@@ -1999,6 +2359,7 @@ function mergeCoverageLimits(existing, incoming) {
|
|
|
1999
2359
|
const incomingCoverages = Array.isArray(incoming.coverages) ? incoming.coverages : [];
|
|
2000
2360
|
const coverageKey = (coverage) => [
|
|
2001
2361
|
String(coverage.name ?? "").toLowerCase(),
|
|
2362
|
+
String(coverage.limitType ?? "").toLowerCase(),
|
|
2002
2363
|
String(coverage.limit ?? "").toLowerCase(),
|
|
2003
2364
|
String(coverage.deductible ?? "").toLowerCase(),
|
|
2004
2365
|
String(coverage.formNumber ?? "").toLowerCase()
|
|
@@ -2964,6 +3325,7 @@ Available extractors:
|
|
|
2964
3325
|
- supplementary
|
|
2965
3326
|
|
|
2966
3327
|
Rules:
|
|
3328
|
+
- Identify the broad section or form context first, then assign focused extractors within that context.
|
|
2967
3329
|
- Use specific extractors for declarations, schedules, endorsements, exclusions, conditions, premium pages, and loss runs.
|
|
2968
3330
|
- Use "sections" for pages that contain substantive policy text or mixed content that should still be preserved as raw sections.
|
|
2969
3331
|
- Avoid assigning broad ranges mentally; decide page by page.
|
|
@@ -2974,6 +3336,8 @@ Rules:
|
|
|
2974
3336
|
- Headings like "Limits of Insurance", "Deductible", "Coinsurance", "Loss Conditions", or "Definitions" inside a policy form usually indicate form language, not declarations or schedules.
|
|
2975
3337
|
- Continuation pages near the end of a form should stay mapped to "sections" plus "conditions"/"exclusions" when applicable, even if they mention limits or deductibles.
|
|
2976
3338
|
- When a form inventory entry identifies a page range as a specific form type (e.g., endorsement, coverage, application), use that classification to guide your extractor choice. Do not assign "coverage_limits" to pages the inventory identifies as endorsement or condition/exclusion forms unless the page contains actual schedule values.
|
|
3339
|
+
- Do not tag a page with "exclusions" or "conditions" if it only contains a table of contents, page-number reference, running header/footer, or a heading that points to another page without substantive wording.
|
|
3340
|
+
- If a page appears to be part of a larger exclusion, conditions, or endorsement section within the same form, keep the assignment consistent across nearby pages in that section rather than isolating a single page fragment.
|
|
2977
3341
|
- Return every page in the supplied chunk exactly once.
|
|
2978
3342
|
|
|
2979
3343
|
Return JSON:
|
|
@@ -3057,21 +3421,69 @@ Use the page map to target follow-up extraction pages precisely. Prefer narrow,
|
|
|
3057
3421
|
Respond with JSON only.`;
|
|
3058
3422
|
}
|
|
3059
3423
|
|
|
3060
|
-
// src/prompts/
|
|
3424
|
+
// src/prompts/coordinator/summarize.ts
|
|
3061
3425
|
import { z as z22 } from "zod";
|
|
3062
|
-
var
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3426
|
+
var SummaryResultSchema = z22.object({
|
|
3427
|
+
summary: z22.string().describe("A 1-3 sentence overview of this insurance document")
|
|
3428
|
+
});
|
|
3429
|
+
function buildSummaryPrompt(doc) {
|
|
3430
|
+
const snapshot = {
|
|
3431
|
+
type: doc.type,
|
|
3432
|
+
carrier: doc.carrier,
|
|
3433
|
+
insuredName: doc.insuredName,
|
|
3434
|
+
policyTypes: doc.policyTypes,
|
|
3435
|
+
premium: doc.premium,
|
|
3436
|
+
coverageCount: doc.coverages?.length ?? 0
|
|
3437
|
+
};
|
|
3438
|
+
if (doc.type === "policy") {
|
|
3439
|
+
snapshot.policyNumber = doc.policyNumber;
|
|
3440
|
+
snapshot.effectiveDate = doc.effectiveDate;
|
|
3441
|
+
snapshot.expirationDate = doc.expirationDate;
|
|
3442
|
+
} else {
|
|
3443
|
+
snapshot.quoteNumber = doc.quoteNumber;
|
|
3444
|
+
snapshot.proposedEffectiveDate = doc.proposedEffectiveDate;
|
|
3445
|
+
}
|
|
3446
|
+
const raw = doc;
|
|
3447
|
+
if (raw.limits) snapshot.limits = raw.limits;
|
|
3448
|
+
if (raw.deductibles) snapshot.deductibles = raw.deductibles;
|
|
3449
|
+
if (raw.brokerAgency) snapshot.brokerAgency = raw.brokerAgency;
|
|
3450
|
+
if (doc.endorsements?.length) snapshot.endorsementCount = doc.endorsements.length;
|
|
3451
|
+
if (doc.exclusions?.length) snapshot.exclusionCount = doc.exclusions.length;
|
|
3452
|
+
if (doc.coverages?.length) {
|
|
3453
|
+
snapshot.topCoverages = doc.coverages.slice(0, 5).map((c) => c.name);
|
|
3454
|
+
}
|
|
3455
|
+
return `You are an expert insurance document analyst. Generate a brief summary of this insurance document.
|
|
3456
|
+
|
|
3457
|
+
Write 1-3 sentences that capture the essential facts a broker or underwriter would want at a glance:
|
|
3458
|
+
- Who is insured and by whom
|
|
3459
|
+
- What type of policy/quote and the key coverages
|
|
3460
|
+
- Policy period and premium if available
|
|
3461
|
+
- Any notable features (high limits, unusual exclusions, etc.)
|
|
3462
|
+
|
|
3463
|
+
Document data:
|
|
3464
|
+
${JSON.stringify(snapshot, null, 2)}
|
|
3465
|
+
|
|
3466
|
+
Return JSON only with a "summary" field.`;
|
|
3467
|
+
}
|
|
3468
|
+
|
|
3469
|
+
// src/prompts/extractors/carrier-info.ts
|
|
3470
|
+
import { z as z23 } from "zod";
|
|
3471
|
+
var CarrierInfoSchema = z23.object({
|
|
3472
|
+
carrierName: z23.string().describe("Primary insurance company name for display"),
|
|
3473
|
+
carrierLegalName: z23.string().optional().describe("Legal entity name of insurer"),
|
|
3474
|
+
naicNumber: z23.string().optional().describe("NAIC company code"),
|
|
3475
|
+
amBestRating: z23.string().optional().describe("AM Best rating, e.g. 'A+ XV'"),
|
|
3476
|
+
admittedStatus: z23.enum(["admitted", "non_admitted", "surplus_lines"]).optional().describe("Admitted status of the carrier"),
|
|
3477
|
+
mga: z23.string().optional().describe("Managing General Agent or Program Administrator name"),
|
|
3478
|
+
underwriter: z23.string().optional().describe("Named individual underwriter"),
|
|
3479
|
+
brokerAgency: z23.string().optional().describe("Broker or producer agency name"),
|
|
3480
|
+
brokerContactName: z23.string().optional().describe("Broker or producer contact person name"),
|
|
3481
|
+
brokerLicenseNumber: z23.string().optional().describe("Broker or producer license number"),
|
|
3482
|
+
policyNumber: z23.string().optional().describe("Policy or quote reference number"),
|
|
3483
|
+
effectiveDate: z23.string().optional().describe("Policy effective date (MM/DD/YYYY)"),
|
|
3484
|
+
expirationDate: z23.string().optional().describe("Policy expiration date (MM/DD/YYYY)"),
|
|
3485
|
+
quoteNumber: z23.string().optional().describe("Quote or proposal reference number"),
|
|
3486
|
+
proposedEffectiveDate: z23.string().optional().describe("Proposed effective date for quotes (MM/DD/YYYY)")
|
|
3075
3487
|
});
|
|
3076
3488
|
function buildCarrierInfoPrompt() {
|
|
3077
3489
|
return `You are an expert insurance document analyst. Extract carrier and policy identification information from this document.
|
|
@@ -3082,27 +3494,30 @@ Focus on:
|
|
|
3082
3494
|
- Whether the carrier is admitted, non-admitted, or surplus lines
|
|
3083
3495
|
- Managing General Agent (MGA) or Program Administrator if applicable
|
|
3084
3496
|
- Named individual underwriter if listed
|
|
3497
|
+
- Broker/producer/agent: agency name, contact person name, and license number
|
|
3085
3498
|
- Policy number and effective/expiration dates
|
|
3086
3499
|
- For quotes: quote number and proposed effective date
|
|
3087
3500
|
|
|
3088
3501
|
For carrier vs. security distinction: "carrier" is the primary company name; the legal entity on risk (e.g. "Lloyd's Underwriters") may differ from the display name.
|
|
3089
3502
|
|
|
3503
|
+
Look for broker/producer/agent information near the carrier or on the declarations page. This may be labeled "Producer", "Agent", "Broker", or similar.
|
|
3504
|
+
|
|
3090
3505
|
Return JSON only.`;
|
|
3091
3506
|
}
|
|
3092
3507
|
|
|
3093
3508
|
// src/prompts/extractors/named-insured.ts
|
|
3094
|
-
import { z as
|
|
3095
|
-
var AddressSchema2 =
|
|
3096
|
-
street1:
|
|
3097
|
-
city:
|
|
3098
|
-
state:
|
|
3099
|
-
zip:
|
|
3509
|
+
import { z as z24 } from "zod";
|
|
3510
|
+
var AddressSchema2 = z24.object({
|
|
3511
|
+
street1: z24.string(),
|
|
3512
|
+
city: z24.string(),
|
|
3513
|
+
state: z24.string(),
|
|
3514
|
+
zip: z24.string()
|
|
3100
3515
|
});
|
|
3101
|
-
var NamedInsuredSchema2 =
|
|
3102
|
-
insuredName:
|
|
3103
|
-
insuredDba:
|
|
3516
|
+
var NamedInsuredSchema2 = z24.object({
|
|
3517
|
+
insuredName: z24.string().describe("Name of primary named insured"),
|
|
3518
|
+
insuredDba: z24.string().optional().describe("Doing-business-as name"),
|
|
3104
3519
|
insuredAddress: AddressSchema2.optional().describe("Primary insured mailing address"),
|
|
3105
|
-
insuredEntityType:
|
|
3520
|
+
insuredEntityType: z24.enum([
|
|
3106
3521
|
"corporation",
|
|
3107
3522
|
"llc",
|
|
3108
3523
|
"partnership",
|
|
@@ -3115,16 +3530,28 @@ var NamedInsuredSchema2 = z23.object({
|
|
|
3115
3530
|
"married_couple",
|
|
3116
3531
|
"other"
|
|
3117
3532
|
]).optional().describe("Legal entity type of the insured"),
|
|
3118
|
-
insuredFein:
|
|
3119
|
-
insuredSicCode:
|
|
3120
|
-
insuredNaicsCode:
|
|
3121
|
-
additionalNamedInsureds:
|
|
3122
|
-
|
|
3123
|
-
name:
|
|
3124
|
-
relationship:
|
|
3533
|
+
insuredFein: z24.string().optional().describe("Federal Employer Identification Number"),
|
|
3534
|
+
insuredSicCode: z24.string().optional().describe("SIC code"),
|
|
3535
|
+
insuredNaicsCode: z24.string().optional().describe("NAICS code"),
|
|
3536
|
+
additionalNamedInsureds: z24.array(
|
|
3537
|
+
z24.object({
|
|
3538
|
+
name: z24.string(),
|
|
3539
|
+
relationship: z24.string().optional().describe("e.g. subsidiary, affiliate"),
|
|
3125
3540
|
address: AddressSchema2.optional()
|
|
3126
3541
|
})
|
|
3127
|
-
).optional().describe("Additional named insureds listed on the policy")
|
|
3542
|
+
).optional().describe("Additional named insureds listed on the policy"),
|
|
3543
|
+
lossPayees: z24.array(
|
|
3544
|
+
z24.object({
|
|
3545
|
+
name: z24.string(),
|
|
3546
|
+
address: AddressSchema2.optional()
|
|
3547
|
+
})
|
|
3548
|
+
).optional().describe("Loss payees listed on the policy"),
|
|
3549
|
+
mortgageHolders: z24.array(
|
|
3550
|
+
z24.object({
|
|
3551
|
+
name: z24.string(),
|
|
3552
|
+
address: AddressSchema2.optional()
|
|
3553
|
+
})
|
|
3554
|
+
).optional().describe("Mortgage holders / lienholders listed on the policy")
|
|
3128
3555
|
});
|
|
3129
3556
|
function buildNamedInsuredPrompt() {
|
|
3130
3557
|
return `You are an expert insurance document analyst. Extract all named insured information from this document.
|
|
@@ -3135,21 +3562,23 @@ Focus on:
|
|
|
3135
3562
|
- FEIN (Federal Employer Identification Number) if listed
|
|
3136
3563
|
- SIC code and NAICS code if listed
|
|
3137
3564
|
- ALL additional named insureds with their relationship (subsidiary, affiliate, etc.) and address if provided
|
|
3565
|
+
- ALL loss payees with name and address (e.g. "Loss Payee: BMO Bank of Montreal")
|
|
3566
|
+
- ALL mortgage holders / lienholders / mortgagees with name and address
|
|
3138
3567
|
|
|
3139
|
-
Look on the declarations page, named insured schedule, and any endorsements that add or modify named insureds.
|
|
3568
|
+
Look on the declarations page, named insured schedule, loss payee schedule, mortgagee schedule, and any endorsements that add or modify named insureds, loss payees, or mortgage holders.
|
|
3140
3569
|
|
|
3141
3570
|
Return JSON only.`;
|
|
3142
3571
|
}
|
|
3143
3572
|
|
|
3144
3573
|
// src/prompts/extractors/coverage-limits.ts
|
|
3145
|
-
import { z as
|
|
3574
|
+
import { z as z25 } from "zod";
|
|
3146
3575
|
var ExtractorCoverageSchema = CoverageSchema.extend({
|
|
3147
|
-
coverageCode:
|
|
3576
|
+
coverageCode: z25.string().optional().describe("Coverage code or class code")
|
|
3148
3577
|
});
|
|
3149
|
-
var CoverageLimitsSchema =
|
|
3150
|
-
coverages:
|
|
3151
|
-
coverageForm:
|
|
3152
|
-
retroactiveDate:
|
|
3578
|
+
var CoverageLimitsSchema = z25.object({
|
|
3579
|
+
coverages: z25.array(ExtractorCoverageSchema).describe("All coverages with their limits"),
|
|
3580
|
+
coverageForm: z25.enum(["occurrence", "claims_made", "accident"]).optional().describe("Primary coverage trigger type"),
|
|
3581
|
+
retroactiveDate: z25.string().optional().describe("Retroactive date for claims-made policies (MM/DD/YYYY)")
|
|
3153
3582
|
});
|
|
3154
3583
|
function buildCoverageLimitsPrompt() {
|
|
3155
3584
|
return `You are an expert insurance document analyst. Extract all coverage limits and deductibles from this document.
|
|
@@ -3158,7 +3587,7 @@ Extract only insured-specific declaration, schedule, or endorsement entries that
|
|
|
3158
3587
|
|
|
3159
3588
|
Focus on:
|
|
3160
3589
|
- Every coverage listed on the declarations page or coverage schedule
|
|
3161
|
-
- Per-occurrence, aggregate, and sub-limits for each coverage
|
|
3590
|
+
- Per-occurrence, individual/occurrence, aggregate, and sub-limits for each coverage
|
|
3162
3591
|
- Deductible or self-insured retention for each coverage
|
|
3163
3592
|
- Coverage form type: occurrence-based, claims-made, or accident
|
|
3164
3593
|
- Retroactive date for claims-made policies
|
|
@@ -3170,6 +3599,7 @@ For EACH coverage, also extract:
|
|
|
3170
3599
|
- pageNumber: the original page number where the coverage row/value appears
|
|
3171
3600
|
- sectionRef: the declarations/schedule/endorsement section heading where it appears
|
|
3172
3601
|
- originalContent: the verbatim row or short source snippet used for this coverage
|
|
3602
|
+
- limitType: when applicable, classify the limit as per_occurrence, per_claim, aggregate, per_person, per_accident, statutory, blanket, or scheduled
|
|
3173
3603
|
- limitValueType: classify the limit as numeric, included, not_included, as_stated, waiting_period, referential, or other
|
|
3174
3604
|
- deductibleValueType: classify the deductible/value term similarly when deductible is present
|
|
3175
3605
|
|
|
@@ -3181,19 +3611,20 @@ Critical rules:
|
|
|
3181
3611
|
- If a waiting period or hour deductible is shown as part of a specific declarations/schedule row, it may be captured in deductible. Otherwise omit it.
|
|
3182
3612
|
- Use limitValueType or deductibleValueType to preserve non-numeric terms precisely instead of forcing them into numeric semantics.
|
|
3183
3613
|
- Preserve one row per real coverage entry. Do not merge adjacent schedule rows into malformed names.
|
|
3614
|
+
- Keep individual/per-occurrence limits separate from aggregate limits even when they have the same coverage name, limit amount, deductible, and form number. Use limitType to distinguish them.
|
|
3184
3615
|
|
|
3185
3616
|
Return JSON only.`;
|
|
3186
3617
|
}
|
|
3187
3618
|
|
|
3188
3619
|
// src/prompts/extractors/endorsements.ts
|
|
3189
|
-
import { z as
|
|
3190
|
-
var EndorsementsSchema =
|
|
3191
|
-
endorsements:
|
|
3192
|
-
|
|
3193
|
-
formNumber:
|
|
3194
|
-
editionDate:
|
|
3195
|
-
title:
|
|
3196
|
-
endorsementType:
|
|
3620
|
+
import { z as z26 } from "zod";
|
|
3621
|
+
var EndorsementsSchema = z26.object({
|
|
3622
|
+
endorsements: z26.array(
|
|
3623
|
+
z26.object({
|
|
3624
|
+
formNumber: z26.string().describe("Form number, e.g. 'CG 21 47'"),
|
|
3625
|
+
editionDate: z26.string().optional().describe("Edition date, e.g. '12 07'"),
|
|
3626
|
+
title: z26.string().describe("Endorsement title"),
|
|
3627
|
+
endorsementType: z26.enum([
|
|
3197
3628
|
"additional_insured",
|
|
3198
3629
|
"waiver_of_subrogation",
|
|
3199
3630
|
"primary_noncontributory",
|
|
@@ -3213,12 +3644,12 @@ var EndorsementsSchema = z25.object({
|
|
|
3213
3644
|
"territorial_extension",
|
|
3214
3645
|
"other"
|
|
3215
3646
|
]).describe("Endorsement type classification"),
|
|
3216
|
-
effectiveDate:
|
|
3217
|
-
affectedCoverageParts:
|
|
3218
|
-
namedParties:
|
|
3219
|
-
|
|
3220
|
-
name:
|
|
3221
|
-
role:
|
|
3647
|
+
effectiveDate: z26.string().optional().describe("Endorsement effective date"),
|
|
3648
|
+
affectedCoverageParts: z26.array(z26.string()).optional().describe("Coverage parts affected by this endorsement"),
|
|
3649
|
+
namedParties: z26.array(
|
|
3650
|
+
z26.object({
|
|
3651
|
+
name: z26.string().describe("Party name"),
|
|
3652
|
+
role: z26.enum([
|
|
3222
3653
|
"additional_insured",
|
|
3223
3654
|
"loss_payee",
|
|
3224
3655
|
"mortgage_holder",
|
|
@@ -3227,15 +3658,15 @@ var EndorsementsSchema = z25.object({
|
|
|
3227
3658
|
"designated_person",
|
|
3228
3659
|
"other"
|
|
3229
3660
|
]).describe("Party role"),
|
|
3230
|
-
relationship:
|
|
3231
|
-
scope:
|
|
3661
|
+
relationship: z26.string().optional().describe("Relationship to insured"),
|
|
3662
|
+
scope: z26.string().optional().describe("Scope of coverage for this party")
|
|
3232
3663
|
})
|
|
3233
3664
|
).optional().describe("Named parties (additional insureds, loss payees, etc.)"),
|
|
3234
|
-
keyTerms:
|
|
3235
|
-
premiumImpact:
|
|
3236
|
-
content:
|
|
3237
|
-
pageStart:
|
|
3238
|
-
pageEnd:
|
|
3665
|
+
keyTerms: z26.array(z26.string()).optional().describe("Key terms or notable provisions in the endorsement"),
|
|
3666
|
+
premiumImpact: z26.string().optional().describe("Additional premium or credit"),
|
|
3667
|
+
content: z26.string().describe("Full verbatim text of the endorsement"),
|
|
3668
|
+
pageStart: z26.number().describe("Starting page number of this endorsement"),
|
|
3669
|
+
pageEnd: z26.number().optional().describe("Ending page number of this endorsement")
|
|
3239
3670
|
})
|
|
3240
3671
|
).describe("All endorsements found in the document")
|
|
3241
3672
|
});
|
|
@@ -3266,20 +3697,20 @@ Return JSON only.`;
|
|
|
3266
3697
|
}
|
|
3267
3698
|
|
|
3268
3699
|
// src/prompts/extractors/exclusions.ts
|
|
3269
|
-
import { z as
|
|
3270
|
-
var ExclusionsSchema =
|
|
3271
|
-
exclusions:
|
|
3272
|
-
|
|
3273
|
-
name:
|
|
3274
|
-
formNumber:
|
|
3275
|
-
excludedPerils:
|
|
3276
|
-
isAbsolute:
|
|
3277
|
-
exceptions:
|
|
3278
|
-
buybackAvailable:
|
|
3279
|
-
buybackEndorsement:
|
|
3280
|
-
appliesTo:
|
|
3281
|
-
content:
|
|
3282
|
-
pageNumber:
|
|
3700
|
+
import { z as z27 } from "zod";
|
|
3701
|
+
var ExclusionsSchema = z27.object({
|
|
3702
|
+
exclusions: z27.array(
|
|
3703
|
+
z27.object({
|
|
3704
|
+
name: z27.string().describe("Exclusion title or short description"),
|
|
3705
|
+
formNumber: z27.string().optional().describe("Form number if part of a named endorsement"),
|
|
3706
|
+
excludedPerils: z27.array(z27.string()).optional().describe("Specific perils excluded"),
|
|
3707
|
+
isAbsolute: z27.boolean().optional().describe("Whether the exclusion is absolute (no exceptions)"),
|
|
3708
|
+
exceptions: z27.array(z27.string()).optional().describe("Exceptions to the exclusion, if any"),
|
|
3709
|
+
buybackAvailable: z27.boolean().optional().describe("Whether coverage can be bought back via endorsement"),
|
|
3710
|
+
buybackEndorsement: z27.string().optional().describe("Form number of the buyback endorsement if available"),
|
|
3711
|
+
appliesTo: z27.array(z27.string()).optional().describe("Coverage types this exclusion applies to"),
|
|
3712
|
+
content: z27.string().describe("Full verbatim exclusion text"),
|
|
3713
|
+
pageNumber: z27.number().optional().describe("Page number where exclusion appears")
|
|
3283
3714
|
})
|
|
3284
3715
|
).describe("All exclusions found in the document")
|
|
3285
3716
|
});
|
|
@@ -3315,12 +3746,12 @@ Return JSON only.`;
|
|
|
3315
3746
|
}
|
|
3316
3747
|
|
|
3317
3748
|
// src/prompts/extractors/conditions.ts
|
|
3318
|
-
import { z as
|
|
3319
|
-
var ConditionsSchema =
|
|
3320
|
-
conditions:
|
|
3321
|
-
|
|
3322
|
-
name:
|
|
3323
|
-
conditionType:
|
|
3749
|
+
import { z as z28 } from "zod";
|
|
3750
|
+
var ConditionsSchema = z28.object({
|
|
3751
|
+
conditions: z28.array(
|
|
3752
|
+
z28.object({
|
|
3753
|
+
name: z28.string().describe("Condition title"),
|
|
3754
|
+
conditionType: z28.enum([
|
|
3324
3755
|
"duties_after_loss",
|
|
3325
3756
|
"notice_requirements",
|
|
3326
3757
|
"other_insurance",
|
|
@@ -3339,14 +3770,14 @@ var ConditionsSchema = z27.object({
|
|
|
3339
3770
|
"separation_of_insureds",
|
|
3340
3771
|
"other"
|
|
3341
3772
|
]).describe("Condition category"),
|
|
3342
|
-
content:
|
|
3343
|
-
keyValues:
|
|
3344
|
-
|
|
3345
|
-
key:
|
|
3346
|
-
value:
|
|
3773
|
+
content: z28.string().describe("Full verbatim condition text"),
|
|
3774
|
+
keyValues: z28.array(
|
|
3775
|
+
z28.object({
|
|
3776
|
+
key: z28.string().describe("Key name (e.g. 'noticePeriod', 'suitDeadline')"),
|
|
3777
|
+
value: z28.string().describe("Value (e.g. '30 days', '2 years')")
|
|
3347
3778
|
})
|
|
3348
3779
|
).optional().describe("Key values extracted from the condition (notice periods, deadlines, etc.)"),
|
|
3349
|
-
pageNumber:
|
|
3780
|
+
pageNumber: z28.number().optional().describe("Page number where condition appears")
|
|
3350
3781
|
})
|
|
3351
3782
|
).describe("All policy conditions found in the document")
|
|
3352
3783
|
});
|
|
@@ -3384,28 +3815,28 @@ Return JSON only.`;
|
|
|
3384
3815
|
}
|
|
3385
3816
|
|
|
3386
3817
|
// src/prompts/extractors/premium-breakdown.ts
|
|
3387
|
-
import { z as
|
|
3388
|
-
var PremiumBreakdownSchema =
|
|
3389
|
-
premium:
|
|
3390
|
-
totalCost:
|
|
3391
|
-
premiumBreakdown:
|
|
3392
|
-
|
|
3393
|
-
line:
|
|
3394
|
-
amount:
|
|
3818
|
+
import { z as z29 } from "zod";
|
|
3819
|
+
var PremiumBreakdownSchema = z29.object({
|
|
3820
|
+
premium: z29.string().optional().describe("Total premium amount, e.g. '$5,000'"),
|
|
3821
|
+
totalCost: z29.string().optional().describe("Total cost including taxes and fees, e.g. '$5,250'"),
|
|
3822
|
+
premiumBreakdown: z29.array(
|
|
3823
|
+
z29.object({
|
|
3824
|
+
line: z29.string().describe("Coverage line name"),
|
|
3825
|
+
amount: z29.string().describe("Premium amount for this line")
|
|
3395
3826
|
})
|
|
3396
3827
|
).optional().describe("Per-coverage-line premium breakdown"),
|
|
3397
|
-
taxesAndFees:
|
|
3398
|
-
|
|
3399
|
-
name:
|
|
3400
|
-
amount:
|
|
3401
|
-
type:
|
|
3828
|
+
taxesAndFees: z29.array(
|
|
3829
|
+
z29.object({
|
|
3830
|
+
name: z29.string().describe("Fee or tax name"),
|
|
3831
|
+
amount: z29.string().describe("Dollar amount"),
|
|
3832
|
+
type: z29.enum(["tax", "fee", "surcharge", "assessment"]).optional().describe("Fee category")
|
|
3402
3833
|
})
|
|
3403
3834
|
).optional().describe("Taxes, fees, surcharges, and assessments"),
|
|
3404
|
-
minimumPremium:
|
|
3405
|
-
depositPremium:
|
|
3406
|
-
paymentPlan:
|
|
3407
|
-
auditType:
|
|
3408
|
-
ratingBasis:
|
|
3835
|
+
minimumPremium: z29.string().optional().describe("Minimum premium if stated"),
|
|
3836
|
+
depositPremium: z29.string().optional().describe("Deposit premium if stated"),
|
|
3837
|
+
paymentPlan: z29.string().optional().describe("Payment plan description"),
|
|
3838
|
+
auditType: z29.enum(["annual", "semi_annual", "quarterly", "monthly", "final", "self"]).optional().describe("Premium audit type"),
|
|
3839
|
+
ratingBasis: z29.string().optional().describe("Rating basis, e.g. payroll, revenue, area, units")
|
|
3409
3840
|
});
|
|
3410
3841
|
function buildPremiumBreakdownPrompt() {
|
|
3411
3842
|
return `You are an expert insurance document analyst. Extract all premium and cost information from this document.
|
|
@@ -3425,14 +3856,14 @@ Return JSON only.`;
|
|
|
3425
3856
|
}
|
|
3426
3857
|
|
|
3427
3858
|
// src/prompts/extractors/declarations.ts
|
|
3428
|
-
import { z as
|
|
3429
|
-
var DeclarationsFieldSchema =
|
|
3430
|
-
field:
|
|
3431
|
-
value:
|
|
3432
|
-
section:
|
|
3859
|
+
import { z as z30 } from "zod";
|
|
3860
|
+
var DeclarationsFieldSchema = z30.object({
|
|
3861
|
+
field: z30.string().describe("Descriptive field name (e.g. 'policyNumber', 'effectiveDate', 'coverageALimit')"),
|
|
3862
|
+
value: z30.string().describe("Extracted value exactly as it appears in the document"),
|
|
3863
|
+
section: z30.string().optional().describe("Section or grouping this field belongs to (e.g. 'Coverage Limits', 'Vehicle Schedule')")
|
|
3433
3864
|
});
|
|
3434
|
-
var DeclarationsExtractSchema =
|
|
3435
|
-
fields:
|
|
3865
|
+
var DeclarationsExtractSchema = z30.object({
|
|
3866
|
+
fields: z30.array(DeclarationsFieldSchema).describe("All declarations page fields extracted as key-value pairs. Structure varies by line of business.")
|
|
3436
3867
|
});
|
|
3437
3868
|
function buildDeclarationsPrompt() {
|
|
3438
3869
|
return `You are an expert insurance document analyst. Extract all declarations page data from this document into a flexible key-value structure.
|
|
@@ -3472,21 +3903,21 @@ Preserve original values exactly as they appear. Return JSON only.`;
|
|
|
3472
3903
|
}
|
|
3473
3904
|
|
|
3474
3905
|
// src/prompts/extractors/loss-history.ts
|
|
3475
|
-
import { z as
|
|
3476
|
-
var LossHistorySchema =
|
|
3477
|
-
lossSummary:
|
|
3478
|
-
individualClaims:
|
|
3479
|
-
|
|
3480
|
-
date:
|
|
3481
|
-
type:
|
|
3482
|
-
description:
|
|
3483
|
-
amountPaid:
|
|
3484
|
-
amountReserved:
|
|
3485
|
-
status:
|
|
3486
|
-
claimNumber:
|
|
3906
|
+
import { z as z31 } from "zod";
|
|
3907
|
+
var LossHistorySchema = z31.object({
|
|
3908
|
+
lossSummary: z31.string().optional().describe("Summary of loss history, e.g. '3 claims in past 5 years totaling $125,000'"),
|
|
3909
|
+
individualClaims: z31.array(
|
|
3910
|
+
z31.object({
|
|
3911
|
+
date: z31.string().optional().describe("Date of loss or claim"),
|
|
3912
|
+
type: z31.string().optional().describe("Type of claim, e.g. 'property damage', 'bodily injury'"),
|
|
3913
|
+
description: z31.string().optional().describe("Brief description of the claim"),
|
|
3914
|
+
amountPaid: z31.string().optional().describe("Amount paid"),
|
|
3915
|
+
amountReserved: z31.string().optional().describe("Amount reserved"),
|
|
3916
|
+
status: z31.enum(["open", "closed", "reopened"]).optional().describe("Claim status"),
|
|
3917
|
+
claimNumber: z31.string().optional().describe("Claim reference number")
|
|
3487
3918
|
})
|
|
3488
3919
|
).optional().describe("Individual claim records"),
|
|
3489
|
-
experienceMod:
|
|
3920
|
+
experienceMod: z31.string().optional().describe("Experience modification factor for workers comp, e.g. '0.85'")
|
|
3490
3921
|
});
|
|
3491
3922
|
function buildLossHistoryPrompt() {
|
|
3492
3923
|
return `You are an expert insurance document analyst. Extract all loss history and claims information from this document.
|
|
@@ -3503,18 +3934,18 @@ Return JSON only.`;
|
|
|
3503
3934
|
}
|
|
3504
3935
|
|
|
3505
3936
|
// src/prompts/extractors/sections.ts
|
|
3506
|
-
import { z as
|
|
3507
|
-
var SubsectionSchema2 =
|
|
3508
|
-
title:
|
|
3509
|
-
sectionNumber:
|
|
3510
|
-
pageNumber:
|
|
3511
|
-
content:
|
|
3937
|
+
import { z as z32 } from "zod";
|
|
3938
|
+
var SubsectionSchema2 = z32.object({
|
|
3939
|
+
title: z32.string().describe("Subsection title"),
|
|
3940
|
+
sectionNumber: z32.string().optional().describe("Subsection number"),
|
|
3941
|
+
pageNumber: z32.number().optional().describe("Page number"),
|
|
3942
|
+
content: z32.string().describe("Full verbatim text")
|
|
3512
3943
|
});
|
|
3513
|
-
var SectionsSchema =
|
|
3514
|
-
sections:
|
|
3515
|
-
|
|
3516
|
-
title:
|
|
3517
|
-
type:
|
|
3944
|
+
var SectionsSchema = z32.object({
|
|
3945
|
+
sections: z32.array(
|
|
3946
|
+
z32.object({
|
|
3947
|
+
title: z32.string().describe("Section title"),
|
|
3948
|
+
type: z32.enum([
|
|
3518
3949
|
"declarations",
|
|
3519
3950
|
"insuring_agreement",
|
|
3520
3951
|
"policy_form",
|
|
@@ -3528,10 +3959,10 @@ var SectionsSchema = z31.object({
|
|
|
3528
3959
|
"regulatory",
|
|
3529
3960
|
"other"
|
|
3530
3961
|
]).describe("Section type classification"),
|
|
3531
|
-
content:
|
|
3532
|
-
pageStart:
|
|
3533
|
-
pageEnd:
|
|
3534
|
-
subsections:
|
|
3962
|
+
content: z32.string().describe("Full verbatim text of the section"),
|
|
3963
|
+
pageStart: z32.number().describe("Starting page number"),
|
|
3964
|
+
pageEnd: z32.number().optional().describe("Ending page number"),
|
|
3965
|
+
subsections: z32.array(SubsectionSchema2).optional().describe("Subsections within this section")
|
|
3535
3966
|
})
|
|
3536
3967
|
).describe("All document sections")
|
|
3537
3968
|
});
|
|
@@ -3561,20 +3992,20 @@ Return JSON only.`;
|
|
|
3561
3992
|
}
|
|
3562
3993
|
|
|
3563
3994
|
// src/prompts/extractors/supplementary.ts
|
|
3564
|
-
import { z as
|
|
3565
|
-
var ContactSchema2 =
|
|
3566
|
-
name:
|
|
3567
|
-
phone:
|
|
3568
|
-
email:
|
|
3569
|
-
address:
|
|
3570
|
-
type:
|
|
3995
|
+
import { z as z33 } from "zod";
|
|
3996
|
+
var ContactSchema2 = z33.object({
|
|
3997
|
+
name: z33.string().optional().describe("Organization or person name"),
|
|
3998
|
+
phone: z33.string().optional().describe("Phone number"),
|
|
3999
|
+
email: z33.string().optional().describe("Email address"),
|
|
4000
|
+
address: z33.string().optional().describe("Mailing address"),
|
|
4001
|
+
type: z33.string().optional().describe("Contact type, e.g. 'State Department of Insurance'")
|
|
3571
4002
|
});
|
|
3572
|
-
var SupplementarySchema =
|
|
3573
|
-
regulatoryContacts:
|
|
3574
|
-
claimsContacts:
|
|
3575
|
-
thirdPartyAdministrators:
|
|
3576
|
-
cancellationNoticeDays:
|
|
3577
|
-
nonrenewalNoticeDays:
|
|
4003
|
+
var SupplementarySchema = z33.object({
|
|
4004
|
+
regulatoryContacts: z33.array(ContactSchema2).optional().describe("Regulatory body contacts (state department of insurance, ombudsman)"),
|
|
4005
|
+
claimsContacts: z33.array(ContactSchema2).optional().describe("Claims reporting contacts and instructions"),
|
|
4006
|
+
thirdPartyAdministrators: z33.array(ContactSchema2).optional().describe("Third-party administrators for claims handling"),
|
|
4007
|
+
cancellationNoticeDays: z33.number().optional().describe("Required notice period for cancellation in days"),
|
|
4008
|
+
nonrenewalNoticeDays: z33.number().optional().describe("Required notice period for nonrenewal in days")
|
|
3578
4009
|
});
|
|
3579
4010
|
function buildSupplementaryPrompt() {
|
|
3580
4011
|
return `You are an expert insurance document analyst. Extract supplementary and regulatory information from this document.
|
|
@@ -4058,7 +4489,7 @@ function createExtractor(config) {
|
|
|
4058
4489
|
ranges.push({ startPage: start, endPage: previous });
|
|
4059
4490
|
return ranges;
|
|
4060
4491
|
}
|
|
4061
|
-
function buildPlanFromPageAssignments(pageAssignments, pageCount) {
|
|
4492
|
+
function buildPlanFromPageAssignments(pageAssignments, pageCount, formInventory) {
|
|
4062
4493
|
const extractorPages = /* @__PURE__ */ new Map();
|
|
4063
4494
|
for (const assignment of pageAssignments) {
|
|
4064
4495
|
const extractors = assignment.extractorNames.length > 0 ? assignment.extractorNames : ["sections"];
|
|
@@ -4075,8 +4506,30 @@ function createExtractor(config) {
|
|
|
4075
4506
|
extractorPages.set("sections", [...extractorPages.get("sections") ?? [], page]);
|
|
4076
4507
|
}
|
|
4077
4508
|
}
|
|
4509
|
+
const contextualExtractors = /* @__PURE__ */ new Set(["conditions", "exclusions", "endorsements"]);
|
|
4510
|
+
const contextualForms = (formInventory?.forms ?? []).filter(
|
|
4511
|
+
(form) => form.pageStart != null && (form.pageEnd ?? form.pageStart) != null
|
|
4512
|
+
);
|
|
4513
|
+
const expandPagesToFormRanges = (extractorName, pages) => {
|
|
4514
|
+
if (!contextualExtractors.has(extractorName)) return pages;
|
|
4515
|
+
const expanded = new Set(pages);
|
|
4516
|
+
for (const page of pages) {
|
|
4517
|
+
for (const form of contextualForms) {
|
|
4518
|
+
const pageStart = form.pageStart;
|
|
4519
|
+
const pageEnd = form.pageEnd ?? form.pageStart;
|
|
4520
|
+
const formType = form.formType;
|
|
4521
|
+
const supportsContextualExpansion = extractorName === "endorsements" ? formType === "endorsement" : formType === "coverage" || formType === "endorsement";
|
|
4522
|
+
if (!supportsContextualExpansion) continue;
|
|
4523
|
+
if (page < pageStart || page > pageEnd) continue;
|
|
4524
|
+
for (let current = pageStart; current <= pageEnd; current += 1) {
|
|
4525
|
+
expanded.add(current);
|
|
4526
|
+
}
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
return [...expanded].sort((a, b) => a - b);
|
|
4530
|
+
};
|
|
4078
4531
|
const tasks = [...extractorPages.entries()].flatMap(
|
|
4079
|
-
([extractorName, pages]) => groupContiguousPages(pages).map(({ startPage, endPage }) => ({
|
|
4532
|
+
([extractorName, pages]) => groupContiguousPages(expandPagesToFormRanges(extractorName, pages)).map(({ startPage, endPage }) => ({
|
|
4080
4533
|
extractorName,
|
|
4081
4534
|
startPage,
|
|
4082
4535
|
endPage,
|
|
@@ -4244,7 +4697,7 @@ function createExtractor(config) {
|
|
|
4244
4697
|
onProgress?.("Resuming from checkpoint (plan complete)...");
|
|
4245
4698
|
} else {
|
|
4246
4699
|
onProgress?.(`Building extraction plan from page map for ${primaryType} ${documentType}...`);
|
|
4247
|
-
plan = buildPlanFromPageAssignments(pageAssignments, pageCount);
|
|
4700
|
+
plan = buildPlanFromPageAssignments(pageAssignments, pageCount, formInventory);
|
|
4248
4701
|
await pipelineCtx.save("plan", {
|
|
4249
4702
|
id,
|
|
4250
4703
|
pageCount,
|
|
@@ -4411,6 +4864,31 @@ function createExtractor(config) {
|
|
|
4411
4864
|
memory: Object.fromEntries(memory),
|
|
4412
4865
|
document
|
|
4413
4866
|
});
|
|
4867
|
+
if (!document.summary) {
|
|
4868
|
+
onProgress?.("Generating document summary...");
|
|
4869
|
+
try {
|
|
4870
|
+
const summaryResponse = await safeGenerateObject(
|
|
4871
|
+
generateObject,
|
|
4872
|
+
{
|
|
4873
|
+
prompt: buildSummaryPrompt(document),
|
|
4874
|
+
schema: SummaryResultSchema,
|
|
4875
|
+
maxTokens: 512,
|
|
4876
|
+
providerOptions
|
|
4877
|
+
},
|
|
4878
|
+
{
|
|
4879
|
+
fallback: { summary: "" },
|
|
4880
|
+
log,
|
|
4881
|
+
onError: (err, attempt) => log?.(`Summary attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
4882
|
+
}
|
|
4883
|
+
);
|
|
4884
|
+
trackUsage(summaryResponse.usage);
|
|
4885
|
+
if (summaryResponse.object.summary) {
|
|
4886
|
+
document.summary = summaryResponse.object.summary;
|
|
4887
|
+
}
|
|
4888
|
+
} catch (error) {
|
|
4889
|
+
await log?.(`Summary generation failed, skipping: ${error instanceof Error ? error.message : String(error)}`);
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4414
4892
|
onProgress?.("Formatting extracted content...");
|
|
4415
4893
|
const formatResult = await formatDocumentContent(document, generateText, {
|
|
4416
4894
|
providerOptions,
|
|
@@ -4654,8 +5132,8 @@ Respond with JSON only:
|
|
|
4654
5132
|
}`;
|
|
4655
5133
|
|
|
4656
5134
|
// src/schemas/application.ts
|
|
4657
|
-
import { z as
|
|
4658
|
-
var FieldTypeSchema =
|
|
5135
|
+
import { z as z34 } from "zod";
|
|
5136
|
+
var FieldTypeSchema = z34.enum([
|
|
4659
5137
|
"text",
|
|
4660
5138
|
"numeric",
|
|
4661
5139
|
"currency",
|
|
@@ -4664,131 +5142,131 @@ var FieldTypeSchema = z33.enum([
|
|
|
4664
5142
|
"table",
|
|
4665
5143
|
"declaration"
|
|
4666
5144
|
]);
|
|
4667
|
-
var ApplicationFieldSchema =
|
|
4668
|
-
id:
|
|
4669
|
-
label:
|
|
4670
|
-
section:
|
|
5145
|
+
var ApplicationFieldSchema = z34.object({
|
|
5146
|
+
id: z34.string(),
|
|
5147
|
+
label: z34.string(),
|
|
5148
|
+
section: z34.string(),
|
|
4671
5149
|
fieldType: FieldTypeSchema,
|
|
4672
|
-
required:
|
|
4673
|
-
options:
|
|
4674
|
-
columns:
|
|
4675
|
-
requiresExplanationIfYes:
|
|
4676
|
-
condition:
|
|
4677
|
-
dependsOn:
|
|
4678
|
-
whenValue:
|
|
5150
|
+
required: z34.boolean(),
|
|
5151
|
+
options: z34.array(z34.string()).optional(),
|
|
5152
|
+
columns: z34.array(z34.string()).optional(),
|
|
5153
|
+
requiresExplanationIfYes: z34.boolean().optional(),
|
|
5154
|
+
condition: z34.object({
|
|
5155
|
+
dependsOn: z34.string(),
|
|
5156
|
+
whenValue: z34.string()
|
|
4679
5157
|
}).optional(),
|
|
4680
|
-
value:
|
|
4681
|
-
source:
|
|
4682
|
-
confidence:
|
|
5158
|
+
value: z34.string().optional(),
|
|
5159
|
+
source: z34.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
|
|
5160
|
+
confidence: z34.enum(["confirmed", "high", "medium", "low"]).optional()
|
|
4683
5161
|
});
|
|
4684
|
-
var ApplicationClassifyResultSchema =
|
|
4685
|
-
isApplication:
|
|
4686
|
-
confidence:
|
|
4687
|
-
applicationType:
|
|
5162
|
+
var ApplicationClassifyResultSchema = z34.object({
|
|
5163
|
+
isApplication: z34.boolean(),
|
|
5164
|
+
confidence: z34.number().min(0).max(1),
|
|
5165
|
+
applicationType: z34.string().nullable()
|
|
4688
5166
|
});
|
|
4689
|
-
var FieldExtractionResultSchema =
|
|
4690
|
-
fields:
|
|
5167
|
+
var FieldExtractionResultSchema = z34.object({
|
|
5168
|
+
fields: z34.array(ApplicationFieldSchema)
|
|
4691
5169
|
});
|
|
4692
|
-
var AutoFillMatchSchema =
|
|
4693
|
-
fieldId:
|
|
4694
|
-
value:
|
|
4695
|
-
confidence:
|
|
4696
|
-
contextKey:
|
|
5170
|
+
var AutoFillMatchSchema = z34.object({
|
|
5171
|
+
fieldId: z34.string(),
|
|
5172
|
+
value: z34.string(),
|
|
5173
|
+
confidence: z34.enum(["confirmed"]),
|
|
5174
|
+
contextKey: z34.string()
|
|
4697
5175
|
});
|
|
4698
|
-
var AutoFillResultSchema =
|
|
4699
|
-
matches:
|
|
5176
|
+
var AutoFillResultSchema = z34.object({
|
|
5177
|
+
matches: z34.array(AutoFillMatchSchema)
|
|
4700
5178
|
});
|
|
4701
|
-
var QuestionBatchResultSchema =
|
|
4702
|
-
batches:
|
|
5179
|
+
var QuestionBatchResultSchema = z34.object({
|
|
5180
|
+
batches: z34.array(z34.array(z34.string()).describe("Array of field IDs in this batch"))
|
|
4703
5181
|
});
|
|
4704
|
-
var LookupRequestSchema =
|
|
4705
|
-
type:
|
|
4706
|
-
description:
|
|
4707
|
-
url:
|
|
4708
|
-
targetFieldIds:
|
|
5182
|
+
var LookupRequestSchema = z34.object({
|
|
5183
|
+
type: z34.string().describe("Type of lookup: 'records', 'website', 'policy'"),
|
|
5184
|
+
description: z34.string(),
|
|
5185
|
+
url: z34.string().optional(),
|
|
5186
|
+
targetFieldIds: z34.array(z34.string())
|
|
4709
5187
|
});
|
|
4710
|
-
var ReplyIntentSchema =
|
|
4711
|
-
primaryIntent:
|
|
4712
|
-
hasAnswers:
|
|
4713
|
-
questionText:
|
|
4714
|
-
questionFieldIds:
|
|
4715
|
-
lookupRequests:
|
|
5188
|
+
var ReplyIntentSchema = z34.object({
|
|
5189
|
+
primaryIntent: z34.enum(["answers_only", "question", "lookup_request", "mixed"]),
|
|
5190
|
+
hasAnswers: z34.boolean(),
|
|
5191
|
+
questionText: z34.string().optional(),
|
|
5192
|
+
questionFieldIds: z34.array(z34.string()).optional(),
|
|
5193
|
+
lookupRequests: z34.array(LookupRequestSchema).optional()
|
|
4716
5194
|
});
|
|
4717
|
-
var ParsedAnswerSchema =
|
|
4718
|
-
fieldId:
|
|
4719
|
-
value:
|
|
4720
|
-
explanation:
|
|
5195
|
+
var ParsedAnswerSchema = z34.object({
|
|
5196
|
+
fieldId: z34.string(),
|
|
5197
|
+
value: z34.string(),
|
|
5198
|
+
explanation: z34.string().optional()
|
|
4721
5199
|
});
|
|
4722
|
-
var AnswerParsingResultSchema =
|
|
4723
|
-
answers:
|
|
4724
|
-
unanswered:
|
|
5200
|
+
var AnswerParsingResultSchema = z34.object({
|
|
5201
|
+
answers: z34.array(ParsedAnswerSchema),
|
|
5202
|
+
unanswered: z34.array(z34.string()).describe("Field IDs that were not answered")
|
|
4725
5203
|
});
|
|
4726
|
-
var LookupFillSchema =
|
|
4727
|
-
fieldId:
|
|
4728
|
-
value:
|
|
4729
|
-
source:
|
|
5204
|
+
var LookupFillSchema = z34.object({
|
|
5205
|
+
fieldId: z34.string(),
|
|
5206
|
+
value: z34.string(),
|
|
5207
|
+
source: z34.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'")
|
|
4730
5208
|
});
|
|
4731
|
-
var LookupFillResultSchema =
|
|
4732
|
-
fills:
|
|
4733
|
-
unfillable:
|
|
4734
|
-
explanation:
|
|
5209
|
+
var LookupFillResultSchema = z34.object({
|
|
5210
|
+
fills: z34.array(LookupFillSchema),
|
|
5211
|
+
unfillable: z34.array(z34.string()),
|
|
5212
|
+
explanation: z34.string().optional()
|
|
4735
5213
|
});
|
|
4736
|
-
var FlatPdfPlacementSchema =
|
|
4737
|
-
fieldId:
|
|
4738
|
-
page:
|
|
4739
|
-
x:
|
|
4740
|
-
y:
|
|
4741
|
-
text:
|
|
4742
|
-
fontSize:
|
|
4743
|
-
isCheckmark:
|
|
5214
|
+
var FlatPdfPlacementSchema = z34.object({
|
|
5215
|
+
fieldId: z34.string(),
|
|
5216
|
+
page: z34.number(),
|
|
5217
|
+
x: z34.number().describe("Percentage from left edge (0-100)"),
|
|
5218
|
+
y: z34.number().describe("Percentage from top edge (0-100)"),
|
|
5219
|
+
text: z34.string(),
|
|
5220
|
+
fontSize: z34.number().optional(),
|
|
5221
|
+
isCheckmark: z34.boolean().optional()
|
|
4744
5222
|
});
|
|
4745
|
-
var AcroFormMappingSchema =
|
|
4746
|
-
fieldId:
|
|
4747
|
-
acroFormName:
|
|
4748
|
-
value:
|
|
5223
|
+
var AcroFormMappingSchema = z34.object({
|
|
5224
|
+
fieldId: z34.string(),
|
|
5225
|
+
acroFormName: z34.string(),
|
|
5226
|
+
value: z34.string()
|
|
4749
5227
|
});
|
|
4750
|
-
var QualityGateStatusSchema =
|
|
4751
|
-
var QualitySeveritySchema =
|
|
4752
|
-
var ApplicationQualityIssueSchema =
|
|
4753
|
-
code:
|
|
5228
|
+
var QualityGateStatusSchema = z34.enum(["passed", "warning", "failed"]);
|
|
5229
|
+
var QualitySeveritySchema = z34.enum(["info", "warning", "blocking"]);
|
|
5230
|
+
var ApplicationQualityIssueSchema = z34.object({
|
|
5231
|
+
code: z34.string(),
|
|
4754
5232
|
severity: QualitySeveritySchema,
|
|
4755
|
-
message:
|
|
4756
|
-
fieldId:
|
|
5233
|
+
message: z34.string(),
|
|
5234
|
+
fieldId: z34.string().optional()
|
|
4757
5235
|
});
|
|
4758
|
-
var ApplicationQualityRoundSchema =
|
|
4759
|
-
round:
|
|
4760
|
-
kind:
|
|
5236
|
+
var ApplicationQualityRoundSchema = z34.object({
|
|
5237
|
+
round: z34.number(),
|
|
5238
|
+
kind: z34.string(),
|
|
4761
5239
|
status: QualityGateStatusSchema,
|
|
4762
|
-
summary:
|
|
5240
|
+
summary: z34.string().optional()
|
|
4763
5241
|
});
|
|
4764
|
-
var ApplicationQualityArtifactSchema =
|
|
4765
|
-
kind:
|
|
4766
|
-
label:
|
|
4767
|
-
itemCount:
|
|
5242
|
+
var ApplicationQualityArtifactSchema = z34.object({
|
|
5243
|
+
kind: z34.string(),
|
|
5244
|
+
label: z34.string().optional(),
|
|
5245
|
+
itemCount: z34.number().optional()
|
|
4768
5246
|
});
|
|
4769
|
-
var ApplicationEmailReviewSchema =
|
|
4770
|
-
issues:
|
|
5247
|
+
var ApplicationEmailReviewSchema = z34.object({
|
|
5248
|
+
issues: z34.array(ApplicationQualityIssueSchema),
|
|
4771
5249
|
qualityGateStatus: QualityGateStatusSchema
|
|
4772
5250
|
});
|
|
4773
|
-
var ApplicationQualityReportSchema =
|
|
4774
|
-
issues:
|
|
4775
|
-
rounds:
|
|
4776
|
-
artifacts:
|
|
5251
|
+
var ApplicationQualityReportSchema = z34.object({
|
|
5252
|
+
issues: z34.array(ApplicationQualityIssueSchema),
|
|
5253
|
+
rounds: z34.array(ApplicationQualityRoundSchema).optional(),
|
|
5254
|
+
artifacts: z34.array(ApplicationQualityArtifactSchema).optional(),
|
|
4777
5255
|
emailReview: ApplicationEmailReviewSchema.optional(),
|
|
4778
5256
|
qualityGateStatus: QualityGateStatusSchema
|
|
4779
5257
|
});
|
|
4780
|
-
var ApplicationStateSchema =
|
|
4781
|
-
id:
|
|
4782
|
-
pdfBase64:
|
|
4783
|
-
title:
|
|
4784
|
-
applicationType:
|
|
4785
|
-
fields:
|
|
4786
|
-
batches:
|
|
4787
|
-
currentBatchIndex:
|
|
5258
|
+
var ApplicationStateSchema = z34.object({
|
|
5259
|
+
id: z34.string(),
|
|
5260
|
+
pdfBase64: z34.string().optional().describe("Original PDF, omitted after extraction"),
|
|
5261
|
+
title: z34.string().optional(),
|
|
5262
|
+
applicationType: z34.string().nullable().optional(),
|
|
5263
|
+
fields: z34.array(ApplicationFieldSchema),
|
|
5264
|
+
batches: z34.array(z34.array(z34.string())).optional(),
|
|
5265
|
+
currentBatchIndex: z34.number().default(0),
|
|
4788
5266
|
qualityReport: ApplicationQualityReportSchema.optional(),
|
|
4789
|
-
status:
|
|
4790
|
-
createdAt:
|
|
4791
|
-
updatedAt:
|
|
5267
|
+
status: z34.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
|
|
5268
|
+
createdAt: z34.number(),
|
|
5269
|
+
updatedAt: z34.number()
|
|
4792
5270
|
});
|
|
4793
5271
|
|
|
4794
5272
|
// src/application/agents/classifier.ts
|
|
@@ -5921,73 +6399,73 @@ Respond with the final answer, deduplicated citations array, overall confidence
|
|
|
5921
6399
|
}
|
|
5922
6400
|
|
|
5923
6401
|
// src/schemas/query.ts
|
|
5924
|
-
import { z as
|
|
5925
|
-
var QueryIntentSchema =
|
|
6402
|
+
import { z as z35 } from "zod";
|
|
6403
|
+
var QueryIntentSchema = z35.enum([
|
|
5926
6404
|
"policy_question",
|
|
5927
6405
|
"coverage_comparison",
|
|
5928
6406
|
"document_search",
|
|
5929
6407
|
"claims_inquiry",
|
|
5930
6408
|
"general_knowledge"
|
|
5931
6409
|
]);
|
|
5932
|
-
var SubQuestionSchema =
|
|
5933
|
-
question:
|
|
6410
|
+
var SubQuestionSchema = z35.object({
|
|
6411
|
+
question: z35.string().describe("Atomic sub-question to retrieve and answer independently"),
|
|
5934
6412
|
intent: QueryIntentSchema,
|
|
5935
|
-
chunkTypes:
|
|
5936
|
-
documentFilters:
|
|
5937
|
-
type:
|
|
5938
|
-
carrier:
|
|
5939
|
-
insuredName:
|
|
5940
|
-
policyNumber:
|
|
5941
|
-
quoteNumber:
|
|
6413
|
+
chunkTypes: z35.array(z35.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
|
|
6414
|
+
documentFilters: z35.object({
|
|
6415
|
+
type: z35.enum(["policy", "quote"]).optional(),
|
|
6416
|
+
carrier: z35.string().optional(),
|
|
6417
|
+
insuredName: z35.string().optional(),
|
|
6418
|
+
policyNumber: z35.string().optional(),
|
|
6419
|
+
quoteNumber: z35.string().optional()
|
|
5942
6420
|
}).optional().describe("Structured filters to narrow document lookup")
|
|
5943
6421
|
});
|
|
5944
|
-
var QueryClassifyResultSchema =
|
|
6422
|
+
var QueryClassifyResultSchema = z35.object({
|
|
5945
6423
|
intent: QueryIntentSchema,
|
|
5946
|
-
subQuestions:
|
|
5947
|
-
requiresDocumentLookup:
|
|
5948
|
-
requiresChunkSearch:
|
|
5949
|
-
requiresConversationHistory:
|
|
6424
|
+
subQuestions: z35.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
|
|
6425
|
+
requiresDocumentLookup: z35.boolean().describe("Whether structured document lookup is needed"),
|
|
6426
|
+
requiresChunkSearch: z35.boolean().describe("Whether semantic chunk search is needed"),
|
|
6427
|
+
requiresConversationHistory: z35.boolean().describe("Whether conversation history is relevant")
|
|
5950
6428
|
});
|
|
5951
|
-
var EvidenceItemSchema =
|
|
5952
|
-
source:
|
|
5953
|
-
chunkId:
|
|
5954
|
-
documentId:
|
|
5955
|
-
turnId:
|
|
5956
|
-
text:
|
|
5957
|
-
relevance:
|
|
5958
|
-
metadata:
|
|
6429
|
+
var EvidenceItemSchema = z35.object({
|
|
6430
|
+
source: z35.enum(["chunk", "document", "conversation"]),
|
|
6431
|
+
chunkId: z35.string().optional(),
|
|
6432
|
+
documentId: z35.string().optional(),
|
|
6433
|
+
turnId: z35.string().optional(),
|
|
6434
|
+
text: z35.string().describe("Text excerpt from the source"),
|
|
6435
|
+
relevance: z35.number().min(0).max(1),
|
|
6436
|
+
metadata: z35.array(z35.object({ key: z35.string(), value: z35.string() })).optional()
|
|
5959
6437
|
});
|
|
5960
|
-
var RetrievalResultSchema =
|
|
5961
|
-
subQuestion:
|
|
5962
|
-
evidence:
|
|
6438
|
+
var RetrievalResultSchema = z35.object({
|
|
6439
|
+
subQuestion: z35.string(),
|
|
6440
|
+
evidence: z35.array(EvidenceItemSchema)
|
|
5963
6441
|
});
|
|
5964
|
-
var CitationSchema =
|
|
5965
|
-
index:
|
|
5966
|
-
chunkId:
|
|
5967
|
-
documentId:
|
|
5968
|
-
documentType:
|
|
5969
|
-
field:
|
|
5970
|
-
quote:
|
|
5971
|
-
relevance:
|
|
6442
|
+
var CitationSchema = z35.object({
|
|
6443
|
+
index: z35.number().describe("Citation number [1], [2], etc."),
|
|
6444
|
+
chunkId: z35.string().describe("Source chunk ID, e.g. doc-123:coverage:2"),
|
|
6445
|
+
documentId: z35.string(),
|
|
6446
|
+
documentType: z35.enum(["policy", "quote"]).optional(),
|
|
6447
|
+
field: z35.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
|
|
6448
|
+
quote: z35.string().describe("Exact text from source that supports the claim"),
|
|
6449
|
+
relevance: z35.number().min(0).max(1)
|
|
5972
6450
|
});
|
|
5973
|
-
var SubAnswerSchema =
|
|
5974
|
-
subQuestion:
|
|
5975
|
-
answer:
|
|
5976
|
-
citations:
|
|
5977
|
-
confidence:
|
|
5978
|
-
needsMoreContext:
|
|
6451
|
+
var SubAnswerSchema = z35.object({
|
|
6452
|
+
subQuestion: z35.string(),
|
|
6453
|
+
answer: z35.string(),
|
|
6454
|
+
citations: z35.array(CitationSchema),
|
|
6455
|
+
confidence: z35.number().min(0).max(1),
|
|
6456
|
+
needsMoreContext: z35.boolean().describe("True if evidence was insufficient to answer fully")
|
|
5979
6457
|
});
|
|
5980
|
-
var VerifyResultSchema =
|
|
5981
|
-
approved:
|
|
5982
|
-
issues:
|
|
5983
|
-
retrySubQuestions:
|
|
6458
|
+
var VerifyResultSchema = z35.object({
|
|
6459
|
+
approved: z35.boolean().describe("Whether all sub-answers are adequately grounded"),
|
|
6460
|
+
issues: z35.array(z35.string()).describe("Specific grounding or consistency issues found"),
|
|
6461
|
+
retrySubQuestions: z35.array(z35.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
|
|
5984
6462
|
});
|
|
5985
|
-
var QueryResultSchema =
|
|
5986
|
-
answer:
|
|
5987
|
-
citations:
|
|
6463
|
+
var QueryResultSchema = z35.object({
|
|
6464
|
+
answer: z35.string(),
|
|
6465
|
+
citations: z35.array(CitationSchema),
|
|
5988
6466
|
intent: QueryIntentSchema,
|
|
5989
|
-
confidence:
|
|
5990
|
-
followUp:
|
|
6467
|
+
confidence: z35.number().min(0).max(1),
|
|
6468
|
+
followUp: z35.string().optional().describe("Suggested follow-up question if applicable")
|
|
5991
6469
|
});
|
|
5992
6470
|
|
|
5993
6471
|
// src/query/retriever.ts
|