@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.js
CHANGED
|
@@ -787,6 +787,7 @@ var CoverageValueTypeSchema = import_zod4.z.enum([
|
|
|
787
787
|
var CoverageSchema = import_zod4.z.object({
|
|
788
788
|
name: import_zod4.z.string(),
|
|
789
789
|
limit: import_zod4.z.string(),
|
|
790
|
+
limitType: LimitTypeSchema.optional(),
|
|
790
791
|
limitValueType: CoverageValueTypeSchema.optional(),
|
|
791
792
|
deductible: import_zod4.z.string().optional(),
|
|
792
793
|
deductibleValueType: CoverageValueTypeSchema.optional(),
|
|
@@ -1813,6 +1814,358 @@ async function runExtractor(params) {
|
|
|
1813
1814
|
};
|
|
1814
1815
|
}
|
|
1815
1816
|
|
|
1817
|
+
// src/extraction/promote.ts
|
|
1818
|
+
function getDeclarationFields(doc) {
|
|
1819
|
+
const decl = doc.declarations;
|
|
1820
|
+
return Array.isArray(decl?.fields) ? decl.fields : [];
|
|
1821
|
+
}
|
|
1822
|
+
function fieldMatches(fieldName, patterns) {
|
|
1823
|
+
const lower = fieldName.toLowerCase().replace(/[\s_-]/g, "");
|
|
1824
|
+
return patterns.some((p) => lower === p.toLowerCase().replace(/[\s_-]/g, ""));
|
|
1825
|
+
}
|
|
1826
|
+
function findFieldValue(fields, patterns) {
|
|
1827
|
+
const match = fields.find((f) => fieldMatches(f.field, patterns));
|
|
1828
|
+
return match?.value;
|
|
1829
|
+
}
|
|
1830
|
+
function promoteCarrierFields(doc) {
|
|
1831
|
+
const raw = doc;
|
|
1832
|
+
if (!raw.carrierNaicNumber && raw.naicNumber) {
|
|
1833
|
+
raw.carrierNaicNumber = raw.naicNumber;
|
|
1834
|
+
}
|
|
1835
|
+
if (!raw.carrierAmBestRating && raw.amBestRating) {
|
|
1836
|
+
raw.carrierAmBestRating = raw.amBestRating;
|
|
1837
|
+
}
|
|
1838
|
+
if (!raw.carrierAdmittedStatus && raw.admittedStatus) {
|
|
1839
|
+
raw.carrierAdmittedStatus = raw.admittedStatus;
|
|
1840
|
+
}
|
|
1841
|
+
delete raw.naicNumber;
|
|
1842
|
+
delete raw.amBestRating;
|
|
1843
|
+
delete raw.admittedStatus;
|
|
1844
|
+
if (!raw.insurer && raw.carrierLegalName) {
|
|
1845
|
+
raw.insurer = {
|
|
1846
|
+
legalName: raw.carrierLegalName,
|
|
1847
|
+
...raw.carrierNaicNumber ? { naicNumber: raw.carrierNaicNumber } : {},
|
|
1848
|
+
...raw.carrierAmBestRating ? { amBestRating: raw.carrierAmBestRating } : {},
|
|
1849
|
+
...raw.carrierAdmittedStatus ? { admittedStatus: raw.carrierAdmittedStatus } : {}
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
var BROKER_NAME_PATTERNS = [
|
|
1854
|
+
"brokerName",
|
|
1855
|
+
"broker",
|
|
1856
|
+
"agentName",
|
|
1857
|
+
"agent",
|
|
1858
|
+
"producerName",
|
|
1859
|
+
"producerAgency",
|
|
1860
|
+
"agencyName",
|
|
1861
|
+
"brokerAgency"
|
|
1862
|
+
];
|
|
1863
|
+
var BROKER_CONTACT_PATTERNS = [
|
|
1864
|
+
"brokerContactName",
|
|
1865
|
+
"brokerContact",
|
|
1866
|
+
"agentContactName",
|
|
1867
|
+
"producerContactName",
|
|
1868
|
+
"producerContact"
|
|
1869
|
+
];
|
|
1870
|
+
var BROKER_LICENSE_PATTERNS = [
|
|
1871
|
+
"brokerLicenseNumber",
|
|
1872
|
+
"brokerNumber",
|
|
1873
|
+
"agentLicenseNumber",
|
|
1874
|
+
"producerLicenseNumber",
|
|
1875
|
+
"producerNumber",
|
|
1876
|
+
"agentNumber"
|
|
1877
|
+
];
|
|
1878
|
+
var BROKER_PHONE_PATTERNS = ["brokerPhone", "agentPhone", "producerPhone"];
|
|
1879
|
+
var BROKER_EMAIL_PATTERNS = ["brokerEmail", "agentEmail", "producerEmail"];
|
|
1880
|
+
var BROKER_ADDRESS_PATTERNS = ["brokerAddress", "agentAddress", "producerAddress"];
|
|
1881
|
+
function promoteBroker(doc) {
|
|
1882
|
+
const raw = doc;
|
|
1883
|
+
const fields = getDeclarationFields(doc);
|
|
1884
|
+
const brokerAgency = raw.brokerAgency || findFieldValue(fields, BROKER_NAME_PATTERNS);
|
|
1885
|
+
const brokerContact = raw.brokerContactName || findFieldValue(fields, BROKER_CONTACT_PATTERNS);
|
|
1886
|
+
const brokerLicense = raw.brokerLicenseNumber || findFieldValue(fields, BROKER_LICENSE_PATTERNS);
|
|
1887
|
+
const brokerPhone = findFieldValue(fields, BROKER_PHONE_PATTERNS);
|
|
1888
|
+
const brokerEmail = findFieldValue(fields, BROKER_EMAIL_PATTERNS);
|
|
1889
|
+
const brokerAddress = findFieldValue(fields, BROKER_ADDRESS_PATTERNS);
|
|
1890
|
+
if (brokerAgency) raw.brokerAgency = brokerAgency;
|
|
1891
|
+
if (brokerContact) raw.brokerContactName = brokerContact;
|
|
1892
|
+
if (brokerLicense) raw.brokerLicenseNumber = brokerLicense;
|
|
1893
|
+
if (!raw.producer && brokerAgency) {
|
|
1894
|
+
raw.producer = {
|
|
1895
|
+
agencyName: brokerAgency,
|
|
1896
|
+
...brokerContact ? { contactName: brokerContact } : {},
|
|
1897
|
+
...brokerLicense ? { licenseNumber: brokerLicense } : {},
|
|
1898
|
+
...brokerPhone ? { phone: brokerPhone } : {},
|
|
1899
|
+
...brokerEmail ? { email: brokerEmail } : {},
|
|
1900
|
+
...brokerAddress ? { address: { street1: brokerAddress } } : {}
|
|
1901
|
+
};
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
var LOSS_PAYEE_NAME_PATTERNS = [
|
|
1905
|
+
"lossPayeeName",
|
|
1906
|
+
"lossPayee",
|
|
1907
|
+
"lossPayeeHolder"
|
|
1908
|
+
];
|
|
1909
|
+
var LOSS_PAYEE_ADDRESS_PATTERNS = ["lossPayeeAddress"];
|
|
1910
|
+
var MORTGAGE_HOLDER_NAME_PATTERNS = [
|
|
1911
|
+
"mortgagee",
|
|
1912
|
+
"mortgageHolder",
|
|
1913
|
+
"mortgageHolderName",
|
|
1914
|
+
"mortgageeName",
|
|
1915
|
+
"lienholder",
|
|
1916
|
+
"lienholderName"
|
|
1917
|
+
];
|
|
1918
|
+
var MORTGAGE_HOLDER_ADDRESS_PATTERNS = [
|
|
1919
|
+
"mortgageeAddress",
|
|
1920
|
+
"mortgageHolderAddress",
|
|
1921
|
+
"lienholderAddress"
|
|
1922
|
+
];
|
|
1923
|
+
function promoteLossPayees(doc) {
|
|
1924
|
+
const raw = doc;
|
|
1925
|
+
const fields = getDeclarationFields(doc);
|
|
1926
|
+
if (!raw.lossPayees || Array.isArray(raw.lossPayees) && raw.lossPayees.length === 0) {
|
|
1927
|
+
const name = findFieldValue(fields, LOSS_PAYEE_NAME_PATTERNS);
|
|
1928
|
+
if (name) {
|
|
1929
|
+
const address = findFieldValue(fields, LOSS_PAYEE_ADDRESS_PATTERNS);
|
|
1930
|
+
raw.lossPayees = [{
|
|
1931
|
+
name,
|
|
1932
|
+
role: "loss_payee",
|
|
1933
|
+
...address ? { address: { street1: address } } : {}
|
|
1934
|
+
}];
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
if (!raw.mortgageHolders || Array.isArray(raw.mortgageHolders) && raw.mortgageHolders.length === 0) {
|
|
1938
|
+
const name = findFieldValue(fields, MORTGAGE_HOLDER_NAME_PATTERNS);
|
|
1939
|
+
if (name) {
|
|
1940
|
+
const address = findFieldValue(fields, MORTGAGE_HOLDER_ADDRESS_PATTERNS);
|
|
1941
|
+
raw.mortgageHolders = [{
|
|
1942
|
+
name,
|
|
1943
|
+
role: "mortgage_holder",
|
|
1944
|
+
...address ? { address: { street1: address } } : {}
|
|
1945
|
+
}];
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
function promoteLocations(doc) {
|
|
1950
|
+
const raw = doc;
|
|
1951
|
+
if (Array.isArray(raw.locations) && raw.locations.length > 0) return;
|
|
1952
|
+
const fields = getDeclarationFields(doc);
|
|
1953
|
+
if (fields.length === 0) return;
|
|
1954
|
+
const locationGroups = /* @__PURE__ */ new Map();
|
|
1955
|
+
for (const f of fields) {
|
|
1956
|
+
const lower = f.field.toLowerCase().replace(/[\s_-]/g, "");
|
|
1957
|
+
if (lower.includes("locationnumber") || lower.includes("locnumber") || lower.includes("locno")) {
|
|
1958
|
+
const key = f.value;
|
|
1959
|
+
if (!locationGroups.has(key)) locationGroups.set(key, /* @__PURE__ */ new Map());
|
|
1960
|
+
locationGroups.get(key).set("number", f.value);
|
|
1961
|
+
continue;
|
|
1962
|
+
}
|
|
1963
|
+
if (lower.includes("buildingnumber") || lower.includes("bldgnumber") || lower.includes("bldgno")) {
|
|
1964
|
+
const lastKey2 = [...locationGroups.keys()].pop();
|
|
1965
|
+
if (lastKey2) locationGroups.get(lastKey2).set("buildingNumber", f.value);
|
|
1966
|
+
continue;
|
|
1967
|
+
}
|
|
1968
|
+
const section = (f.section ?? "").toLowerCase();
|
|
1969
|
+
const isLocationField = section.includes("location") || section.includes("building") || section.includes("premises") || section.includes("schedule of locations");
|
|
1970
|
+
if (!isLocationField) continue;
|
|
1971
|
+
if (locationGroups.size === 0) {
|
|
1972
|
+
locationGroups.set("1", /* @__PURE__ */ new Map([["number", "1"]]));
|
|
1973
|
+
}
|
|
1974
|
+
const lastKey = [...locationGroups.keys()].pop();
|
|
1975
|
+
const group = locationGroups.get(lastKey);
|
|
1976
|
+
if (lower.includes("construction") || lower.includes("constructiontype")) {
|
|
1977
|
+
group.set("constructionType", f.value);
|
|
1978
|
+
} else if (lower.includes("occupancy") || lower.includes("occupancytype")) {
|
|
1979
|
+
group.set("occupancy", f.value);
|
|
1980
|
+
} else if (lower.includes("yearbuilt")) {
|
|
1981
|
+
group.set("yearBuilt", f.value);
|
|
1982
|
+
} else if (lower.includes("squarefootage") || lower.includes("sqft") || lower.includes("area")) {
|
|
1983
|
+
group.set("squareFootage", f.value);
|
|
1984
|
+
} else if (lower.includes("protectionclass") || lower.includes("fireprotection")) {
|
|
1985
|
+
group.set("protectionClass", f.value);
|
|
1986
|
+
} else if (lower.includes("sprinkler")) {
|
|
1987
|
+
group.set("sprinklered", f.value);
|
|
1988
|
+
} else if (lower.includes("buildingvalue") || lower.includes("buildingamt") || lower.includes("buildingcoverage")) {
|
|
1989
|
+
group.set("buildingValue", f.value);
|
|
1990
|
+
} else if (lower.includes("contentsvalue") || lower.includes("contentsamt") || lower.includes("contentscoverage")) {
|
|
1991
|
+
group.set("contentsValue", f.value);
|
|
1992
|
+
} else if (lower.includes("businessincome") || lower.includes("bivalue") || lower.includes("businessincomevalue")) {
|
|
1993
|
+
group.set("businessIncomeValue", f.value);
|
|
1994
|
+
} else if (lower.includes("description") || lower.includes("buildingdescription") || lower.includes("locationdescription")) {
|
|
1995
|
+
group.set("description", f.value);
|
|
1996
|
+
} else if (lower.includes("address") || lower.includes("industryaddress") || lower.includes("locationaddress") || lower.includes("premisesaddress")) {
|
|
1997
|
+
group.set("address", f.value);
|
|
1998
|
+
} else if (lower.includes("alarm") || lower.includes("alarmtype")) {
|
|
1999
|
+
group.set("alarmType", f.value);
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
if (locationGroups.size === 0) return;
|
|
2003
|
+
const locations = [];
|
|
2004
|
+
for (const [, group] of locationGroups) {
|
|
2005
|
+
const num = parseInt(group.get("number") ?? "0", 10) || locations.length + 1;
|
|
2006
|
+
const addressStr = group.get("address");
|
|
2007
|
+
locations.push({
|
|
2008
|
+
number: num,
|
|
2009
|
+
address: addressStr ? { street1: addressStr } : { street1: "See declarations" },
|
|
2010
|
+
...group.get("description") ? { description: group.get("description") } : {},
|
|
2011
|
+
...group.get("constructionType") ? { constructionType: group.get("constructionType") } : {},
|
|
2012
|
+
...group.get("occupancy") ? { occupancy: group.get("occupancy") } : {},
|
|
2013
|
+
...group.get("yearBuilt") ? { yearBuilt: parseInt(group.get("yearBuilt"), 10) || void 0 } : {},
|
|
2014
|
+
...group.get("squareFootage") ? { squareFootage: parseInt(group.get("squareFootage").replace(/[^0-9]/g, ""), 10) || void 0 } : {},
|
|
2015
|
+
...group.get("protectionClass") ? { protectionClass: group.get("protectionClass") } : {},
|
|
2016
|
+
...group.get("sprinklered") ? { sprinklered: /yes|true/i.test(group.get("sprinklered")) } : {},
|
|
2017
|
+
...group.get("buildingValue") ? { buildingValue: group.get("buildingValue") } : {},
|
|
2018
|
+
...group.get("contentsValue") ? { contentsValue: group.get("contentsValue") } : {},
|
|
2019
|
+
...group.get("businessIncomeValue") ? { businessIncomeValue: group.get("businessIncomeValue") } : {},
|
|
2020
|
+
...group.get("alarmType") ? { alarmType: group.get("alarmType") } : {}
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
if (locations.length > 0) {
|
|
2024
|
+
raw.locations = locations;
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
function normalizeName(name) {
|
|
2028
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
2029
|
+
}
|
|
2030
|
+
var LIMIT_COVERAGE_MAP = [
|
|
2031
|
+
// GL standard
|
|
2032
|
+
[["eachoccurrence", "peroccurrence", "occurrencecombined"], "perOccurrence"],
|
|
2033
|
+
[["generalaggregate"], "generalAggregate"],
|
|
2034
|
+
[["productscompletedoperationsaggregate", "productscompletedopsaggregate", "prodcompopsagg"], "productsCompletedOpsAggregate"],
|
|
2035
|
+
[["personaladvertisinginjury", "personaladvinjury", "pai"], "personalAdvertisingInjury"],
|
|
2036
|
+
[["firedamage", "firedamagelegalliability", "damagetorentedpremises", "damagetopremisesrentedtoyou"], "fireDamage"],
|
|
2037
|
+
[["medicalexpense", "medexp", "medicalexpenseanypersonanyperson", "medicalexpenseanyone"], "medicalExpense"],
|
|
2038
|
+
// Auto
|
|
2039
|
+
[["combinedsingle", "combinedsinglelimit", "csl"], "combinedSingleLimit"],
|
|
2040
|
+
[["bodilyinjuryperperson", "biperperson"], "bodilyInjuryPerPerson"],
|
|
2041
|
+
[["bodilyinjuryperaccident", "biperaccident"], "bodilyInjuryPerAccident"],
|
|
2042
|
+
[["propertydamage", "pdperaccident"], "propertyDamage"],
|
|
2043
|
+
// Umbrella/Excess
|
|
2044
|
+
[["umbrellaoccurrence", "eachoccurrenceumbrella", "excessoccurrence", "excesseachoccurrence"], "eachOccurrenceUmbrella"],
|
|
2045
|
+
[["umbrellaaggregate", "excessaggregate"], "umbrellaAggregate"],
|
|
2046
|
+
[["umbrella retention", "selfinsuredretention", "sir", "excessretention"], "umbrellaRetention"]
|
|
2047
|
+
];
|
|
2048
|
+
function synthesizeLimits(doc) {
|
|
2049
|
+
const raw = doc;
|
|
2050
|
+
if (raw.limits && typeof raw.limits === "object" && Object.keys(raw.limits).length > 0) return;
|
|
2051
|
+
const coverages = doc.coverages;
|
|
2052
|
+
if (!coverages || coverages.length === 0) return;
|
|
2053
|
+
const limits = {};
|
|
2054
|
+
for (const cov of coverages) {
|
|
2055
|
+
if (!cov.name || !cov.limit) continue;
|
|
2056
|
+
const normalized = normalizeName(cov.name);
|
|
2057
|
+
for (const [patterns, fieldName] of LIMIT_COVERAGE_MAP) {
|
|
2058
|
+
if (patterns.some((p) => normalized.includes(p) || p.includes(normalized))) {
|
|
2059
|
+
if (fieldName.includes("Aggregate") || fieldName.includes("aggregate")) {
|
|
2060
|
+
if (!cov.limitType || cov.limitType === "aggregate") {
|
|
2061
|
+
limits[fieldName] = cov.limit;
|
|
2062
|
+
}
|
|
2063
|
+
} else {
|
|
2064
|
+
if (!limits[fieldName]) {
|
|
2065
|
+
limits[fieldName] = cov.limit;
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
break;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
const hasStatutory = coverages.some(
|
|
2073
|
+
(c) => c.limitType === "statutory" || normalizeName(c.name ?? "").includes("statutory")
|
|
2074
|
+
);
|
|
2075
|
+
if (hasStatutory) {
|
|
2076
|
+
limits.statutory = "true";
|
|
2077
|
+
}
|
|
2078
|
+
const elCoverages = coverages.filter(
|
|
2079
|
+
(c) => normalizeName(c.name ?? "").includes("employersliability")
|
|
2080
|
+
);
|
|
2081
|
+
if (elCoverages.length > 0) {
|
|
2082
|
+
const el = {};
|
|
2083
|
+
for (const c of elCoverages) {
|
|
2084
|
+
if (!c.limit) continue;
|
|
2085
|
+
const n = normalizeName(c.name ?? "");
|
|
2086
|
+
if (n.includes("accident") || n.includes("eachaccident")) el.eachAccident = c.limit;
|
|
2087
|
+
else if (n.includes("diseasepolicy") || n.includes("diseasepolicylimit")) el.diseasePolicyLimit = c.limit;
|
|
2088
|
+
else if (n.includes("diseaseemployee") || n.includes("diseaseeachemployee")) el.diseaseEachEmployee = c.limit;
|
|
2089
|
+
else if (!el.eachAccident) el.eachAccident = c.limit;
|
|
2090
|
+
}
|
|
2091
|
+
if (Object.keys(el).length > 0) {
|
|
2092
|
+
limits.employersLiability = el;
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
if (Object.keys(limits).length > 0) {
|
|
2096
|
+
const result = { ...limits };
|
|
2097
|
+
if (result.statutory === "true") result.statutory = true;
|
|
2098
|
+
raw.limits = result;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
function synthesizeDeductibles(doc) {
|
|
2102
|
+
const raw = doc;
|
|
2103
|
+
if (raw.deductibles && typeof raw.deductibles === "object" && Object.keys(raw.deductibles).length > 0) return;
|
|
2104
|
+
const coverages = doc.coverages;
|
|
2105
|
+
if (!coverages || coverages.length === 0) return;
|
|
2106
|
+
const deductibleValues = coverages.filter((c) => c.deductible && c.deductible.trim() !== "" && c.deductible !== "N/A" && c.deductible !== "None").map((c) => c.deductible);
|
|
2107
|
+
if (deductibleValues.length === 0) return;
|
|
2108
|
+
const freq = /* @__PURE__ */ new Map();
|
|
2109
|
+
for (const d of deductibleValues) {
|
|
2110
|
+
freq.set(d, (freq.get(d) ?? 0) + 1);
|
|
2111
|
+
}
|
|
2112
|
+
let mostCommon = deductibleValues[0];
|
|
2113
|
+
let maxFreq = 0;
|
|
2114
|
+
for (const [val, count] of freq) {
|
|
2115
|
+
if (count > maxFreq) {
|
|
2116
|
+
mostCommon = val;
|
|
2117
|
+
maxFreq = count;
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
const deductibles = {};
|
|
2121
|
+
const hasPerClaim = coverages.some(
|
|
2122
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("perclaim")
|
|
2123
|
+
);
|
|
2124
|
+
if (hasPerClaim) {
|
|
2125
|
+
deductibles.perClaim = mostCommon;
|
|
2126
|
+
} else {
|
|
2127
|
+
deductibles.perOccurrence = mostCommon;
|
|
2128
|
+
}
|
|
2129
|
+
const sirCoverage = coverages.find(
|
|
2130
|
+
(c) => c.deductible && (normalizeName(c.name ?? "").includes("selfinsuredretention") || normalizeName(c.name ?? "").includes("sir"))
|
|
2131
|
+
);
|
|
2132
|
+
if (sirCoverage?.deductible) {
|
|
2133
|
+
deductibles.selfInsuredRetention = sirCoverage.deductible;
|
|
2134
|
+
}
|
|
2135
|
+
const aggDed = coverages.find(
|
|
2136
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("aggregatedeductible")
|
|
2137
|
+
);
|
|
2138
|
+
if (aggDed?.deductible) {
|
|
2139
|
+
deductibles.aggregateDeductible = aggDed.deductible;
|
|
2140
|
+
}
|
|
2141
|
+
if (Object.keys(deductibles).length > 0) {
|
|
2142
|
+
raw.deductibles = deductibles;
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
var PREMIUM_PATTERNS = ["premium", "totalPremium", "annualPremium", "policyPremium", "basePremium"];
|
|
2146
|
+
var TOTAL_COST_PATTERNS = ["totalCost", "totalDue", "totalAmount", "totalPolicyPremium"];
|
|
2147
|
+
function promotePremium(doc) {
|
|
2148
|
+
const raw = doc;
|
|
2149
|
+
const fields = getDeclarationFields(doc);
|
|
2150
|
+
if (!raw.premium) {
|
|
2151
|
+
const premium = findFieldValue(fields, PREMIUM_PATTERNS);
|
|
2152
|
+
if (premium) raw.premium = premium;
|
|
2153
|
+
}
|
|
2154
|
+
if (!raw.totalCost) {
|
|
2155
|
+
const totalCost = findFieldValue(fields, TOTAL_COST_PATTERNS);
|
|
2156
|
+
if (totalCost) raw.totalCost = totalCost;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
function promoteExtractedFields(doc) {
|
|
2160
|
+
promoteCarrierFields(doc);
|
|
2161
|
+
promoteBroker(doc);
|
|
2162
|
+
promoteLossPayees(doc);
|
|
2163
|
+
promoteLocations(doc);
|
|
2164
|
+
synthesizeLimits(doc);
|
|
2165
|
+
synthesizeDeductibles(doc);
|
|
2166
|
+
promotePremium(doc);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
1816
2169
|
// src/extraction/assembler.ts
|
|
1817
2170
|
function assembleDocument(documentId, documentType, memory) {
|
|
1818
2171
|
const carrier = memory.get("carrier_info");
|
|
@@ -1836,6 +2189,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1836
2189
|
policyTypes: classify?.policyTypes,
|
|
1837
2190
|
...sanitizeNulls(carrier ?? {}),
|
|
1838
2191
|
...sanitizeNulls(insured ?? {}),
|
|
2192
|
+
// Map named_insured extractor's loss payees/mortgage holders to EndorsementParty shape
|
|
2193
|
+
...Array.isArray(insured?.lossPayees) && insured.lossPayees.length > 0 ? { lossPayees: insured.lossPayees.map((lp) => ({ ...lp, role: "loss_payee" })) } : {},
|
|
2194
|
+
...Array.isArray(insured?.mortgageHolders) && insured.mortgageHolders.length > 0 ? { mortgageHolders: insured.mortgageHolders.map((mh) => ({ ...mh, role: "mortgage_holder" })) } : {},
|
|
1839
2195
|
...sanitizeNulls(coverages ?? {}),
|
|
1840
2196
|
...sanitizeNulls(premium ?? {}),
|
|
1841
2197
|
...sanitizeNulls(supplementary ?? {}),
|
|
@@ -1847,8 +2203,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1847
2203
|
declarations: declarations ? sanitizeNulls(declarations) : void 0,
|
|
1848
2204
|
...sanitizeNulls(lossHistory ?? {})
|
|
1849
2205
|
};
|
|
2206
|
+
let doc;
|
|
1850
2207
|
if (documentType === "policy") {
|
|
1851
|
-
|
|
2208
|
+
doc = {
|
|
1852
2209
|
...base,
|
|
1853
2210
|
type: "policy",
|
|
1854
2211
|
policyNumber: carrier?.policyNumber ?? insured?.policyNumber ?? "Unknown",
|
|
@@ -1856,17 +2213,20 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1856
2213
|
expirationDate: carrier?.expirationDate,
|
|
1857
2214
|
policyTermType: carrier?.policyTermType
|
|
1858
2215
|
};
|
|
2216
|
+
} else {
|
|
2217
|
+
doc = {
|
|
2218
|
+
...base,
|
|
2219
|
+
type: "quote",
|
|
2220
|
+
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
2221
|
+
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
2222
|
+
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
2223
|
+
subjectivities: coverages?.subjectivities,
|
|
2224
|
+
underwritingConditions: coverages?.underwritingConditions,
|
|
2225
|
+
premiumBreakdown: premium?.premiumBreakdown
|
|
2226
|
+
};
|
|
1859
2227
|
}
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
type: "quote",
|
|
1863
|
-
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
1864
|
-
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
1865
|
-
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
1866
|
-
subjectivities: coverages?.subjectivities,
|
|
1867
|
-
underwritingConditions: coverages?.underwritingConditions,
|
|
1868
|
-
premiumBreakdown: premium?.premiumBreakdown
|
|
1869
|
-
};
|
|
2228
|
+
promoteExtractedFields(doc);
|
|
2229
|
+
return doc;
|
|
1870
2230
|
}
|
|
1871
2231
|
|
|
1872
2232
|
// src/prompts/coordinator/format.ts
|
|
@@ -2238,6 +2598,7 @@ function mergeCoverageLimits(existing, incoming) {
|
|
|
2238
2598
|
const incomingCoverages = Array.isArray(incoming.coverages) ? incoming.coverages : [];
|
|
2239
2599
|
const coverageKey = (coverage) => [
|
|
2240
2600
|
String(coverage.name ?? "").toLowerCase(),
|
|
2601
|
+
String(coverage.limitType ?? "").toLowerCase(),
|
|
2241
2602
|
String(coverage.limit ?? "").toLowerCase(),
|
|
2242
2603
|
String(coverage.deductible ?? "").toLowerCase(),
|
|
2243
2604
|
String(coverage.formNumber ?? "").toLowerCase()
|
|
@@ -3203,6 +3564,7 @@ Available extractors:
|
|
|
3203
3564
|
- supplementary
|
|
3204
3565
|
|
|
3205
3566
|
Rules:
|
|
3567
|
+
- Identify the broad section or form context first, then assign focused extractors within that context.
|
|
3206
3568
|
- Use specific extractors for declarations, schedules, endorsements, exclusions, conditions, premium pages, and loss runs.
|
|
3207
3569
|
- Use "sections" for pages that contain substantive policy text or mixed content that should still be preserved as raw sections.
|
|
3208
3570
|
- Avoid assigning broad ranges mentally; decide page by page.
|
|
@@ -3213,6 +3575,8 @@ Rules:
|
|
|
3213
3575
|
- Headings like "Limits of Insurance", "Deductible", "Coinsurance", "Loss Conditions", or "Definitions" inside a policy form usually indicate form language, not declarations or schedules.
|
|
3214
3576
|
- 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.
|
|
3215
3577
|
- 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.
|
|
3578
|
+
- 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.
|
|
3579
|
+
- 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.
|
|
3216
3580
|
- Return every page in the supplied chunk exactly once.
|
|
3217
3581
|
|
|
3218
3582
|
Return JSON:
|
|
@@ -3296,21 +3660,69 @@ Use the page map to target follow-up extraction pages precisely. Prefer narrow,
|
|
|
3296
3660
|
Respond with JSON only.`;
|
|
3297
3661
|
}
|
|
3298
3662
|
|
|
3299
|
-
// src/prompts/
|
|
3663
|
+
// src/prompts/coordinator/summarize.ts
|
|
3300
3664
|
var import_zod22 = require("zod");
|
|
3301
|
-
var
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3665
|
+
var SummaryResultSchema = import_zod22.z.object({
|
|
3666
|
+
summary: import_zod22.z.string().describe("A 1-3 sentence overview of this insurance document")
|
|
3667
|
+
});
|
|
3668
|
+
function buildSummaryPrompt(doc) {
|
|
3669
|
+
const snapshot = {
|
|
3670
|
+
type: doc.type,
|
|
3671
|
+
carrier: doc.carrier,
|
|
3672
|
+
insuredName: doc.insuredName,
|
|
3673
|
+
policyTypes: doc.policyTypes,
|
|
3674
|
+
premium: doc.premium,
|
|
3675
|
+
coverageCount: doc.coverages?.length ?? 0
|
|
3676
|
+
};
|
|
3677
|
+
if (doc.type === "policy") {
|
|
3678
|
+
snapshot.policyNumber = doc.policyNumber;
|
|
3679
|
+
snapshot.effectiveDate = doc.effectiveDate;
|
|
3680
|
+
snapshot.expirationDate = doc.expirationDate;
|
|
3681
|
+
} else {
|
|
3682
|
+
snapshot.quoteNumber = doc.quoteNumber;
|
|
3683
|
+
snapshot.proposedEffectiveDate = doc.proposedEffectiveDate;
|
|
3684
|
+
}
|
|
3685
|
+
const raw = doc;
|
|
3686
|
+
if (raw.limits) snapshot.limits = raw.limits;
|
|
3687
|
+
if (raw.deductibles) snapshot.deductibles = raw.deductibles;
|
|
3688
|
+
if (raw.brokerAgency) snapshot.brokerAgency = raw.brokerAgency;
|
|
3689
|
+
if (doc.endorsements?.length) snapshot.endorsementCount = doc.endorsements.length;
|
|
3690
|
+
if (doc.exclusions?.length) snapshot.exclusionCount = doc.exclusions.length;
|
|
3691
|
+
if (doc.coverages?.length) {
|
|
3692
|
+
snapshot.topCoverages = doc.coverages.slice(0, 5).map((c) => c.name);
|
|
3693
|
+
}
|
|
3694
|
+
return `You are an expert insurance document analyst. Generate a brief summary of this insurance document.
|
|
3695
|
+
|
|
3696
|
+
Write 1-3 sentences that capture the essential facts a broker or underwriter would want at a glance:
|
|
3697
|
+
- Who is insured and by whom
|
|
3698
|
+
- What type of policy/quote and the key coverages
|
|
3699
|
+
- Policy period and premium if available
|
|
3700
|
+
- Any notable features (high limits, unusual exclusions, etc.)
|
|
3701
|
+
|
|
3702
|
+
Document data:
|
|
3703
|
+
${JSON.stringify(snapshot, null, 2)}
|
|
3704
|
+
|
|
3705
|
+
Return JSON only with a "summary" field.`;
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
// src/prompts/extractors/carrier-info.ts
|
|
3709
|
+
var import_zod23 = require("zod");
|
|
3710
|
+
var CarrierInfoSchema = import_zod23.z.object({
|
|
3711
|
+
carrierName: import_zod23.z.string().describe("Primary insurance company name for display"),
|
|
3712
|
+
carrierLegalName: import_zod23.z.string().optional().describe("Legal entity name of insurer"),
|
|
3713
|
+
naicNumber: import_zod23.z.string().optional().describe("NAIC company code"),
|
|
3714
|
+
amBestRating: import_zod23.z.string().optional().describe("AM Best rating, e.g. 'A+ XV'"),
|
|
3715
|
+
admittedStatus: import_zod23.z.enum(["admitted", "non_admitted", "surplus_lines"]).optional().describe("Admitted status of the carrier"),
|
|
3716
|
+
mga: import_zod23.z.string().optional().describe("Managing General Agent or Program Administrator name"),
|
|
3717
|
+
underwriter: import_zod23.z.string().optional().describe("Named individual underwriter"),
|
|
3718
|
+
brokerAgency: import_zod23.z.string().optional().describe("Broker or producer agency name"),
|
|
3719
|
+
brokerContactName: import_zod23.z.string().optional().describe("Broker or producer contact person name"),
|
|
3720
|
+
brokerLicenseNumber: import_zod23.z.string().optional().describe("Broker or producer license number"),
|
|
3721
|
+
policyNumber: import_zod23.z.string().optional().describe("Policy or quote reference number"),
|
|
3722
|
+
effectiveDate: import_zod23.z.string().optional().describe("Policy effective date (MM/DD/YYYY)"),
|
|
3723
|
+
expirationDate: import_zod23.z.string().optional().describe("Policy expiration date (MM/DD/YYYY)"),
|
|
3724
|
+
quoteNumber: import_zod23.z.string().optional().describe("Quote or proposal reference number"),
|
|
3725
|
+
proposedEffectiveDate: import_zod23.z.string().optional().describe("Proposed effective date for quotes (MM/DD/YYYY)")
|
|
3314
3726
|
});
|
|
3315
3727
|
function buildCarrierInfoPrompt() {
|
|
3316
3728
|
return `You are an expert insurance document analyst. Extract carrier and policy identification information from this document.
|
|
@@ -3321,27 +3733,30 @@ Focus on:
|
|
|
3321
3733
|
- Whether the carrier is admitted, non-admitted, or surplus lines
|
|
3322
3734
|
- Managing General Agent (MGA) or Program Administrator if applicable
|
|
3323
3735
|
- Named individual underwriter if listed
|
|
3736
|
+
- Broker/producer/agent: agency name, contact person name, and license number
|
|
3324
3737
|
- Policy number and effective/expiration dates
|
|
3325
3738
|
- For quotes: quote number and proposed effective date
|
|
3326
3739
|
|
|
3327
3740
|
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.
|
|
3328
3741
|
|
|
3742
|
+
Look for broker/producer/agent information near the carrier or on the declarations page. This may be labeled "Producer", "Agent", "Broker", or similar.
|
|
3743
|
+
|
|
3329
3744
|
Return JSON only.`;
|
|
3330
3745
|
}
|
|
3331
3746
|
|
|
3332
3747
|
// src/prompts/extractors/named-insured.ts
|
|
3333
|
-
var
|
|
3334
|
-
var AddressSchema2 =
|
|
3335
|
-
street1:
|
|
3336
|
-
city:
|
|
3337
|
-
state:
|
|
3338
|
-
zip:
|
|
3748
|
+
var import_zod24 = require("zod");
|
|
3749
|
+
var AddressSchema2 = import_zod24.z.object({
|
|
3750
|
+
street1: import_zod24.z.string(),
|
|
3751
|
+
city: import_zod24.z.string(),
|
|
3752
|
+
state: import_zod24.z.string(),
|
|
3753
|
+
zip: import_zod24.z.string()
|
|
3339
3754
|
});
|
|
3340
|
-
var NamedInsuredSchema2 =
|
|
3341
|
-
insuredName:
|
|
3342
|
-
insuredDba:
|
|
3755
|
+
var NamedInsuredSchema2 = import_zod24.z.object({
|
|
3756
|
+
insuredName: import_zod24.z.string().describe("Name of primary named insured"),
|
|
3757
|
+
insuredDba: import_zod24.z.string().optional().describe("Doing-business-as name"),
|
|
3343
3758
|
insuredAddress: AddressSchema2.optional().describe("Primary insured mailing address"),
|
|
3344
|
-
insuredEntityType:
|
|
3759
|
+
insuredEntityType: import_zod24.z.enum([
|
|
3345
3760
|
"corporation",
|
|
3346
3761
|
"llc",
|
|
3347
3762
|
"partnership",
|
|
@@ -3354,16 +3769,28 @@ var NamedInsuredSchema2 = import_zod23.z.object({
|
|
|
3354
3769
|
"married_couple",
|
|
3355
3770
|
"other"
|
|
3356
3771
|
]).optional().describe("Legal entity type of the insured"),
|
|
3357
|
-
insuredFein:
|
|
3358
|
-
insuredSicCode:
|
|
3359
|
-
insuredNaicsCode:
|
|
3360
|
-
additionalNamedInsureds:
|
|
3361
|
-
|
|
3362
|
-
name:
|
|
3363
|
-
relationship:
|
|
3772
|
+
insuredFein: import_zod24.z.string().optional().describe("Federal Employer Identification Number"),
|
|
3773
|
+
insuredSicCode: import_zod24.z.string().optional().describe("SIC code"),
|
|
3774
|
+
insuredNaicsCode: import_zod24.z.string().optional().describe("NAICS code"),
|
|
3775
|
+
additionalNamedInsureds: import_zod24.z.array(
|
|
3776
|
+
import_zod24.z.object({
|
|
3777
|
+
name: import_zod24.z.string(),
|
|
3778
|
+
relationship: import_zod24.z.string().optional().describe("e.g. subsidiary, affiliate"),
|
|
3364
3779
|
address: AddressSchema2.optional()
|
|
3365
3780
|
})
|
|
3366
|
-
).optional().describe("Additional named insureds listed on the policy")
|
|
3781
|
+
).optional().describe("Additional named insureds listed on the policy"),
|
|
3782
|
+
lossPayees: import_zod24.z.array(
|
|
3783
|
+
import_zod24.z.object({
|
|
3784
|
+
name: import_zod24.z.string(),
|
|
3785
|
+
address: AddressSchema2.optional()
|
|
3786
|
+
})
|
|
3787
|
+
).optional().describe("Loss payees listed on the policy"),
|
|
3788
|
+
mortgageHolders: import_zod24.z.array(
|
|
3789
|
+
import_zod24.z.object({
|
|
3790
|
+
name: import_zod24.z.string(),
|
|
3791
|
+
address: AddressSchema2.optional()
|
|
3792
|
+
})
|
|
3793
|
+
).optional().describe("Mortgage holders / lienholders listed on the policy")
|
|
3367
3794
|
});
|
|
3368
3795
|
function buildNamedInsuredPrompt() {
|
|
3369
3796
|
return `You are an expert insurance document analyst. Extract all named insured information from this document.
|
|
@@ -3374,21 +3801,23 @@ Focus on:
|
|
|
3374
3801
|
- FEIN (Federal Employer Identification Number) if listed
|
|
3375
3802
|
- SIC code and NAICS code if listed
|
|
3376
3803
|
- ALL additional named insureds with their relationship (subsidiary, affiliate, etc.) and address if provided
|
|
3804
|
+
- ALL loss payees with name and address (e.g. "Loss Payee: BMO Bank of Montreal")
|
|
3805
|
+
- ALL mortgage holders / lienholders / mortgagees with name and address
|
|
3377
3806
|
|
|
3378
|
-
Look on the declarations page, named insured schedule, and any endorsements that add or modify named insureds.
|
|
3807
|
+
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.
|
|
3379
3808
|
|
|
3380
3809
|
Return JSON only.`;
|
|
3381
3810
|
}
|
|
3382
3811
|
|
|
3383
3812
|
// src/prompts/extractors/coverage-limits.ts
|
|
3384
|
-
var
|
|
3813
|
+
var import_zod25 = require("zod");
|
|
3385
3814
|
var ExtractorCoverageSchema = CoverageSchema.extend({
|
|
3386
|
-
coverageCode:
|
|
3815
|
+
coverageCode: import_zod25.z.string().optional().describe("Coverage code or class code")
|
|
3387
3816
|
});
|
|
3388
|
-
var CoverageLimitsSchema =
|
|
3389
|
-
coverages:
|
|
3390
|
-
coverageForm:
|
|
3391
|
-
retroactiveDate:
|
|
3817
|
+
var CoverageLimitsSchema = import_zod25.z.object({
|
|
3818
|
+
coverages: import_zod25.z.array(ExtractorCoverageSchema).describe("All coverages with their limits"),
|
|
3819
|
+
coverageForm: import_zod25.z.enum(["occurrence", "claims_made", "accident"]).optional().describe("Primary coverage trigger type"),
|
|
3820
|
+
retroactiveDate: import_zod25.z.string().optional().describe("Retroactive date for claims-made policies (MM/DD/YYYY)")
|
|
3392
3821
|
});
|
|
3393
3822
|
function buildCoverageLimitsPrompt() {
|
|
3394
3823
|
return `You are an expert insurance document analyst. Extract all coverage limits and deductibles from this document.
|
|
@@ -3397,7 +3826,7 @@ Extract only insured-specific declaration, schedule, or endorsement entries that
|
|
|
3397
3826
|
|
|
3398
3827
|
Focus on:
|
|
3399
3828
|
- Every coverage listed on the declarations page or coverage schedule
|
|
3400
|
-
- Per-occurrence, aggregate, and sub-limits for each coverage
|
|
3829
|
+
- Per-occurrence, individual/occurrence, aggregate, and sub-limits for each coverage
|
|
3401
3830
|
- Deductible or self-insured retention for each coverage
|
|
3402
3831
|
- Coverage form type: occurrence-based, claims-made, or accident
|
|
3403
3832
|
- Retroactive date for claims-made policies
|
|
@@ -3409,6 +3838,7 @@ For EACH coverage, also extract:
|
|
|
3409
3838
|
- pageNumber: the original page number where the coverage row/value appears
|
|
3410
3839
|
- sectionRef: the declarations/schedule/endorsement section heading where it appears
|
|
3411
3840
|
- originalContent: the verbatim row or short source snippet used for this coverage
|
|
3841
|
+
- limitType: when applicable, classify the limit as per_occurrence, per_claim, aggregate, per_person, per_accident, statutory, blanket, or scheduled
|
|
3412
3842
|
- limitValueType: classify the limit as numeric, included, not_included, as_stated, waiting_period, referential, or other
|
|
3413
3843
|
- deductibleValueType: classify the deductible/value term similarly when deductible is present
|
|
3414
3844
|
|
|
@@ -3420,19 +3850,20 @@ Critical rules:
|
|
|
3420
3850
|
- 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.
|
|
3421
3851
|
- Use limitValueType or deductibleValueType to preserve non-numeric terms precisely instead of forcing them into numeric semantics.
|
|
3422
3852
|
- Preserve one row per real coverage entry. Do not merge adjacent schedule rows into malformed names.
|
|
3853
|
+
- 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.
|
|
3423
3854
|
|
|
3424
3855
|
Return JSON only.`;
|
|
3425
3856
|
}
|
|
3426
3857
|
|
|
3427
3858
|
// src/prompts/extractors/endorsements.ts
|
|
3428
|
-
var
|
|
3429
|
-
var EndorsementsSchema =
|
|
3430
|
-
endorsements:
|
|
3431
|
-
|
|
3432
|
-
formNumber:
|
|
3433
|
-
editionDate:
|
|
3434
|
-
title:
|
|
3435
|
-
endorsementType:
|
|
3859
|
+
var import_zod26 = require("zod");
|
|
3860
|
+
var EndorsementsSchema = import_zod26.z.object({
|
|
3861
|
+
endorsements: import_zod26.z.array(
|
|
3862
|
+
import_zod26.z.object({
|
|
3863
|
+
formNumber: import_zod26.z.string().describe("Form number, e.g. 'CG 21 47'"),
|
|
3864
|
+
editionDate: import_zod26.z.string().optional().describe("Edition date, e.g. '12 07'"),
|
|
3865
|
+
title: import_zod26.z.string().describe("Endorsement title"),
|
|
3866
|
+
endorsementType: import_zod26.z.enum([
|
|
3436
3867
|
"additional_insured",
|
|
3437
3868
|
"waiver_of_subrogation",
|
|
3438
3869
|
"primary_noncontributory",
|
|
@@ -3452,12 +3883,12 @@ var EndorsementsSchema = import_zod25.z.object({
|
|
|
3452
3883
|
"territorial_extension",
|
|
3453
3884
|
"other"
|
|
3454
3885
|
]).describe("Endorsement type classification"),
|
|
3455
|
-
effectiveDate:
|
|
3456
|
-
affectedCoverageParts:
|
|
3457
|
-
namedParties:
|
|
3458
|
-
|
|
3459
|
-
name:
|
|
3460
|
-
role:
|
|
3886
|
+
effectiveDate: import_zod26.z.string().optional().describe("Endorsement effective date"),
|
|
3887
|
+
affectedCoverageParts: import_zod26.z.array(import_zod26.z.string()).optional().describe("Coverage parts affected by this endorsement"),
|
|
3888
|
+
namedParties: import_zod26.z.array(
|
|
3889
|
+
import_zod26.z.object({
|
|
3890
|
+
name: import_zod26.z.string().describe("Party name"),
|
|
3891
|
+
role: import_zod26.z.enum([
|
|
3461
3892
|
"additional_insured",
|
|
3462
3893
|
"loss_payee",
|
|
3463
3894
|
"mortgage_holder",
|
|
@@ -3466,15 +3897,15 @@ var EndorsementsSchema = import_zod25.z.object({
|
|
|
3466
3897
|
"designated_person",
|
|
3467
3898
|
"other"
|
|
3468
3899
|
]).describe("Party role"),
|
|
3469
|
-
relationship:
|
|
3470
|
-
scope:
|
|
3900
|
+
relationship: import_zod26.z.string().optional().describe("Relationship to insured"),
|
|
3901
|
+
scope: import_zod26.z.string().optional().describe("Scope of coverage for this party")
|
|
3471
3902
|
})
|
|
3472
3903
|
).optional().describe("Named parties (additional insureds, loss payees, etc.)"),
|
|
3473
|
-
keyTerms:
|
|
3474
|
-
premiumImpact:
|
|
3475
|
-
content:
|
|
3476
|
-
pageStart:
|
|
3477
|
-
pageEnd:
|
|
3904
|
+
keyTerms: import_zod26.z.array(import_zod26.z.string()).optional().describe("Key terms or notable provisions in the endorsement"),
|
|
3905
|
+
premiumImpact: import_zod26.z.string().optional().describe("Additional premium or credit"),
|
|
3906
|
+
content: import_zod26.z.string().describe("Full verbatim text of the endorsement"),
|
|
3907
|
+
pageStart: import_zod26.z.number().describe("Starting page number of this endorsement"),
|
|
3908
|
+
pageEnd: import_zod26.z.number().optional().describe("Ending page number of this endorsement")
|
|
3478
3909
|
})
|
|
3479
3910
|
).describe("All endorsements found in the document")
|
|
3480
3911
|
});
|
|
@@ -3505,20 +3936,20 @@ Return JSON only.`;
|
|
|
3505
3936
|
}
|
|
3506
3937
|
|
|
3507
3938
|
// src/prompts/extractors/exclusions.ts
|
|
3508
|
-
var
|
|
3509
|
-
var ExclusionsSchema =
|
|
3510
|
-
exclusions:
|
|
3511
|
-
|
|
3512
|
-
name:
|
|
3513
|
-
formNumber:
|
|
3514
|
-
excludedPerils:
|
|
3515
|
-
isAbsolute:
|
|
3516
|
-
exceptions:
|
|
3517
|
-
buybackAvailable:
|
|
3518
|
-
buybackEndorsement:
|
|
3519
|
-
appliesTo:
|
|
3520
|
-
content:
|
|
3521
|
-
pageNumber:
|
|
3939
|
+
var import_zod27 = require("zod");
|
|
3940
|
+
var ExclusionsSchema = import_zod27.z.object({
|
|
3941
|
+
exclusions: import_zod27.z.array(
|
|
3942
|
+
import_zod27.z.object({
|
|
3943
|
+
name: import_zod27.z.string().describe("Exclusion title or short description"),
|
|
3944
|
+
formNumber: import_zod27.z.string().optional().describe("Form number if part of a named endorsement"),
|
|
3945
|
+
excludedPerils: import_zod27.z.array(import_zod27.z.string()).optional().describe("Specific perils excluded"),
|
|
3946
|
+
isAbsolute: import_zod27.z.boolean().optional().describe("Whether the exclusion is absolute (no exceptions)"),
|
|
3947
|
+
exceptions: import_zod27.z.array(import_zod27.z.string()).optional().describe("Exceptions to the exclusion, if any"),
|
|
3948
|
+
buybackAvailable: import_zod27.z.boolean().optional().describe("Whether coverage can be bought back via endorsement"),
|
|
3949
|
+
buybackEndorsement: import_zod27.z.string().optional().describe("Form number of the buyback endorsement if available"),
|
|
3950
|
+
appliesTo: import_zod27.z.array(import_zod27.z.string()).optional().describe("Coverage types this exclusion applies to"),
|
|
3951
|
+
content: import_zod27.z.string().describe("Full verbatim exclusion text"),
|
|
3952
|
+
pageNumber: import_zod27.z.number().optional().describe("Page number where exclusion appears")
|
|
3522
3953
|
})
|
|
3523
3954
|
).describe("All exclusions found in the document")
|
|
3524
3955
|
});
|
|
@@ -3554,12 +3985,12 @@ Return JSON only.`;
|
|
|
3554
3985
|
}
|
|
3555
3986
|
|
|
3556
3987
|
// src/prompts/extractors/conditions.ts
|
|
3557
|
-
var
|
|
3558
|
-
var ConditionsSchema =
|
|
3559
|
-
conditions:
|
|
3560
|
-
|
|
3561
|
-
name:
|
|
3562
|
-
conditionType:
|
|
3988
|
+
var import_zod28 = require("zod");
|
|
3989
|
+
var ConditionsSchema = import_zod28.z.object({
|
|
3990
|
+
conditions: import_zod28.z.array(
|
|
3991
|
+
import_zod28.z.object({
|
|
3992
|
+
name: import_zod28.z.string().describe("Condition title"),
|
|
3993
|
+
conditionType: import_zod28.z.enum([
|
|
3563
3994
|
"duties_after_loss",
|
|
3564
3995
|
"notice_requirements",
|
|
3565
3996
|
"other_insurance",
|
|
@@ -3578,14 +4009,14 @@ var ConditionsSchema = import_zod27.z.object({
|
|
|
3578
4009
|
"separation_of_insureds",
|
|
3579
4010
|
"other"
|
|
3580
4011
|
]).describe("Condition category"),
|
|
3581
|
-
content:
|
|
3582
|
-
keyValues:
|
|
3583
|
-
|
|
3584
|
-
key:
|
|
3585
|
-
value:
|
|
4012
|
+
content: import_zod28.z.string().describe("Full verbatim condition text"),
|
|
4013
|
+
keyValues: import_zod28.z.array(
|
|
4014
|
+
import_zod28.z.object({
|
|
4015
|
+
key: import_zod28.z.string().describe("Key name (e.g. 'noticePeriod', 'suitDeadline')"),
|
|
4016
|
+
value: import_zod28.z.string().describe("Value (e.g. '30 days', '2 years')")
|
|
3586
4017
|
})
|
|
3587
4018
|
).optional().describe("Key values extracted from the condition (notice periods, deadlines, etc.)"),
|
|
3588
|
-
pageNumber:
|
|
4019
|
+
pageNumber: import_zod28.z.number().optional().describe("Page number where condition appears")
|
|
3589
4020
|
})
|
|
3590
4021
|
).describe("All policy conditions found in the document")
|
|
3591
4022
|
});
|
|
@@ -3623,28 +4054,28 @@ Return JSON only.`;
|
|
|
3623
4054
|
}
|
|
3624
4055
|
|
|
3625
4056
|
// src/prompts/extractors/premium-breakdown.ts
|
|
3626
|
-
var
|
|
3627
|
-
var PremiumBreakdownSchema =
|
|
3628
|
-
premium:
|
|
3629
|
-
totalCost:
|
|
3630
|
-
premiumBreakdown:
|
|
3631
|
-
|
|
3632
|
-
line:
|
|
3633
|
-
amount:
|
|
4057
|
+
var import_zod29 = require("zod");
|
|
4058
|
+
var PremiumBreakdownSchema = import_zod29.z.object({
|
|
4059
|
+
premium: import_zod29.z.string().optional().describe("Total premium amount, e.g. '$5,000'"),
|
|
4060
|
+
totalCost: import_zod29.z.string().optional().describe("Total cost including taxes and fees, e.g. '$5,250'"),
|
|
4061
|
+
premiumBreakdown: import_zod29.z.array(
|
|
4062
|
+
import_zod29.z.object({
|
|
4063
|
+
line: import_zod29.z.string().describe("Coverage line name"),
|
|
4064
|
+
amount: import_zod29.z.string().describe("Premium amount for this line")
|
|
3634
4065
|
})
|
|
3635
4066
|
).optional().describe("Per-coverage-line premium breakdown"),
|
|
3636
|
-
taxesAndFees:
|
|
3637
|
-
|
|
3638
|
-
name:
|
|
3639
|
-
amount:
|
|
3640
|
-
type:
|
|
4067
|
+
taxesAndFees: import_zod29.z.array(
|
|
4068
|
+
import_zod29.z.object({
|
|
4069
|
+
name: import_zod29.z.string().describe("Fee or tax name"),
|
|
4070
|
+
amount: import_zod29.z.string().describe("Dollar amount"),
|
|
4071
|
+
type: import_zod29.z.enum(["tax", "fee", "surcharge", "assessment"]).optional().describe("Fee category")
|
|
3641
4072
|
})
|
|
3642
4073
|
).optional().describe("Taxes, fees, surcharges, and assessments"),
|
|
3643
|
-
minimumPremium:
|
|
3644
|
-
depositPremium:
|
|
3645
|
-
paymentPlan:
|
|
3646
|
-
auditType:
|
|
3647
|
-
ratingBasis:
|
|
4074
|
+
minimumPremium: import_zod29.z.string().optional().describe("Minimum premium if stated"),
|
|
4075
|
+
depositPremium: import_zod29.z.string().optional().describe("Deposit premium if stated"),
|
|
4076
|
+
paymentPlan: import_zod29.z.string().optional().describe("Payment plan description"),
|
|
4077
|
+
auditType: import_zod29.z.enum(["annual", "semi_annual", "quarterly", "monthly", "final", "self"]).optional().describe("Premium audit type"),
|
|
4078
|
+
ratingBasis: import_zod29.z.string().optional().describe("Rating basis, e.g. payroll, revenue, area, units")
|
|
3648
4079
|
});
|
|
3649
4080
|
function buildPremiumBreakdownPrompt() {
|
|
3650
4081
|
return `You are an expert insurance document analyst. Extract all premium and cost information from this document.
|
|
@@ -3664,14 +4095,14 @@ Return JSON only.`;
|
|
|
3664
4095
|
}
|
|
3665
4096
|
|
|
3666
4097
|
// src/prompts/extractors/declarations.ts
|
|
3667
|
-
var
|
|
3668
|
-
var DeclarationsFieldSchema =
|
|
3669
|
-
field:
|
|
3670
|
-
value:
|
|
3671
|
-
section:
|
|
4098
|
+
var import_zod30 = require("zod");
|
|
4099
|
+
var DeclarationsFieldSchema = import_zod30.z.object({
|
|
4100
|
+
field: import_zod30.z.string().describe("Descriptive field name (e.g. 'policyNumber', 'effectiveDate', 'coverageALimit')"),
|
|
4101
|
+
value: import_zod30.z.string().describe("Extracted value exactly as it appears in the document"),
|
|
4102
|
+
section: import_zod30.z.string().optional().describe("Section or grouping this field belongs to (e.g. 'Coverage Limits', 'Vehicle Schedule')")
|
|
3672
4103
|
});
|
|
3673
|
-
var DeclarationsExtractSchema =
|
|
3674
|
-
fields:
|
|
4104
|
+
var DeclarationsExtractSchema = import_zod30.z.object({
|
|
4105
|
+
fields: import_zod30.z.array(DeclarationsFieldSchema).describe("All declarations page fields extracted as key-value pairs. Structure varies by line of business.")
|
|
3675
4106
|
});
|
|
3676
4107
|
function buildDeclarationsPrompt() {
|
|
3677
4108
|
return `You are an expert insurance document analyst. Extract all declarations page data from this document into a flexible key-value structure.
|
|
@@ -3711,21 +4142,21 @@ Preserve original values exactly as they appear. Return JSON only.`;
|
|
|
3711
4142
|
}
|
|
3712
4143
|
|
|
3713
4144
|
// src/prompts/extractors/loss-history.ts
|
|
3714
|
-
var
|
|
3715
|
-
var LossHistorySchema =
|
|
3716
|
-
lossSummary:
|
|
3717
|
-
individualClaims:
|
|
3718
|
-
|
|
3719
|
-
date:
|
|
3720
|
-
type:
|
|
3721
|
-
description:
|
|
3722
|
-
amountPaid:
|
|
3723
|
-
amountReserved:
|
|
3724
|
-
status:
|
|
3725
|
-
claimNumber:
|
|
4145
|
+
var import_zod31 = require("zod");
|
|
4146
|
+
var LossHistorySchema = import_zod31.z.object({
|
|
4147
|
+
lossSummary: import_zod31.z.string().optional().describe("Summary of loss history, e.g. '3 claims in past 5 years totaling $125,000'"),
|
|
4148
|
+
individualClaims: import_zod31.z.array(
|
|
4149
|
+
import_zod31.z.object({
|
|
4150
|
+
date: import_zod31.z.string().optional().describe("Date of loss or claim"),
|
|
4151
|
+
type: import_zod31.z.string().optional().describe("Type of claim, e.g. 'property damage', 'bodily injury'"),
|
|
4152
|
+
description: import_zod31.z.string().optional().describe("Brief description of the claim"),
|
|
4153
|
+
amountPaid: import_zod31.z.string().optional().describe("Amount paid"),
|
|
4154
|
+
amountReserved: import_zod31.z.string().optional().describe("Amount reserved"),
|
|
4155
|
+
status: import_zod31.z.enum(["open", "closed", "reopened"]).optional().describe("Claim status"),
|
|
4156
|
+
claimNumber: import_zod31.z.string().optional().describe("Claim reference number")
|
|
3726
4157
|
})
|
|
3727
4158
|
).optional().describe("Individual claim records"),
|
|
3728
|
-
experienceMod:
|
|
4159
|
+
experienceMod: import_zod31.z.string().optional().describe("Experience modification factor for workers comp, e.g. '0.85'")
|
|
3729
4160
|
});
|
|
3730
4161
|
function buildLossHistoryPrompt() {
|
|
3731
4162
|
return `You are an expert insurance document analyst. Extract all loss history and claims information from this document.
|
|
@@ -3742,18 +4173,18 @@ Return JSON only.`;
|
|
|
3742
4173
|
}
|
|
3743
4174
|
|
|
3744
4175
|
// src/prompts/extractors/sections.ts
|
|
3745
|
-
var
|
|
3746
|
-
var SubsectionSchema2 =
|
|
3747
|
-
title:
|
|
3748
|
-
sectionNumber:
|
|
3749
|
-
pageNumber:
|
|
3750
|
-
content:
|
|
4176
|
+
var import_zod32 = require("zod");
|
|
4177
|
+
var SubsectionSchema2 = import_zod32.z.object({
|
|
4178
|
+
title: import_zod32.z.string().describe("Subsection title"),
|
|
4179
|
+
sectionNumber: import_zod32.z.string().optional().describe("Subsection number"),
|
|
4180
|
+
pageNumber: import_zod32.z.number().optional().describe("Page number"),
|
|
4181
|
+
content: import_zod32.z.string().describe("Full verbatim text")
|
|
3751
4182
|
});
|
|
3752
|
-
var SectionsSchema =
|
|
3753
|
-
sections:
|
|
3754
|
-
|
|
3755
|
-
title:
|
|
3756
|
-
type:
|
|
4183
|
+
var SectionsSchema = import_zod32.z.object({
|
|
4184
|
+
sections: import_zod32.z.array(
|
|
4185
|
+
import_zod32.z.object({
|
|
4186
|
+
title: import_zod32.z.string().describe("Section title"),
|
|
4187
|
+
type: import_zod32.z.enum([
|
|
3757
4188
|
"declarations",
|
|
3758
4189
|
"insuring_agreement",
|
|
3759
4190
|
"policy_form",
|
|
@@ -3767,10 +4198,10 @@ var SectionsSchema = import_zod31.z.object({
|
|
|
3767
4198
|
"regulatory",
|
|
3768
4199
|
"other"
|
|
3769
4200
|
]).describe("Section type classification"),
|
|
3770
|
-
content:
|
|
3771
|
-
pageStart:
|
|
3772
|
-
pageEnd:
|
|
3773
|
-
subsections:
|
|
4201
|
+
content: import_zod32.z.string().describe("Full verbatim text of the section"),
|
|
4202
|
+
pageStart: import_zod32.z.number().describe("Starting page number"),
|
|
4203
|
+
pageEnd: import_zod32.z.number().optional().describe("Ending page number"),
|
|
4204
|
+
subsections: import_zod32.z.array(SubsectionSchema2).optional().describe("Subsections within this section")
|
|
3774
4205
|
})
|
|
3775
4206
|
).describe("All document sections")
|
|
3776
4207
|
});
|
|
@@ -3800,20 +4231,20 @@ Return JSON only.`;
|
|
|
3800
4231
|
}
|
|
3801
4232
|
|
|
3802
4233
|
// src/prompts/extractors/supplementary.ts
|
|
3803
|
-
var
|
|
3804
|
-
var ContactSchema2 =
|
|
3805
|
-
name:
|
|
3806
|
-
phone:
|
|
3807
|
-
email:
|
|
3808
|
-
address:
|
|
3809
|
-
type:
|
|
4234
|
+
var import_zod33 = require("zod");
|
|
4235
|
+
var ContactSchema2 = import_zod33.z.object({
|
|
4236
|
+
name: import_zod33.z.string().optional().describe("Organization or person name"),
|
|
4237
|
+
phone: import_zod33.z.string().optional().describe("Phone number"),
|
|
4238
|
+
email: import_zod33.z.string().optional().describe("Email address"),
|
|
4239
|
+
address: import_zod33.z.string().optional().describe("Mailing address"),
|
|
4240
|
+
type: import_zod33.z.string().optional().describe("Contact type, e.g. 'State Department of Insurance'")
|
|
3810
4241
|
});
|
|
3811
|
-
var SupplementarySchema =
|
|
3812
|
-
regulatoryContacts:
|
|
3813
|
-
claimsContacts:
|
|
3814
|
-
thirdPartyAdministrators:
|
|
3815
|
-
cancellationNoticeDays:
|
|
3816
|
-
nonrenewalNoticeDays:
|
|
4242
|
+
var SupplementarySchema = import_zod33.z.object({
|
|
4243
|
+
regulatoryContacts: import_zod33.z.array(ContactSchema2).optional().describe("Regulatory body contacts (state department of insurance, ombudsman)"),
|
|
4244
|
+
claimsContacts: import_zod33.z.array(ContactSchema2).optional().describe("Claims reporting contacts and instructions"),
|
|
4245
|
+
thirdPartyAdministrators: import_zod33.z.array(ContactSchema2).optional().describe("Third-party administrators for claims handling"),
|
|
4246
|
+
cancellationNoticeDays: import_zod33.z.number().optional().describe("Required notice period for cancellation in days"),
|
|
4247
|
+
nonrenewalNoticeDays: import_zod33.z.number().optional().describe("Required notice period for nonrenewal in days")
|
|
3817
4248
|
});
|
|
3818
4249
|
function buildSupplementaryPrompt() {
|
|
3819
4250
|
return `You are an expert insurance document analyst. Extract supplementary and regulatory information from this document.
|
|
@@ -4297,7 +4728,7 @@ function createExtractor(config) {
|
|
|
4297
4728
|
ranges.push({ startPage: start, endPage: previous });
|
|
4298
4729
|
return ranges;
|
|
4299
4730
|
}
|
|
4300
|
-
function buildPlanFromPageAssignments(pageAssignments, pageCount) {
|
|
4731
|
+
function buildPlanFromPageAssignments(pageAssignments, pageCount, formInventory) {
|
|
4301
4732
|
const extractorPages = /* @__PURE__ */ new Map();
|
|
4302
4733
|
for (const assignment of pageAssignments) {
|
|
4303
4734
|
const extractors = assignment.extractorNames.length > 0 ? assignment.extractorNames : ["sections"];
|
|
@@ -4314,8 +4745,30 @@ function createExtractor(config) {
|
|
|
4314
4745
|
extractorPages.set("sections", [...extractorPages.get("sections") ?? [], page]);
|
|
4315
4746
|
}
|
|
4316
4747
|
}
|
|
4748
|
+
const contextualExtractors = /* @__PURE__ */ new Set(["conditions", "exclusions", "endorsements"]);
|
|
4749
|
+
const contextualForms = (formInventory?.forms ?? []).filter(
|
|
4750
|
+
(form) => form.pageStart != null && (form.pageEnd ?? form.pageStart) != null
|
|
4751
|
+
);
|
|
4752
|
+
const expandPagesToFormRanges = (extractorName, pages) => {
|
|
4753
|
+
if (!contextualExtractors.has(extractorName)) return pages;
|
|
4754
|
+
const expanded = new Set(pages);
|
|
4755
|
+
for (const page of pages) {
|
|
4756
|
+
for (const form of contextualForms) {
|
|
4757
|
+
const pageStart = form.pageStart;
|
|
4758
|
+
const pageEnd = form.pageEnd ?? form.pageStart;
|
|
4759
|
+
const formType = form.formType;
|
|
4760
|
+
const supportsContextualExpansion = extractorName === "endorsements" ? formType === "endorsement" : formType === "coverage" || formType === "endorsement";
|
|
4761
|
+
if (!supportsContextualExpansion) continue;
|
|
4762
|
+
if (page < pageStart || page > pageEnd) continue;
|
|
4763
|
+
for (let current = pageStart; current <= pageEnd; current += 1) {
|
|
4764
|
+
expanded.add(current);
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
return [...expanded].sort((a, b) => a - b);
|
|
4769
|
+
};
|
|
4317
4770
|
const tasks = [...extractorPages.entries()].flatMap(
|
|
4318
|
-
([extractorName, pages]) => groupContiguousPages(pages).map(({ startPage, endPage }) => ({
|
|
4771
|
+
([extractorName, pages]) => groupContiguousPages(expandPagesToFormRanges(extractorName, pages)).map(({ startPage, endPage }) => ({
|
|
4319
4772
|
extractorName,
|
|
4320
4773
|
startPage,
|
|
4321
4774
|
endPage,
|
|
@@ -4483,7 +4936,7 @@ function createExtractor(config) {
|
|
|
4483
4936
|
onProgress?.("Resuming from checkpoint (plan complete)...");
|
|
4484
4937
|
} else {
|
|
4485
4938
|
onProgress?.(`Building extraction plan from page map for ${primaryType} ${documentType}...`);
|
|
4486
|
-
plan = buildPlanFromPageAssignments(pageAssignments, pageCount);
|
|
4939
|
+
plan = buildPlanFromPageAssignments(pageAssignments, pageCount, formInventory);
|
|
4487
4940
|
await pipelineCtx.save("plan", {
|
|
4488
4941
|
id,
|
|
4489
4942
|
pageCount,
|
|
@@ -4650,6 +5103,31 @@ function createExtractor(config) {
|
|
|
4650
5103
|
memory: Object.fromEntries(memory),
|
|
4651
5104
|
document
|
|
4652
5105
|
});
|
|
5106
|
+
if (!document.summary) {
|
|
5107
|
+
onProgress?.("Generating document summary...");
|
|
5108
|
+
try {
|
|
5109
|
+
const summaryResponse = await safeGenerateObject(
|
|
5110
|
+
generateObject,
|
|
5111
|
+
{
|
|
5112
|
+
prompt: buildSummaryPrompt(document),
|
|
5113
|
+
schema: SummaryResultSchema,
|
|
5114
|
+
maxTokens: 512,
|
|
5115
|
+
providerOptions
|
|
5116
|
+
},
|
|
5117
|
+
{
|
|
5118
|
+
fallback: { summary: "" },
|
|
5119
|
+
log,
|
|
5120
|
+
onError: (err, attempt) => log?.(`Summary attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
5121
|
+
}
|
|
5122
|
+
);
|
|
5123
|
+
trackUsage(summaryResponse.usage);
|
|
5124
|
+
if (summaryResponse.object.summary) {
|
|
5125
|
+
document.summary = summaryResponse.object.summary;
|
|
5126
|
+
}
|
|
5127
|
+
} catch (error) {
|
|
5128
|
+
await log?.(`Summary generation failed, skipping: ${error instanceof Error ? error.message : String(error)}`);
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
4653
5131
|
onProgress?.("Formatting extracted content...");
|
|
4654
5132
|
const formatResult = await formatDocumentContent(document, generateText, {
|
|
4655
5133
|
providerOptions,
|
|
@@ -4893,8 +5371,8 @@ Respond with JSON only:
|
|
|
4893
5371
|
}`;
|
|
4894
5372
|
|
|
4895
5373
|
// src/schemas/application.ts
|
|
4896
|
-
var
|
|
4897
|
-
var FieldTypeSchema =
|
|
5374
|
+
var import_zod34 = require("zod");
|
|
5375
|
+
var FieldTypeSchema = import_zod34.z.enum([
|
|
4898
5376
|
"text",
|
|
4899
5377
|
"numeric",
|
|
4900
5378
|
"currency",
|
|
@@ -4903,131 +5381,131 @@ var FieldTypeSchema = import_zod33.z.enum([
|
|
|
4903
5381
|
"table",
|
|
4904
5382
|
"declaration"
|
|
4905
5383
|
]);
|
|
4906
|
-
var ApplicationFieldSchema =
|
|
4907
|
-
id:
|
|
4908
|
-
label:
|
|
4909
|
-
section:
|
|
5384
|
+
var ApplicationFieldSchema = import_zod34.z.object({
|
|
5385
|
+
id: import_zod34.z.string(),
|
|
5386
|
+
label: import_zod34.z.string(),
|
|
5387
|
+
section: import_zod34.z.string(),
|
|
4910
5388
|
fieldType: FieldTypeSchema,
|
|
4911
|
-
required:
|
|
4912
|
-
options:
|
|
4913
|
-
columns:
|
|
4914
|
-
requiresExplanationIfYes:
|
|
4915
|
-
condition:
|
|
4916
|
-
dependsOn:
|
|
4917
|
-
whenValue:
|
|
5389
|
+
required: import_zod34.z.boolean(),
|
|
5390
|
+
options: import_zod34.z.array(import_zod34.z.string()).optional(),
|
|
5391
|
+
columns: import_zod34.z.array(import_zod34.z.string()).optional(),
|
|
5392
|
+
requiresExplanationIfYes: import_zod34.z.boolean().optional(),
|
|
5393
|
+
condition: import_zod34.z.object({
|
|
5394
|
+
dependsOn: import_zod34.z.string(),
|
|
5395
|
+
whenValue: import_zod34.z.string()
|
|
4918
5396
|
}).optional(),
|
|
4919
|
-
value:
|
|
4920
|
-
source:
|
|
4921
|
-
confidence:
|
|
5397
|
+
value: import_zod34.z.string().optional(),
|
|
5398
|
+
source: import_zod34.z.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
|
|
5399
|
+
confidence: import_zod34.z.enum(["confirmed", "high", "medium", "low"]).optional()
|
|
4922
5400
|
});
|
|
4923
|
-
var ApplicationClassifyResultSchema =
|
|
4924
|
-
isApplication:
|
|
4925
|
-
confidence:
|
|
4926
|
-
applicationType:
|
|
5401
|
+
var ApplicationClassifyResultSchema = import_zod34.z.object({
|
|
5402
|
+
isApplication: import_zod34.z.boolean(),
|
|
5403
|
+
confidence: import_zod34.z.number().min(0).max(1),
|
|
5404
|
+
applicationType: import_zod34.z.string().nullable()
|
|
4927
5405
|
});
|
|
4928
|
-
var FieldExtractionResultSchema =
|
|
4929
|
-
fields:
|
|
5406
|
+
var FieldExtractionResultSchema = import_zod34.z.object({
|
|
5407
|
+
fields: import_zod34.z.array(ApplicationFieldSchema)
|
|
4930
5408
|
});
|
|
4931
|
-
var AutoFillMatchSchema =
|
|
4932
|
-
fieldId:
|
|
4933
|
-
value:
|
|
4934
|
-
confidence:
|
|
4935
|
-
contextKey:
|
|
5409
|
+
var AutoFillMatchSchema = import_zod34.z.object({
|
|
5410
|
+
fieldId: import_zod34.z.string(),
|
|
5411
|
+
value: import_zod34.z.string(),
|
|
5412
|
+
confidence: import_zod34.z.enum(["confirmed"]),
|
|
5413
|
+
contextKey: import_zod34.z.string()
|
|
4936
5414
|
});
|
|
4937
|
-
var AutoFillResultSchema =
|
|
4938
|
-
matches:
|
|
5415
|
+
var AutoFillResultSchema = import_zod34.z.object({
|
|
5416
|
+
matches: import_zod34.z.array(AutoFillMatchSchema)
|
|
4939
5417
|
});
|
|
4940
|
-
var QuestionBatchResultSchema =
|
|
4941
|
-
batches:
|
|
5418
|
+
var QuestionBatchResultSchema = import_zod34.z.object({
|
|
5419
|
+
batches: import_zod34.z.array(import_zod34.z.array(import_zod34.z.string()).describe("Array of field IDs in this batch"))
|
|
4942
5420
|
});
|
|
4943
|
-
var LookupRequestSchema =
|
|
4944
|
-
type:
|
|
4945
|
-
description:
|
|
4946
|
-
url:
|
|
4947
|
-
targetFieldIds:
|
|
5421
|
+
var LookupRequestSchema = import_zod34.z.object({
|
|
5422
|
+
type: import_zod34.z.string().describe("Type of lookup: 'records', 'website', 'policy'"),
|
|
5423
|
+
description: import_zod34.z.string(),
|
|
5424
|
+
url: import_zod34.z.string().optional(),
|
|
5425
|
+
targetFieldIds: import_zod34.z.array(import_zod34.z.string())
|
|
4948
5426
|
});
|
|
4949
|
-
var ReplyIntentSchema =
|
|
4950
|
-
primaryIntent:
|
|
4951
|
-
hasAnswers:
|
|
4952
|
-
questionText:
|
|
4953
|
-
questionFieldIds:
|
|
4954
|
-
lookupRequests:
|
|
5427
|
+
var ReplyIntentSchema = import_zod34.z.object({
|
|
5428
|
+
primaryIntent: import_zod34.z.enum(["answers_only", "question", "lookup_request", "mixed"]),
|
|
5429
|
+
hasAnswers: import_zod34.z.boolean(),
|
|
5430
|
+
questionText: import_zod34.z.string().optional(),
|
|
5431
|
+
questionFieldIds: import_zod34.z.array(import_zod34.z.string()).optional(),
|
|
5432
|
+
lookupRequests: import_zod34.z.array(LookupRequestSchema).optional()
|
|
4955
5433
|
});
|
|
4956
|
-
var ParsedAnswerSchema =
|
|
4957
|
-
fieldId:
|
|
4958
|
-
value:
|
|
4959
|
-
explanation:
|
|
5434
|
+
var ParsedAnswerSchema = import_zod34.z.object({
|
|
5435
|
+
fieldId: import_zod34.z.string(),
|
|
5436
|
+
value: import_zod34.z.string(),
|
|
5437
|
+
explanation: import_zod34.z.string().optional()
|
|
4960
5438
|
});
|
|
4961
|
-
var AnswerParsingResultSchema =
|
|
4962
|
-
answers:
|
|
4963
|
-
unanswered:
|
|
5439
|
+
var AnswerParsingResultSchema = import_zod34.z.object({
|
|
5440
|
+
answers: import_zod34.z.array(ParsedAnswerSchema),
|
|
5441
|
+
unanswered: import_zod34.z.array(import_zod34.z.string()).describe("Field IDs that were not answered")
|
|
4964
5442
|
});
|
|
4965
|
-
var LookupFillSchema =
|
|
4966
|
-
fieldId:
|
|
4967
|
-
value:
|
|
4968
|
-
source:
|
|
5443
|
+
var LookupFillSchema = import_zod34.z.object({
|
|
5444
|
+
fieldId: import_zod34.z.string(),
|
|
5445
|
+
value: import_zod34.z.string(),
|
|
5446
|
+
source: import_zod34.z.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'")
|
|
4969
5447
|
});
|
|
4970
|
-
var LookupFillResultSchema =
|
|
4971
|
-
fills:
|
|
4972
|
-
unfillable:
|
|
4973
|
-
explanation:
|
|
5448
|
+
var LookupFillResultSchema = import_zod34.z.object({
|
|
5449
|
+
fills: import_zod34.z.array(LookupFillSchema),
|
|
5450
|
+
unfillable: import_zod34.z.array(import_zod34.z.string()),
|
|
5451
|
+
explanation: import_zod34.z.string().optional()
|
|
4974
5452
|
});
|
|
4975
|
-
var FlatPdfPlacementSchema =
|
|
4976
|
-
fieldId:
|
|
4977
|
-
page:
|
|
4978
|
-
x:
|
|
4979
|
-
y:
|
|
4980
|
-
text:
|
|
4981
|
-
fontSize:
|
|
4982
|
-
isCheckmark:
|
|
5453
|
+
var FlatPdfPlacementSchema = import_zod34.z.object({
|
|
5454
|
+
fieldId: import_zod34.z.string(),
|
|
5455
|
+
page: import_zod34.z.number(),
|
|
5456
|
+
x: import_zod34.z.number().describe("Percentage from left edge (0-100)"),
|
|
5457
|
+
y: import_zod34.z.number().describe("Percentage from top edge (0-100)"),
|
|
5458
|
+
text: import_zod34.z.string(),
|
|
5459
|
+
fontSize: import_zod34.z.number().optional(),
|
|
5460
|
+
isCheckmark: import_zod34.z.boolean().optional()
|
|
4983
5461
|
});
|
|
4984
|
-
var AcroFormMappingSchema =
|
|
4985
|
-
fieldId:
|
|
4986
|
-
acroFormName:
|
|
4987
|
-
value:
|
|
5462
|
+
var AcroFormMappingSchema = import_zod34.z.object({
|
|
5463
|
+
fieldId: import_zod34.z.string(),
|
|
5464
|
+
acroFormName: import_zod34.z.string(),
|
|
5465
|
+
value: import_zod34.z.string()
|
|
4988
5466
|
});
|
|
4989
|
-
var QualityGateStatusSchema =
|
|
4990
|
-
var QualitySeveritySchema =
|
|
4991
|
-
var ApplicationQualityIssueSchema =
|
|
4992
|
-
code:
|
|
5467
|
+
var QualityGateStatusSchema = import_zod34.z.enum(["passed", "warning", "failed"]);
|
|
5468
|
+
var QualitySeveritySchema = import_zod34.z.enum(["info", "warning", "blocking"]);
|
|
5469
|
+
var ApplicationQualityIssueSchema = import_zod34.z.object({
|
|
5470
|
+
code: import_zod34.z.string(),
|
|
4993
5471
|
severity: QualitySeveritySchema,
|
|
4994
|
-
message:
|
|
4995
|
-
fieldId:
|
|
5472
|
+
message: import_zod34.z.string(),
|
|
5473
|
+
fieldId: import_zod34.z.string().optional()
|
|
4996
5474
|
});
|
|
4997
|
-
var ApplicationQualityRoundSchema =
|
|
4998
|
-
round:
|
|
4999
|
-
kind:
|
|
5475
|
+
var ApplicationQualityRoundSchema = import_zod34.z.object({
|
|
5476
|
+
round: import_zod34.z.number(),
|
|
5477
|
+
kind: import_zod34.z.string(),
|
|
5000
5478
|
status: QualityGateStatusSchema,
|
|
5001
|
-
summary:
|
|
5479
|
+
summary: import_zod34.z.string().optional()
|
|
5002
5480
|
});
|
|
5003
|
-
var ApplicationQualityArtifactSchema =
|
|
5004
|
-
kind:
|
|
5005
|
-
label:
|
|
5006
|
-
itemCount:
|
|
5481
|
+
var ApplicationQualityArtifactSchema = import_zod34.z.object({
|
|
5482
|
+
kind: import_zod34.z.string(),
|
|
5483
|
+
label: import_zod34.z.string().optional(),
|
|
5484
|
+
itemCount: import_zod34.z.number().optional()
|
|
5007
5485
|
});
|
|
5008
|
-
var ApplicationEmailReviewSchema =
|
|
5009
|
-
issues:
|
|
5486
|
+
var ApplicationEmailReviewSchema = import_zod34.z.object({
|
|
5487
|
+
issues: import_zod34.z.array(ApplicationQualityIssueSchema),
|
|
5010
5488
|
qualityGateStatus: QualityGateStatusSchema
|
|
5011
5489
|
});
|
|
5012
|
-
var ApplicationQualityReportSchema =
|
|
5013
|
-
issues:
|
|
5014
|
-
rounds:
|
|
5015
|
-
artifacts:
|
|
5490
|
+
var ApplicationQualityReportSchema = import_zod34.z.object({
|
|
5491
|
+
issues: import_zod34.z.array(ApplicationQualityIssueSchema),
|
|
5492
|
+
rounds: import_zod34.z.array(ApplicationQualityRoundSchema).optional(),
|
|
5493
|
+
artifacts: import_zod34.z.array(ApplicationQualityArtifactSchema).optional(),
|
|
5016
5494
|
emailReview: ApplicationEmailReviewSchema.optional(),
|
|
5017
5495
|
qualityGateStatus: QualityGateStatusSchema
|
|
5018
5496
|
});
|
|
5019
|
-
var ApplicationStateSchema =
|
|
5020
|
-
id:
|
|
5021
|
-
pdfBase64:
|
|
5022
|
-
title:
|
|
5023
|
-
applicationType:
|
|
5024
|
-
fields:
|
|
5025
|
-
batches:
|
|
5026
|
-
currentBatchIndex:
|
|
5497
|
+
var ApplicationStateSchema = import_zod34.z.object({
|
|
5498
|
+
id: import_zod34.z.string(),
|
|
5499
|
+
pdfBase64: import_zod34.z.string().optional().describe("Original PDF, omitted after extraction"),
|
|
5500
|
+
title: import_zod34.z.string().optional(),
|
|
5501
|
+
applicationType: import_zod34.z.string().nullable().optional(),
|
|
5502
|
+
fields: import_zod34.z.array(ApplicationFieldSchema),
|
|
5503
|
+
batches: import_zod34.z.array(import_zod34.z.array(import_zod34.z.string())).optional(),
|
|
5504
|
+
currentBatchIndex: import_zod34.z.number().default(0),
|
|
5027
5505
|
qualityReport: ApplicationQualityReportSchema.optional(),
|
|
5028
|
-
status:
|
|
5029
|
-
createdAt:
|
|
5030
|
-
updatedAt:
|
|
5506
|
+
status: import_zod34.z.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
|
|
5507
|
+
createdAt: import_zod34.z.number(),
|
|
5508
|
+
updatedAt: import_zod34.z.number()
|
|
5031
5509
|
});
|
|
5032
5510
|
|
|
5033
5511
|
// src/application/agents/classifier.ts
|
|
@@ -6160,73 +6638,73 @@ Respond with the final answer, deduplicated citations array, overall confidence
|
|
|
6160
6638
|
}
|
|
6161
6639
|
|
|
6162
6640
|
// src/schemas/query.ts
|
|
6163
|
-
var
|
|
6164
|
-
var QueryIntentSchema =
|
|
6641
|
+
var import_zod35 = require("zod");
|
|
6642
|
+
var QueryIntentSchema = import_zod35.z.enum([
|
|
6165
6643
|
"policy_question",
|
|
6166
6644
|
"coverage_comparison",
|
|
6167
6645
|
"document_search",
|
|
6168
6646
|
"claims_inquiry",
|
|
6169
6647
|
"general_knowledge"
|
|
6170
6648
|
]);
|
|
6171
|
-
var SubQuestionSchema =
|
|
6172
|
-
question:
|
|
6649
|
+
var SubQuestionSchema = import_zod35.z.object({
|
|
6650
|
+
question: import_zod35.z.string().describe("Atomic sub-question to retrieve and answer independently"),
|
|
6173
6651
|
intent: QueryIntentSchema,
|
|
6174
|
-
chunkTypes:
|
|
6175
|
-
documentFilters:
|
|
6176
|
-
type:
|
|
6177
|
-
carrier:
|
|
6178
|
-
insuredName:
|
|
6179
|
-
policyNumber:
|
|
6180
|
-
quoteNumber:
|
|
6652
|
+
chunkTypes: import_zod35.z.array(import_zod35.z.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
|
|
6653
|
+
documentFilters: import_zod35.z.object({
|
|
6654
|
+
type: import_zod35.z.enum(["policy", "quote"]).optional(),
|
|
6655
|
+
carrier: import_zod35.z.string().optional(),
|
|
6656
|
+
insuredName: import_zod35.z.string().optional(),
|
|
6657
|
+
policyNumber: import_zod35.z.string().optional(),
|
|
6658
|
+
quoteNumber: import_zod35.z.string().optional()
|
|
6181
6659
|
}).optional().describe("Structured filters to narrow document lookup")
|
|
6182
6660
|
});
|
|
6183
|
-
var QueryClassifyResultSchema =
|
|
6661
|
+
var QueryClassifyResultSchema = import_zod35.z.object({
|
|
6184
6662
|
intent: QueryIntentSchema,
|
|
6185
|
-
subQuestions:
|
|
6186
|
-
requiresDocumentLookup:
|
|
6187
|
-
requiresChunkSearch:
|
|
6188
|
-
requiresConversationHistory:
|
|
6663
|
+
subQuestions: import_zod35.z.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
|
|
6664
|
+
requiresDocumentLookup: import_zod35.z.boolean().describe("Whether structured document lookup is needed"),
|
|
6665
|
+
requiresChunkSearch: import_zod35.z.boolean().describe("Whether semantic chunk search is needed"),
|
|
6666
|
+
requiresConversationHistory: import_zod35.z.boolean().describe("Whether conversation history is relevant")
|
|
6189
6667
|
});
|
|
6190
|
-
var EvidenceItemSchema =
|
|
6191
|
-
source:
|
|
6192
|
-
chunkId:
|
|
6193
|
-
documentId:
|
|
6194
|
-
turnId:
|
|
6195
|
-
text:
|
|
6196
|
-
relevance:
|
|
6197
|
-
metadata:
|
|
6668
|
+
var EvidenceItemSchema = import_zod35.z.object({
|
|
6669
|
+
source: import_zod35.z.enum(["chunk", "document", "conversation"]),
|
|
6670
|
+
chunkId: import_zod35.z.string().optional(),
|
|
6671
|
+
documentId: import_zod35.z.string().optional(),
|
|
6672
|
+
turnId: import_zod35.z.string().optional(),
|
|
6673
|
+
text: import_zod35.z.string().describe("Text excerpt from the source"),
|
|
6674
|
+
relevance: import_zod35.z.number().min(0).max(1),
|
|
6675
|
+
metadata: import_zod35.z.array(import_zod35.z.object({ key: import_zod35.z.string(), value: import_zod35.z.string() })).optional()
|
|
6198
6676
|
});
|
|
6199
|
-
var RetrievalResultSchema =
|
|
6200
|
-
subQuestion:
|
|
6201
|
-
evidence:
|
|
6677
|
+
var RetrievalResultSchema = import_zod35.z.object({
|
|
6678
|
+
subQuestion: import_zod35.z.string(),
|
|
6679
|
+
evidence: import_zod35.z.array(EvidenceItemSchema)
|
|
6202
6680
|
});
|
|
6203
|
-
var CitationSchema =
|
|
6204
|
-
index:
|
|
6205
|
-
chunkId:
|
|
6206
|
-
documentId:
|
|
6207
|
-
documentType:
|
|
6208
|
-
field:
|
|
6209
|
-
quote:
|
|
6210
|
-
relevance:
|
|
6681
|
+
var CitationSchema = import_zod35.z.object({
|
|
6682
|
+
index: import_zod35.z.number().describe("Citation number [1], [2], etc."),
|
|
6683
|
+
chunkId: import_zod35.z.string().describe("Source chunk ID, e.g. doc-123:coverage:2"),
|
|
6684
|
+
documentId: import_zod35.z.string(),
|
|
6685
|
+
documentType: import_zod35.z.enum(["policy", "quote"]).optional(),
|
|
6686
|
+
field: import_zod35.z.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
|
|
6687
|
+
quote: import_zod35.z.string().describe("Exact text from source that supports the claim"),
|
|
6688
|
+
relevance: import_zod35.z.number().min(0).max(1)
|
|
6211
6689
|
});
|
|
6212
|
-
var SubAnswerSchema =
|
|
6213
|
-
subQuestion:
|
|
6214
|
-
answer:
|
|
6215
|
-
citations:
|
|
6216
|
-
confidence:
|
|
6217
|
-
needsMoreContext:
|
|
6690
|
+
var SubAnswerSchema = import_zod35.z.object({
|
|
6691
|
+
subQuestion: import_zod35.z.string(),
|
|
6692
|
+
answer: import_zod35.z.string(),
|
|
6693
|
+
citations: import_zod35.z.array(CitationSchema),
|
|
6694
|
+
confidence: import_zod35.z.number().min(0).max(1),
|
|
6695
|
+
needsMoreContext: import_zod35.z.boolean().describe("True if evidence was insufficient to answer fully")
|
|
6218
6696
|
});
|
|
6219
|
-
var VerifyResultSchema =
|
|
6220
|
-
approved:
|
|
6221
|
-
issues:
|
|
6222
|
-
retrySubQuestions:
|
|
6697
|
+
var VerifyResultSchema = import_zod35.z.object({
|
|
6698
|
+
approved: import_zod35.z.boolean().describe("Whether all sub-answers are adequately grounded"),
|
|
6699
|
+
issues: import_zod35.z.array(import_zod35.z.string()).describe("Specific grounding or consistency issues found"),
|
|
6700
|
+
retrySubQuestions: import_zod35.z.array(import_zod35.z.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
|
|
6223
6701
|
});
|
|
6224
|
-
var QueryResultSchema =
|
|
6225
|
-
answer:
|
|
6226
|
-
citations:
|
|
6702
|
+
var QueryResultSchema = import_zod35.z.object({
|
|
6703
|
+
answer: import_zod35.z.string(),
|
|
6704
|
+
citations: import_zod35.z.array(CitationSchema),
|
|
6227
6705
|
intent: QueryIntentSchema,
|
|
6228
|
-
confidence:
|
|
6229
|
-
followUp:
|
|
6706
|
+
confidence: import_zod35.z.number().min(0).max(1),
|
|
6707
|
+
followUp: import_zod35.z.string().optional().describe("Suggested follow-up question if applicable")
|
|
6230
6708
|
});
|
|
6231
6709
|
|
|
6232
6710
|
// src/query/retriever.ts
|