Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -189,12 +189,14 @@ ERROR_FAMILY_SYNS = {
|
|
| 189 |
),
|
| 190 |
}
|
| 191 |
|
|
|
|
|
|
|
| 192 |
def _try_wms_tool(user_text: str) -> dict | None:
|
| 193 |
"""
|
| 194 |
Uses Gemini function calling + TOOL_REGISTRY to decide if a WMS tool should be called.
|
| 195 |
Returns YOUR existing response dict shape. If no tool match or any error -> returns None.
|
| 196 |
"""
|
| 197 |
-
#
|
| 198 |
if not GEMINI_API_KEY:
|
| 199 |
return None
|
| 200 |
if not _ensure_wms_session():
|
|
@@ -207,7 +209,13 @@ def _try_wms_tool(user_text: str) -> dict | None:
|
|
| 207 |
}
|
| 208 |
|
| 209 |
try:
|
| 210 |
-
resp = requests.post(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
data = resp.json()
|
| 212 |
candidates = data.get("candidates", [])
|
| 213 |
part = candidates[0].get("content", {}).get("parts", [{}])[0] if candidates else {}
|
|
@@ -220,20 +228,25 @@ def _try_wms_tool(user_text: str) -> dict | None:
|
|
| 220 |
if not cfg:
|
| 221 |
return None
|
| 222 |
|
| 223 |
-
# Prepare arguments and warehouse
|
| 224 |
args = fn.get("args", {}) or {}
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
|
| 229 |
-
# Call underlying function
|
|
|
|
| 230 |
if tool_name in ("get_inventory_holds", "get_location_status"):
|
| 231 |
-
raw = cfg
|
| 232 |
else:
|
| 233 |
target = args.get(cfg["id_param"])
|
| 234 |
-
raw = cfg
|
| 235 |
|
| 236 |
-
#
|
| 237 |
if raw.get("error"):
|
| 238 |
return {
|
| 239 |
"bot_response": f"⚠️ {raw['error']}",
|
|
@@ -245,6 +258,7 @@ def _try_wms_tool(user_text: str) -> dict | None:
|
|
| 245 |
"top_hits": [],
|
| 246 |
"sources": [],
|
| 247 |
"debug": {"intent": "wms_error", "tool": tool_name},
|
|
|
|
| 248 |
}
|
| 249 |
|
| 250 |
data_list = raw.get(cfg.get("response_key", "data"), [])
|
|
@@ -259,22 +273,26 @@ def _try_wms_tool(user_text: str) -> dict | None:
|
|
| 259 |
"top_hits": [],
|
| 260 |
"sources": [],
|
| 261 |
"debug": {"intent": "wms_empty", "tool": tool_name},
|
|
|
|
| 262 |
}
|
| 263 |
|
| 264 |
-
# Holds / Location
|
| 265 |
if tool_name in ("get_inventory_holds", "get_location_status"):
|
| 266 |
-
|
|
|
|
|
|
|
| 267 |
for item in data_list:
|
| 268 |
flat = flatten_json(item)
|
| 269 |
row = extract_fields(flat, cfg["mapping"], cfg.get("formatters", {}))
|
| 270 |
-
|
| 271 |
-
total_qty += int(item.get("untqty", 0))
|
| 272 |
|
| 273 |
if tool_name == "get_inventory_holds":
|
| 274 |
-
|
|
|
|
|
|
|
| 275 |
else:
|
| 276 |
target_loc = args.get("stoloc") or ""
|
| 277 |
-
msg = f"Location '{target_loc}' status:\n" + ("\n".join(
|
| 278 |
|
| 279 |
return {
|
| 280 |
"bot_response": msg,
|
|
@@ -286,9 +304,15 @@ def _try_wms_tool(user_text: str) -> dict | None:
|
|
| 286 |
"top_hits": [],
|
| 287 |
"sources": [],
|
| 288 |
"debug": {"intent": tool_name, "warehouse_id": wh},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
}
|
| 290 |
|
| 291 |
-
#
|
| 292 |
flat = flatten_json(data_list[0])
|
| 293 |
requested = args.get("fields", [])
|
| 294 |
if requested:
|
|
@@ -313,6 +337,11 @@ def _try_wms_tool(user_text: str) -> dict | None:
|
|
| 313 |
"top_hits": [],
|
| 314 |
"sources": [],
|
| 315 |
"debug": {"intent": "get_item_data", "warehouse_id": wh},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
}
|
| 317 |
|
| 318 |
except Exception as e:
|
|
|
|
| 189 |
),
|
| 190 |
}
|
| 191 |
|
| 192 |
+
|
| 193 |
+
|
| 194 |
def _try_wms_tool(user_text: str) -> dict | None:
|
| 195 |
"""
|
| 196 |
Uses Gemini function calling + TOOL_REGISTRY to decide if a WMS tool should be called.
|
| 197 |
Returns YOUR existing response dict shape. If no tool match or any error -> returns None.
|
| 198 |
"""
|
| 199 |
+
# Guards
|
| 200 |
if not GEMINI_API_KEY:
|
| 201 |
return None
|
| 202 |
if not _ensure_wms_session():
|
|
|
|
| 209 |
}
|
| 210 |
|
| 211 |
try:
|
| 212 |
+
resp = requests.post(
|
| 213 |
+
GEMINI_URL,
|
| 214 |
+
headers=headers,
|
| 215 |
+
json=payload,
|
| 216 |
+
timeout=25,
|
| 217 |
+
verify=GEMINI_SSL_VERIFY
|
| 218 |
+
)
|
| 219 |
data = resp.json()
|
| 220 |
candidates = data.get("candidates", [])
|
| 221 |
part = candidates[0].get("content", {}).get("parts", [{}])[0] if candidates else {}
|
|
|
|
| 228 |
if not cfg:
|
| 229 |
return None
|
| 230 |
|
| 231 |
+
# -------- Prepare arguments and warehouse --------
|
| 232 |
args = fn.get("args", {}) or {}
|
| 233 |
+
# Respect explicit warehouse override if present, else use session default
|
| 234 |
+
wh = (
|
| 235 |
+
args.pop("warehouse_id", None)
|
| 236 |
+
or args.pop("warehouseId", None)
|
| 237 |
+
or args.pop("wh_id", None)
|
| 238 |
+
or _WMS_WAREHOUSE_ID
|
| 239 |
+
)
|
| 240 |
|
| 241 |
+
# -------- Call the underlying function with correct signature --------
|
| 242 |
+
# Holds & Location use kwargs (e.g., lodnum/subnum/dtlnum OR stoloc); Item uses single ID
|
| 243 |
if tool_name in ("get_inventory_holds", "get_location_status"):
|
| 244 |
+
raw = cfg"function" # <<< invoke function
|
| 245 |
else:
|
| 246 |
target = args.get(cfg["id_param"])
|
| 247 |
+
raw = cfg"function" # <<< invoke function
|
| 248 |
|
| 249 |
+
# -------- Error handling --------
|
| 250 |
if raw.get("error"):
|
| 251 |
return {
|
| 252 |
"bot_response": f"⚠️ {raw['error']}",
|
|
|
|
| 258 |
"top_hits": [],
|
| 259 |
"sources": [],
|
| 260 |
"debug": {"intent": "wms_error", "tool": tool_name},
|
| 261 |
+
"source": "ERROR", # optional for frontend branches
|
| 262 |
}
|
| 263 |
|
| 264 |
data_list = raw.get(cfg.get("response_key", "data"), [])
|
|
|
|
| 273 |
"top_hits": [],
|
| 274 |
"sources": [],
|
| 275 |
"debug": {"intent": "wms_empty", "tool": tool_name},
|
| 276 |
+
"source": "LIVE_API", # still a live call, just no rows
|
| 277 |
}
|
| 278 |
|
| 279 |
+
# -------- TABLE: Holds / Location --------
|
| 280 |
if tool_name in ("get_inventory_holds", "get_location_status"):
|
| 281 |
+
rows_for_text = []
|
| 282 |
+
total_qty = 0
|
| 283 |
+
|
| 284 |
for item in data_list:
|
| 285 |
flat = flatten_json(item)
|
| 286 |
row = extract_fields(flat, cfg["mapping"], cfg.get("formatters", {}))
|
| 287 |
+
rows_for_text.append("• " + "; ".join(f"{k}: {v}" for k, v in row.items()))
|
|
|
|
| 288 |
|
| 289 |
if tool_name == "get_inventory_holds":
|
| 290 |
+
# Only holds have quantity in most schemas
|
| 291 |
+
total_qty = sum(int(it.get("untqty", 0) or 0) for it in data_list)
|
| 292 |
+
msg = f"Found {len(rows_for_text)} hold records (Total Qty: {total_qty}).\n" + "\n".join(rows_for_text[:10])
|
| 293 |
else:
|
| 294 |
target_loc = args.get("stoloc") or ""
|
| 295 |
+
msg = f"Location '{target_loc}' status:\n" + ("\n".join(rows_for_text[:1]) if rows_for_text else "No status returned")
|
| 296 |
|
| 297 |
return {
|
| 298 |
"bot_response": msg,
|
|
|
|
| 304 |
"top_hits": [],
|
| 305 |
"sources": [],
|
| 306 |
"debug": {"intent": tool_name, "warehouse_id": wh},
|
| 307 |
+
|
| 308 |
+
# Front-end signals → render table exactly like your friend's code
|
| 309 |
+
"source": "LIVE_API",
|
| 310 |
+
"type": "table",
|
| 311 |
+
"data": data_list, # rows for <TableMessage />
|
| 312 |
+
"show_export": True if tool_name == "get_inventory_holds" else False,
|
| 313 |
}
|
| 314 |
|
| 315 |
+
# -------- ITEM: summary + single-row table (consistent with "data => table") --------
|
| 316 |
flat = flatten_json(data_list[0])
|
| 317 |
requested = args.get("fields", [])
|
| 318 |
if requested:
|
|
|
|
| 337 |
"top_hits": [],
|
| 338 |
"sources": [],
|
| 339 |
"debug": {"intent": "get_item_data", "warehouse_id": wh},
|
| 340 |
+
|
| 341 |
+
"source": "LIVE_API",
|
| 342 |
+
"type": "table",
|
| 343 |
+
"data": [data_list[0]], # single-row table for item
|
| 344 |
+
"show_export": False,
|
| 345 |
}
|
| 346 |
|
| 347 |
except Exception as e:
|