@sfranalytics/mcp 0.6.2 → 0.6.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/README.md +67 -50
- package/dist/analytics/logger.d.ts +3 -0
- package/dist/analytics/logger.js +39 -0
- package/dist/analytics/logger.js.map +1 -0
- package/dist/analytics/requestContext.d.ts +21 -0
- package/dist/analytics/requestContext.js +39 -0
- package/dist/analytics/requestContext.js.map +1 -0
- package/dist/analytics/sanitize.d.ts +1 -0
- package/dist/analytics/sanitize.js +78 -0
- package/dist/analytics/sanitize.js.map +1 -0
- package/dist/http.js +260 -41
- package/dist/http.js.map +1 -1
- package/dist/index.js +17 -4
- package/dist/index.js.map +1 -1
- package/dist/landing.d.ts +3 -0
- package/dist/landing.js +904 -0
- package/dist/landing.js.map +1 -0
- package/dist/server.d.ts +5 -1
- package/dist/server.js +12 -4
- package/dist/server.js.map +1 -1
- package/dist/services/httpClient.d.ts +22 -0
- package/dist/services/httpClient.js +147 -26
- package/dist/services/httpClient.js.map +1 -1
- package/dist/tools/formatters.js +33 -1
- package/dist/tools/formatters.js.map +1 -1
- package/dist/tools/health.js +84 -7
- package/dist/tools/health.js.map +1 -1
- package/dist/tools/plr/borrowerContacts.js +47 -10
- package/dist/tools/plr/borrowerContacts.js.map +1 -1
- package/dist/tools/plr/borrowerProfile.js +11 -5
- package/dist/tools/plr/borrowerProfile.js.map +1 -1
- package/dist/tools/plr/loansNearby.js +100 -84
- package/dist/tools/plr/loansNearby.js.map +1 -1
- package/dist/tools/plr/transactionHistory.js +67 -50
- package/dist/tools/plr/transactionHistory.js.map +1 -1
- package/dist/tools/registerToolSafe.d.ts +5 -1
- package/dist/tools/registerToolSafe.js +110 -4
- package/dist/tools/registerToolSafe.js.map +1 -1
- package/dist/tools/sfr/bestBuyers.js +58 -41
- package/dist/tools/sfr/bestBuyers.js.map +1 -1
- package/dist/tools/sfr/buyerProfile.js +6 -3
- package/dist/tools/sfr/buyerProfile.js.map +1 -1
- package/dist/tools/sfr/getProperty.js +147 -124
- package/dist/tools/sfr/getProperty.js.map +1 -1
- package/dist/tools/sfr/propertyBatch.js +3 -1
- package/dist/tools/sfr/propertyBatch.js.map +1 -1
- package/dist/tools/sfr/propertyComps.js +51 -34
- package/dist/tools/sfr/propertyComps.js.map +1 -1
- package/dist/tools/sfr/propertyTransactions.js +48 -31
- package/dist/tools/sfr/propertyTransactions.js.map +1 -1
- package/dist/tools/sfr/rentalComparables.js +83 -66
- package/dist/tools/sfr/rentalComparables.js.map +1 -1
- package/dist/tools/sfr/rentalMarketAnalysis.js +5 -2
- package/dist/tools/sfr/rentalMarketAnalysis.js.map +1 -1
- package/dist/tools/sfr/rentalStats.js +19 -3
- package/dist/tools/sfr/rentalStats.js.map +1 -1
- package/dist/tools/sfr/searchProperties.js +3 -1
- package/dist/tools/sfr/searchProperties.js.map +1 -1
- package/dist/tools/sfr/topBuyers.js +4 -0
- package/dist/tools/sfr/topBuyers.js.map +1 -1
- package/dist/tools/sfr/zipDetail.js +83 -72
- package/dist/tools/sfr/zipDetail.js.map +1 -1
- package/dist/tools/sfr/zipFinder.js +24 -15
- package/dist/tools/sfr/zipFinder.js.map +1 -1
- package/dist/tools/welcome.d.ts +3 -0
- package/dist/tools/welcome.js +58 -0
- package/dist/tools/welcome.js.map +1 -0
- package/package.json +2 -2
|
@@ -1,13 +1,94 @@
|
|
|
1
|
+
import { getCtx } from "../analytics/requestContext.js";
|
|
2
|
+
import { sanitizeArgs } from "../analytics/sanitize.js";
|
|
3
|
+
import { logEvent } from "../analytics/logger.js";
|
|
4
|
+
import { ApiError } from "../services/httpClient.js";
|
|
1
5
|
import { handleToolError } from "./formatters.js";
|
|
6
|
+
function truncateErrorMessage(message, maxLen = 500) {
|
|
7
|
+
return message.length > maxLen ? `${message.slice(0, maxLen)}...[truncated]` : message;
|
|
8
|
+
}
|
|
9
|
+
function toToolErrorEvent(err) {
|
|
10
|
+
if (err instanceof ApiError) {
|
|
11
|
+
return {
|
|
12
|
+
kind: "api_error",
|
|
13
|
+
message: truncateErrorMessage(err.message || `HTTP ${err.status}`),
|
|
14
|
+
status: err.status,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const maybeObj = err;
|
|
18
|
+
if (typeof maybeObj?.name === "string" && maybeObj.name === "ZodError") {
|
|
19
|
+
return {
|
|
20
|
+
kind: "validation",
|
|
21
|
+
message: truncateErrorMessage(typeof maybeObj.message === "string" ? maybeObj.message : "Validation error"),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (err instanceof Error) {
|
|
25
|
+
return { kind: "unknown", message: truncateErrorMessage(err.message || "Unknown error") };
|
|
26
|
+
}
|
|
27
|
+
return { kind: "unknown", message: truncateErrorMessage(String(err)) };
|
|
28
|
+
}
|
|
29
|
+
function inferErrorFromResult(result) {
|
|
30
|
+
if (!result.isError)
|
|
31
|
+
return null;
|
|
32
|
+
const text = result.content.find((item) => item.type === "text")?.text;
|
|
33
|
+
const message = text ? text.replace(/^Error:\s*/i, "") : "Tool returned isError=true";
|
|
34
|
+
return {
|
|
35
|
+
kind: "tool_error",
|
|
36
|
+
message: truncateErrorMessage(message),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function toolCategory(name) {
|
|
40
|
+
if (name === "sfra_health" || name === "sfra_welcome")
|
|
41
|
+
return "health";
|
|
42
|
+
if (name.startsWith("plr_"))
|
|
43
|
+
return "plr";
|
|
44
|
+
if (name.startsWith("sfr_"))
|
|
45
|
+
return "sfr";
|
|
46
|
+
return "other";
|
|
47
|
+
}
|
|
48
|
+
function extractOutputText(result) {
|
|
49
|
+
const texts = result.content
|
|
50
|
+
.filter((c) => c.type === "text" && c.text)
|
|
51
|
+
.map((c) => c.text);
|
|
52
|
+
return texts.length > 0 ? texts.join("\n") : null;
|
|
53
|
+
}
|
|
54
|
+
function extractOutputMeta(result) {
|
|
55
|
+
const raw = JSON.stringify(result);
|
|
56
|
+
const bytes = raw.length;
|
|
57
|
+
const text = extractOutputText(result);
|
|
58
|
+
const sc = result.structuredContent;
|
|
59
|
+
if (!sc)
|
|
60
|
+
return { items: null, bytes, truncated: false, keys: null, text };
|
|
61
|
+
const keys = Object.keys(sc).filter((k) => !k.startsWith("_"));
|
|
62
|
+
const truncated = !!sc._outputMeta?.truncated;
|
|
63
|
+
let items = null;
|
|
64
|
+
if (Array.isArray(sc.items)) {
|
|
65
|
+
items = sc.items.length;
|
|
66
|
+
}
|
|
67
|
+
else if (typeof sc.total === "number") {
|
|
68
|
+
items = sc.total;
|
|
69
|
+
}
|
|
70
|
+
return { items, bytes, truncated, keys, text };
|
|
71
|
+
}
|
|
72
|
+
/** Names of all tools registered via registerToolSafe (populated during createServer). */
|
|
73
|
+
const registeredToolNames = [];
|
|
74
|
+
/** Clear the registry — call before each createServer() in HTTP mode. */
|
|
75
|
+
export function clearToolRegistry() {
|
|
76
|
+
registeredToolNames.length = 0;
|
|
77
|
+
}
|
|
78
|
+
/** Returns a snapshot of all registered tool names. */
|
|
79
|
+
export function getRegisteredToolNames() {
|
|
80
|
+
return [...registeredToolNames];
|
|
81
|
+
}
|
|
2
82
|
/**
|
|
3
83
|
* Wrapper around `server.registerTool` that adds:
|
|
4
84
|
* - readOnlyHint + idempotentHint annotations by default
|
|
5
85
|
* - automatic try/catch → handleToolError
|
|
6
|
-
* -
|
|
86
|
+
* - structured analytics logging to stderr
|
|
7
87
|
*/
|
|
8
88
|
export function registerToolSafe(server, toolName, config,
|
|
9
89
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
90
|
cb) {
|
|
91
|
+
registeredToolNames.push(toolName);
|
|
11
92
|
const mergedConfig = {
|
|
12
93
|
...config,
|
|
13
94
|
annotations: {
|
|
@@ -18,18 +99,43 @@ cb) {
|
|
|
18
99
|
};
|
|
19
100
|
server.registerTool(toolName, mergedConfig, async (args) => {
|
|
20
101
|
const t0 = performance.now();
|
|
102
|
+
const ctx = getCtx();
|
|
103
|
+
const input = sanitizeArgs(args);
|
|
104
|
+
let ok = true;
|
|
105
|
+
let error = null;
|
|
106
|
+
let output = null;
|
|
21
107
|
try {
|
|
22
108
|
const result = await cb(args);
|
|
109
|
+
error = inferErrorFromResult(result);
|
|
110
|
+
if (error)
|
|
111
|
+
ok = false;
|
|
112
|
+
output = extractOutputMeta(result);
|
|
23
113
|
return result;
|
|
24
114
|
}
|
|
25
115
|
catch (err) {
|
|
116
|
+
ok = false;
|
|
117
|
+
error = toToolErrorEvent(err);
|
|
26
118
|
return handleToolError(err, toolName);
|
|
27
119
|
}
|
|
28
120
|
finally {
|
|
29
121
|
const elapsed = performance.now() - t0;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
122
|
+
logEvent({
|
|
123
|
+
v: 1,
|
|
124
|
+
event: "tool_call",
|
|
125
|
+
ts: new Date().toISOString(),
|
|
126
|
+
tool: toolName,
|
|
127
|
+
tool_category: toolCategory(toolName),
|
|
128
|
+
latency_ms: Number(elapsed.toFixed(1)),
|
|
129
|
+
ok,
|
|
130
|
+
token_hash: ctx?.tokenHash ?? null,
|
|
131
|
+
token_hash_sfr: ctx?.tokenHashSfr ?? null,
|
|
132
|
+
token_hash_plr: ctx?.tokenHashPlr ?? null,
|
|
133
|
+
request_id: ctx?.requestId ?? null,
|
|
134
|
+
mode: ctx?.mode ?? "stdio",
|
|
135
|
+
input,
|
|
136
|
+
output,
|
|
137
|
+
error,
|
|
138
|
+
});
|
|
33
139
|
}
|
|
34
140
|
});
|
|
35
141
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerToolSafe.js","sourceRoot":"","sources":["../../src/tools/registerToolSafe.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"registerToolSafe.js","sourceRoot":"","sources":["../../src/tools/registerToolSafe.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,12 @@ import { z } from "zod";
|
|
|
2
2
|
import { structuredResult, markdownTable, truncatedJson } from "../formatters.js";
|
|
3
3
|
import { action } from "../nextActions.js";
|
|
4
4
|
import { registerToolSafe } from "../registerToolSafe.js";
|
|
5
|
+
import { ApiError } from "../../services/httpClient.js";
|
|
5
6
|
const Input = z.object({
|
|
6
|
-
address: z.string().describe("Full property address
|
|
7
|
+
address: z.string().describe("Full property address exactly as recorded (e.g. '123 Main St, Phoenix, AZ 85004'). " +
|
|
8
|
+
"Must match dataset precisely — abbreviations (St/Ave/Blvd), directional prefixes (N/S/E/W), " +
|
|
9
|
+
"and unit numbers matter. If unsure, use sfr_search_properties with the zip code first to find " +
|
|
10
|
+
"the canonical address."),
|
|
7
11
|
});
|
|
8
12
|
export function registerBestBuyersTool(server, sfr) {
|
|
9
13
|
registerToolSafe(server, "sfr_best_buyers", {
|
|
@@ -13,48 +17,61 @@ export function registerBestBuyersTool(server, sfr) {
|
|
|
13
17
|
"Ideal for sellers, wholesalers, or agents matching properties to active buyers.",
|
|
14
18
|
inputSchema: Input,
|
|
15
19
|
}, async (args) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
i
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
try {
|
|
21
|
+
const data = await sfr.getBestBuyers(args.address);
|
|
22
|
+
const buyers = data?.data ?? data?.buyers ?? (Array.isArray(data) ? data : []);
|
|
23
|
+
const lines = [
|
|
24
|
+
`## Best Buyers — ${args.address}`,
|
|
25
|
+
`**Matches:** ${buyers.length} investors`,
|
|
26
|
+
"",
|
|
27
|
+
];
|
|
28
|
+
if (buyers.length > 0) {
|
|
29
|
+
// API returns {name, matchScore, totalAcquisitions, recentPurchasesCount, matchReasons}
|
|
30
|
+
const rows = buyers.slice(0, 25).map((b, i) => [
|
|
31
|
+
i + 1,
|
|
32
|
+
b.name ?? b.buyer_name ?? "—",
|
|
33
|
+
b.totalAcquisitions ?? b.acquisitions ?? "—",
|
|
34
|
+
b.recentPurchasesCount ?? "—",
|
|
35
|
+
b.matchScore != null ? `${b.matchScore}%` : "—",
|
|
36
|
+
Array.isArray(b.matchReasons) ? b.matchReasons[0] ?? "—" : "—",
|
|
37
|
+
]);
|
|
38
|
+
lines.push(markdownTable(["#", "Buyer", "Total Acq.", "Recent", "Match", "Reason"], rows));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
lines.push("```json");
|
|
42
|
+
lines.push(truncatedJson(data, 3000));
|
|
43
|
+
lines.push("```");
|
|
44
|
+
}
|
|
45
|
+
// Slim buyers — keep match-specific fields, strip URL slugs
|
|
46
|
+
const slimBuyers = buyers.slice(0, 25).map((b) => ({
|
|
47
|
+
name: b.name ?? b.buyer_name,
|
|
48
|
+
totalAcquisitions: b.totalAcquisitions ?? b.acquisitions,
|
|
49
|
+
recentPurchasesCount: b.recentPurchasesCount,
|
|
50
|
+
purchasesWithinQuarterMile: b.purchasesWithinQuarterMile || undefined,
|
|
51
|
+
matchScore: b.matchScore,
|
|
52
|
+
matchReasons: b.matchReasons,
|
|
53
|
+
hasProfile: b.hasProfilePage || undefined,
|
|
54
|
+
hasContact: b.hasContactInfo || undefined,
|
|
55
|
+
}));
|
|
56
|
+
const firstName = buyers[0]?.name ?? buyers[0]?.buyer_name;
|
|
57
|
+
const actions = [
|
|
58
|
+
...(firstName ? [action("sfr_buyer_profile", "Profile top match", { name: firstName })] : []),
|
|
59
|
+
...(firstName ? [action("sfr_buyer_growth", "Growth trend for top match", { name: firstName })] : []),
|
|
60
|
+
action("sfr_get_property", "Full property details", { address: args.address }),
|
|
61
|
+
];
|
|
62
|
+
return structuredResult(lines.join("\n"), { items: slimBuyers, total: buyers.length, page: 1 }, actions);
|
|
34
63
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
64
|
+
catch (err) {
|
|
65
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
66
|
+
const zipMatch = args.address.match(/\b(\d{5})\b/);
|
|
67
|
+
const zip = zipMatch?.[1];
|
|
68
|
+
return structuredResult(`## Best Buyers — ${args.address}\n\n` +
|
|
69
|
+
`_Property not found at this address. The address must exactly match the dataset ` +
|
|
70
|
+
`(including directional prefixes like 'E'/'W', abbreviations like 'St'/'Ave', and unit numbers). ` +
|
|
71
|
+
`Use sfr_search_properties with the zip code to find the canonical address._`, { address: args.address, error: "not_found" }, [action("sfr_search_properties", "Search by zip to find correct address", zip ? { search_type: "zip", zips: zip } : undefined)]);
|
|
72
|
+
}
|
|
73
|
+
throw err;
|
|
39
74
|
}
|
|
40
|
-
// Slim buyers — keep match-specific fields, strip URL slugs
|
|
41
|
-
const slimBuyers = buyers.slice(0, 25).map((b) => ({
|
|
42
|
-
name: b.name ?? b.buyer_name,
|
|
43
|
-
totalAcquisitions: b.totalAcquisitions ?? b.acquisitions,
|
|
44
|
-
recentPurchasesCount: b.recentPurchasesCount,
|
|
45
|
-
purchasesWithinQuarterMile: b.purchasesWithinQuarterMile || undefined,
|
|
46
|
-
matchScore: b.matchScore,
|
|
47
|
-
matchReasons: b.matchReasons,
|
|
48
|
-
hasProfile: b.hasProfilePage || undefined,
|
|
49
|
-
hasContact: b.hasContactInfo || undefined,
|
|
50
|
-
}));
|
|
51
|
-
const firstName = buyers[0]?.name ?? buyers[0]?.buyer_name;
|
|
52
|
-
const actions = [
|
|
53
|
-
...(firstName ? [action("sfr_buyer_profile", "Profile top match", { name: firstName })] : []),
|
|
54
|
-
...(firstName ? [action("sfr_buyer_growth", "Growth trend for top match", { name: firstName })] : []),
|
|
55
|
-
action("sfr_get_property", "Full property details", { address: args.address }),
|
|
56
|
-
];
|
|
57
|
-
return structuredResult(lines.join("\n"), { items: slimBuyers, total: buyers.length, page: 1 }, actions);
|
|
58
75
|
});
|
|
59
76
|
}
|
|
60
77
|
//# sourceMappingURL=bestBuyers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bestBuyers.js","sourceRoot":"","sources":["../../../src/tools/sfr/bestBuyers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"bestBuyers.js","sourceRoot":"","sources":["../../../src/tools/sfr/bestBuyers.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,8 +16,10 @@ export function registerBuyerProfileTool(server, sfr) {
|
|
|
16
16
|
"target property type, price range), geographic focus, related LLCs, and contact info. " +
|
|
17
17
|
"Includes flip vs hold percentages and target margin ranges. " +
|
|
18
18
|
"Returns relatedLLCs — use these names with sfr_flip_activity(buyer_name=) to find flip transactions across all entities. " +
|
|
19
|
+
"Note: relatedLLCs may return simplified/slug names rather than exact deed-recorded entity names for some investors. " +
|
|
19
20
|
"For iBuyer/flipper margin analysis, chain: buyer_profile → get relatedLLCs → sfr_flip_activity per LLC. " +
|
|
20
|
-
"
|
|
21
|
+
"Profiles exist for investors with significant recorded transaction volume (typically 50+ acquisitions). " +
|
|
22
|
+
"Smaller investors won't have profiles — use sfr_top_buyers to discover names. " +
|
|
21
23
|
"For acquisition trends over time, use sfr_buyer_growth. " +
|
|
22
24
|
"CHAIN: Use plr_borrower_search with the investor name to check if they borrow from private lenders.",
|
|
23
25
|
inputSchema: Input,
|
|
@@ -152,8 +154,9 @@ export function registerBuyerProfileTool(server, sfr) {
|
|
|
152
154
|
if (err instanceof ApiError && err.status === 404) {
|
|
153
155
|
const slug = slugifyBuyerName(args.name);
|
|
154
156
|
return structuredResult(`## Investor Profile — ${args.name}\n\n` +
|
|
155
|
-
`_No profile found (slug: "${slug}").
|
|
156
|
-
`
|
|
157
|
+
`_No profile found (slug: "${slug}"). Profiles exist only for investors with significant transaction volume ` +
|
|
158
|
+
`(typically 50+ acquisitions). Note: sfr_top_buyers may show hasProfile=true for buyers whose profiles ` +
|
|
159
|
+
`don't resolve — this is a known upstream data inconsistency. Use sfr_top_buyers to discover names._`, { name: args.name, slug, error: "not_found" }, [action("sfr_top_buyers", "Find buyers with profiles", {})]);
|
|
157
160
|
}
|
|
158
161
|
throw err;
|
|
159
162
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buyerProfile.js","sourceRoot":"","sources":["../../../src/tools/sfr/buyerProfile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACvB,yEAAyE;QACzE,qEAAqE,CACtE;CACF,CAAC,CAAC;AAEH,MAAM,UAAU,wBAAwB,CAAC,MAAiB,EAAE,GAAc;IACxE,gBAAgB,CAAC,MAAM,EACrB,mBAAmB,EACnB;QACE,KAAK,EAAE,mCAAmC;QAC1C,WAAW,EACT,oEAAoE;YACpE,wFAAwF;YACxF,wFAAwF;YACxF,8DAA8D;YAC9D,2HAA2H;YAC3H,0GAA0G;YAC1G,
|
|
1
|
+
{"version":3,"file":"buyerProfile.js","sourceRoot":"","sources":["../../../src/tools/sfr/buyerProfile.ts"],"names":[],"mappings":"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"}
|