@land-catalyst/batch-data-sdk 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builders/builders.js +0 -1
- package/dist/property-field/metadata.js +1 -1
- package/dist/property-field/search-criteria-ai-context.d.ts +4 -1
- package/dist/property-field/search-criteria-ai-context.js +86 -25
- package/dist/property-field/search-criteria-filter-context.d.ts +1 -1
- package/dist/property-field/search-criteria-filter-context.js +32 -3
- package/package.json +1 -1
|
@@ -89,7 +89,6 @@ class BaseBuilder {
|
|
|
89
89
|
*/
|
|
90
90
|
getSearchCriteriaFieldMetadata(searchCriteriaPath) {
|
|
91
91
|
// Dynamic import to avoid circular dependency
|
|
92
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
93
92
|
const { getSearchCriteriaFieldMetadata, } = require("../property-field/utils");
|
|
94
93
|
return getSearchCriteriaFieldMetadata(searchCriteriaPath);
|
|
95
94
|
}
|
|
@@ -2555,7 +2555,7 @@ exports.PROPERTY_FIELD_METADATA = {
|
|
|
2555
2555
|
resourceSubGroupName: undefined,
|
|
2556
2556
|
name: "salePropensity",
|
|
2557
2557
|
dataType: "number",
|
|
2558
|
-
description: "
|
|
2558
|
+
description: "sale propensity score (0-100). This is a highly impactful automated value metric (AVM) that predicts the likelihood that a property will go on market and sell. Higher scores indicate higher likelihood. This is one of the most valuable predictive indicators for identifying properties likely to be listed soon. Use min values to target high-propensity properties (e.g., min: 70 for very high likelihood, min: 80 for extremely high likelihood).",
|
|
2559
2559
|
isArrayElement: false,
|
|
2560
2560
|
},
|
|
2561
2561
|
"intel.salePropensityStatus": {
|
|
@@ -30,7 +30,7 @@ export declare const SEARCH_CRITERIA_DOMAINS: SearchCriteriaDomain[];
|
|
|
30
30
|
* Array of all valid SearchCriteria domain names (for autocomplete)
|
|
31
31
|
* Using `as const` preserves literal types for better IDE autocomplete
|
|
32
32
|
*/
|
|
33
|
-
export declare const SEARCH_CRITERIA_DOMAIN_NAMES: readonly ["query", "address", "assessment", "building", "lot", "owner", "sale", "tax", "valuation", "listing", "openLien", "foreclosure", "quickList"];
|
|
33
|
+
export declare const SEARCH_CRITERIA_DOMAIN_NAMES: readonly ["query", "address", "assessment", "building", "lot", "owner", "sale", "tax", "valuation", "listing", "openLien", "foreclosure", "intel", "demographics", "general", "ids", "involuntaryLien", "legal", "permit", "propertyOwnerProfile", "quickList"];
|
|
34
34
|
/**
|
|
35
35
|
* Type representing valid SearchCriteria domain names
|
|
36
36
|
* This union type provides better autocomplete in IDEs
|
|
@@ -113,5 +113,8 @@ export declare function getDomainContext(domainName: string, options?: SearchCri
|
|
|
113
113
|
* @param userPrompt The user's natural language prompt
|
|
114
114
|
* @param existingCriteria Optional existing search criteria to modify
|
|
115
115
|
* @returns Formatted user prompt string
|
|
116
|
+
* @deprecated This function is kept for backward compatibility but is no longer needed.
|
|
117
|
+
* The service should format the user prompt and existing criteria directly.
|
|
118
|
+
* The system prompt already describes the expected input and output format.
|
|
116
119
|
*/
|
|
117
120
|
export declare function buildSearchCriteriaUserPrompt(userPrompt: string, existingCriteria?: unknown): string;
|
|
@@ -75,6 +75,46 @@ exports.SEARCH_CRITERIA_DOMAINS = [
|
|
|
75
75
|
responseGroup: "foreclosure",
|
|
76
76
|
description: "Foreclosure status and auction information",
|
|
77
77
|
},
|
|
78
|
+
{
|
|
79
|
+
name: "intel",
|
|
80
|
+
responseGroup: "intel",
|
|
81
|
+
description: "Intelligence and predictive analytics (sale propensity, last sold information)",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "demographics",
|
|
85
|
+
responseGroup: "demographics",
|
|
86
|
+
description: "Demographic information about property owners (age, income, net worth, household size, etc.)",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "general",
|
|
90
|
+
responseGroup: "general",
|
|
91
|
+
description: "General property type and category filters",
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "ids",
|
|
95
|
+
responseGroup: "ids",
|
|
96
|
+
description: "Property identifiers (APN, tax ID, FIPS code, address hash, etc.)",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "involuntaryLien",
|
|
100
|
+
responseGroup: "involuntaryLien",
|
|
101
|
+
description: "Involuntary lien information (liens recorded against the property)",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "legal",
|
|
105
|
+
responseGroup: "legal",
|
|
106
|
+
description: "Legal information (subdivision name, etc.)",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "permit",
|
|
110
|
+
responseGroup: "permit",
|
|
111
|
+
description: "Building permit information (permit count, dates, job values, etc.)",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "propertyOwnerProfile",
|
|
115
|
+
responseGroup: "propertyOwnerProfile",
|
|
116
|
+
description: "Property owner profile information (total properties owned, equity, mortgages, etc.)",
|
|
117
|
+
},
|
|
78
118
|
{
|
|
79
119
|
name: "quickList",
|
|
80
120
|
responseGroup: "quickList",
|
|
@@ -98,6 +138,14 @@ exports.SEARCH_CRITERIA_DOMAIN_NAMES = [
|
|
|
98
138
|
"listing",
|
|
99
139
|
"openLien",
|
|
100
140
|
"foreclosure",
|
|
141
|
+
"intel",
|
|
142
|
+
"demographics",
|
|
143
|
+
"general",
|
|
144
|
+
"ids",
|
|
145
|
+
"involuntaryLien",
|
|
146
|
+
"legal",
|
|
147
|
+
"permit",
|
|
148
|
+
"propertyOwnerProfile",
|
|
101
149
|
"quickList",
|
|
102
150
|
];
|
|
103
151
|
/**
|
|
@@ -167,6 +215,7 @@ FILTER TYPES:
|
|
|
167
215
|
- StringFilter: { equals?, contains?, startsWith?, endsWith?, inList?, matches? }
|
|
168
216
|
- NumericRangeFilter: { min?, max? }
|
|
169
217
|
- DateRangeFilter: { minDate?, maxDate? }
|
|
218
|
+
- BooleanFilter: { equals: boolean }
|
|
170
219
|
- GeoLocationDistance: { latitude, longitude, distanceMiles }
|
|
171
220
|
- GeoLocationBoundingBox: { minLat, maxLat, minLon, maxLon }
|
|
172
221
|
- GeoLocationPolygon: { geoPoints: [{ latitude, longitude }] }
|
|
@@ -182,15 +231,42 @@ IMPORTANT RULES:
|
|
|
182
231
|
- "under $400,000" = assessment.totalMarketValue: {max: 400000}
|
|
183
232
|
- "over $500,000" = assessment.totalMarketValue: {min: 500000}
|
|
184
233
|
- "built after 2010" = building.yearBuilt: {min: 2010}
|
|
234
|
+
- "last sold after 2015" = sale.lastSaleDate: {minDate: "2016-01-01"} (use next year's January 1st for "after [year]")
|
|
185
235
|
5. Extract geographic information and populate both query and address filters appropriately
|
|
186
236
|
6. Only include domains that are clearly relevant to the prompt
|
|
187
237
|
7. If modifying existing criteria, merge intelligently - update what's mentioned, keep what's not
|
|
188
238
|
|
|
239
|
+
INPUT FORMAT:
|
|
240
|
+
You will receive:
|
|
241
|
+
1. A user prompt in natural language describing the property search criteria they want
|
|
242
|
+
2. Optionally, existing search criteria in JSON format that should be modified
|
|
243
|
+
|
|
244
|
+
RESPONSE FORMAT:
|
|
189
245
|
Return your response as a JSON array. Each object should have:
|
|
190
246
|
- searchCriteria: The complete SearchCriteria object
|
|
191
247
|
- description: A natural language description of what this search criteria finds
|
|
192
248
|
|
|
193
|
-
If the prompt
|
|
249
|
+
IMPORTANT: Only return multiple objects if they represent DISTINCT, meaningfully different searches. Do not return duplicate or near-duplicate search criteria. If the prompt describes a single search, return a single object. If the prompt describes multiple distinct searches (e.g., "luxury homes in Scottsdale" AND "starter homes in Tempe"), return multiple objects.
|
|
250
|
+
|
|
251
|
+
Example response format:
|
|
252
|
+
[
|
|
253
|
+
{
|
|
254
|
+
"searchCriteria": {
|
|
255
|
+
"query": "Maricopa County, AZ",
|
|
256
|
+
"building": {
|
|
257
|
+
"bedroomCount": { "min": 3, "max": 3 },
|
|
258
|
+
"yearBuilt": { "min": 2000 }
|
|
259
|
+
},
|
|
260
|
+
"assessment": {
|
|
261
|
+
"totalMarketValue": { "max": 500000 }
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
"description": "3-bedroom homes built after 2000 in Maricopa County, Arizona, with a market value under $500,000"
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
|
|
268
|
+
If existing criteria is provided, merge intelligently - update fields mentioned in the prompt, preserve others.
|
|
269
|
+
Return only valid JSON, no markdown formatting or code blocks.`;
|
|
194
270
|
}
|
|
195
271
|
/**
|
|
196
272
|
* Get context documentation for a specific domain
|
|
@@ -322,30 +398,15 @@ function buildDomainDocumentation(domainNames, options = {}) {
|
|
|
322
398
|
* @param userPrompt The user's natural language prompt
|
|
323
399
|
* @param existingCriteria Optional existing search criteria to modify
|
|
324
400
|
* @returns Formatted user prompt string
|
|
401
|
+
* @deprecated This function is kept for backward compatibility but is no longer needed.
|
|
402
|
+
* The service should format the user prompt and existing criteria directly.
|
|
403
|
+
* The system prompt already describes the expected input and output format.
|
|
325
404
|
*/
|
|
326
405
|
function buildSearchCriteriaUserPrompt(userPrompt, existingCriteria) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
"bedroomCount": { "min": 3, "max": 3 },
|
|
334
|
-
"yearBuilt": { "min": 2000 }
|
|
335
|
-
},
|
|
336
|
-
"assessment": {
|
|
337
|
-
"totalMarketValue": { "max": 500000 }
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
"description": "3-bedroom homes built after 2000 in Maricopa County, Arizona, with a market value under $500,000"
|
|
341
|
-
}
|
|
342
|
-
]
|
|
343
|
-
|
|
344
|
-
${existingCriteria ? `\nEXISTING SEARCH CRITERIA TO MODIFY:\n${JSON.stringify(existingCriteria, null, 2)}\n\nModify the existing criteria based on the user's prompt. Merge intelligently - update fields mentioned in the prompt, preserve others.` : ""}
|
|
345
|
-
|
|
346
|
-
USER PROMPT:
|
|
347
|
-
${userPrompt}
|
|
348
|
-
|
|
349
|
-
Return only valid JSON, no markdown formatting or code blocks.`;
|
|
350
|
-
return basePrompt;
|
|
406
|
+
// Simple format - service can customize this as needed
|
|
407
|
+
let prompt = userPrompt;
|
|
408
|
+
if (existingCriteria) {
|
|
409
|
+
prompt = `EXISTING SEARCH CRITERIA TO MODIFY:\n${JSON.stringify(existingCriteria, null, 2)}\n\nModify the existing criteria based on the following prompt:\n\n${userPrompt}`;
|
|
410
|
+
}
|
|
411
|
+
return prompt;
|
|
351
412
|
}
|
|
@@ -8,7 +8,7 @@ import type { PropertyFieldMetadata } from "./metadata";
|
|
|
8
8
|
/**
|
|
9
9
|
* Filter type for a SearchCriteria field
|
|
10
10
|
*/
|
|
11
|
-
export type SearchCriteriaFilterType = "StringFilter" | "NumericRangeFilter" | "DateRangeFilter" | "QuickListValue";
|
|
11
|
+
export type SearchCriteriaFilterType = "StringFilter" | "NumericRangeFilter" | "DateRangeFilter" | "BooleanFilter" | "QuickListValue";
|
|
12
12
|
/**
|
|
13
13
|
* Context about how a SearchCriteria field should be filtered
|
|
14
14
|
*/
|
|
@@ -84,6 +84,7 @@ const SEARCH_CRITERIA_FILTER_TYPE_MAP = {
|
|
|
84
84
|
"demographics.homeownerRenter": "StringFilter",
|
|
85
85
|
"demographics.businessOwner": "StringFilter",
|
|
86
86
|
"demographics.gender": "StringFilter",
|
|
87
|
+
"demographics.hasChildren": "BooleanFilter",
|
|
87
88
|
"demographics.investments": "StringFilter",
|
|
88
89
|
"demographics.demographics": "StringFilter",
|
|
89
90
|
"demographics.religiousAffiliation": "StringFilter",
|
|
@@ -150,6 +151,7 @@ const SEARCH_CRITERIA_FILTER_TYPE_MAP = {
|
|
|
150
151
|
// Owner - mix
|
|
151
152
|
"owner.firstName": "StringFilter",
|
|
152
153
|
"owner.lastName": "StringFilter",
|
|
154
|
+
"owner.ownerOccupied": "BooleanFilter",
|
|
153
155
|
"owner.mailingStreet": "StringFilter",
|
|
154
156
|
"owner.mailingCity": "StringFilter",
|
|
155
157
|
"owner.mailingState": "StringFilter",
|
|
@@ -197,7 +199,9 @@ function getFilterGuidance(filterType) {
|
|
|
197
199
|
case "NumericRangeFilter":
|
|
198
200
|
return `Use NumericRangeFilter with: min (minimum value), max (maximum value), or both. Example: { min: 3, max: 5 } for "3-5 bedrooms" or { min: 2010 } for "built after 2010"`;
|
|
199
201
|
case "DateRangeFilter":
|
|
200
|
-
return `Use DateRangeFilter with: minDate (earliest date), maxDate (latest date), or both. Dates should be in ISO 8601 format (YYYY-MM-DD). Example: { minDate: "
|
|
202
|
+
return `Use DateRangeFilter with: minDate (earliest date), maxDate (latest date), or both. Dates should be in ISO 8601 format (YYYY-MM-DD). For "after [year]", use the next year's January 1st. Example: "last sold after 2015" = { minDate: "2016-01-01" }, "after 2020" = { minDate: "2021-01-01" }`;
|
|
203
|
+
case "BooleanFilter":
|
|
204
|
+
return `Use BooleanFilter with: { equals: boolean }. Example: { equals: true } for ownerOccupied or { equals: false } for hasChildren`;
|
|
201
205
|
case "QuickListValue":
|
|
202
206
|
return `Use a QuickListValue string. Can be prefixed with "not-" to exclude. Available as: quickList (single value), quickLists (array), orQuickLists (array for OR logic). Example: "owner-occupied" or "not-vacant"`;
|
|
203
207
|
default:
|
|
@@ -227,7 +231,17 @@ function getExamples(fieldPath, filterType, _propertyMetadata) {
|
|
|
227
231
|
}
|
|
228
232
|
break;
|
|
229
233
|
case "NumericRangeFilter":
|
|
230
|
-
if (fieldPath.includes("
|
|
234
|
+
if (fieldPath.includes("salePropensity")) {
|
|
235
|
+
// Sale propensity is a 0-100 score predicting likelihood to go on market and sell
|
|
236
|
+
// Higher scores = higher likelihood
|
|
237
|
+
examples.push("{ min: 70 } // Very high propensity (70-100) - properties most likely to list/sell soon");
|
|
238
|
+
examples.push("{ min: 80 } // Extremely high propensity (80-100) - highest likelihood properties");
|
|
239
|
+
examples.push("{ min: 50, max: 70 } // Medium-high propensity (50-70) - moderate likelihood");
|
|
240
|
+
examples.push("{ min: 60 } // High propensity (60-100) - good likelihood of listing/selling");
|
|
241
|
+
examples.push("{ min: 75, max: 100 } // Very high to maximum propensity range");
|
|
242
|
+
}
|
|
243
|
+
else if (fieldPath.includes("bedroom") ||
|
|
244
|
+
fieldPath.includes("bathroom")) {
|
|
231
245
|
examples.push("{ min: 3, max: 3 } // exactly 3");
|
|
232
246
|
examples.push("{ min: 3 } // at least 3");
|
|
233
247
|
examples.push("{ min: 3, max: 5 } // between 3 and 5");
|
|
@@ -247,8 +261,23 @@ function getExamples(fieldPath, filterType, _propertyMetadata) {
|
|
|
247
261
|
examples.push("{ min: 10, max: 50 }");
|
|
248
262
|
}
|
|
249
263
|
break;
|
|
264
|
+
case "BooleanFilter":
|
|
265
|
+
if (fieldPath.includes("ownerOccupied")) {
|
|
266
|
+
examples.push("{ equals: true } // owner-occupied properties");
|
|
267
|
+
examples.push("{ equals: false } // non-owner-occupied properties");
|
|
268
|
+
}
|
|
269
|
+
else if (fieldPath.includes("hasChildren")) {
|
|
270
|
+
examples.push("{ equals: true } // properties with children");
|
|
271
|
+
examples.push("{ equals: false } // properties without children");
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
examples.push("{ equals: true }");
|
|
275
|
+
examples.push("{ equals: false }");
|
|
276
|
+
}
|
|
277
|
+
break;
|
|
250
278
|
case "DateRangeFilter":
|
|
251
|
-
examples.push('{ minDate: "2020-01-01" } // after January 1, 2020');
|
|
279
|
+
examples.push('{ minDate: "2020-01-01" } // on or after January 1, 2020');
|
|
280
|
+
examples.push('{ minDate: "2016-01-01" } // last sold after 2015 (use next year for "after [year]")');
|
|
252
281
|
examples.push('{ maxDate: "2023-12-31" } // before December 31, 2023');
|
|
253
282
|
examples.push('{ minDate: "2020-01-01", maxDate: "2023-12-31" } // between dates');
|
|
254
283
|
break;
|
package/package.json
CHANGED