@land-catalyst/batch-data-sdk 1.2.5 → 1.2.6
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.
|
@@ -78,7 +78,7 @@ exports.SEARCH_CRITERIA_DOMAINS = [
|
|
|
78
78
|
{
|
|
79
79
|
name: "intel",
|
|
80
80
|
responseGroup: "intel",
|
|
81
|
-
description: "Intelligence and predictive analytics (sale propensity, last sold
|
|
81
|
+
description: "Intelligence and predictive analytics (sale propensity score 0-100 predicting likelihood to list/sell, last sold date and price derived from assessor and listing data, length of residence)",
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
name: "demographics",
|
|
@@ -113,12 +113,12 @@ exports.SEARCH_CRITERIA_DOMAINS = [
|
|
|
113
113
|
{
|
|
114
114
|
name: "propertyOwnerProfile",
|
|
115
115
|
responseGroup: "propertyOwnerProfile",
|
|
116
|
-
description: "Property owner profile information (total properties owned, equity, mortgages, etc.)",
|
|
116
|
+
description: "Property owner profile information - aggregate values across ALL properties owned by the owner (total properties owned, total equity, total mortgages, averages, etc.)",
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
name: "quickList",
|
|
120
120
|
responseGroup: "quickList",
|
|
121
|
-
description: "Pre-defined quick filters (owner-occupied, vacant, absentee-owner, high-equity, low-equity, free-and-clear, active-listing, recently-sold, preforeclosure, tax-default, etc.).
|
|
121
|
+
description: "Pre-defined quick filters (owner-occupied, vacant, absentee-owner, high-equity, low-equity, free-and-clear, active-listing, recently-sold, preforeclosure, tax-default, etc.). Available as top-level fields: quickList (single value), quickLists (array, AND logic), orQuickLists (array, OR logic). Values can be negated with 'not-' prefix. Use orQuickLists for conceptual categories (e.g., 'distressed properties' = orQuickLists: ['vacant', 'preforeclosure', 'tax-default']).",
|
|
122
122
|
},
|
|
123
123
|
];
|
|
124
124
|
/**
|
|
@@ -214,8 +214,9 @@ ${domainDocs}
|
|
|
214
214
|
FILTER TYPES:
|
|
215
215
|
- StringFilter: { equals?, contains?, startsWith?, endsWith?, inList?, matches? }
|
|
216
216
|
- NumericRangeFilter: { min?, max? }
|
|
217
|
-
- DateRangeFilter: { minDate?, maxDate? }
|
|
217
|
+
- DateRangeFilter: { minDate?, maxDate? } (Dates in ISO 8601 format YYYY-MM-DD. For "after [year]", use next year's January 1st, e.g., "after 2015" = { minDate: "2016-01-01" })
|
|
218
218
|
- BooleanFilter: { equals: boolean }
|
|
219
|
+
- QuickListValue: string (can prefix with "not-" to exclude, e.g., "not-vacant")
|
|
219
220
|
- GeoLocationDistance: { latitude, longitude, distanceMiles }
|
|
220
221
|
- GeoLocationBoundingBox: { minLat, maxLat, minLon, maxLon }
|
|
221
222
|
- GeoLocationPolygon: { geoPoints: [{ latitude, longitude }] }
|
|
@@ -232,9 +233,23 @@ IMPORTANT RULES:
|
|
|
232
233
|
- "over $500,000" = assessment.totalMarketValue: {min: 500000}
|
|
233
234
|
- "built after 2010" = building.yearBuilt: {min: 2010}
|
|
234
235
|
- "last sold after 2015" = sale.lastSaleDate: {minDate: "2016-01-01"} (use next year's January 1st for "after [year]")
|
|
236
|
+
- "high sale propensity" = intel.salePropensity: {min: 70} (salePropensity is 0-100, higher = more likely to sell)
|
|
237
|
+
- "flip properties" = properties bought and sold quickly (use sale.flipLength or quickList: "fix-and-flip")
|
|
235
238
|
5. Extract geographic information and populate both query and address filters appropriately
|
|
236
239
|
6. Only include domains that are clearly relevant to the prompt
|
|
237
240
|
7. If modifying existing criteria, merge intelligently - update what's mentioned, keep what's not
|
|
241
|
+
8. Conceptual groupings and orQuickLists: When prompts describe conceptual categories that map to multiple quickList values with OR logic, use orQuickLists:
|
|
242
|
+
- "distressed properties" or "distressed" = orQuickLists: ["vacant", "preforeclosure", "tax-default"] (properties with financial distress indicators)
|
|
243
|
+
- "motivated sellers" = orQuickLists: ["preforeclosure", "tax-default", "inherited", "vacant"] (properties where owner may be motivated to sell)
|
|
244
|
+
- "investment properties" = orQuickLists: ["absentee-owner", "corporate-owned", "out-of-state-owner"] (non-owner-occupied investment properties)
|
|
245
|
+
- "off-market" = orQuickLists: ["not-active-listing", "not-on-market", "not-pending-listing"] (properties not currently listed)
|
|
246
|
+
- "equity-rich" = orQuickLists: ["high-equity", "free-and-clear"] (properties with significant equity)
|
|
247
|
+
9. Field-specific notes:
|
|
248
|
+
- building.totalBuildingAreaSquareFeet: Often includes both living and non-living areas (cumulative total)
|
|
249
|
+
- intel.lastSoldDate vs sale.lastSaleDate: intel.lastSoldDate is derived from assessor and listing data, sale.lastSaleDate is from sale records
|
|
250
|
+
- foreclosure.filingDate vs foreclosure.recordingDate: filingDate may differ from recordingDate
|
|
251
|
+
- owner.ownershipStartDate: Date when the current owner took ownership
|
|
252
|
+
- owner.lengthOfResidence*: Based on last sale date from assessor and listing data
|
|
238
253
|
|
|
239
254
|
INPUT FORMAT:
|
|
240
255
|
You will receive:
|
|
@@ -312,9 +327,7 @@ function getDomainContext(domainName, options = {}) {
|
|
|
312
327
|
doc += "\n Available fields:\n";
|
|
313
328
|
for (const field of fields) {
|
|
314
329
|
doc += ` - ${field.name} (${field.type}): ${field.description}\n`;
|
|
315
|
-
|
|
316
|
-
doc += ` Filter: ${field.filterGuidance}\n`;
|
|
317
|
-
}
|
|
330
|
+
// Removed filterGuidance - filter types are already defined in FILTER TYPES section
|
|
318
331
|
if (field.examples && field.examples.length > 0) {
|
|
319
332
|
doc += ` Examples: ${field.examples.join(", ")}\n`;
|
|
320
333
|
}
|
|
@@ -366,6 +379,9 @@ function buildDomainDocumentation(domainNames, options = {}) {
|
|
|
366
379
|
let doc = "";
|
|
367
380
|
const queryDomainItem = domains.find((d) => d.name === "query");
|
|
368
381
|
const optionalDomains = domains.filter((d) => d.name !== "query");
|
|
382
|
+
const quickListDomain = optionalDomains.find((d) => d.name === "quickList");
|
|
383
|
+
const otherOptionalDomains = optionalDomains.filter((d) => d.name !== "quickList");
|
|
384
|
+
const hasQuickListDomain = !!quickListDomain;
|
|
369
385
|
if (queryDomainItem) {
|
|
370
386
|
doc += "REQUIRED:\n";
|
|
371
387
|
doc += `- query: ${queryDomainItem.description}\n`;
|
|
@@ -376,15 +392,34 @@ function buildDomainDocumentation(domainNames, options = {}) {
|
|
|
376
392
|
else if (optionalDomains.length > 0) {
|
|
377
393
|
doc += "OPTIONAL DOMAINS:\n";
|
|
378
394
|
}
|
|
379
|
-
|
|
395
|
+
// Add QuickList values section once if quickList domain is included
|
|
396
|
+
if (hasQuickListDomain) {
|
|
397
|
+
doc += "\n";
|
|
398
|
+
doc += (0, search_criteria_filter_context_1.getQuickListValuesSection)();
|
|
399
|
+
doc += "\n";
|
|
400
|
+
}
|
|
401
|
+
// Output quickList domain immediately after QUICKLIST VALUES section for clarity
|
|
402
|
+
if (quickListDomain) {
|
|
403
|
+
doc += `\n- ${quickListDomain.name}: ${quickListDomain.description}`;
|
|
404
|
+
if (quickListDomain.fields.length > 0) {
|
|
405
|
+
doc += "\n Available fields:\n";
|
|
406
|
+
for (const field of quickListDomain.fields) {
|
|
407
|
+
doc += ` - ${field.name} (${field.type}): ${field.description}\n`;
|
|
408
|
+
// Removed filterGuidance - filter types are already defined in FILTER TYPES section
|
|
409
|
+
if (field.examples && field.examples.length > 0) {
|
|
410
|
+
doc += ` Examples: ${field.examples.join(", ")}\n`;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Output all other domains
|
|
416
|
+
for (const domain of otherOptionalDomains) {
|
|
380
417
|
doc += `\n- ${domain.name}: ${domain.description}`;
|
|
381
418
|
if (domain.fields.length > 0) {
|
|
382
419
|
doc += "\n Available fields:\n";
|
|
383
420
|
for (const field of domain.fields) {
|
|
384
421
|
doc += ` - ${field.name} (${field.type}): ${field.description}\n`;
|
|
385
|
-
|
|
386
|
-
doc += ` Filter: ${field.filterGuidance}\n`;
|
|
387
|
-
}
|
|
422
|
+
// Removed filterGuidance - filter types are already defined in FILTER TYPES section
|
|
388
423
|
if (field.examples && field.examples.length > 0) {
|
|
389
424
|
doc += ` Examples: ${field.examples.join(", ")}\n`;
|
|
390
425
|
}
|
|
@@ -70,6 +70,11 @@ export declare function getSearchCriteriaFilterContext(searchCriteriaPath: strin
|
|
|
70
70
|
* ```
|
|
71
71
|
*/
|
|
72
72
|
export declare function getSearchCriteriaFilterContextString(searchCriteriaPath: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* Get formatted QuickList values section for documentation
|
|
75
|
+
* @returns Formatted string with all QuickList values and descriptions
|
|
76
|
+
*/
|
|
77
|
+
export declare function getQuickListValuesSection(): string;
|
|
73
78
|
/**
|
|
74
79
|
* Get filter context for all fields in a SearchCriteria domain/group
|
|
75
80
|
* @param domainName The domain name (e.g., "address", "building", "assessment", "quickList")
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.getSearchCriteriaFilterContext = getSearchCriteriaFilterContext;
|
|
10
10
|
exports.getSearchCriteriaFilterContextString = getSearchCriteriaFilterContextString;
|
|
11
|
+
exports.getQuickListValuesSection = getQuickListValuesSection;
|
|
11
12
|
exports.getDomainFilterContexts = getDomainFilterContexts;
|
|
12
13
|
exports.getDomainFilterContextDocumentation = getDomainFilterContextDocumentation;
|
|
13
14
|
const metadata_1 = require("./metadata");
|
|
@@ -225,14 +226,28 @@ function getExamples(fieldPath, filterType, _propertyMetadata) {
|
|
|
225
226
|
else if (fieldPath.includes("status")) {
|
|
226
227
|
examples.push('{ equals: "active" }');
|
|
227
228
|
}
|
|
228
|
-
else {
|
|
229
|
-
examples.push('{ equals: "
|
|
230
|
-
examples.push('{ contains: "
|
|
229
|
+
else if (fieldPath.includes("street")) {
|
|
230
|
+
examples.push('{ equals: "123 Main Street" }');
|
|
231
|
+
examples.push('{ contains: "Main" } // streets containing "Main"');
|
|
232
|
+
}
|
|
233
|
+
else if (fieldPath.includes("description")) {
|
|
234
|
+
examples.push('{ contains: "pool" } // listings containing "pool"');
|
|
235
|
+
examples.push('{ contains: "renovated" } // listings containing "renovated"');
|
|
236
|
+
}
|
|
237
|
+
else if (fieldPath.includes("subdivisionName")) {
|
|
238
|
+
examples.push('{ equals: "Sunset Hills" }');
|
|
239
|
+
examples.push('{ contains: "Hills" } // subdivisions containing "Hills"');
|
|
240
|
+
}
|
|
241
|
+
else if (fieldPath.includes("Name") &&
|
|
242
|
+
(fieldPath.includes("firstName") || fieldPath.includes("lastName"))) {
|
|
243
|
+
examples.push('{ equals: "Smith" }');
|
|
244
|
+
examples.push('{ contains: "Smith" } // names containing "Smith"');
|
|
231
245
|
}
|
|
246
|
+
// Removed generic examples - only include meaningful, field-specific ones
|
|
232
247
|
break;
|
|
233
248
|
case "NumericRangeFilter":
|
|
234
249
|
if (fieldPath.includes("salePropensity")) {
|
|
235
|
-
// Sale propensity is a 0-100 score predicting likelihood to go on market and sell
|
|
250
|
+
// Sale propensity is a 0-100 AVM score predicting likelihood to go on market and sell
|
|
236
251
|
// Higher scores = higher likelihood
|
|
237
252
|
examples.push("{ min: 70 } // Very high propensity (70-100) - properties most likely to list/sell soon");
|
|
238
253
|
examples.push("{ min: 80 } // Extremely high propensity (80-100) - highest likelihood properties");
|
|
@@ -250,16 +265,29 @@ function getExamples(fieldPath, filterType, _propertyMetadata) {
|
|
|
250
265
|
examples.push("{ min: 2010 } // built after 2010");
|
|
251
266
|
examples.push("{ max: 2000 } // built before 2000");
|
|
252
267
|
}
|
|
268
|
+
else if (fieldPath.includes("totalBuildingAreaSquareFeet")) {
|
|
269
|
+
// Note: This field is often a cumulative total including both living and non-living areas
|
|
270
|
+
examples.push("{ min: 1500 } // at least 1500 sq ft");
|
|
271
|
+
examples.push("{ max: 2500 } // under 2500 sq ft");
|
|
272
|
+
examples.push("{ min: 2000, max: 3000 } // between 2000 and 3000 sq ft");
|
|
273
|
+
}
|
|
274
|
+
else if (fieldPath.includes("flipLength") ||
|
|
275
|
+
fieldPath.includes("flipProfit")) {
|
|
276
|
+
// Flip properties are those bought and sold within a short timeframe
|
|
277
|
+
if (fieldPath.includes("flipLength")) {
|
|
278
|
+
examples.push("{ max: 12 } // flipped within 12 months (short-term flips)");
|
|
279
|
+
examples.push("{ min: 6, max: 12 } // flipped between 6-12 months");
|
|
280
|
+
}
|
|
281
|
+
else if (fieldPath.includes("flipProfit")) {
|
|
282
|
+
examples.push("{ min: 50000 } // flip profit of at least $50,000");
|
|
283
|
+
examples.push("{ min: 30000, max: 100000 } // flip profit between $30k-$100k");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
253
286
|
else if (fieldPath.includes("Value") || fieldPath.includes("Price")) {
|
|
254
287
|
examples.push("{ max: 400000 } // under $400,000");
|
|
255
288
|
examples.push("{ min: 500000 } // over $500,000");
|
|
256
289
|
examples.push("{ min: 300000, max: 500000 } // between $300k and $500k");
|
|
257
290
|
}
|
|
258
|
-
else {
|
|
259
|
-
examples.push("{ min: 0 }");
|
|
260
|
-
examples.push("{ max: 100 }");
|
|
261
|
-
examples.push("{ min: 10, max: 50 }");
|
|
262
|
-
}
|
|
263
291
|
break;
|
|
264
292
|
case "BooleanFilter":
|
|
265
293
|
if (fieldPath.includes("ownerOccupied")) {
|
|
@@ -270,16 +298,23 @@ function getExamples(fieldPath, filterType, _propertyMetadata) {
|
|
|
270
298
|
examples.push("{ equals: true } // properties with children");
|
|
271
299
|
examples.push("{ equals: false } // properties without children");
|
|
272
300
|
}
|
|
273
|
-
else {
|
|
274
|
-
examples.push("{ equals: true }");
|
|
275
|
-
examples.push("{ equals: false }");
|
|
276
|
-
}
|
|
277
301
|
break;
|
|
278
302
|
case "DateRangeFilter":
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
303
|
+
if (fieldPath.includes("ownershipStartDate")) {
|
|
304
|
+
examples.push('{ minDate: "2020-01-01" } // owner took ownership on or after January 1, 2020');
|
|
305
|
+
examples.push('{ maxDate: "2015-12-31" } // owner took ownership before 2016');
|
|
306
|
+
}
|
|
307
|
+
else if (fieldPath.includes("filingDate")) {
|
|
308
|
+
examples.push('{ minDate: "2020-01-01" } // filed on or after January 1, 2020 (filing date may differ from recording date)');
|
|
309
|
+
examples.push('{ minDate: "2020-01-01", maxDate: "2023-12-31" } // filed between dates');
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
// Include one example for general date filtering
|
|
313
|
+
examples.push('{ minDate: "2020-01-01" } // on or after January 1, 2020');
|
|
314
|
+
examples.push('{ minDate: "2016-01-01" } // last sold after 2015 (use next year for "after [year]")');
|
|
315
|
+
examples.push('{ maxDate: "2023-12-31" } // before December 31, 2023');
|
|
316
|
+
examples.push('{ minDate: "2020-01-01", maxDate: "2023-12-31" } // between dates');
|
|
317
|
+
}
|
|
283
318
|
break;
|
|
284
319
|
}
|
|
285
320
|
return examples;
|
|
@@ -466,12 +501,17 @@ function getSearchCriteriaFilterContext(searchCriteriaPath) {
|
|
|
466
501
|
filterType: "QuickListValue",
|
|
467
502
|
propertyPath: undefined,
|
|
468
503
|
propertyMetadata: undefined,
|
|
469
|
-
description: `Pre-defined quick filter${searchCriteriaPath === "quickList" ? "" : "s"} for common property characteristics. Values can be prefixed with "not-" to exclude (e.g., "not-vacant" excludes vacant properties). Use ${searchCriteriaPath === "orQuickLists" ? "orQuickLists array for OR logic" : searchCriteriaPath === "quickLists" ? "quickLists array for multiple values" : "quickList for a single value"}.`,
|
|
504
|
+
description: `Pre-defined quick filter${searchCriteriaPath === "quickList" ? "" : "s"} for common property characteristics. Values can be prefixed with "not-" to exclude (e.g., "not-vacant" excludes vacant properties). Use ${searchCriteriaPath === "orQuickLists" ? "orQuickLists array for OR logic (e.g., conceptual categories like 'distressed properties' = ['vacant', 'preforeclosure', 'tax-default'])" : searchCriteriaPath === "quickLists" ? "quickLists array for multiple values (AND logic)" : "quickList for a single value"}. See QUICKLIST VALUES section for all available values.`,
|
|
470
505
|
examples: [
|
|
471
|
-
...QUICK_LIST_VALUES_WITH_DESCRIPTIONS.slice(0,
|
|
506
|
+
...QUICK_LIST_VALUES_WITH_DESCRIPTIONS.slice(0, 3).map((item) => `"${item.value}" // ${item.description}`),
|
|
472
507
|
'"not-vacant" // Exclude vacant properties',
|
|
473
508
|
'"not-owner-occupied" // Exclude owner-occupied properties',
|
|
474
|
-
|
|
509
|
+
...(searchCriteriaPath === "orQuickLists"
|
|
510
|
+
? [
|
|
511
|
+
'["vacant", "preforeclosure", "tax-default"] // Distressed properties (OR logic)',
|
|
512
|
+
'["absentee-owner", "corporate-owned", "out-of-state-owner"] // Investment properties (OR logic)',
|
|
513
|
+
]
|
|
514
|
+
: []),
|
|
475
515
|
],
|
|
476
516
|
filterGuidance: getFilterGuidance("QuickListValue"),
|
|
477
517
|
};
|
|
@@ -480,10 +520,42 @@ function getSearchCriteriaFilterContext(searchCriteriaPath) {
|
|
|
480
520
|
// Try to get Property field metadata
|
|
481
521
|
const propertyMetadata = (0, metadata_1.getFieldMetadata)(searchCriteriaPath);
|
|
482
522
|
const propertyPath = propertyMetadata ? searchCriteriaPath : undefined;
|
|
483
|
-
// Build description
|
|
523
|
+
// Build description with additional context from data dictionary
|
|
484
524
|
let description;
|
|
485
525
|
if (propertyMetadata) {
|
|
486
526
|
description = `Filter on ${propertyMetadata.description}`;
|
|
527
|
+
// Add additional important context for specific fields based on data dictionary
|
|
528
|
+
if (searchCriteriaPath === "building.totalBuildingAreaSquareFeet") {
|
|
529
|
+
description +=
|
|
530
|
+
" (Note: Often includes cumulative total of living and non-living areas when county doesn't differentiate)";
|
|
531
|
+
}
|
|
532
|
+
else if (searchCriteriaPath === "intel.salePropensity") {
|
|
533
|
+
description +=
|
|
534
|
+
" (0-100 score where higher values indicate greater likelihood to list/sell)";
|
|
535
|
+
}
|
|
536
|
+
else if (searchCriteriaPath === "intel.lastSoldDate") {
|
|
537
|
+
description += " (Derived from assessor and listing data)";
|
|
538
|
+
}
|
|
539
|
+
else if (searchCriteriaPath === "owner.ownershipStartDate") {
|
|
540
|
+
description += " (Date current owner took ownership)";
|
|
541
|
+
}
|
|
542
|
+
else if (searchCriteriaPath.includes("lengthOfResidence")) {
|
|
543
|
+
description +=
|
|
544
|
+
" (Based on last sale date from assessor and listing data)";
|
|
545
|
+
}
|
|
546
|
+
else if (searchCriteriaPath === "foreclosure.filingDate") {
|
|
547
|
+
description +=
|
|
548
|
+
" (Preforeclosure filing date, may differ from recording date)";
|
|
549
|
+
}
|
|
550
|
+
else if (searchCriteriaPath === "involuntaryLien.filingDate") {
|
|
551
|
+
description += " (Lien filing date, may differ from recording date)";
|
|
552
|
+
}
|
|
553
|
+
else if (searchCriteriaPath.includes("flipLength")) {
|
|
554
|
+
description += " (Time between purchase and sale for flipped properties)";
|
|
555
|
+
}
|
|
556
|
+
else if (searchCriteriaPath.includes("flipProfit")) {
|
|
557
|
+
description += " (Profit from flipped property transactions)";
|
|
558
|
+
}
|
|
487
559
|
}
|
|
488
560
|
else {
|
|
489
561
|
const parts = searchCriteriaPath.split(".");
|
|
@@ -532,6 +604,17 @@ function getSearchCriteriaFilterContextString(searchCriteriaPath) {
|
|
|
532
604
|
}
|
|
533
605
|
return parts.join("\n");
|
|
534
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* Get formatted QuickList values section for documentation
|
|
609
|
+
* @returns Formatted string with all QuickList values and descriptions
|
|
610
|
+
*/
|
|
611
|
+
function getQuickListValuesSection() {
|
|
612
|
+
let section = `QUICKLIST VALUES (${QUICK_LIST_VALUES_WITH_DESCRIPTIONS.length} total):\n`;
|
|
613
|
+
for (const item of QUICK_LIST_VALUES_WITH_DESCRIPTIONS) {
|
|
614
|
+
section += ` - "${item.value}": ${item.description}\n`;
|
|
615
|
+
}
|
|
616
|
+
return section;
|
|
617
|
+
}
|
|
535
618
|
/**
|
|
536
619
|
* Get filter context for all fields in a SearchCriteria domain/group
|
|
537
620
|
* @param domainName The domain name (e.g., "address", "building", "assessment", "quickList")
|
package/package.json
CHANGED