@claritylabs/cl-sdk 0.10.3 → 0.12.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 +50 -2
- package/dist/index.d.mts +69 -11
- package/dist/index.d.ts +69 -11
- package/dist/index.js +960 -325
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +956 -325
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -6
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ __export(index_exports, {
|
|
|
36
36
|
ApplicationQualityReportSchema: () => ApplicationQualityReportSchema,
|
|
37
37
|
ApplicationQualityRoundSchema: () => ApplicationQualityRoundSchema,
|
|
38
38
|
ApplicationStateSchema: () => ApplicationStateSchema,
|
|
39
|
+
AttachmentInterpretationSchema: () => AttachmentInterpretationSchema,
|
|
39
40
|
AuditTypeSchema: () => AuditTypeSchema,
|
|
40
41
|
AutoFillMatchSchema: () => AutoFillMatchSchema,
|
|
41
42
|
AutoFillResultSchema: () => AutoFillResultSchema,
|
|
@@ -157,6 +158,8 @@ __export(index_exports, {
|
|
|
157
158
|
ProducerInfoSchema: () => ProducerInfoSchema,
|
|
158
159
|
ProfessionalLiabilityDeclarationsSchema: () => ProfessionalLiabilityDeclarationsSchema,
|
|
159
160
|
QUOTE_SECTION_TYPES: () => QUOTE_SECTION_TYPES,
|
|
161
|
+
QueryAttachmentKindSchema: () => QueryAttachmentKindSchema,
|
|
162
|
+
QueryAttachmentSchema: () => QueryAttachmentSchema,
|
|
160
163
|
QueryClassifyResultSchema: () => QueryClassifyResultSchema,
|
|
161
164
|
QueryIntentSchema: () => QueryIntentSchema,
|
|
162
165
|
QueryResultSchema: () => QueryResultSchema,
|
|
@@ -215,6 +218,7 @@ __export(index_exports, {
|
|
|
215
218
|
buildFormattingPrompt: () => buildFormattingPrompt,
|
|
216
219
|
buildIdentityPrompt: () => buildIdentityPrompt,
|
|
217
220
|
buildIntentPrompt: () => buildIntentPrompt,
|
|
221
|
+
buildInterpretAttachmentPrompt: () => buildInterpretAttachmentPrompt,
|
|
218
222
|
buildLookupFillPrompt: () => buildLookupFillPrompt,
|
|
219
223
|
buildQueryClassifyPrompt: () => buildQueryClassifyPrompt,
|
|
220
224
|
buildQuestionBatchPrompt: () => buildQuestionBatchPrompt,
|
|
@@ -1814,6 +1818,358 @@ async function runExtractor(params) {
|
|
|
1814
1818
|
};
|
|
1815
1819
|
}
|
|
1816
1820
|
|
|
1821
|
+
// src/extraction/promote.ts
|
|
1822
|
+
function getDeclarationFields(doc) {
|
|
1823
|
+
const decl = doc.declarations;
|
|
1824
|
+
return Array.isArray(decl?.fields) ? decl.fields : [];
|
|
1825
|
+
}
|
|
1826
|
+
function fieldMatches(fieldName, patterns) {
|
|
1827
|
+
const lower = fieldName.toLowerCase().replace(/[\s_-]/g, "");
|
|
1828
|
+
return patterns.some((p) => lower === p.toLowerCase().replace(/[\s_-]/g, ""));
|
|
1829
|
+
}
|
|
1830
|
+
function findFieldValue(fields, patterns) {
|
|
1831
|
+
const match = fields.find((f) => fieldMatches(f.field, patterns));
|
|
1832
|
+
return match?.value;
|
|
1833
|
+
}
|
|
1834
|
+
function promoteCarrierFields(doc) {
|
|
1835
|
+
const raw = doc;
|
|
1836
|
+
if (!raw.carrierNaicNumber && raw.naicNumber) {
|
|
1837
|
+
raw.carrierNaicNumber = raw.naicNumber;
|
|
1838
|
+
}
|
|
1839
|
+
if (!raw.carrierAmBestRating && raw.amBestRating) {
|
|
1840
|
+
raw.carrierAmBestRating = raw.amBestRating;
|
|
1841
|
+
}
|
|
1842
|
+
if (!raw.carrierAdmittedStatus && raw.admittedStatus) {
|
|
1843
|
+
raw.carrierAdmittedStatus = raw.admittedStatus;
|
|
1844
|
+
}
|
|
1845
|
+
delete raw.naicNumber;
|
|
1846
|
+
delete raw.amBestRating;
|
|
1847
|
+
delete raw.admittedStatus;
|
|
1848
|
+
if (!raw.insurer && raw.carrierLegalName) {
|
|
1849
|
+
raw.insurer = {
|
|
1850
|
+
legalName: raw.carrierLegalName,
|
|
1851
|
+
...raw.carrierNaicNumber ? { naicNumber: raw.carrierNaicNumber } : {},
|
|
1852
|
+
...raw.carrierAmBestRating ? { amBestRating: raw.carrierAmBestRating } : {},
|
|
1853
|
+
...raw.carrierAdmittedStatus ? { admittedStatus: raw.carrierAdmittedStatus } : {}
|
|
1854
|
+
};
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
var BROKER_NAME_PATTERNS = [
|
|
1858
|
+
"brokerName",
|
|
1859
|
+
"broker",
|
|
1860
|
+
"agentName",
|
|
1861
|
+
"agent",
|
|
1862
|
+
"producerName",
|
|
1863
|
+
"producerAgency",
|
|
1864
|
+
"agencyName",
|
|
1865
|
+
"brokerAgency"
|
|
1866
|
+
];
|
|
1867
|
+
var BROKER_CONTACT_PATTERNS = [
|
|
1868
|
+
"brokerContactName",
|
|
1869
|
+
"brokerContact",
|
|
1870
|
+
"agentContactName",
|
|
1871
|
+
"producerContactName",
|
|
1872
|
+
"producerContact"
|
|
1873
|
+
];
|
|
1874
|
+
var BROKER_LICENSE_PATTERNS = [
|
|
1875
|
+
"brokerLicenseNumber",
|
|
1876
|
+
"brokerNumber",
|
|
1877
|
+
"agentLicenseNumber",
|
|
1878
|
+
"producerLicenseNumber",
|
|
1879
|
+
"producerNumber",
|
|
1880
|
+
"agentNumber"
|
|
1881
|
+
];
|
|
1882
|
+
var BROKER_PHONE_PATTERNS = ["brokerPhone", "agentPhone", "producerPhone"];
|
|
1883
|
+
var BROKER_EMAIL_PATTERNS = ["brokerEmail", "agentEmail", "producerEmail"];
|
|
1884
|
+
var BROKER_ADDRESS_PATTERNS = ["brokerAddress", "agentAddress", "producerAddress"];
|
|
1885
|
+
function promoteBroker(doc) {
|
|
1886
|
+
const raw = doc;
|
|
1887
|
+
const fields = getDeclarationFields(doc);
|
|
1888
|
+
const brokerAgency = raw.brokerAgency || findFieldValue(fields, BROKER_NAME_PATTERNS);
|
|
1889
|
+
const brokerContact = raw.brokerContactName || findFieldValue(fields, BROKER_CONTACT_PATTERNS);
|
|
1890
|
+
const brokerLicense = raw.brokerLicenseNumber || findFieldValue(fields, BROKER_LICENSE_PATTERNS);
|
|
1891
|
+
const brokerPhone = findFieldValue(fields, BROKER_PHONE_PATTERNS);
|
|
1892
|
+
const brokerEmail = findFieldValue(fields, BROKER_EMAIL_PATTERNS);
|
|
1893
|
+
const brokerAddress = findFieldValue(fields, BROKER_ADDRESS_PATTERNS);
|
|
1894
|
+
if (brokerAgency) raw.brokerAgency = brokerAgency;
|
|
1895
|
+
if (brokerContact) raw.brokerContactName = brokerContact;
|
|
1896
|
+
if (brokerLicense) raw.brokerLicenseNumber = brokerLicense;
|
|
1897
|
+
if (!raw.producer && brokerAgency) {
|
|
1898
|
+
raw.producer = {
|
|
1899
|
+
agencyName: brokerAgency,
|
|
1900
|
+
...brokerContact ? { contactName: brokerContact } : {},
|
|
1901
|
+
...brokerLicense ? { licenseNumber: brokerLicense } : {},
|
|
1902
|
+
...brokerPhone ? { phone: brokerPhone } : {},
|
|
1903
|
+
...brokerEmail ? { email: brokerEmail } : {},
|
|
1904
|
+
...brokerAddress ? { address: { street1: brokerAddress } } : {}
|
|
1905
|
+
};
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
var LOSS_PAYEE_NAME_PATTERNS = [
|
|
1909
|
+
"lossPayeeName",
|
|
1910
|
+
"lossPayee",
|
|
1911
|
+
"lossPayeeHolder"
|
|
1912
|
+
];
|
|
1913
|
+
var LOSS_PAYEE_ADDRESS_PATTERNS = ["lossPayeeAddress"];
|
|
1914
|
+
var MORTGAGE_HOLDER_NAME_PATTERNS = [
|
|
1915
|
+
"mortgagee",
|
|
1916
|
+
"mortgageHolder",
|
|
1917
|
+
"mortgageHolderName",
|
|
1918
|
+
"mortgageeName",
|
|
1919
|
+
"lienholder",
|
|
1920
|
+
"lienholderName"
|
|
1921
|
+
];
|
|
1922
|
+
var MORTGAGE_HOLDER_ADDRESS_PATTERNS = [
|
|
1923
|
+
"mortgageeAddress",
|
|
1924
|
+
"mortgageHolderAddress",
|
|
1925
|
+
"lienholderAddress"
|
|
1926
|
+
];
|
|
1927
|
+
function promoteLossPayees(doc) {
|
|
1928
|
+
const raw = doc;
|
|
1929
|
+
const fields = getDeclarationFields(doc);
|
|
1930
|
+
if (!raw.lossPayees || Array.isArray(raw.lossPayees) && raw.lossPayees.length === 0) {
|
|
1931
|
+
const name = findFieldValue(fields, LOSS_PAYEE_NAME_PATTERNS);
|
|
1932
|
+
if (name) {
|
|
1933
|
+
const address = findFieldValue(fields, LOSS_PAYEE_ADDRESS_PATTERNS);
|
|
1934
|
+
raw.lossPayees = [{
|
|
1935
|
+
name,
|
|
1936
|
+
role: "loss_payee",
|
|
1937
|
+
...address ? { address: { street1: address } } : {}
|
|
1938
|
+
}];
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
if (!raw.mortgageHolders || Array.isArray(raw.mortgageHolders) && raw.mortgageHolders.length === 0) {
|
|
1942
|
+
const name = findFieldValue(fields, MORTGAGE_HOLDER_NAME_PATTERNS);
|
|
1943
|
+
if (name) {
|
|
1944
|
+
const address = findFieldValue(fields, MORTGAGE_HOLDER_ADDRESS_PATTERNS);
|
|
1945
|
+
raw.mortgageHolders = [{
|
|
1946
|
+
name,
|
|
1947
|
+
role: "mortgage_holder",
|
|
1948
|
+
...address ? { address: { street1: address } } : {}
|
|
1949
|
+
}];
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
function promoteLocations(doc) {
|
|
1954
|
+
const raw = doc;
|
|
1955
|
+
if (Array.isArray(raw.locations) && raw.locations.length > 0) return;
|
|
1956
|
+
const fields = getDeclarationFields(doc);
|
|
1957
|
+
if (fields.length === 0) return;
|
|
1958
|
+
const locationGroups = /* @__PURE__ */ new Map();
|
|
1959
|
+
for (const f of fields) {
|
|
1960
|
+
const lower = f.field.toLowerCase().replace(/[\s_-]/g, "");
|
|
1961
|
+
if (lower.includes("locationnumber") || lower.includes("locnumber") || lower.includes("locno")) {
|
|
1962
|
+
const key = f.value;
|
|
1963
|
+
if (!locationGroups.has(key)) locationGroups.set(key, /* @__PURE__ */ new Map());
|
|
1964
|
+
locationGroups.get(key).set("number", f.value);
|
|
1965
|
+
continue;
|
|
1966
|
+
}
|
|
1967
|
+
if (lower.includes("buildingnumber") || lower.includes("bldgnumber") || lower.includes("bldgno")) {
|
|
1968
|
+
const lastKey2 = [...locationGroups.keys()].pop();
|
|
1969
|
+
if (lastKey2) locationGroups.get(lastKey2).set("buildingNumber", f.value);
|
|
1970
|
+
continue;
|
|
1971
|
+
}
|
|
1972
|
+
const section = (f.section ?? "").toLowerCase();
|
|
1973
|
+
const isLocationField = section.includes("location") || section.includes("building") || section.includes("premises") || section.includes("schedule of locations");
|
|
1974
|
+
if (!isLocationField) continue;
|
|
1975
|
+
if (locationGroups.size === 0) {
|
|
1976
|
+
locationGroups.set("1", /* @__PURE__ */ new Map([["number", "1"]]));
|
|
1977
|
+
}
|
|
1978
|
+
const lastKey = [...locationGroups.keys()].pop();
|
|
1979
|
+
const group = locationGroups.get(lastKey);
|
|
1980
|
+
if (lower.includes("construction") || lower.includes("constructiontype")) {
|
|
1981
|
+
group.set("constructionType", f.value);
|
|
1982
|
+
} else if (lower.includes("occupancy") || lower.includes("occupancytype")) {
|
|
1983
|
+
group.set("occupancy", f.value);
|
|
1984
|
+
} else if (lower.includes("yearbuilt")) {
|
|
1985
|
+
group.set("yearBuilt", f.value);
|
|
1986
|
+
} else if (lower.includes("squarefootage") || lower.includes("sqft") || lower.includes("area")) {
|
|
1987
|
+
group.set("squareFootage", f.value);
|
|
1988
|
+
} else if (lower.includes("protectionclass") || lower.includes("fireprotection")) {
|
|
1989
|
+
group.set("protectionClass", f.value);
|
|
1990
|
+
} else if (lower.includes("sprinkler")) {
|
|
1991
|
+
group.set("sprinklered", f.value);
|
|
1992
|
+
} else if (lower.includes("buildingvalue") || lower.includes("buildingamt") || lower.includes("buildingcoverage")) {
|
|
1993
|
+
group.set("buildingValue", f.value);
|
|
1994
|
+
} else if (lower.includes("contentsvalue") || lower.includes("contentsamt") || lower.includes("contentscoverage")) {
|
|
1995
|
+
group.set("contentsValue", f.value);
|
|
1996
|
+
} else if (lower.includes("businessincome") || lower.includes("bivalue") || lower.includes("businessincomevalue")) {
|
|
1997
|
+
group.set("businessIncomeValue", f.value);
|
|
1998
|
+
} else if (lower.includes("description") || lower.includes("buildingdescription") || lower.includes("locationdescription")) {
|
|
1999
|
+
group.set("description", f.value);
|
|
2000
|
+
} else if (lower.includes("address") || lower.includes("industryaddress") || lower.includes("locationaddress") || lower.includes("premisesaddress")) {
|
|
2001
|
+
group.set("address", f.value);
|
|
2002
|
+
} else if (lower.includes("alarm") || lower.includes("alarmtype")) {
|
|
2003
|
+
group.set("alarmType", f.value);
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
if (locationGroups.size === 0) return;
|
|
2007
|
+
const locations = [];
|
|
2008
|
+
for (const [, group] of locationGroups) {
|
|
2009
|
+
const num = parseInt(group.get("number") ?? "0", 10) || locations.length + 1;
|
|
2010
|
+
const addressStr = group.get("address");
|
|
2011
|
+
locations.push({
|
|
2012
|
+
number: num,
|
|
2013
|
+
address: addressStr ? { street1: addressStr } : { street1: "See declarations" },
|
|
2014
|
+
...group.get("description") ? { description: group.get("description") } : {},
|
|
2015
|
+
...group.get("constructionType") ? { constructionType: group.get("constructionType") } : {},
|
|
2016
|
+
...group.get("occupancy") ? { occupancy: group.get("occupancy") } : {},
|
|
2017
|
+
...group.get("yearBuilt") ? { yearBuilt: parseInt(group.get("yearBuilt"), 10) || void 0 } : {},
|
|
2018
|
+
...group.get("squareFootage") ? { squareFootage: parseInt(group.get("squareFootage").replace(/[^0-9]/g, ""), 10) || void 0 } : {},
|
|
2019
|
+
...group.get("protectionClass") ? { protectionClass: group.get("protectionClass") } : {},
|
|
2020
|
+
...group.get("sprinklered") ? { sprinklered: /yes|true/i.test(group.get("sprinklered")) } : {},
|
|
2021
|
+
...group.get("buildingValue") ? { buildingValue: group.get("buildingValue") } : {},
|
|
2022
|
+
...group.get("contentsValue") ? { contentsValue: group.get("contentsValue") } : {},
|
|
2023
|
+
...group.get("businessIncomeValue") ? { businessIncomeValue: group.get("businessIncomeValue") } : {},
|
|
2024
|
+
...group.get("alarmType") ? { alarmType: group.get("alarmType") } : {}
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
if (locations.length > 0) {
|
|
2028
|
+
raw.locations = locations;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
function normalizeName(name) {
|
|
2032
|
+
return name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
2033
|
+
}
|
|
2034
|
+
var LIMIT_COVERAGE_MAP = [
|
|
2035
|
+
// GL standard
|
|
2036
|
+
[["eachoccurrence", "peroccurrence", "occurrencecombined"], "perOccurrence"],
|
|
2037
|
+
[["generalaggregate"], "generalAggregate"],
|
|
2038
|
+
[["productscompletedoperationsaggregate", "productscompletedopsaggregate", "prodcompopsagg"], "productsCompletedOpsAggregate"],
|
|
2039
|
+
[["personaladvertisinginjury", "personaladvinjury", "pai"], "personalAdvertisingInjury"],
|
|
2040
|
+
[["firedamage", "firedamagelegalliability", "damagetorentedpremises", "damagetopremisesrentedtoyou"], "fireDamage"],
|
|
2041
|
+
[["medicalexpense", "medexp", "medicalexpenseanypersonanyperson", "medicalexpenseanyone"], "medicalExpense"],
|
|
2042
|
+
// Auto
|
|
2043
|
+
[["combinedsingle", "combinedsinglelimit", "csl"], "combinedSingleLimit"],
|
|
2044
|
+
[["bodilyinjuryperperson", "biperperson"], "bodilyInjuryPerPerson"],
|
|
2045
|
+
[["bodilyinjuryperaccident", "biperaccident"], "bodilyInjuryPerAccident"],
|
|
2046
|
+
[["propertydamage", "pdperaccident"], "propertyDamage"],
|
|
2047
|
+
// Umbrella/Excess
|
|
2048
|
+
[["umbrellaoccurrence", "eachoccurrenceumbrella", "excessoccurrence", "excesseachoccurrence"], "eachOccurrenceUmbrella"],
|
|
2049
|
+
[["umbrellaaggregate", "excessaggregate"], "umbrellaAggregate"],
|
|
2050
|
+
[["umbrella retention", "selfinsuredretention", "sir", "excessretention"], "umbrellaRetention"]
|
|
2051
|
+
];
|
|
2052
|
+
function synthesizeLimits(doc) {
|
|
2053
|
+
const raw = doc;
|
|
2054
|
+
if (raw.limits && typeof raw.limits === "object" && Object.keys(raw.limits).length > 0) return;
|
|
2055
|
+
const coverages = doc.coverages;
|
|
2056
|
+
if (!coverages || coverages.length === 0) return;
|
|
2057
|
+
const limits = {};
|
|
2058
|
+
for (const cov of coverages) {
|
|
2059
|
+
if (!cov.name || !cov.limit) continue;
|
|
2060
|
+
const normalized = normalizeName(cov.name);
|
|
2061
|
+
for (const [patterns, fieldName] of LIMIT_COVERAGE_MAP) {
|
|
2062
|
+
if (patterns.some((p) => normalized.includes(p) || p.includes(normalized))) {
|
|
2063
|
+
if (fieldName.includes("Aggregate") || fieldName.includes("aggregate")) {
|
|
2064
|
+
if (!cov.limitType || cov.limitType === "aggregate") {
|
|
2065
|
+
limits[fieldName] = cov.limit;
|
|
2066
|
+
}
|
|
2067
|
+
} else {
|
|
2068
|
+
if (!limits[fieldName]) {
|
|
2069
|
+
limits[fieldName] = cov.limit;
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
break;
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
const hasStatutory = coverages.some(
|
|
2077
|
+
(c) => c.limitType === "statutory" || normalizeName(c.name ?? "").includes("statutory")
|
|
2078
|
+
);
|
|
2079
|
+
if (hasStatutory) {
|
|
2080
|
+
limits.statutory = "true";
|
|
2081
|
+
}
|
|
2082
|
+
const elCoverages = coverages.filter(
|
|
2083
|
+
(c) => normalizeName(c.name ?? "").includes("employersliability")
|
|
2084
|
+
);
|
|
2085
|
+
if (elCoverages.length > 0) {
|
|
2086
|
+
const el = {};
|
|
2087
|
+
for (const c of elCoverages) {
|
|
2088
|
+
if (!c.limit) continue;
|
|
2089
|
+
const n = normalizeName(c.name ?? "");
|
|
2090
|
+
if (n.includes("accident") || n.includes("eachaccident")) el.eachAccident = c.limit;
|
|
2091
|
+
else if (n.includes("diseasepolicy") || n.includes("diseasepolicylimit")) el.diseasePolicyLimit = c.limit;
|
|
2092
|
+
else if (n.includes("diseaseemployee") || n.includes("diseaseeachemployee")) el.diseaseEachEmployee = c.limit;
|
|
2093
|
+
else if (!el.eachAccident) el.eachAccident = c.limit;
|
|
2094
|
+
}
|
|
2095
|
+
if (Object.keys(el).length > 0) {
|
|
2096
|
+
limits.employersLiability = el;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
if (Object.keys(limits).length > 0) {
|
|
2100
|
+
const result = { ...limits };
|
|
2101
|
+
if (result.statutory === "true") result.statutory = true;
|
|
2102
|
+
raw.limits = result;
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
function synthesizeDeductibles(doc) {
|
|
2106
|
+
const raw = doc;
|
|
2107
|
+
if (raw.deductibles && typeof raw.deductibles === "object" && Object.keys(raw.deductibles).length > 0) return;
|
|
2108
|
+
const coverages = doc.coverages;
|
|
2109
|
+
if (!coverages || coverages.length === 0) return;
|
|
2110
|
+
const deductibleValues = coverages.filter((c) => c.deductible && c.deductible.trim() !== "" && c.deductible !== "N/A" && c.deductible !== "None").map((c) => c.deductible);
|
|
2111
|
+
if (deductibleValues.length === 0) return;
|
|
2112
|
+
const freq = /* @__PURE__ */ new Map();
|
|
2113
|
+
for (const d of deductibleValues) {
|
|
2114
|
+
freq.set(d, (freq.get(d) ?? 0) + 1);
|
|
2115
|
+
}
|
|
2116
|
+
let mostCommon = deductibleValues[0];
|
|
2117
|
+
let maxFreq = 0;
|
|
2118
|
+
for (const [val, count] of freq) {
|
|
2119
|
+
if (count > maxFreq) {
|
|
2120
|
+
mostCommon = val;
|
|
2121
|
+
maxFreq = count;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
const deductibles = {};
|
|
2125
|
+
const hasPerClaim = coverages.some(
|
|
2126
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("perclaim")
|
|
2127
|
+
);
|
|
2128
|
+
if (hasPerClaim) {
|
|
2129
|
+
deductibles.perClaim = mostCommon;
|
|
2130
|
+
} else {
|
|
2131
|
+
deductibles.perOccurrence = mostCommon;
|
|
2132
|
+
}
|
|
2133
|
+
const sirCoverage = coverages.find(
|
|
2134
|
+
(c) => c.deductible && (normalizeName(c.name ?? "").includes("selfinsuredretention") || normalizeName(c.name ?? "").includes("sir"))
|
|
2135
|
+
);
|
|
2136
|
+
if (sirCoverage?.deductible) {
|
|
2137
|
+
deductibles.selfInsuredRetention = sirCoverage.deductible;
|
|
2138
|
+
}
|
|
2139
|
+
const aggDed = coverages.find(
|
|
2140
|
+
(c) => c.deductible && normalizeName(c.name ?? "").includes("aggregatedeductible")
|
|
2141
|
+
);
|
|
2142
|
+
if (aggDed?.deductible) {
|
|
2143
|
+
deductibles.aggregateDeductible = aggDed.deductible;
|
|
2144
|
+
}
|
|
2145
|
+
if (Object.keys(deductibles).length > 0) {
|
|
2146
|
+
raw.deductibles = deductibles;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
var PREMIUM_PATTERNS = ["premium", "totalPremium", "annualPremium", "policyPremium", "basePremium"];
|
|
2150
|
+
var TOTAL_COST_PATTERNS = ["totalCost", "totalDue", "totalAmount", "totalPolicyPremium"];
|
|
2151
|
+
function promotePremium(doc) {
|
|
2152
|
+
const raw = doc;
|
|
2153
|
+
const fields = getDeclarationFields(doc);
|
|
2154
|
+
if (!raw.premium) {
|
|
2155
|
+
const premium = findFieldValue(fields, PREMIUM_PATTERNS);
|
|
2156
|
+
if (premium) raw.premium = premium;
|
|
2157
|
+
}
|
|
2158
|
+
if (!raw.totalCost) {
|
|
2159
|
+
const totalCost = findFieldValue(fields, TOTAL_COST_PATTERNS);
|
|
2160
|
+
if (totalCost) raw.totalCost = totalCost;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
function promoteExtractedFields(doc) {
|
|
2164
|
+
promoteCarrierFields(doc);
|
|
2165
|
+
promoteBroker(doc);
|
|
2166
|
+
promoteLossPayees(doc);
|
|
2167
|
+
promoteLocations(doc);
|
|
2168
|
+
synthesizeLimits(doc);
|
|
2169
|
+
synthesizeDeductibles(doc);
|
|
2170
|
+
promotePremium(doc);
|
|
2171
|
+
}
|
|
2172
|
+
|
|
1817
2173
|
// src/extraction/assembler.ts
|
|
1818
2174
|
function assembleDocument(documentId, documentType, memory) {
|
|
1819
2175
|
const carrier = memory.get("carrier_info");
|
|
@@ -1837,6 +2193,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1837
2193
|
policyTypes: classify?.policyTypes,
|
|
1838
2194
|
...sanitizeNulls(carrier ?? {}),
|
|
1839
2195
|
...sanitizeNulls(insured ?? {}),
|
|
2196
|
+
// Map named_insured extractor's loss payees/mortgage holders to EndorsementParty shape
|
|
2197
|
+
...Array.isArray(insured?.lossPayees) && insured.lossPayees.length > 0 ? { lossPayees: insured.lossPayees.map((lp) => ({ ...lp, role: "loss_payee" })) } : {},
|
|
2198
|
+
...Array.isArray(insured?.mortgageHolders) && insured.mortgageHolders.length > 0 ? { mortgageHolders: insured.mortgageHolders.map((mh) => ({ ...mh, role: "mortgage_holder" })) } : {},
|
|
1840
2199
|
...sanitizeNulls(coverages ?? {}),
|
|
1841
2200
|
...sanitizeNulls(premium ?? {}),
|
|
1842
2201
|
...sanitizeNulls(supplementary ?? {}),
|
|
@@ -1848,8 +2207,9 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1848
2207
|
declarations: declarations ? sanitizeNulls(declarations) : void 0,
|
|
1849
2208
|
...sanitizeNulls(lossHistory ?? {})
|
|
1850
2209
|
};
|
|
2210
|
+
let doc;
|
|
1851
2211
|
if (documentType === "policy") {
|
|
1852
|
-
|
|
2212
|
+
doc = {
|
|
1853
2213
|
...base,
|
|
1854
2214
|
type: "policy",
|
|
1855
2215
|
policyNumber: carrier?.policyNumber ?? insured?.policyNumber ?? "Unknown",
|
|
@@ -1857,17 +2217,20 @@ function assembleDocument(documentId, documentType, memory) {
|
|
|
1857
2217
|
expirationDate: carrier?.expirationDate,
|
|
1858
2218
|
policyTermType: carrier?.policyTermType
|
|
1859
2219
|
};
|
|
2220
|
+
} else {
|
|
2221
|
+
doc = {
|
|
2222
|
+
...base,
|
|
2223
|
+
type: "quote",
|
|
2224
|
+
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
2225
|
+
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
2226
|
+
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
2227
|
+
subjectivities: coverages?.subjectivities,
|
|
2228
|
+
underwritingConditions: coverages?.underwritingConditions,
|
|
2229
|
+
premiumBreakdown: premium?.premiumBreakdown
|
|
2230
|
+
};
|
|
1860
2231
|
}
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
type: "quote",
|
|
1864
|
-
quoteNumber: carrier?.quoteNumber ?? "Unknown",
|
|
1865
|
-
proposedEffectiveDate: carrier?.proposedEffectiveDate,
|
|
1866
|
-
proposedExpirationDate: carrier?.proposedExpirationDate,
|
|
1867
|
-
subjectivities: coverages?.subjectivities,
|
|
1868
|
-
underwritingConditions: coverages?.underwritingConditions,
|
|
1869
|
-
premiumBreakdown: premium?.premiumBreakdown
|
|
1870
|
-
};
|
|
2232
|
+
promoteExtractedFields(doc);
|
|
2233
|
+
return doc;
|
|
1871
2234
|
}
|
|
1872
2235
|
|
|
1873
2236
|
// src/prompts/coordinator/format.ts
|
|
@@ -3301,21 +3664,69 @@ Use the page map to target follow-up extraction pages precisely. Prefer narrow,
|
|
|
3301
3664
|
Respond with JSON only.`;
|
|
3302
3665
|
}
|
|
3303
3666
|
|
|
3304
|
-
// src/prompts/
|
|
3667
|
+
// src/prompts/coordinator/summarize.ts
|
|
3305
3668
|
var import_zod22 = require("zod");
|
|
3306
|
-
var
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3669
|
+
var SummaryResultSchema = import_zod22.z.object({
|
|
3670
|
+
summary: import_zod22.z.string().describe("A 1-3 sentence overview of this insurance document")
|
|
3671
|
+
});
|
|
3672
|
+
function buildSummaryPrompt(doc) {
|
|
3673
|
+
const snapshot = {
|
|
3674
|
+
type: doc.type,
|
|
3675
|
+
carrier: doc.carrier,
|
|
3676
|
+
insuredName: doc.insuredName,
|
|
3677
|
+
policyTypes: doc.policyTypes,
|
|
3678
|
+
premium: doc.premium,
|
|
3679
|
+
coverageCount: doc.coverages?.length ?? 0
|
|
3680
|
+
};
|
|
3681
|
+
if (doc.type === "policy") {
|
|
3682
|
+
snapshot.policyNumber = doc.policyNumber;
|
|
3683
|
+
snapshot.effectiveDate = doc.effectiveDate;
|
|
3684
|
+
snapshot.expirationDate = doc.expirationDate;
|
|
3685
|
+
} else {
|
|
3686
|
+
snapshot.quoteNumber = doc.quoteNumber;
|
|
3687
|
+
snapshot.proposedEffectiveDate = doc.proposedEffectiveDate;
|
|
3688
|
+
}
|
|
3689
|
+
const raw = doc;
|
|
3690
|
+
if (raw.limits) snapshot.limits = raw.limits;
|
|
3691
|
+
if (raw.deductibles) snapshot.deductibles = raw.deductibles;
|
|
3692
|
+
if (raw.brokerAgency) snapshot.brokerAgency = raw.brokerAgency;
|
|
3693
|
+
if (doc.endorsements?.length) snapshot.endorsementCount = doc.endorsements.length;
|
|
3694
|
+
if (doc.exclusions?.length) snapshot.exclusionCount = doc.exclusions.length;
|
|
3695
|
+
if (doc.coverages?.length) {
|
|
3696
|
+
snapshot.topCoverages = doc.coverages.slice(0, 5).map((c) => c.name);
|
|
3697
|
+
}
|
|
3698
|
+
return `You are an expert insurance document analyst. Generate a brief summary of this insurance document.
|
|
3699
|
+
|
|
3700
|
+
Write 1-3 sentences that capture the essential facts a broker or underwriter would want at a glance:
|
|
3701
|
+
- Who is insured and by whom
|
|
3702
|
+
- What type of policy/quote and the key coverages
|
|
3703
|
+
- Policy period and premium if available
|
|
3704
|
+
- Any notable features (high limits, unusual exclusions, etc.)
|
|
3705
|
+
|
|
3706
|
+
Document data:
|
|
3707
|
+
${JSON.stringify(snapshot, null, 2)}
|
|
3708
|
+
|
|
3709
|
+
Return JSON only with a "summary" field.`;
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3712
|
+
// src/prompts/extractors/carrier-info.ts
|
|
3713
|
+
var import_zod23 = require("zod");
|
|
3714
|
+
var CarrierInfoSchema = import_zod23.z.object({
|
|
3715
|
+
carrierName: import_zod23.z.string().describe("Primary insurance company name for display"),
|
|
3716
|
+
carrierLegalName: import_zod23.z.string().optional().describe("Legal entity name of insurer"),
|
|
3717
|
+
naicNumber: import_zod23.z.string().optional().describe("NAIC company code"),
|
|
3718
|
+
amBestRating: import_zod23.z.string().optional().describe("AM Best rating, e.g. 'A+ XV'"),
|
|
3719
|
+
admittedStatus: import_zod23.z.enum(["admitted", "non_admitted", "surplus_lines"]).optional().describe("Admitted status of the carrier"),
|
|
3720
|
+
mga: import_zod23.z.string().optional().describe("Managing General Agent or Program Administrator name"),
|
|
3721
|
+
underwriter: import_zod23.z.string().optional().describe("Named individual underwriter"),
|
|
3722
|
+
brokerAgency: import_zod23.z.string().optional().describe("Broker or producer agency name"),
|
|
3723
|
+
brokerContactName: import_zod23.z.string().optional().describe("Broker or producer contact person name"),
|
|
3724
|
+
brokerLicenseNumber: import_zod23.z.string().optional().describe("Broker or producer license number"),
|
|
3725
|
+
policyNumber: import_zod23.z.string().optional().describe("Policy or quote reference number"),
|
|
3726
|
+
effectiveDate: import_zod23.z.string().optional().describe("Policy effective date (MM/DD/YYYY)"),
|
|
3727
|
+
expirationDate: import_zod23.z.string().optional().describe("Policy expiration date (MM/DD/YYYY)"),
|
|
3728
|
+
quoteNumber: import_zod23.z.string().optional().describe("Quote or proposal reference number"),
|
|
3729
|
+
proposedEffectiveDate: import_zod23.z.string().optional().describe("Proposed effective date for quotes (MM/DD/YYYY)")
|
|
3319
3730
|
});
|
|
3320
3731
|
function buildCarrierInfoPrompt() {
|
|
3321
3732
|
return `You are an expert insurance document analyst. Extract carrier and policy identification information from this document.
|
|
@@ -3326,27 +3737,30 @@ Focus on:
|
|
|
3326
3737
|
- Whether the carrier is admitted, non-admitted, or surplus lines
|
|
3327
3738
|
- Managing General Agent (MGA) or Program Administrator if applicable
|
|
3328
3739
|
- Named individual underwriter if listed
|
|
3740
|
+
- Broker/producer/agent: agency name, contact person name, and license number
|
|
3329
3741
|
- Policy number and effective/expiration dates
|
|
3330
3742
|
- For quotes: quote number and proposed effective date
|
|
3331
3743
|
|
|
3332
3744
|
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.
|
|
3333
3745
|
|
|
3746
|
+
Look for broker/producer/agent information near the carrier or on the declarations page. This may be labeled "Producer", "Agent", "Broker", or similar.
|
|
3747
|
+
|
|
3334
3748
|
Return JSON only.`;
|
|
3335
3749
|
}
|
|
3336
3750
|
|
|
3337
3751
|
// src/prompts/extractors/named-insured.ts
|
|
3338
|
-
var
|
|
3339
|
-
var AddressSchema2 =
|
|
3340
|
-
street1:
|
|
3341
|
-
city:
|
|
3342
|
-
state:
|
|
3343
|
-
zip:
|
|
3752
|
+
var import_zod24 = require("zod");
|
|
3753
|
+
var AddressSchema2 = import_zod24.z.object({
|
|
3754
|
+
street1: import_zod24.z.string(),
|
|
3755
|
+
city: import_zod24.z.string(),
|
|
3756
|
+
state: import_zod24.z.string(),
|
|
3757
|
+
zip: import_zod24.z.string()
|
|
3344
3758
|
});
|
|
3345
|
-
var NamedInsuredSchema2 =
|
|
3346
|
-
insuredName:
|
|
3347
|
-
insuredDba:
|
|
3759
|
+
var NamedInsuredSchema2 = import_zod24.z.object({
|
|
3760
|
+
insuredName: import_zod24.z.string().describe("Name of primary named insured"),
|
|
3761
|
+
insuredDba: import_zod24.z.string().optional().describe("Doing-business-as name"),
|
|
3348
3762
|
insuredAddress: AddressSchema2.optional().describe("Primary insured mailing address"),
|
|
3349
|
-
insuredEntityType:
|
|
3763
|
+
insuredEntityType: import_zod24.z.enum([
|
|
3350
3764
|
"corporation",
|
|
3351
3765
|
"llc",
|
|
3352
3766
|
"partnership",
|
|
@@ -3359,16 +3773,28 @@ var NamedInsuredSchema2 = import_zod23.z.object({
|
|
|
3359
3773
|
"married_couple",
|
|
3360
3774
|
"other"
|
|
3361
3775
|
]).optional().describe("Legal entity type of the insured"),
|
|
3362
|
-
insuredFein:
|
|
3363
|
-
insuredSicCode:
|
|
3364
|
-
insuredNaicsCode:
|
|
3365
|
-
additionalNamedInsureds:
|
|
3366
|
-
|
|
3367
|
-
name:
|
|
3368
|
-
relationship:
|
|
3776
|
+
insuredFein: import_zod24.z.string().optional().describe("Federal Employer Identification Number"),
|
|
3777
|
+
insuredSicCode: import_zod24.z.string().optional().describe("SIC code"),
|
|
3778
|
+
insuredNaicsCode: import_zod24.z.string().optional().describe("NAICS code"),
|
|
3779
|
+
additionalNamedInsureds: import_zod24.z.array(
|
|
3780
|
+
import_zod24.z.object({
|
|
3781
|
+
name: import_zod24.z.string(),
|
|
3782
|
+
relationship: import_zod24.z.string().optional().describe("e.g. subsidiary, affiliate"),
|
|
3783
|
+
address: AddressSchema2.optional()
|
|
3784
|
+
})
|
|
3785
|
+
).optional().describe("Additional named insureds listed on the policy"),
|
|
3786
|
+
lossPayees: import_zod24.z.array(
|
|
3787
|
+
import_zod24.z.object({
|
|
3788
|
+
name: import_zod24.z.string(),
|
|
3789
|
+
address: AddressSchema2.optional()
|
|
3790
|
+
})
|
|
3791
|
+
).optional().describe("Loss payees listed on the policy"),
|
|
3792
|
+
mortgageHolders: import_zod24.z.array(
|
|
3793
|
+
import_zod24.z.object({
|
|
3794
|
+
name: import_zod24.z.string(),
|
|
3369
3795
|
address: AddressSchema2.optional()
|
|
3370
3796
|
})
|
|
3371
|
-
).optional().describe("
|
|
3797
|
+
).optional().describe("Mortgage holders / lienholders listed on the policy")
|
|
3372
3798
|
});
|
|
3373
3799
|
function buildNamedInsuredPrompt() {
|
|
3374
3800
|
return `You are an expert insurance document analyst. Extract all named insured information from this document.
|
|
@@ -3379,21 +3805,23 @@ Focus on:
|
|
|
3379
3805
|
- FEIN (Federal Employer Identification Number) if listed
|
|
3380
3806
|
- SIC code and NAICS code if listed
|
|
3381
3807
|
- ALL additional named insureds with their relationship (subsidiary, affiliate, etc.) and address if provided
|
|
3808
|
+
- ALL loss payees with name and address (e.g. "Loss Payee: BMO Bank of Montreal")
|
|
3809
|
+
- ALL mortgage holders / lienholders / mortgagees with name and address
|
|
3382
3810
|
|
|
3383
|
-
Look on the declarations page, named insured schedule, and any endorsements that add or modify named insureds.
|
|
3811
|
+
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.
|
|
3384
3812
|
|
|
3385
3813
|
Return JSON only.`;
|
|
3386
3814
|
}
|
|
3387
3815
|
|
|
3388
3816
|
// src/prompts/extractors/coverage-limits.ts
|
|
3389
|
-
var
|
|
3817
|
+
var import_zod25 = require("zod");
|
|
3390
3818
|
var ExtractorCoverageSchema = CoverageSchema.extend({
|
|
3391
|
-
coverageCode:
|
|
3819
|
+
coverageCode: import_zod25.z.string().optional().describe("Coverage code or class code")
|
|
3392
3820
|
});
|
|
3393
|
-
var CoverageLimitsSchema =
|
|
3394
|
-
coverages:
|
|
3395
|
-
coverageForm:
|
|
3396
|
-
retroactiveDate:
|
|
3821
|
+
var CoverageLimitsSchema = import_zod25.z.object({
|
|
3822
|
+
coverages: import_zod25.z.array(ExtractorCoverageSchema).describe("All coverages with their limits"),
|
|
3823
|
+
coverageForm: import_zod25.z.enum(["occurrence", "claims_made", "accident"]).optional().describe("Primary coverage trigger type"),
|
|
3824
|
+
retroactiveDate: import_zod25.z.string().optional().describe("Retroactive date for claims-made policies (MM/DD/YYYY)")
|
|
3397
3825
|
});
|
|
3398
3826
|
function buildCoverageLimitsPrompt() {
|
|
3399
3827
|
return `You are an expert insurance document analyst. Extract all coverage limits and deductibles from this document.
|
|
@@ -3432,14 +3860,14 @@ Return JSON only.`;
|
|
|
3432
3860
|
}
|
|
3433
3861
|
|
|
3434
3862
|
// src/prompts/extractors/endorsements.ts
|
|
3435
|
-
var
|
|
3436
|
-
var EndorsementsSchema =
|
|
3437
|
-
endorsements:
|
|
3438
|
-
|
|
3439
|
-
formNumber:
|
|
3440
|
-
editionDate:
|
|
3441
|
-
title:
|
|
3442
|
-
endorsementType:
|
|
3863
|
+
var import_zod26 = require("zod");
|
|
3864
|
+
var EndorsementsSchema = import_zod26.z.object({
|
|
3865
|
+
endorsements: import_zod26.z.array(
|
|
3866
|
+
import_zod26.z.object({
|
|
3867
|
+
formNumber: import_zod26.z.string().describe("Form number, e.g. 'CG 21 47'"),
|
|
3868
|
+
editionDate: import_zod26.z.string().optional().describe("Edition date, e.g. '12 07'"),
|
|
3869
|
+
title: import_zod26.z.string().describe("Endorsement title"),
|
|
3870
|
+
endorsementType: import_zod26.z.enum([
|
|
3443
3871
|
"additional_insured",
|
|
3444
3872
|
"waiver_of_subrogation",
|
|
3445
3873
|
"primary_noncontributory",
|
|
@@ -3459,12 +3887,12 @@ var EndorsementsSchema = import_zod25.z.object({
|
|
|
3459
3887
|
"territorial_extension",
|
|
3460
3888
|
"other"
|
|
3461
3889
|
]).describe("Endorsement type classification"),
|
|
3462
|
-
effectiveDate:
|
|
3463
|
-
affectedCoverageParts:
|
|
3464
|
-
namedParties:
|
|
3465
|
-
|
|
3466
|
-
name:
|
|
3467
|
-
role:
|
|
3890
|
+
effectiveDate: import_zod26.z.string().optional().describe("Endorsement effective date"),
|
|
3891
|
+
affectedCoverageParts: import_zod26.z.array(import_zod26.z.string()).optional().describe("Coverage parts affected by this endorsement"),
|
|
3892
|
+
namedParties: import_zod26.z.array(
|
|
3893
|
+
import_zod26.z.object({
|
|
3894
|
+
name: import_zod26.z.string().describe("Party name"),
|
|
3895
|
+
role: import_zod26.z.enum([
|
|
3468
3896
|
"additional_insured",
|
|
3469
3897
|
"loss_payee",
|
|
3470
3898
|
"mortgage_holder",
|
|
@@ -3473,15 +3901,15 @@ var EndorsementsSchema = import_zod25.z.object({
|
|
|
3473
3901
|
"designated_person",
|
|
3474
3902
|
"other"
|
|
3475
3903
|
]).describe("Party role"),
|
|
3476
|
-
relationship:
|
|
3477
|
-
scope:
|
|
3904
|
+
relationship: import_zod26.z.string().optional().describe("Relationship to insured"),
|
|
3905
|
+
scope: import_zod26.z.string().optional().describe("Scope of coverage for this party")
|
|
3478
3906
|
})
|
|
3479
3907
|
).optional().describe("Named parties (additional insureds, loss payees, etc.)"),
|
|
3480
|
-
keyTerms:
|
|
3481
|
-
premiumImpact:
|
|
3482
|
-
content:
|
|
3483
|
-
pageStart:
|
|
3484
|
-
pageEnd:
|
|
3908
|
+
keyTerms: import_zod26.z.array(import_zod26.z.string()).optional().describe("Key terms or notable provisions in the endorsement"),
|
|
3909
|
+
premiumImpact: import_zod26.z.string().optional().describe("Additional premium or credit"),
|
|
3910
|
+
content: import_zod26.z.string().describe("Full verbatim text of the endorsement"),
|
|
3911
|
+
pageStart: import_zod26.z.number().describe("Starting page number of this endorsement"),
|
|
3912
|
+
pageEnd: import_zod26.z.number().optional().describe("Ending page number of this endorsement")
|
|
3485
3913
|
})
|
|
3486
3914
|
).describe("All endorsements found in the document")
|
|
3487
3915
|
});
|
|
@@ -3512,20 +3940,20 @@ Return JSON only.`;
|
|
|
3512
3940
|
}
|
|
3513
3941
|
|
|
3514
3942
|
// src/prompts/extractors/exclusions.ts
|
|
3515
|
-
var
|
|
3516
|
-
var ExclusionsSchema =
|
|
3517
|
-
exclusions:
|
|
3518
|
-
|
|
3519
|
-
name:
|
|
3520
|
-
formNumber:
|
|
3521
|
-
excludedPerils:
|
|
3522
|
-
isAbsolute:
|
|
3523
|
-
exceptions:
|
|
3524
|
-
buybackAvailable:
|
|
3525
|
-
buybackEndorsement:
|
|
3526
|
-
appliesTo:
|
|
3527
|
-
content:
|
|
3528
|
-
pageNumber:
|
|
3943
|
+
var import_zod27 = require("zod");
|
|
3944
|
+
var ExclusionsSchema = import_zod27.z.object({
|
|
3945
|
+
exclusions: import_zod27.z.array(
|
|
3946
|
+
import_zod27.z.object({
|
|
3947
|
+
name: import_zod27.z.string().describe("Exclusion title or short description"),
|
|
3948
|
+
formNumber: import_zod27.z.string().optional().describe("Form number if part of a named endorsement"),
|
|
3949
|
+
excludedPerils: import_zod27.z.array(import_zod27.z.string()).optional().describe("Specific perils excluded"),
|
|
3950
|
+
isAbsolute: import_zod27.z.boolean().optional().describe("Whether the exclusion is absolute (no exceptions)"),
|
|
3951
|
+
exceptions: import_zod27.z.array(import_zod27.z.string()).optional().describe("Exceptions to the exclusion, if any"),
|
|
3952
|
+
buybackAvailable: import_zod27.z.boolean().optional().describe("Whether coverage can be bought back via endorsement"),
|
|
3953
|
+
buybackEndorsement: import_zod27.z.string().optional().describe("Form number of the buyback endorsement if available"),
|
|
3954
|
+
appliesTo: import_zod27.z.array(import_zod27.z.string()).optional().describe("Coverage types this exclusion applies to"),
|
|
3955
|
+
content: import_zod27.z.string().describe("Full verbatim exclusion text"),
|
|
3956
|
+
pageNumber: import_zod27.z.number().optional().describe("Page number where exclusion appears")
|
|
3529
3957
|
})
|
|
3530
3958
|
).describe("All exclusions found in the document")
|
|
3531
3959
|
});
|
|
@@ -3561,12 +3989,12 @@ Return JSON only.`;
|
|
|
3561
3989
|
}
|
|
3562
3990
|
|
|
3563
3991
|
// src/prompts/extractors/conditions.ts
|
|
3564
|
-
var
|
|
3565
|
-
var ConditionsSchema =
|
|
3566
|
-
conditions:
|
|
3567
|
-
|
|
3568
|
-
name:
|
|
3569
|
-
conditionType:
|
|
3992
|
+
var import_zod28 = require("zod");
|
|
3993
|
+
var ConditionsSchema = import_zod28.z.object({
|
|
3994
|
+
conditions: import_zod28.z.array(
|
|
3995
|
+
import_zod28.z.object({
|
|
3996
|
+
name: import_zod28.z.string().describe("Condition title"),
|
|
3997
|
+
conditionType: import_zod28.z.enum([
|
|
3570
3998
|
"duties_after_loss",
|
|
3571
3999
|
"notice_requirements",
|
|
3572
4000
|
"other_insurance",
|
|
@@ -3585,14 +4013,14 @@ var ConditionsSchema = import_zod27.z.object({
|
|
|
3585
4013
|
"separation_of_insureds",
|
|
3586
4014
|
"other"
|
|
3587
4015
|
]).describe("Condition category"),
|
|
3588
|
-
content:
|
|
3589
|
-
keyValues:
|
|
3590
|
-
|
|
3591
|
-
key:
|
|
3592
|
-
value:
|
|
4016
|
+
content: import_zod28.z.string().describe("Full verbatim condition text"),
|
|
4017
|
+
keyValues: import_zod28.z.array(
|
|
4018
|
+
import_zod28.z.object({
|
|
4019
|
+
key: import_zod28.z.string().describe("Key name (e.g. 'noticePeriod', 'suitDeadline')"),
|
|
4020
|
+
value: import_zod28.z.string().describe("Value (e.g. '30 days', '2 years')")
|
|
3593
4021
|
})
|
|
3594
4022
|
).optional().describe("Key values extracted from the condition (notice periods, deadlines, etc.)"),
|
|
3595
|
-
pageNumber:
|
|
4023
|
+
pageNumber: import_zod28.z.number().optional().describe("Page number where condition appears")
|
|
3596
4024
|
})
|
|
3597
4025
|
).describe("All policy conditions found in the document")
|
|
3598
4026
|
});
|
|
@@ -3630,28 +4058,28 @@ Return JSON only.`;
|
|
|
3630
4058
|
}
|
|
3631
4059
|
|
|
3632
4060
|
// src/prompts/extractors/premium-breakdown.ts
|
|
3633
|
-
var
|
|
3634
|
-
var PremiumBreakdownSchema =
|
|
3635
|
-
premium:
|
|
3636
|
-
totalCost:
|
|
3637
|
-
premiumBreakdown:
|
|
3638
|
-
|
|
3639
|
-
line:
|
|
3640
|
-
amount:
|
|
4061
|
+
var import_zod29 = require("zod");
|
|
4062
|
+
var PremiumBreakdownSchema = import_zod29.z.object({
|
|
4063
|
+
premium: import_zod29.z.string().optional().describe("Total premium amount, e.g. '$5,000'"),
|
|
4064
|
+
totalCost: import_zod29.z.string().optional().describe("Total cost including taxes and fees, e.g. '$5,250'"),
|
|
4065
|
+
premiumBreakdown: import_zod29.z.array(
|
|
4066
|
+
import_zod29.z.object({
|
|
4067
|
+
line: import_zod29.z.string().describe("Coverage line name"),
|
|
4068
|
+
amount: import_zod29.z.string().describe("Premium amount for this line")
|
|
3641
4069
|
})
|
|
3642
4070
|
).optional().describe("Per-coverage-line premium breakdown"),
|
|
3643
|
-
taxesAndFees:
|
|
3644
|
-
|
|
3645
|
-
name:
|
|
3646
|
-
amount:
|
|
3647
|
-
type:
|
|
4071
|
+
taxesAndFees: import_zod29.z.array(
|
|
4072
|
+
import_zod29.z.object({
|
|
4073
|
+
name: import_zod29.z.string().describe("Fee or tax name"),
|
|
4074
|
+
amount: import_zod29.z.string().describe("Dollar amount"),
|
|
4075
|
+
type: import_zod29.z.enum(["tax", "fee", "surcharge", "assessment"]).optional().describe("Fee category")
|
|
3648
4076
|
})
|
|
3649
4077
|
).optional().describe("Taxes, fees, surcharges, and assessments"),
|
|
3650
|
-
minimumPremium:
|
|
3651
|
-
depositPremium:
|
|
3652
|
-
paymentPlan:
|
|
3653
|
-
auditType:
|
|
3654
|
-
ratingBasis:
|
|
4078
|
+
minimumPremium: import_zod29.z.string().optional().describe("Minimum premium if stated"),
|
|
4079
|
+
depositPremium: import_zod29.z.string().optional().describe("Deposit premium if stated"),
|
|
4080
|
+
paymentPlan: import_zod29.z.string().optional().describe("Payment plan description"),
|
|
4081
|
+
auditType: import_zod29.z.enum(["annual", "semi_annual", "quarterly", "monthly", "final", "self"]).optional().describe("Premium audit type"),
|
|
4082
|
+
ratingBasis: import_zod29.z.string().optional().describe("Rating basis, e.g. payroll, revenue, area, units")
|
|
3655
4083
|
});
|
|
3656
4084
|
function buildPremiumBreakdownPrompt() {
|
|
3657
4085
|
return `You are an expert insurance document analyst. Extract all premium and cost information from this document.
|
|
@@ -3671,14 +4099,14 @@ Return JSON only.`;
|
|
|
3671
4099
|
}
|
|
3672
4100
|
|
|
3673
4101
|
// src/prompts/extractors/declarations.ts
|
|
3674
|
-
var
|
|
3675
|
-
var DeclarationsFieldSchema =
|
|
3676
|
-
field:
|
|
3677
|
-
value:
|
|
3678
|
-
section:
|
|
4102
|
+
var import_zod30 = require("zod");
|
|
4103
|
+
var DeclarationsFieldSchema = import_zod30.z.object({
|
|
4104
|
+
field: import_zod30.z.string().describe("Descriptive field name (e.g. 'policyNumber', 'effectiveDate', 'coverageALimit')"),
|
|
4105
|
+
value: import_zod30.z.string().describe("Extracted value exactly as it appears in the document"),
|
|
4106
|
+
section: import_zod30.z.string().optional().describe("Section or grouping this field belongs to (e.g. 'Coverage Limits', 'Vehicle Schedule')")
|
|
3679
4107
|
});
|
|
3680
|
-
var DeclarationsExtractSchema =
|
|
3681
|
-
fields:
|
|
4108
|
+
var DeclarationsExtractSchema = import_zod30.z.object({
|
|
4109
|
+
fields: import_zod30.z.array(DeclarationsFieldSchema).describe("All declarations page fields extracted as key-value pairs. Structure varies by line of business.")
|
|
3682
4110
|
});
|
|
3683
4111
|
function buildDeclarationsPrompt() {
|
|
3684
4112
|
return `You are an expert insurance document analyst. Extract all declarations page data from this document into a flexible key-value structure.
|
|
@@ -3718,21 +4146,21 @@ Preserve original values exactly as they appear. Return JSON only.`;
|
|
|
3718
4146
|
}
|
|
3719
4147
|
|
|
3720
4148
|
// src/prompts/extractors/loss-history.ts
|
|
3721
|
-
var
|
|
3722
|
-
var LossHistorySchema =
|
|
3723
|
-
lossSummary:
|
|
3724
|
-
individualClaims:
|
|
3725
|
-
|
|
3726
|
-
date:
|
|
3727
|
-
type:
|
|
3728
|
-
description:
|
|
3729
|
-
amountPaid:
|
|
3730
|
-
amountReserved:
|
|
3731
|
-
status:
|
|
3732
|
-
claimNumber:
|
|
4149
|
+
var import_zod31 = require("zod");
|
|
4150
|
+
var LossHistorySchema = import_zod31.z.object({
|
|
4151
|
+
lossSummary: import_zod31.z.string().optional().describe("Summary of loss history, e.g. '3 claims in past 5 years totaling $125,000'"),
|
|
4152
|
+
individualClaims: import_zod31.z.array(
|
|
4153
|
+
import_zod31.z.object({
|
|
4154
|
+
date: import_zod31.z.string().optional().describe("Date of loss or claim"),
|
|
4155
|
+
type: import_zod31.z.string().optional().describe("Type of claim, e.g. 'property damage', 'bodily injury'"),
|
|
4156
|
+
description: import_zod31.z.string().optional().describe("Brief description of the claim"),
|
|
4157
|
+
amountPaid: import_zod31.z.string().optional().describe("Amount paid"),
|
|
4158
|
+
amountReserved: import_zod31.z.string().optional().describe("Amount reserved"),
|
|
4159
|
+
status: import_zod31.z.enum(["open", "closed", "reopened"]).optional().describe("Claim status"),
|
|
4160
|
+
claimNumber: import_zod31.z.string().optional().describe("Claim reference number")
|
|
3733
4161
|
})
|
|
3734
4162
|
).optional().describe("Individual claim records"),
|
|
3735
|
-
experienceMod:
|
|
4163
|
+
experienceMod: import_zod31.z.string().optional().describe("Experience modification factor for workers comp, e.g. '0.85'")
|
|
3736
4164
|
});
|
|
3737
4165
|
function buildLossHistoryPrompt() {
|
|
3738
4166
|
return `You are an expert insurance document analyst. Extract all loss history and claims information from this document.
|
|
@@ -3749,18 +4177,18 @@ Return JSON only.`;
|
|
|
3749
4177
|
}
|
|
3750
4178
|
|
|
3751
4179
|
// src/prompts/extractors/sections.ts
|
|
3752
|
-
var
|
|
3753
|
-
var SubsectionSchema2 =
|
|
3754
|
-
title:
|
|
3755
|
-
sectionNumber:
|
|
3756
|
-
pageNumber:
|
|
3757
|
-
content:
|
|
4180
|
+
var import_zod32 = require("zod");
|
|
4181
|
+
var SubsectionSchema2 = import_zod32.z.object({
|
|
4182
|
+
title: import_zod32.z.string().describe("Subsection title"),
|
|
4183
|
+
sectionNumber: import_zod32.z.string().optional().describe("Subsection number"),
|
|
4184
|
+
pageNumber: import_zod32.z.number().optional().describe("Page number"),
|
|
4185
|
+
content: import_zod32.z.string().describe("Full verbatim text")
|
|
3758
4186
|
});
|
|
3759
|
-
var SectionsSchema =
|
|
3760
|
-
sections:
|
|
3761
|
-
|
|
3762
|
-
title:
|
|
3763
|
-
type:
|
|
4187
|
+
var SectionsSchema = import_zod32.z.object({
|
|
4188
|
+
sections: import_zod32.z.array(
|
|
4189
|
+
import_zod32.z.object({
|
|
4190
|
+
title: import_zod32.z.string().describe("Section title"),
|
|
4191
|
+
type: import_zod32.z.enum([
|
|
3764
4192
|
"declarations",
|
|
3765
4193
|
"insuring_agreement",
|
|
3766
4194
|
"policy_form",
|
|
@@ -3774,10 +4202,10 @@ var SectionsSchema = import_zod31.z.object({
|
|
|
3774
4202
|
"regulatory",
|
|
3775
4203
|
"other"
|
|
3776
4204
|
]).describe("Section type classification"),
|
|
3777
|
-
content:
|
|
3778
|
-
pageStart:
|
|
3779
|
-
pageEnd:
|
|
3780
|
-
subsections:
|
|
4205
|
+
content: import_zod32.z.string().describe("Full verbatim text of the section"),
|
|
4206
|
+
pageStart: import_zod32.z.number().describe("Starting page number"),
|
|
4207
|
+
pageEnd: import_zod32.z.number().optional().describe("Ending page number"),
|
|
4208
|
+
subsections: import_zod32.z.array(SubsectionSchema2).optional().describe("Subsections within this section")
|
|
3781
4209
|
})
|
|
3782
4210
|
).describe("All document sections")
|
|
3783
4211
|
});
|
|
@@ -3807,20 +4235,20 @@ Return JSON only.`;
|
|
|
3807
4235
|
}
|
|
3808
4236
|
|
|
3809
4237
|
// src/prompts/extractors/supplementary.ts
|
|
3810
|
-
var
|
|
3811
|
-
var ContactSchema2 =
|
|
3812
|
-
name:
|
|
3813
|
-
phone:
|
|
3814
|
-
email:
|
|
3815
|
-
address:
|
|
3816
|
-
type:
|
|
4238
|
+
var import_zod33 = require("zod");
|
|
4239
|
+
var ContactSchema2 = import_zod33.z.object({
|
|
4240
|
+
name: import_zod33.z.string().optional().describe("Organization or person name"),
|
|
4241
|
+
phone: import_zod33.z.string().optional().describe("Phone number"),
|
|
4242
|
+
email: import_zod33.z.string().optional().describe("Email address"),
|
|
4243
|
+
address: import_zod33.z.string().optional().describe("Mailing address"),
|
|
4244
|
+
type: import_zod33.z.string().optional().describe("Contact type, e.g. 'State Department of Insurance'")
|
|
3817
4245
|
});
|
|
3818
|
-
var SupplementarySchema =
|
|
3819
|
-
regulatoryContacts:
|
|
3820
|
-
claimsContacts:
|
|
3821
|
-
thirdPartyAdministrators:
|
|
3822
|
-
cancellationNoticeDays:
|
|
3823
|
-
nonrenewalNoticeDays:
|
|
4246
|
+
var SupplementarySchema = import_zod33.z.object({
|
|
4247
|
+
regulatoryContacts: import_zod33.z.array(ContactSchema2).optional().describe("Regulatory body contacts (state department of insurance, ombudsman)"),
|
|
4248
|
+
claimsContacts: import_zod33.z.array(ContactSchema2).optional().describe("Claims reporting contacts and instructions"),
|
|
4249
|
+
thirdPartyAdministrators: import_zod33.z.array(ContactSchema2).optional().describe("Third-party administrators for claims handling"),
|
|
4250
|
+
cancellationNoticeDays: import_zod33.z.number().optional().describe("Required notice period for cancellation in days"),
|
|
4251
|
+
nonrenewalNoticeDays: import_zod33.z.number().optional().describe("Required notice period for nonrenewal in days")
|
|
3824
4252
|
});
|
|
3825
4253
|
function buildSupplementaryPrompt() {
|
|
3826
4254
|
return `You are an expert insurance document analyst. Extract supplementary and regulatory information from this document.
|
|
@@ -4679,6 +5107,31 @@ function createExtractor(config) {
|
|
|
4679
5107
|
memory: Object.fromEntries(memory),
|
|
4680
5108
|
document
|
|
4681
5109
|
});
|
|
5110
|
+
if (!document.summary) {
|
|
5111
|
+
onProgress?.("Generating document summary...");
|
|
5112
|
+
try {
|
|
5113
|
+
const summaryResponse = await safeGenerateObject(
|
|
5114
|
+
generateObject,
|
|
5115
|
+
{
|
|
5116
|
+
prompt: buildSummaryPrompt(document),
|
|
5117
|
+
schema: SummaryResultSchema,
|
|
5118
|
+
maxTokens: 512,
|
|
5119
|
+
providerOptions
|
|
5120
|
+
},
|
|
5121
|
+
{
|
|
5122
|
+
fallback: { summary: "" },
|
|
5123
|
+
log,
|
|
5124
|
+
onError: (err, attempt) => log?.(`Summary attempt ${attempt + 1} failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
5125
|
+
}
|
|
5126
|
+
);
|
|
5127
|
+
trackUsage(summaryResponse.usage);
|
|
5128
|
+
if (summaryResponse.object.summary) {
|
|
5129
|
+
document.summary = summaryResponse.object.summary;
|
|
5130
|
+
}
|
|
5131
|
+
} catch (error) {
|
|
5132
|
+
await log?.(`Summary generation failed, skipping: ${error instanceof Error ? error.message : String(error)}`);
|
|
5133
|
+
}
|
|
5134
|
+
}
|
|
4682
5135
|
onProgress?.("Formatting extracted content...");
|
|
4683
5136
|
const formatResult = await formatDocumentContent(document, generateText, {
|
|
4684
5137
|
providerOptions,
|
|
@@ -4922,8 +5375,8 @@ Respond with JSON only:
|
|
|
4922
5375
|
}`;
|
|
4923
5376
|
|
|
4924
5377
|
// src/schemas/application.ts
|
|
4925
|
-
var
|
|
4926
|
-
var FieldTypeSchema =
|
|
5378
|
+
var import_zod34 = require("zod");
|
|
5379
|
+
var FieldTypeSchema = import_zod34.z.enum([
|
|
4927
5380
|
"text",
|
|
4928
5381
|
"numeric",
|
|
4929
5382
|
"currency",
|
|
@@ -4932,131 +5385,131 @@ var FieldTypeSchema = import_zod33.z.enum([
|
|
|
4932
5385
|
"table",
|
|
4933
5386
|
"declaration"
|
|
4934
5387
|
]);
|
|
4935
|
-
var ApplicationFieldSchema =
|
|
4936
|
-
id:
|
|
4937
|
-
label:
|
|
4938
|
-
section:
|
|
5388
|
+
var ApplicationFieldSchema = import_zod34.z.object({
|
|
5389
|
+
id: import_zod34.z.string(),
|
|
5390
|
+
label: import_zod34.z.string(),
|
|
5391
|
+
section: import_zod34.z.string(),
|
|
4939
5392
|
fieldType: FieldTypeSchema,
|
|
4940
|
-
required:
|
|
4941
|
-
options:
|
|
4942
|
-
columns:
|
|
4943
|
-
requiresExplanationIfYes:
|
|
4944
|
-
condition:
|
|
4945
|
-
dependsOn:
|
|
4946
|
-
whenValue:
|
|
5393
|
+
required: import_zod34.z.boolean(),
|
|
5394
|
+
options: import_zod34.z.array(import_zod34.z.string()).optional(),
|
|
5395
|
+
columns: import_zod34.z.array(import_zod34.z.string()).optional(),
|
|
5396
|
+
requiresExplanationIfYes: import_zod34.z.boolean().optional(),
|
|
5397
|
+
condition: import_zod34.z.object({
|
|
5398
|
+
dependsOn: import_zod34.z.string(),
|
|
5399
|
+
whenValue: import_zod34.z.string()
|
|
4947
5400
|
}).optional(),
|
|
4948
|
-
value:
|
|
4949
|
-
source:
|
|
4950
|
-
confidence:
|
|
5401
|
+
value: import_zod34.z.string().optional(),
|
|
5402
|
+
source: import_zod34.z.string().optional().describe("Where the value came from: auto-fill, user, lookup"),
|
|
5403
|
+
confidence: import_zod34.z.enum(["confirmed", "high", "medium", "low"]).optional()
|
|
4951
5404
|
});
|
|
4952
|
-
var ApplicationClassifyResultSchema =
|
|
4953
|
-
isApplication:
|
|
4954
|
-
confidence:
|
|
4955
|
-
applicationType:
|
|
5405
|
+
var ApplicationClassifyResultSchema = import_zod34.z.object({
|
|
5406
|
+
isApplication: import_zod34.z.boolean(),
|
|
5407
|
+
confidence: import_zod34.z.number().min(0).max(1),
|
|
5408
|
+
applicationType: import_zod34.z.string().nullable()
|
|
4956
5409
|
});
|
|
4957
|
-
var FieldExtractionResultSchema =
|
|
4958
|
-
fields:
|
|
5410
|
+
var FieldExtractionResultSchema = import_zod34.z.object({
|
|
5411
|
+
fields: import_zod34.z.array(ApplicationFieldSchema)
|
|
4959
5412
|
});
|
|
4960
|
-
var AutoFillMatchSchema =
|
|
4961
|
-
fieldId:
|
|
4962
|
-
value:
|
|
4963
|
-
confidence:
|
|
4964
|
-
contextKey:
|
|
5413
|
+
var AutoFillMatchSchema = import_zod34.z.object({
|
|
5414
|
+
fieldId: import_zod34.z.string(),
|
|
5415
|
+
value: import_zod34.z.string(),
|
|
5416
|
+
confidence: import_zod34.z.enum(["confirmed"]),
|
|
5417
|
+
contextKey: import_zod34.z.string()
|
|
4965
5418
|
});
|
|
4966
|
-
var AutoFillResultSchema =
|
|
4967
|
-
matches:
|
|
5419
|
+
var AutoFillResultSchema = import_zod34.z.object({
|
|
5420
|
+
matches: import_zod34.z.array(AutoFillMatchSchema)
|
|
4968
5421
|
});
|
|
4969
|
-
var QuestionBatchResultSchema =
|
|
4970
|
-
batches:
|
|
5422
|
+
var QuestionBatchResultSchema = import_zod34.z.object({
|
|
5423
|
+
batches: import_zod34.z.array(import_zod34.z.array(import_zod34.z.string()).describe("Array of field IDs in this batch"))
|
|
4971
5424
|
});
|
|
4972
|
-
var LookupRequestSchema =
|
|
4973
|
-
type:
|
|
4974
|
-
description:
|
|
4975
|
-
url:
|
|
4976
|
-
targetFieldIds:
|
|
5425
|
+
var LookupRequestSchema = import_zod34.z.object({
|
|
5426
|
+
type: import_zod34.z.string().describe("Type of lookup: 'records', 'website', 'policy'"),
|
|
5427
|
+
description: import_zod34.z.string(),
|
|
5428
|
+
url: import_zod34.z.string().optional(),
|
|
5429
|
+
targetFieldIds: import_zod34.z.array(import_zod34.z.string())
|
|
4977
5430
|
});
|
|
4978
|
-
var ReplyIntentSchema =
|
|
4979
|
-
primaryIntent:
|
|
4980
|
-
hasAnswers:
|
|
4981
|
-
questionText:
|
|
4982
|
-
questionFieldIds:
|
|
4983
|
-
lookupRequests:
|
|
5431
|
+
var ReplyIntentSchema = import_zod34.z.object({
|
|
5432
|
+
primaryIntent: import_zod34.z.enum(["answers_only", "question", "lookup_request", "mixed"]),
|
|
5433
|
+
hasAnswers: import_zod34.z.boolean(),
|
|
5434
|
+
questionText: import_zod34.z.string().optional(),
|
|
5435
|
+
questionFieldIds: import_zod34.z.array(import_zod34.z.string()).optional(),
|
|
5436
|
+
lookupRequests: import_zod34.z.array(LookupRequestSchema).optional()
|
|
4984
5437
|
});
|
|
4985
|
-
var ParsedAnswerSchema =
|
|
4986
|
-
fieldId:
|
|
4987
|
-
value:
|
|
4988
|
-
explanation:
|
|
5438
|
+
var ParsedAnswerSchema = import_zod34.z.object({
|
|
5439
|
+
fieldId: import_zod34.z.string(),
|
|
5440
|
+
value: import_zod34.z.string(),
|
|
5441
|
+
explanation: import_zod34.z.string().optional()
|
|
4989
5442
|
});
|
|
4990
|
-
var AnswerParsingResultSchema =
|
|
4991
|
-
answers:
|
|
4992
|
-
unanswered:
|
|
5443
|
+
var AnswerParsingResultSchema = import_zod34.z.object({
|
|
5444
|
+
answers: import_zod34.z.array(ParsedAnswerSchema),
|
|
5445
|
+
unanswered: import_zod34.z.array(import_zod34.z.string()).describe("Field IDs that were not answered")
|
|
4993
5446
|
});
|
|
4994
|
-
var LookupFillSchema =
|
|
4995
|
-
fieldId:
|
|
4996
|
-
value:
|
|
4997
|
-
source:
|
|
5447
|
+
var LookupFillSchema = import_zod34.z.object({
|
|
5448
|
+
fieldId: import_zod34.z.string(),
|
|
5449
|
+
value: import_zod34.z.string(),
|
|
5450
|
+
source: import_zod34.z.string().describe("Specific citable reference, e.g. 'GL Policy #POL-12345 (Hartford)'")
|
|
4998
5451
|
});
|
|
4999
|
-
var LookupFillResultSchema =
|
|
5000
|
-
fills:
|
|
5001
|
-
unfillable:
|
|
5002
|
-
explanation:
|
|
5452
|
+
var LookupFillResultSchema = import_zod34.z.object({
|
|
5453
|
+
fills: import_zod34.z.array(LookupFillSchema),
|
|
5454
|
+
unfillable: import_zod34.z.array(import_zod34.z.string()),
|
|
5455
|
+
explanation: import_zod34.z.string().optional()
|
|
5003
5456
|
});
|
|
5004
|
-
var FlatPdfPlacementSchema =
|
|
5005
|
-
fieldId:
|
|
5006
|
-
page:
|
|
5007
|
-
x:
|
|
5008
|
-
y:
|
|
5009
|
-
text:
|
|
5010
|
-
fontSize:
|
|
5011
|
-
isCheckmark:
|
|
5457
|
+
var FlatPdfPlacementSchema = import_zod34.z.object({
|
|
5458
|
+
fieldId: import_zod34.z.string(),
|
|
5459
|
+
page: import_zod34.z.number(),
|
|
5460
|
+
x: import_zod34.z.number().describe("Percentage from left edge (0-100)"),
|
|
5461
|
+
y: import_zod34.z.number().describe("Percentage from top edge (0-100)"),
|
|
5462
|
+
text: import_zod34.z.string(),
|
|
5463
|
+
fontSize: import_zod34.z.number().optional(),
|
|
5464
|
+
isCheckmark: import_zod34.z.boolean().optional()
|
|
5012
5465
|
});
|
|
5013
|
-
var AcroFormMappingSchema =
|
|
5014
|
-
fieldId:
|
|
5015
|
-
acroFormName:
|
|
5016
|
-
value:
|
|
5466
|
+
var AcroFormMappingSchema = import_zod34.z.object({
|
|
5467
|
+
fieldId: import_zod34.z.string(),
|
|
5468
|
+
acroFormName: import_zod34.z.string(),
|
|
5469
|
+
value: import_zod34.z.string()
|
|
5017
5470
|
});
|
|
5018
|
-
var QualityGateStatusSchema =
|
|
5019
|
-
var QualitySeveritySchema =
|
|
5020
|
-
var ApplicationQualityIssueSchema =
|
|
5021
|
-
code:
|
|
5471
|
+
var QualityGateStatusSchema = import_zod34.z.enum(["passed", "warning", "failed"]);
|
|
5472
|
+
var QualitySeveritySchema = import_zod34.z.enum(["info", "warning", "blocking"]);
|
|
5473
|
+
var ApplicationQualityIssueSchema = import_zod34.z.object({
|
|
5474
|
+
code: import_zod34.z.string(),
|
|
5022
5475
|
severity: QualitySeveritySchema,
|
|
5023
|
-
message:
|
|
5024
|
-
fieldId:
|
|
5476
|
+
message: import_zod34.z.string(),
|
|
5477
|
+
fieldId: import_zod34.z.string().optional()
|
|
5025
5478
|
});
|
|
5026
|
-
var ApplicationQualityRoundSchema =
|
|
5027
|
-
round:
|
|
5028
|
-
kind:
|
|
5479
|
+
var ApplicationQualityRoundSchema = import_zod34.z.object({
|
|
5480
|
+
round: import_zod34.z.number(),
|
|
5481
|
+
kind: import_zod34.z.string(),
|
|
5029
5482
|
status: QualityGateStatusSchema,
|
|
5030
|
-
summary:
|
|
5483
|
+
summary: import_zod34.z.string().optional()
|
|
5031
5484
|
});
|
|
5032
|
-
var ApplicationQualityArtifactSchema =
|
|
5033
|
-
kind:
|
|
5034
|
-
label:
|
|
5035
|
-
itemCount:
|
|
5485
|
+
var ApplicationQualityArtifactSchema = import_zod34.z.object({
|
|
5486
|
+
kind: import_zod34.z.string(),
|
|
5487
|
+
label: import_zod34.z.string().optional(),
|
|
5488
|
+
itemCount: import_zod34.z.number().optional()
|
|
5036
5489
|
});
|
|
5037
|
-
var ApplicationEmailReviewSchema =
|
|
5038
|
-
issues:
|
|
5490
|
+
var ApplicationEmailReviewSchema = import_zod34.z.object({
|
|
5491
|
+
issues: import_zod34.z.array(ApplicationQualityIssueSchema),
|
|
5039
5492
|
qualityGateStatus: QualityGateStatusSchema
|
|
5040
5493
|
});
|
|
5041
|
-
var ApplicationQualityReportSchema =
|
|
5042
|
-
issues:
|
|
5043
|
-
rounds:
|
|
5044
|
-
artifacts:
|
|
5494
|
+
var ApplicationQualityReportSchema = import_zod34.z.object({
|
|
5495
|
+
issues: import_zod34.z.array(ApplicationQualityIssueSchema),
|
|
5496
|
+
rounds: import_zod34.z.array(ApplicationQualityRoundSchema).optional(),
|
|
5497
|
+
artifacts: import_zod34.z.array(ApplicationQualityArtifactSchema).optional(),
|
|
5045
5498
|
emailReview: ApplicationEmailReviewSchema.optional(),
|
|
5046
5499
|
qualityGateStatus: QualityGateStatusSchema
|
|
5047
5500
|
});
|
|
5048
|
-
var ApplicationStateSchema =
|
|
5049
|
-
id:
|
|
5050
|
-
pdfBase64:
|
|
5051
|
-
title:
|
|
5052
|
-
applicationType:
|
|
5053
|
-
fields:
|
|
5054
|
-
batches:
|
|
5055
|
-
currentBatchIndex:
|
|
5501
|
+
var ApplicationStateSchema = import_zod34.z.object({
|
|
5502
|
+
id: import_zod34.z.string(),
|
|
5503
|
+
pdfBase64: import_zod34.z.string().optional().describe("Original PDF, omitted after extraction"),
|
|
5504
|
+
title: import_zod34.z.string().optional(),
|
|
5505
|
+
applicationType: import_zod34.z.string().nullable().optional(),
|
|
5506
|
+
fields: import_zod34.z.array(ApplicationFieldSchema),
|
|
5507
|
+
batches: import_zod34.z.array(import_zod34.z.array(import_zod34.z.string())).optional(),
|
|
5508
|
+
currentBatchIndex: import_zod34.z.number().default(0),
|
|
5056
5509
|
qualityReport: ApplicationQualityReportSchema.optional(),
|
|
5057
|
-
status:
|
|
5058
|
-
createdAt:
|
|
5059
|
-
updatedAt:
|
|
5510
|
+
status: import_zod34.z.enum(["classifying", "extracting", "auto_filling", "batching", "collecting", "confirming", "mapping", "complete"]),
|
|
5511
|
+
createdAt: import_zod34.z.number(),
|
|
5512
|
+
updatedAt: import_zod34.z.number()
|
|
5060
5513
|
});
|
|
5061
5514
|
|
|
5062
5515
|
// src/application/agents/classifier.ts
|
|
@@ -6126,7 +6579,7 @@ Respond with the explanation text only \u2014 no JSON, no field ID, no extra for
|
|
|
6126
6579
|
}
|
|
6127
6580
|
|
|
6128
6581
|
// src/prompts/query/classify.ts
|
|
6129
|
-
function buildQueryClassifyPrompt(question, conversationContext) {
|
|
6582
|
+
function buildQueryClassifyPrompt(question, conversationContext, attachmentContext) {
|
|
6130
6583
|
return `You are a query classifier for an insurance document intelligence system.
|
|
6131
6584
|
|
|
6132
6585
|
Analyze the user's question and produce a structured classification.
|
|
@@ -6136,6 +6589,9 @@ ${question}
|
|
|
6136
6589
|
${conversationContext ? `
|
|
6137
6590
|
CONVERSATION CONTEXT:
|
|
6138
6591
|
${conversationContext}` : ""}
|
|
6592
|
+
${attachmentContext ? `
|
|
6593
|
+
ATTACHMENT CONTEXT:
|
|
6594
|
+
${attachmentContext}` : ""}
|
|
6139
6595
|
|
|
6140
6596
|
INSTRUCTIONS:
|
|
6141
6597
|
|
|
@@ -6156,6 +6612,7 @@ INSTRUCTIONS:
|
|
|
6156
6612
|
- requiresDocumentLookup: true if a specific document needs to be fetched by ID/number/carrier
|
|
6157
6613
|
- requiresChunkSearch: true if semantic search over document chunks is needed
|
|
6158
6614
|
- requiresConversationHistory: true if the question references prior conversation
|
|
6615
|
+
- If the user's attachment already contains critical facts, still request chunk/document lookup when policy or quote details should be cross-checked against stored records
|
|
6159
6616
|
|
|
6160
6617
|
CHUNK TYPES (for chunkTypes filter):
|
|
6161
6618
|
carrier_info, named_insured, coverage, endorsement, exclusion, condition, section, declaration, loss_history, premium, supplementary
|
|
@@ -6189,73 +6646,90 @@ Respond with the final answer, deduplicated citations array, overall confidence
|
|
|
6189
6646
|
}
|
|
6190
6647
|
|
|
6191
6648
|
// src/schemas/query.ts
|
|
6192
|
-
var
|
|
6193
|
-
var QueryIntentSchema =
|
|
6649
|
+
var import_zod35 = require("zod");
|
|
6650
|
+
var QueryIntentSchema = import_zod35.z.enum([
|
|
6194
6651
|
"policy_question",
|
|
6195
6652
|
"coverage_comparison",
|
|
6196
6653
|
"document_search",
|
|
6197
6654
|
"claims_inquiry",
|
|
6198
6655
|
"general_knowledge"
|
|
6199
6656
|
]);
|
|
6200
|
-
var
|
|
6201
|
-
|
|
6657
|
+
var QueryAttachmentKindSchema = import_zod35.z.enum(["image", "pdf", "text"]);
|
|
6658
|
+
var QueryAttachmentSchema = import_zod35.z.object({
|
|
6659
|
+
id: import_zod35.z.string().optional().describe("Optional stable attachment ID from the caller"),
|
|
6660
|
+
kind: QueryAttachmentKindSchema,
|
|
6661
|
+
name: import_zod35.z.string().optional().describe("Original filename or user-facing label"),
|
|
6662
|
+
mimeType: import_zod35.z.string().optional().describe("MIME type such as image/jpeg or application/pdf"),
|
|
6663
|
+
base64: import_zod35.z.string().optional().describe("Base64-encoded file content for image/pdf attachments"),
|
|
6664
|
+
text: import_zod35.z.string().optional().describe("Plain-text attachment content when available"),
|
|
6665
|
+
description: import_zod35.z.string().optional().describe("Caller-provided description of the attachment")
|
|
6666
|
+
});
|
|
6667
|
+
var SubQuestionSchema = import_zod35.z.object({
|
|
6668
|
+
question: import_zod35.z.string().describe("Atomic sub-question to retrieve and answer independently"),
|
|
6202
6669
|
intent: QueryIntentSchema,
|
|
6203
|
-
chunkTypes:
|
|
6204
|
-
documentFilters:
|
|
6205
|
-
type:
|
|
6206
|
-
carrier:
|
|
6207
|
-
insuredName:
|
|
6208
|
-
policyNumber:
|
|
6209
|
-
quoteNumber:
|
|
6670
|
+
chunkTypes: import_zod35.z.array(import_zod35.z.string()).optional().describe("Chunk types to filter retrieval (e.g. coverage, endorsement, declaration)"),
|
|
6671
|
+
documentFilters: import_zod35.z.object({
|
|
6672
|
+
type: import_zod35.z.enum(["policy", "quote"]).optional(),
|
|
6673
|
+
carrier: import_zod35.z.string().optional(),
|
|
6674
|
+
insuredName: import_zod35.z.string().optional(),
|
|
6675
|
+
policyNumber: import_zod35.z.string().optional(),
|
|
6676
|
+
quoteNumber: import_zod35.z.string().optional()
|
|
6210
6677
|
}).optional().describe("Structured filters to narrow document lookup")
|
|
6211
6678
|
});
|
|
6212
|
-
var QueryClassifyResultSchema =
|
|
6679
|
+
var QueryClassifyResultSchema = import_zod35.z.object({
|
|
6213
6680
|
intent: QueryIntentSchema,
|
|
6214
|
-
subQuestions:
|
|
6215
|
-
requiresDocumentLookup:
|
|
6216
|
-
requiresChunkSearch:
|
|
6217
|
-
requiresConversationHistory:
|
|
6681
|
+
subQuestions: import_zod35.z.array(SubQuestionSchema).min(1).describe("Decomposed atomic sub-questions"),
|
|
6682
|
+
requiresDocumentLookup: import_zod35.z.boolean().describe("Whether structured document lookup is needed"),
|
|
6683
|
+
requiresChunkSearch: import_zod35.z.boolean().describe("Whether semantic chunk search is needed"),
|
|
6684
|
+
requiresConversationHistory: import_zod35.z.boolean().describe("Whether conversation history is relevant")
|
|
6218
6685
|
});
|
|
6219
|
-
var EvidenceItemSchema =
|
|
6220
|
-
source:
|
|
6221
|
-
chunkId:
|
|
6222
|
-
documentId:
|
|
6223
|
-
turnId:
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6686
|
+
var EvidenceItemSchema = import_zod35.z.object({
|
|
6687
|
+
source: import_zod35.z.enum(["chunk", "document", "conversation", "attachment"]),
|
|
6688
|
+
chunkId: import_zod35.z.string().optional(),
|
|
6689
|
+
documentId: import_zod35.z.string().optional(),
|
|
6690
|
+
turnId: import_zod35.z.string().optional(),
|
|
6691
|
+
attachmentId: import_zod35.z.string().optional(),
|
|
6692
|
+
text: import_zod35.z.string().describe("Text excerpt from the source"),
|
|
6693
|
+
relevance: import_zod35.z.number().min(0).max(1),
|
|
6694
|
+
metadata: import_zod35.z.array(import_zod35.z.object({ key: import_zod35.z.string(), value: import_zod35.z.string() })).optional()
|
|
6227
6695
|
});
|
|
6228
|
-
var
|
|
6229
|
-
|
|
6230
|
-
|
|
6696
|
+
var AttachmentInterpretationSchema = import_zod35.z.object({
|
|
6697
|
+
summary: import_zod35.z.string().describe("Concise summary of what the attachment shows or contains"),
|
|
6698
|
+
extractedFacts: import_zod35.z.array(import_zod35.z.string()).describe("Specific observable or document facts grounded in the attachment"),
|
|
6699
|
+
recommendedFocus: import_zod35.z.array(import_zod35.z.string()).describe("Important details to incorporate when answering follow-up questions"),
|
|
6700
|
+
confidence: import_zod35.z.number().min(0).max(1)
|
|
6231
6701
|
});
|
|
6232
|
-
var
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
documentId: import_zod34.z.string(),
|
|
6236
|
-
documentType: import_zod34.z.enum(["policy", "quote"]).optional(),
|
|
6237
|
-
field: import_zod34.z.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
|
|
6238
|
-
quote: import_zod34.z.string().describe("Exact text from source that supports the claim"),
|
|
6239
|
-
relevance: import_zod34.z.number().min(0).max(1)
|
|
6702
|
+
var RetrievalResultSchema = import_zod35.z.object({
|
|
6703
|
+
subQuestion: import_zod35.z.string(),
|
|
6704
|
+
evidence: import_zod35.z.array(EvidenceItemSchema)
|
|
6240
6705
|
});
|
|
6241
|
-
var
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6706
|
+
var CitationSchema = import_zod35.z.object({
|
|
6707
|
+
index: import_zod35.z.number().describe("Citation number [1], [2], etc."),
|
|
6708
|
+
chunkId: import_zod35.z.string().describe("Source chunk ID, e.g. doc-123:coverage:2"),
|
|
6709
|
+
documentId: import_zod35.z.string(),
|
|
6710
|
+
documentType: import_zod35.z.enum(["policy", "quote"]).optional(),
|
|
6711
|
+
field: import_zod35.z.string().optional().describe("Specific field path, e.g. coverages[0].deductible"),
|
|
6712
|
+
quote: import_zod35.z.string().describe("Exact text from source that supports the claim"),
|
|
6713
|
+
relevance: import_zod35.z.number().min(0).max(1)
|
|
6247
6714
|
});
|
|
6248
|
-
var
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6715
|
+
var SubAnswerSchema = import_zod35.z.object({
|
|
6716
|
+
subQuestion: import_zod35.z.string(),
|
|
6717
|
+
answer: import_zod35.z.string(),
|
|
6718
|
+
citations: import_zod35.z.array(CitationSchema),
|
|
6719
|
+
confidence: import_zod35.z.number().min(0).max(1),
|
|
6720
|
+
needsMoreContext: import_zod35.z.boolean().describe("True if evidence was insufficient to answer fully")
|
|
6252
6721
|
});
|
|
6253
|
-
var
|
|
6254
|
-
|
|
6255
|
-
|
|
6722
|
+
var VerifyResultSchema = import_zod35.z.object({
|
|
6723
|
+
approved: import_zod35.z.boolean().describe("Whether all sub-answers are adequately grounded"),
|
|
6724
|
+
issues: import_zod35.z.array(import_zod35.z.string()).describe("Specific grounding or consistency issues found"),
|
|
6725
|
+
retrySubQuestions: import_zod35.z.array(import_zod35.z.string()).optional().describe("Sub-questions that need additional retrieval or re-reasoning")
|
|
6726
|
+
});
|
|
6727
|
+
var QueryResultSchema = import_zod35.z.object({
|
|
6728
|
+
answer: import_zod35.z.string(),
|
|
6729
|
+
citations: import_zod35.z.array(CitationSchema),
|
|
6256
6730
|
intent: QueryIntentSchema,
|
|
6257
|
-
confidence:
|
|
6258
|
-
followUp:
|
|
6731
|
+
confidence: import_zod35.z.number().min(0).max(1),
|
|
6732
|
+
followUp: import_zod35.z.string().optional().describe("Suggested follow-up question if applicable")
|
|
6259
6733
|
});
|
|
6260
6734
|
|
|
6261
6735
|
// src/query/retriever.ts
|
|
@@ -6545,7 +7019,7 @@ async function verify(originalQuestion, subAnswers, allEvidence, config) {
|
|
|
6545
7019
|
|
|
6546
7020
|
// src/query/quality.ts
|
|
6547
7021
|
function sourceIdForEvidence(evidence) {
|
|
6548
|
-
return evidence.chunkId ?? evidence.documentId ?? evidence.turnId;
|
|
7022
|
+
return evidence.chunkId ?? evidence.documentId ?? evidence.turnId ?? evidence.attachmentId;
|
|
6549
7023
|
}
|
|
6550
7024
|
function citationSourceId(citation) {
|
|
6551
7025
|
return citation.chunkId || citation.documentId;
|
|
@@ -6649,6 +7123,152 @@ function buildQueryReviewReport(params) {
|
|
|
6649
7123
|
};
|
|
6650
7124
|
}
|
|
6651
7125
|
|
|
7126
|
+
// src/prompts/query/interpret-attachment.ts
|
|
7127
|
+
function buildInterpretAttachmentPrompt(question, attachment) {
|
|
7128
|
+
const attachmentLabel = attachment.name ?? attachment.id ?? "attachment";
|
|
7129
|
+
const descriptor = [
|
|
7130
|
+
`Attachment: ${attachmentLabel}`,
|
|
7131
|
+
`Kind: ${attachment.kind}`,
|
|
7132
|
+
attachment.mimeType ? `MIME type: ${attachment.mimeType}` : null,
|
|
7133
|
+
attachment.description ? `Caller description: ${attachment.description}` : null
|
|
7134
|
+
].filter(Boolean).join("\n");
|
|
7135
|
+
return `You are interpreting a user-supplied attachment for an insurance-support question.
|
|
7136
|
+
|
|
7137
|
+
USER QUESTION:
|
|
7138
|
+
${question}
|
|
7139
|
+
|
|
7140
|
+
ATTACHMENT METADATA:
|
|
7141
|
+
${descriptor}
|
|
7142
|
+
|
|
7143
|
+
${attachment.kind === "text" && attachment.text ? `ATTACHMENT TEXT:
|
|
7144
|
+
${attachment.text}
|
|
7145
|
+
` : "The attachment content is provided separately as a file or image input.\n"}
|
|
7146
|
+
INSTRUCTIONS:
|
|
7147
|
+
1. Describe what the attachment appears to show or contain in a concise summary.
|
|
7148
|
+
2. Extract concrete facts that may matter when answering the user's question.
|
|
7149
|
+
3. Note the most important details to carry forward into follow-up questions.
|
|
7150
|
+
4. If the attachment is a document, identify the key business or insurance details visible.
|
|
7151
|
+
5. If the attachment is a photo of damage or a real-world issue, describe the observable issue without guessing beyond what is visible.
|
|
7152
|
+
6. Do not invent unreadable text. If something is unclear, say so in the summary or extracted facts.
|
|
7153
|
+
|
|
7154
|
+
Respond with the structured interpretation.`;
|
|
7155
|
+
}
|
|
7156
|
+
|
|
7157
|
+
// src/query/multimodal.ts
|
|
7158
|
+
function attachmentSourceId(attachment, index) {
|
|
7159
|
+
return attachment.id ?? `attachment-${index + 1}`;
|
|
7160
|
+
}
|
|
7161
|
+
function buildAttachmentProviderOptions(attachment, providerOptions) {
|
|
7162
|
+
const merged = {
|
|
7163
|
+
...providerOptions,
|
|
7164
|
+
attachments: [
|
|
7165
|
+
{
|
|
7166
|
+
kind: attachment.kind,
|
|
7167
|
+
name: attachment.name,
|
|
7168
|
+
mimeType: attachment.mimeType,
|
|
7169
|
+
base64: attachment.base64,
|
|
7170
|
+
text: attachment.text,
|
|
7171
|
+
description: attachment.description
|
|
7172
|
+
}
|
|
7173
|
+
]
|
|
7174
|
+
};
|
|
7175
|
+
if (attachment.kind === "pdf" && attachment.base64) {
|
|
7176
|
+
merged.pdfBase64 = attachment.base64;
|
|
7177
|
+
}
|
|
7178
|
+
if (attachment.kind === "image" && attachment.base64) {
|
|
7179
|
+
merged.images = [
|
|
7180
|
+
{
|
|
7181
|
+
imageBase64: attachment.base64,
|
|
7182
|
+
mimeType: attachment.mimeType ?? "image/jpeg"
|
|
7183
|
+
}
|
|
7184
|
+
];
|
|
7185
|
+
}
|
|
7186
|
+
return merged;
|
|
7187
|
+
}
|
|
7188
|
+
function buildAttachmentEvidenceText(attachment, interpretation) {
|
|
7189
|
+
const lines = [
|
|
7190
|
+
`Attachment kind: ${attachment.kind}`,
|
|
7191
|
+
attachment.name ? `Attachment name: ${attachment.name}` : null,
|
|
7192
|
+
attachment.mimeType ? `MIME type: ${attachment.mimeType}` : null,
|
|
7193
|
+
attachment.description ? `Caller description: ${attachment.description}` : null,
|
|
7194
|
+
`Summary: ${interpretation.summary}`,
|
|
7195
|
+
interpretation.extractedFacts.length > 0 ? `Extracted facts:
|
|
7196
|
+
${interpretation.extractedFacts.map((fact) => `- ${fact}`).join("\n")}` : null,
|
|
7197
|
+
interpretation.recommendedFocus.length > 0 ? `Important follow-up details:
|
|
7198
|
+
${interpretation.recommendedFocus.map((item) => `- ${item}`).join("\n")}` : null,
|
|
7199
|
+
attachment.kind === "text" && attachment.text ? `Original text:
|
|
7200
|
+
${attachment.text}` : null
|
|
7201
|
+
];
|
|
7202
|
+
return lines.filter(Boolean).join("\n");
|
|
7203
|
+
}
|
|
7204
|
+
async function interpretAttachments(params) {
|
|
7205
|
+
const { attachments = [], question, generateObject, providerOptions, log, onUsage } = params;
|
|
7206
|
+
if (attachments.length === 0) {
|
|
7207
|
+
return { evidence: [] };
|
|
7208
|
+
}
|
|
7209
|
+
const evidence = [];
|
|
7210
|
+
for (const [index, attachment] of attachments.entries()) {
|
|
7211
|
+
const id = attachmentSourceId(attachment, index);
|
|
7212
|
+
if (attachment.kind === "text" && attachment.text) {
|
|
7213
|
+
const textEvidence = buildAttachmentEvidenceText(attachment, {
|
|
7214
|
+
summary: attachment.description ?? "User supplied text context.",
|
|
7215
|
+
extractedFacts: [attachment.text],
|
|
7216
|
+
recommendedFocus: [],
|
|
7217
|
+
confidence: 1
|
|
7218
|
+
});
|
|
7219
|
+
evidence.push({
|
|
7220
|
+
source: "attachment",
|
|
7221
|
+
attachmentId: id,
|
|
7222
|
+
chunkId: id,
|
|
7223
|
+
documentId: id,
|
|
7224
|
+
text: textEvidence,
|
|
7225
|
+
relevance: 0.95,
|
|
7226
|
+
metadata: [
|
|
7227
|
+
{ key: "kind", value: attachment.kind },
|
|
7228
|
+
...attachment.name ? [{ key: "name", value: attachment.name }] : []
|
|
7229
|
+
]
|
|
7230
|
+
});
|
|
7231
|
+
continue;
|
|
7232
|
+
}
|
|
7233
|
+
const prompt = buildInterpretAttachmentPrompt(question, attachment);
|
|
7234
|
+
const { object, usage } = await safeGenerateObject(
|
|
7235
|
+
generateObject,
|
|
7236
|
+
{
|
|
7237
|
+
prompt,
|
|
7238
|
+
schema: AttachmentInterpretationSchema,
|
|
7239
|
+
maxTokens: 2048,
|
|
7240
|
+
providerOptions: buildAttachmentProviderOptions(attachment, providerOptions)
|
|
7241
|
+
},
|
|
7242
|
+
{
|
|
7243
|
+
fallback: {
|
|
7244
|
+
summary: attachment.description ?? `User supplied ${attachment.kind} attachment.`,
|
|
7245
|
+
extractedFacts: [],
|
|
7246
|
+
recommendedFocus: [],
|
|
7247
|
+
confidence: 0.2
|
|
7248
|
+
},
|
|
7249
|
+
log,
|
|
7250
|
+
onError: (error, attempt) => log?.(`Attachment interpretation attempt ${attempt + 1} failed for "${attachment.name ?? id}": ${error}`)
|
|
7251
|
+
}
|
|
7252
|
+
);
|
|
7253
|
+
onUsage?.(usage);
|
|
7254
|
+
evidence.push({
|
|
7255
|
+
source: "attachment",
|
|
7256
|
+
attachmentId: id,
|
|
7257
|
+
chunkId: id,
|
|
7258
|
+
documentId: id,
|
|
7259
|
+
text: buildAttachmentEvidenceText(attachment, object),
|
|
7260
|
+
relevance: Math.max(0.7, object.confidence),
|
|
7261
|
+
metadata: [
|
|
7262
|
+
{ key: "kind", value: attachment.kind },
|
|
7263
|
+
...attachment.name ? [{ key: "name", value: attachment.name }] : []
|
|
7264
|
+
]
|
|
7265
|
+
});
|
|
7266
|
+
}
|
|
7267
|
+
const contextSummary = evidence.map((item, index) => `Attachment ${index + 1}:
|
|
7268
|
+
${item.text}`).join("\n\n");
|
|
7269
|
+
return { evidence, contextSummary };
|
|
7270
|
+
}
|
|
7271
|
+
|
|
6652
7272
|
// src/query/coordinator.ts
|
|
6653
7273
|
function createQueryAgent(config) {
|
|
6654
7274
|
const {
|
|
@@ -6676,13 +7296,23 @@ function createQueryAgent(config) {
|
|
|
6676
7296
|
}
|
|
6677
7297
|
async function query(input) {
|
|
6678
7298
|
totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
6679
|
-
const { question, conversationId, context } = input;
|
|
7299
|
+
const { question, conversationId, context, attachments } = input;
|
|
6680
7300
|
const pipelineCtx = createPipelineContext({
|
|
6681
7301
|
id: `query-${Date.now()}`
|
|
6682
7302
|
});
|
|
7303
|
+
onProgress?.("Interpreting attachments...");
|
|
7304
|
+
const { evidence: attachmentEvidence, contextSummary: attachmentContext } = await interpretAttachments({
|
|
7305
|
+
attachments,
|
|
7306
|
+
question,
|
|
7307
|
+
generateObject,
|
|
7308
|
+
providerOptions,
|
|
7309
|
+
log,
|
|
7310
|
+
onUsage: trackUsage
|
|
7311
|
+
});
|
|
7312
|
+
await pipelineCtx.save("attachments", { attachmentEvidence });
|
|
6683
7313
|
onProgress?.("Classifying query...");
|
|
6684
|
-
const classification = await classify(question, conversationId);
|
|
6685
|
-
await pipelineCtx.save("classify", { classification });
|
|
7314
|
+
const classification = await classify(question, conversationId, attachmentContext);
|
|
7315
|
+
await pipelineCtx.save("classify", { classification, attachmentEvidence });
|
|
6686
7316
|
onProgress?.(`Retrieving evidence for ${classification.subQuestions.length} sub-question(s)...`);
|
|
6687
7317
|
const retrieverConfig = {
|
|
6688
7318
|
documentStore,
|
|
@@ -6695,8 +7325,8 @@ function createQueryAgent(config) {
|
|
|
6695
7325
|
(sq) => limit(() => retrieve(sq, conversationId, retrieverConfig))
|
|
6696
7326
|
)
|
|
6697
7327
|
);
|
|
6698
|
-
const allEvidence = retrievalResults.flatMap((r) => r.evidence);
|
|
6699
|
-
await pipelineCtx.save("retrieve", { classification, evidence: allEvidence });
|
|
7328
|
+
const allEvidence = [...attachmentEvidence, ...retrievalResults.flatMap((r) => r.evidence)];
|
|
7329
|
+
await pipelineCtx.save("retrieve", { classification, attachmentEvidence, evidence: allEvidence });
|
|
6700
7330
|
onProgress?.("Reasoning over evidence...");
|
|
6701
7331
|
const reasonerConfig = { generateObject, providerOptions };
|
|
6702
7332
|
const reasonResults = await Promise.allSettled(
|
|
@@ -6705,7 +7335,7 @@ function createQueryAgent(config) {
|
|
|
6705
7335
|
const { subAnswer, usage } = await reason(
|
|
6706
7336
|
sq.question,
|
|
6707
7337
|
sq.intent,
|
|
6708
|
-
retrievalResults[i].evidence,
|
|
7338
|
+
[...attachmentEvidence, ...retrievalResults[i].evidence],
|
|
6709
7339
|
reasonerConfig
|
|
6710
7340
|
);
|
|
6711
7341
|
trackUsage(usage);
|
|
@@ -6729,7 +7359,7 @@ function createQueryAgent(config) {
|
|
|
6729
7359
|
});
|
|
6730
7360
|
}
|
|
6731
7361
|
}
|
|
6732
|
-
await pipelineCtx.save("reason", { classification, evidence: allEvidence, subAnswers });
|
|
7362
|
+
await pipelineCtx.save("reason", { classification, attachmentEvidence, evidence: allEvidence, subAnswers });
|
|
6733
7363
|
onProgress?.("Verifying answer grounding...");
|
|
6734
7364
|
const verifierConfig = { generateObject, providerOptions };
|
|
6735
7365
|
const verifyRounds = [];
|
|
@@ -6777,7 +7407,7 @@ function createQueryAgent(config) {
|
|
|
6777
7407
|
const { subAnswer, usage: u } = await reason(
|
|
6778
7408
|
sq.question,
|
|
6779
7409
|
sq.intent,
|
|
6780
|
-
retryRetrievals[i].evidence,
|
|
7410
|
+
[...attachmentEvidence, ...retryRetrievals[i].evidence],
|
|
6781
7411
|
reasonerConfig
|
|
6782
7412
|
);
|
|
6783
7413
|
trackUsage(u);
|
|
@@ -6812,6 +7442,7 @@ function createQueryAgent(config) {
|
|
|
6812
7442
|
});
|
|
6813
7443
|
await pipelineCtx.save("review", {
|
|
6814
7444
|
classification,
|
|
7445
|
+
attachmentEvidence,
|
|
6815
7446
|
evidence: allEvidence,
|
|
6816
7447
|
subAnswers,
|
|
6817
7448
|
reviewReport
|
|
@@ -6844,7 +7475,7 @@ function createQueryAgent(config) {
|
|
|
6844
7475
|
}
|
|
6845
7476
|
return { ...queryResult, tokenUsage: totalUsage, reviewReport };
|
|
6846
7477
|
}
|
|
6847
|
-
async function classify(question, conversationId) {
|
|
7478
|
+
async function classify(question, conversationId, attachmentContext) {
|
|
6848
7479
|
let conversationContext;
|
|
6849
7480
|
if (conversationId) {
|
|
6850
7481
|
try {
|
|
@@ -6855,7 +7486,7 @@ function createQueryAgent(config) {
|
|
|
6855
7486
|
} catch {
|
|
6856
7487
|
}
|
|
6857
7488
|
}
|
|
6858
|
-
const prompt = buildQueryClassifyPrompt(question, conversationContext);
|
|
7489
|
+
const prompt = buildQueryClassifyPrompt(question, conversationContext, attachmentContext);
|
|
6859
7490
|
const { object, usage } = await safeGenerateObject(
|
|
6860
7491
|
generateObject,
|
|
6861
7492
|
{
|
|
@@ -7071,6 +7702,7 @@ var AGENT_TOOLS = [
|
|
|
7071
7702
|
ApplicationQualityReportSchema,
|
|
7072
7703
|
ApplicationQualityRoundSchema,
|
|
7073
7704
|
ApplicationStateSchema,
|
|
7705
|
+
AttachmentInterpretationSchema,
|
|
7074
7706
|
AuditTypeSchema,
|
|
7075
7707
|
AutoFillMatchSchema,
|
|
7076
7708
|
AutoFillResultSchema,
|
|
@@ -7192,6 +7824,8 @@ var AGENT_TOOLS = [
|
|
|
7192
7824
|
ProducerInfoSchema,
|
|
7193
7825
|
ProfessionalLiabilityDeclarationsSchema,
|
|
7194
7826
|
QUOTE_SECTION_TYPES,
|
|
7827
|
+
QueryAttachmentKindSchema,
|
|
7828
|
+
QueryAttachmentSchema,
|
|
7195
7829
|
QueryClassifyResultSchema,
|
|
7196
7830
|
QueryIntentSchema,
|
|
7197
7831
|
QueryResultSchema,
|
|
@@ -7250,6 +7884,7 @@ var AGENT_TOOLS = [
|
|
|
7250
7884
|
buildFormattingPrompt,
|
|
7251
7885
|
buildIdentityPrompt,
|
|
7252
7886
|
buildIntentPrompt,
|
|
7887
|
+
buildInterpretAttachmentPrompt,
|
|
7253
7888
|
buildLookupFillPrompt,
|
|
7254
7889
|
buildQueryClassifyPrompt,
|
|
7255
7890
|
buildQuestionBatchPrompt,
|