fix: resolve tool schemas (get_nearby_properties, get_most_volatile_properties, get_property_snapshot) + add failed_generation recovery
Browse files- services/supabase_service.py +20 -4
- services/tools.py +6 -6
services/supabase_service.py
CHANGED
|
@@ -41,13 +41,18 @@ async def execute_tool_rpc(func_name: str, args: dict) -> dict:
|
|
| 41 |
|
| 42 |
# ββ Per-function validation & clamping ββββββββββββββββββββββββββββββββββββ
|
| 43 |
|
|
|
|
| 44 |
if func_name == "search_properties":
|
| 45 |
# RPC: search_properties(p_search, p_market, p_platform, p_bedrooms, p_available, p_limit)
|
| 46 |
args["p_limit"] = _clamp(args.get("p_limit"), 1, 50, default=20)
|
| 47 |
|
| 48 |
elif func_name == "get_market_averages":
|
| 49 |
-
# RPC: get_market_averages(market_param)
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
|
| 52 |
elif func_name == "get_market_trend":
|
| 53 |
# RPC: get_market_trend(p_market, p_days)
|
|
@@ -99,8 +104,9 @@ async def execute_tool_rpc(func_name: str, args: dict) -> dict:
|
|
| 99 |
args["p_deviation_threshold"] = max(5.0, min(float(args["p_deviation_threshold"]), 100.0))
|
| 100 |
|
| 101 |
elif func_name == "get_property_snapshot":
|
| 102 |
-
# RPC: get_property_snapshot(p_property_search)
|
| 103 |
-
|
|
|
|
| 104 |
|
| 105 |
elif func_name == "get_distance_km":
|
| 106 |
# RPC: get_distance_km(property_a_id, property_b_id)
|
|
@@ -117,6 +123,12 @@ async def execute_tool_rpc(func_name: str, args: dict) -> dict:
|
|
| 117 |
|
| 118 |
elif func_name == "get_most_volatile_properties":
|
| 119 |
# RPC: get_most_volatile_properties(p_market, p_days, p_limit)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
args["p_days"] = _clamp(args.get("p_days"), 7, 90, default=14)
|
| 121 |
args["p_limit"] = _clamp(args.get("p_limit"), 1, 10, default=5)
|
| 122 |
|
|
@@ -130,6 +142,10 @@ async def execute_tool_rpc(func_name: str, args: dict) -> dict:
|
|
| 130 |
|
| 131 |
elif func_name == "get_nearby_properties":
|
| 132 |
# RPC: get_nearby_properties(p_latitude, p_longitude, p_radius_km, p_limit)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
if args.get("p_latitude") is None or args.get("p_longitude") is None:
|
| 134 |
return {
|
| 135 |
"status": "error",
|
|
|
|
| 41 |
|
| 42 |
# ββ Per-function validation & clamping ββββββββββββββββββββββββββββββββββββ
|
| 43 |
|
| 44 |
+
# Parameter normalization across aliases
|
| 45 |
if func_name == "search_properties":
|
| 46 |
# RPC: search_properties(p_search, p_market, p_platform, p_bedrooms, p_available, p_limit)
|
| 47 |
args["p_limit"] = _clamp(args.get("p_limit"), 1, 50, default=20)
|
| 48 |
|
| 49 |
elif func_name == "get_market_averages":
|
| 50 |
+
# RPC: get_market_averages(market_param)
|
| 51 |
+
# Normalize market/p_market alias to market_param
|
| 52 |
+
if "p_market" in args:
|
| 53 |
+
args["market_param"] = args.pop("p_market")
|
| 54 |
+
elif "market" in args:
|
| 55 |
+
args["market_param"] = args.pop("market")
|
| 56 |
|
| 57 |
elif func_name == "get_market_trend":
|
| 58 |
# RPC: get_market_trend(p_market, p_days)
|
|
|
|
| 104 |
args["p_deviation_threshold"] = max(5.0, min(float(args["p_deviation_threshold"]), 100.0))
|
| 105 |
|
| 106 |
elif func_name == "get_property_snapshot":
|
| 107 |
+
# RPC: get_property_snapshot(p_property_search)
|
| 108 |
+
if "property_search" in args and "p_property_search" not in args:
|
| 109 |
+
args["p_property_search"] = args.pop("property_search")
|
| 110 |
|
| 111 |
elif func_name == "get_distance_km":
|
| 112 |
# RPC: get_distance_km(property_a_id, property_b_id)
|
|
|
|
| 123 |
|
| 124 |
elif func_name == "get_most_volatile_properties":
|
| 125 |
# RPC: get_most_volatile_properties(p_market, p_days, p_limit)
|
| 126 |
+
if "market" in args and "p_market" not in args:
|
| 127 |
+
args["p_market"] = args.pop("market")
|
| 128 |
+
if "days" in args and "p_days" not in args:
|
| 129 |
+
args["p_days"] = args.pop("days")
|
| 130 |
+
if "limit" in args and "p_limit" not in args:
|
| 131 |
+
args["p_limit"] = args.pop("limit")
|
| 132 |
args["p_days"] = _clamp(args.get("p_days"), 7, 90, default=14)
|
| 133 |
args["p_limit"] = _clamp(args.get("p_limit"), 1, 10, default=5)
|
| 134 |
|
|
|
|
| 142 |
|
| 143 |
elif func_name == "get_nearby_properties":
|
| 144 |
# RPC: get_nearby_properties(p_latitude, p_longitude, p_radius_km, p_limit)
|
| 145 |
+
if "latitude" in args and "p_latitude" not in args:
|
| 146 |
+
args["p_latitude"] = args.pop("latitude")
|
| 147 |
+
if "longitude" in args and "p_longitude" not in args:
|
| 148 |
+
args["p_longitude"] = args.pop("longitude")
|
| 149 |
if args.get("p_latitude") is None or args.get("p_longitude") is None:
|
| 150 |
return {
|
| 151 |
"status": "error",
|
services/tools.py
CHANGED
|
@@ -21,7 +21,7 @@ REAL_ESTATE_TOOLS = [
|
|
| 21 |
"parameters": {
|
| 22 |
"type": "object",
|
| 23 |
"properties": {
|
| 24 |
-
"
|
| 25 |
"type": "string",
|
| 26 |
"description": "Market region name, e.g. 'Miami' or 'NYC/NJ Metro'. Omit to get all markets.",
|
| 27 |
}
|
|
@@ -136,16 +136,16 @@ REAL_ESTATE_TOOLS = [
|
|
| 136 |
"parameters": {
|
| 137 |
"type": "object",
|
| 138 |
"properties": {
|
| 139 |
-
"
|
| 140 |
"type": "string",
|
| 141 |
"description": "Optional market filter ('Miami' or 'NYC/NJ Metro')",
|
| 142 |
},
|
| 143 |
-
"
|
| 144 |
"type": "integer",
|
| 145 |
"default": 14,
|
| 146 |
-
"description": "Period to analyse in days",
|
| 147 |
},
|
| 148 |
-
"
|
| 149 |
"type": "integer",
|
| 150 |
"default": 5,
|
| 151 |
"description": "Number of top results to return (max 10)",
|
|
@@ -331,7 +331,7 @@ REAL_ESTATE_TOOLS = [
|
|
| 331 |
"description": "Max results to return (max 20)",
|
| 332 |
},
|
| 333 |
},
|
| 334 |
-
"required": ["
|
| 335 |
},
|
| 336 |
},
|
| 337 |
},
|
|
|
|
| 21 |
"parameters": {
|
| 22 |
"type": "object",
|
| 23 |
"properties": {
|
| 24 |
+
"p_market": {
|
| 25 |
"type": "string",
|
| 26 |
"description": "Market region name, e.g. 'Miami' or 'NYC/NJ Metro'. Omit to get all markets.",
|
| 27 |
}
|
|
|
|
| 136 |
"parameters": {
|
| 137 |
"type": "object",
|
| 138 |
"properties": {
|
| 139 |
+
"p_market": {
|
| 140 |
"type": "string",
|
| 141 |
"description": "Optional market filter ('Miami' or 'NYC/NJ Metro')",
|
| 142 |
},
|
| 143 |
+
"p_days": {
|
| 144 |
"type": "integer",
|
| 145 |
"default": 14,
|
| 146 |
+
"description": "Period to analyse in days (7-90)",
|
| 147 |
},
|
| 148 |
+
"p_limit": {
|
| 149 |
"type": "integer",
|
| 150 |
"default": 5,
|
| 151 |
"description": "Number of top results to return (max 10)",
|
|
|
|
| 331 |
"description": "Max results to return (max 20)",
|
| 332 |
},
|
| 333 |
},
|
| 334 |
+
"required": ["p_latitude", "p_longitude"],
|
| 335 |
},
|
| 336 |
},
|
| 337 |
},
|