@land-catalyst/batch-data-sdk 1.2.1 → 1.2.3
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 +50 -3
- package/dist/property-field/search-criteria-ai-context.js +185 -39
- package/dist/property-field/search-criteria-filter-context.d.ts +1 -1
- package/dist/property-field/search-criteria-filter-context.js +29 -1
- 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": {
|
|
@@ -26,6 +26,16 @@ export interface SearchCriteriaDomain {
|
|
|
26
26
|
* All available SearchCriteria domains with their descriptions
|
|
27
27
|
*/
|
|
28
28
|
export declare const SEARCH_CRITERIA_DOMAINS: SearchCriteriaDomain[];
|
|
29
|
+
/**
|
|
30
|
+
* Array of all valid SearchCriteria domain names (for autocomplete)
|
|
31
|
+
* Using `as const` preserves literal types for better IDE autocomplete
|
|
32
|
+
*/
|
|
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
|
+
/**
|
|
35
|
+
* Type representing valid SearchCriteria domain names
|
|
36
|
+
* This union type provides better autocomplete in IDEs
|
|
37
|
+
*/
|
|
38
|
+
export type SearchCriteriaDomainName = (typeof SEARCH_CRITERIA_DOMAIN_NAMES)[number];
|
|
29
39
|
/**
|
|
30
40
|
* Options for building AI context
|
|
31
41
|
*/
|
|
@@ -41,17 +51,51 @@ export interface SearchCriteriaAIContextOptions {
|
|
|
41
51
|
*/
|
|
42
52
|
maxExamplesPerField?: number;
|
|
43
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Build domain context documentation for specified domains
|
|
56
|
+
* @param domains Array of domain names to include (e.g., ["address", "building", "assessment"])
|
|
57
|
+
* If undefined or empty array, includes all domains (default)
|
|
58
|
+
* Type-safe: only valid domain names from SEARCH_CRITERIA_DOMAINS are allowed
|
|
59
|
+
* @param options Options for customizing the context (applies to all specified domains)
|
|
60
|
+
* @returns Formatted domain documentation string
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* // Get context for all domains (default)
|
|
64
|
+
* const allContext = buildSearchCriteriaContext();
|
|
65
|
+
*
|
|
66
|
+
* // Get context for specific domains
|
|
67
|
+
* const context = buildSearchCriteriaContext(["address", "building", "assessment"]);
|
|
68
|
+
*
|
|
69
|
+
* // Get context for all domains with options
|
|
70
|
+
* const allContextWithOptions = buildSearchCriteriaContext(undefined, { maxFieldsPerDomain: 5 });
|
|
71
|
+
*
|
|
72
|
+
* // Get context for specific domains with options
|
|
73
|
+
* const selectiveContext = buildSearchCriteriaContext(["address", "building"], { maxFieldsPerDomain: 5 });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function buildSearchCriteriaContext(domains?: SearchCriteriaDomainName[], options?: SearchCriteriaAIContextOptions): string;
|
|
44
77
|
/**
|
|
45
78
|
* Build complete system prompt for AI to generate SearchCriteria from natural language
|
|
46
|
-
* @param
|
|
79
|
+
* @param domains Optional domain names to include. If not specified, includes all domains.
|
|
80
|
+
* Only domains that exist in SEARCH_CRITERIA_DOMAINS are allowed
|
|
81
|
+
* @param options Options for customizing the context (applies to all specified domains)
|
|
47
82
|
* @returns Complete system prompt string
|
|
48
83
|
* @example
|
|
49
84
|
* ```typescript
|
|
85
|
+
* // Full context with all domains
|
|
50
86
|
* const systemPrompt = buildSearchCriteriaSystemPrompt();
|
|
51
|
-
*
|
|
87
|
+
*
|
|
88
|
+
* // Selective context for specific domains
|
|
89
|
+
* const systemPrompt = buildSearchCriteriaSystemPrompt(["address", "building", "assessment"]);
|
|
90
|
+
*
|
|
91
|
+
* // All domains with options
|
|
92
|
+
* const systemPrompt = buildSearchCriteriaSystemPrompt(undefined, { maxFieldsPerDomain: 5 });
|
|
93
|
+
*
|
|
94
|
+
* // Specific domains with options
|
|
95
|
+
* const systemPrompt = buildSearchCriteriaSystemPrompt(["address", "building"], { maxFieldsPerDomain: 5 });
|
|
52
96
|
* ```
|
|
53
97
|
*/
|
|
54
|
-
export declare function buildSearchCriteriaSystemPrompt(options?: SearchCriteriaAIContextOptions): string;
|
|
98
|
+
export declare function buildSearchCriteriaSystemPrompt(domains?: SearchCriteriaDomainName[], options?: SearchCriteriaAIContextOptions): string;
|
|
55
99
|
/**
|
|
56
100
|
* Get context documentation for a specific domain
|
|
57
101
|
* @param domainName The domain name (e.g., "address", "building", "assessment")
|
|
@@ -69,5 +113,8 @@ export declare function getDomainContext(domainName: string, options?: SearchCri
|
|
|
69
113
|
* @param userPrompt The user's natural language prompt
|
|
70
114
|
* @param existingCriteria Optional existing search criteria to modify
|
|
71
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.
|
|
72
119
|
*/
|
|
73
120
|
export declare function buildSearchCriteriaUserPrompt(userPrompt: string, existingCriteria?: unknown): string;
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* This includes all domain documentation, filter types, examples, and rules.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.SEARCH_CRITERIA_DOMAINS = void 0;
|
|
9
|
+
exports.SEARCH_CRITERIA_DOMAIN_NAMES = exports.SEARCH_CRITERIA_DOMAINS = void 0;
|
|
10
|
+
exports.buildSearchCriteriaContext = buildSearchCriteriaContext;
|
|
10
11
|
exports.buildSearchCriteriaSystemPrompt = buildSearchCriteriaSystemPrompt;
|
|
11
12
|
exports.getDomainContext = getDomainContext;
|
|
12
13
|
exports.buildSearchCriteriaUserPrompt = buildSearchCriteriaUserPrompt;
|
|
@@ -74,26 +75,138 @@ exports.SEARCH_CRITERIA_DOMAINS = [
|
|
|
74
75
|
responseGroup: "foreclosure",
|
|
75
76
|
description: "Foreclosure status and auction information",
|
|
76
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
|
+
},
|
|
77
118
|
{
|
|
78
119
|
name: "quickList",
|
|
79
120
|
responseGroup: "quickList",
|
|
80
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.). Can be negated with 'not-' prefix.",
|
|
81
122
|
},
|
|
82
123
|
];
|
|
124
|
+
/**
|
|
125
|
+
* Array of all valid SearchCriteria domain names (for autocomplete)
|
|
126
|
+
* Using `as const` preserves literal types for better IDE autocomplete
|
|
127
|
+
*/
|
|
128
|
+
exports.SEARCH_CRITERIA_DOMAIN_NAMES = [
|
|
129
|
+
"query",
|
|
130
|
+
"address",
|
|
131
|
+
"assessment",
|
|
132
|
+
"building",
|
|
133
|
+
"lot",
|
|
134
|
+
"owner",
|
|
135
|
+
"sale",
|
|
136
|
+
"tax",
|
|
137
|
+
"valuation",
|
|
138
|
+
"listing",
|
|
139
|
+
"openLien",
|
|
140
|
+
"foreclosure",
|
|
141
|
+
"intel",
|
|
142
|
+
"demographics",
|
|
143
|
+
"general",
|
|
144
|
+
"ids",
|
|
145
|
+
"involuntaryLien",
|
|
146
|
+
"legal",
|
|
147
|
+
"permit",
|
|
148
|
+
"propertyOwnerProfile",
|
|
149
|
+
"quickList",
|
|
150
|
+
];
|
|
151
|
+
/**
|
|
152
|
+
* Build domain context documentation for specified domains
|
|
153
|
+
* @param domains Array of domain names to include (e.g., ["address", "building", "assessment"])
|
|
154
|
+
* If undefined or empty array, includes all domains (default)
|
|
155
|
+
* Type-safe: only valid domain names from SEARCH_CRITERIA_DOMAINS are allowed
|
|
156
|
+
* @param options Options for customizing the context (applies to all specified domains)
|
|
157
|
+
* @returns Formatted domain documentation string
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* // Get context for all domains (default)
|
|
161
|
+
* const allContext = buildSearchCriteriaContext();
|
|
162
|
+
*
|
|
163
|
+
* // Get context for specific domains
|
|
164
|
+
* const context = buildSearchCriteriaContext(["address", "building", "assessment"]);
|
|
165
|
+
*
|
|
166
|
+
* // Get context for all domains with options
|
|
167
|
+
* const allContextWithOptions = buildSearchCriteriaContext(undefined, { maxFieldsPerDomain: 5 });
|
|
168
|
+
*
|
|
169
|
+
* // Get context for specific domains with options
|
|
170
|
+
* const selectiveContext = buildSearchCriteriaContext(["address", "building"], { maxFieldsPerDomain: 5 });
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
function buildSearchCriteriaContext(domains, options) {
|
|
174
|
+
// Default to all domains if undefined or empty array
|
|
175
|
+
const selectedDomains = !domains || domains.length === 0
|
|
176
|
+
? exports.SEARCH_CRITERIA_DOMAINS.map((d) => d.name)
|
|
177
|
+
: domains;
|
|
178
|
+
// Validate that all specified domains exist
|
|
179
|
+
const validDomainNames = new Set(exports.SEARCH_CRITERIA_DOMAINS.map((d) => d.name));
|
|
180
|
+
const invalidDomains = selectedDomains.filter((d) => !validDomainNames.has(d));
|
|
181
|
+
if (invalidDomains.length > 0) {
|
|
182
|
+
throw new Error(`Invalid domain(s): ${invalidDomains.join(", ")}. Valid domains are: ${Array.from(validDomainNames).join(", ")}`);
|
|
183
|
+
}
|
|
184
|
+
return buildDomainDocumentation(selectedDomains, options || {});
|
|
185
|
+
}
|
|
83
186
|
/**
|
|
84
187
|
* Build complete system prompt for AI to generate SearchCriteria from natural language
|
|
85
|
-
* @param
|
|
188
|
+
* @param domains Optional domain names to include. If not specified, includes all domains.
|
|
189
|
+
* Only domains that exist in SEARCH_CRITERIA_DOMAINS are allowed
|
|
190
|
+
* @param options Options for customizing the context (applies to all specified domains)
|
|
86
191
|
* @returns Complete system prompt string
|
|
87
192
|
* @example
|
|
88
193
|
* ```typescript
|
|
194
|
+
* // Full context with all domains
|
|
89
195
|
* const systemPrompt = buildSearchCriteriaSystemPrompt();
|
|
90
|
-
*
|
|
196
|
+
*
|
|
197
|
+
* // Selective context for specific domains
|
|
198
|
+
* const systemPrompt = buildSearchCriteriaSystemPrompt(["address", "building", "assessment"]);
|
|
199
|
+
*
|
|
200
|
+
* // All domains with options
|
|
201
|
+
* const systemPrompt = buildSearchCriteriaSystemPrompt(undefined, { maxFieldsPerDomain: 5 });
|
|
202
|
+
*
|
|
203
|
+
* // Specific domains with options
|
|
204
|
+
* const systemPrompt = buildSearchCriteriaSystemPrompt(["address", "building"], { maxFieldsPerDomain: 5 });
|
|
91
205
|
* ```
|
|
92
206
|
*/
|
|
93
|
-
function buildSearchCriteriaSystemPrompt(options
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const domainDocs = buildDomainDocumentation(maxFieldsPerDomain, maxExamplesPerField);
|
|
207
|
+
function buildSearchCriteriaSystemPrompt(domains, options) {
|
|
208
|
+
// Build domain documentation using the unified function
|
|
209
|
+
const domainDocs = buildSearchCriteriaContext(domains, options);
|
|
97
210
|
return `You are an expert at creating property search criteria for real estate professionals. Your task is to convert natural language requests into structured BatchData.io search criteria.
|
|
98
211
|
|
|
99
212
|
${domainDocs}
|
|
@@ -102,6 +215,7 @@ FILTER TYPES:
|
|
|
102
215
|
- StringFilter: { equals?, contains?, startsWith?, endsWith?, inList?, matches? }
|
|
103
216
|
- NumericRangeFilter: { min?, max? }
|
|
104
217
|
- DateRangeFilter: { minDate?, maxDate? }
|
|
218
|
+
- BooleanFilter: { equals: boolean }
|
|
105
219
|
- GeoLocationDistance: { latitude, longitude, distanceMiles }
|
|
106
220
|
- GeoLocationBoundingBox: { minLat, maxLat, minLon, maxLon }
|
|
107
221
|
- GeoLocationPolygon: { geoPoints: [{ latitude, longitude }] }
|
|
@@ -121,11 +235,37 @@ IMPORTANT RULES:
|
|
|
121
235
|
6. Only include domains that are clearly relevant to the prompt
|
|
122
236
|
7. If modifying existing criteria, merge intelligently - update what's mentioned, keep what's not
|
|
123
237
|
|
|
238
|
+
INPUT FORMAT:
|
|
239
|
+
You will receive:
|
|
240
|
+
1. A user prompt in natural language describing the property search criteria they want
|
|
241
|
+
2. Optionally, existing search criteria in JSON format that should be modified
|
|
242
|
+
|
|
243
|
+
RESPONSE FORMAT:
|
|
124
244
|
Return your response as a JSON array. Each object should have:
|
|
125
245
|
- searchCriteria: The complete SearchCriteria object
|
|
126
246
|
- description: A natural language description of what this search criteria finds
|
|
127
247
|
|
|
128
|
-
If the prompt suggests multiple distinct searches, return multiple objects. Otherwise, return a single object
|
|
248
|
+
If the prompt suggests multiple distinct searches, return multiple objects. Otherwise, return a single object.
|
|
249
|
+
|
|
250
|
+
Example response format:
|
|
251
|
+
[
|
|
252
|
+
{
|
|
253
|
+
"searchCriteria": {
|
|
254
|
+
"query": "Maricopa County, AZ",
|
|
255
|
+
"building": {
|
|
256
|
+
"bedroomCount": { "min": 3, "max": 3 },
|
|
257
|
+
"yearBuilt": { "min": 2000 }
|
|
258
|
+
},
|
|
259
|
+
"assessment": {
|
|
260
|
+
"totalMarketValue": { "max": 500000 }
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"description": "3-bedroom homes built after 2000 in Maricopa County, Arizona, with a market value under $500,000"
|
|
264
|
+
}
|
|
265
|
+
]
|
|
266
|
+
|
|
267
|
+
If existing criteria is provided, merge intelligently - update fields mentioned in the prompt, preserve others.
|
|
268
|
+
Return only valid JSON, no markdown formatting or code blocks.`;
|
|
129
269
|
}
|
|
130
270
|
/**
|
|
131
271
|
* Get context documentation for a specific domain
|
|
@@ -182,10 +322,21 @@ function getDomainContext(domainName, options = {}) {
|
|
|
182
322
|
return doc;
|
|
183
323
|
}
|
|
184
324
|
/**
|
|
185
|
-
* Build domain documentation string for
|
|
325
|
+
* Build domain documentation string for specified domains
|
|
326
|
+
* @param domainNames Array of domain names to include
|
|
327
|
+
* @param options Options for customizing the context
|
|
186
328
|
*/
|
|
187
|
-
function buildDomainDocumentation(
|
|
188
|
-
const
|
|
329
|
+
function buildDomainDocumentation(domainNames, options = {}) {
|
|
330
|
+
const { maxFieldsPerDomain, maxExamplesPerField } = options;
|
|
331
|
+
// Filter domains to only include specified ones
|
|
332
|
+
const selectedDomains = exports.SEARCH_CRITERIA_DOMAINS.filter((domain) => domainNames.includes(domain.name));
|
|
333
|
+
// Ensure query is always first if included
|
|
334
|
+
const queryDomain = selectedDomains.find((d) => d.name === "query");
|
|
335
|
+
const otherDomains = selectedDomains.filter((d) => d.name !== "query");
|
|
336
|
+
const orderedDomains = queryDomain
|
|
337
|
+
? [queryDomain, ...otherDomains]
|
|
338
|
+
: otherDomains;
|
|
339
|
+
const domains = orderedDomains.map((domain) => ({
|
|
189
340
|
...domain,
|
|
190
341
|
fields: [],
|
|
191
342
|
}));
|
|
@@ -211,10 +362,20 @@ function buildDomainDocumentation(maxFieldsPerDomain, maxExamplesPerField) {
|
|
|
211
362
|
}
|
|
212
363
|
}
|
|
213
364
|
// Build the documentation string
|
|
214
|
-
let doc = "
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
365
|
+
let doc = "";
|
|
366
|
+
const queryDomainItem = domains.find((d) => d.name === "query");
|
|
367
|
+
const optionalDomains = domains.filter((d) => d.name !== "query");
|
|
368
|
+
if (queryDomainItem) {
|
|
369
|
+
doc += "REQUIRED:\n";
|
|
370
|
+
doc += `- query: ${queryDomainItem.description}\n`;
|
|
371
|
+
if (optionalDomains.length > 0) {
|
|
372
|
+
doc += "\nOPTIONAL DOMAINS:\n";
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else if (optionalDomains.length > 0) {
|
|
376
|
+
doc += "OPTIONAL DOMAINS:\n";
|
|
377
|
+
}
|
|
378
|
+
for (const domain of optionalDomains) {
|
|
218
379
|
doc += `\n- ${domain.name}: ${domain.description}`;
|
|
219
380
|
if (domain.fields.length > 0) {
|
|
220
381
|
doc += "\n Available fields:\n";
|
|
@@ -236,30 +397,15 @@ function buildDomainDocumentation(maxFieldsPerDomain, maxExamplesPerField) {
|
|
|
236
397
|
* @param userPrompt The user's natural language prompt
|
|
237
398
|
* @param existingCriteria Optional existing search criteria to modify
|
|
238
399
|
* @returns Formatted user prompt string
|
|
400
|
+
* @deprecated This function is kept for backward compatibility but is no longer needed.
|
|
401
|
+
* The service should format the user prompt and existing criteria directly.
|
|
402
|
+
* The system prompt already describes the expected input and output format.
|
|
239
403
|
*/
|
|
240
404
|
function buildSearchCriteriaUserPrompt(userPrompt, existingCriteria) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
"bedroomCount": { "min": 3, "max": 3 },
|
|
248
|
-
"yearBuilt": { "min": 2000 }
|
|
249
|
-
},
|
|
250
|
-
"assessment": {
|
|
251
|
-
"totalMarketValue": { "max": 500000 }
|
|
252
|
-
}
|
|
253
|
-
},
|
|
254
|
-
"description": "3-bedroom homes built after 2000 in Maricopa County, Arizona, with a market value under $500,000"
|
|
255
|
-
}
|
|
256
|
-
]
|
|
257
|
-
|
|
258
|
-
${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.` : ""}
|
|
259
|
-
|
|
260
|
-
USER PROMPT:
|
|
261
|
-
${userPrompt}
|
|
262
|
-
|
|
263
|
-
Return only valid JSON, no markdown formatting or code blocks.`;
|
|
264
|
-
return basePrompt;
|
|
405
|
+
// Simple format - service can customize this as needed
|
|
406
|
+
let prompt = userPrompt;
|
|
407
|
+
if (existingCriteria) {
|
|
408
|
+
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}`;
|
|
409
|
+
}
|
|
410
|
+
return prompt;
|
|
265
411
|
}
|
|
@@ -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",
|
|
@@ -198,6 +200,8 @@ function getFilterGuidance(filterType) {
|
|
|
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
202
|
return `Use DateRangeFilter with: minDate (earliest date), maxDate (latest date), or both. Dates should be in ISO 8601 format (YYYY-MM-DD). Example: { minDate: "2020-01-01" } for "after 2020"`;
|
|
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,6 +261,20 @@ 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
279
|
examples.push('{ minDate: "2020-01-01" } // after January 1, 2020');
|
|
252
280
|
examples.push('{ maxDate: "2023-12-31" } // before December 31, 2023');
|
package/package.json
CHANGED