CatoG commited on
Commit ·
788f59d
1
Parent(s): 35b0f08
more precise geoloc
Browse files
app.py
CHANGED
|
@@ -407,8 +407,49 @@ def generate_uuid(_: str = "") -> str:
|
|
| 407 |
|
| 408 |
@tool
|
| 409 |
def get_user_location(_: str = "") -> str:
|
| 410 |
-
"""Determine the user's
|
| 411 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
url = f"http://ip-api.com/json/{client_ip}" if client_ip else "http://ip-api.com/json/"
|
| 413 |
try:
|
| 414 |
response = requests.get(url, timeout=5)
|
|
@@ -423,7 +464,8 @@ def get_user_location(_: str = "") -> str:
|
|
| 423 |
f"Latitude: {data.get('lat', 'N/A')}\n"
|
| 424 |
f"Longitude: {data.get('lon', 'N/A')}\n"
|
| 425 |
f"Timezone: {data.get('timezone', 'N/A')}\n"
|
| 426 |
-
f"ISP: {data.get('isp', 'N/A')}"
|
|
|
|
| 427 |
)
|
| 428 |
except requests.RequestException as exc:
|
| 429 |
return f"Location lookup failed: {exc}"
|
|
@@ -587,7 +629,7 @@ def build_debug_report(
|
|
| 587 |
def run_agent(message, history, selected_tools, model_id, client_ip: str = ""):
|
| 588 |
history = history or []
|
| 589 |
|
| 590 |
-
# Store
|
| 591 |
_request_context.client_ip = client_ip.strip() if client_ip else ""
|
| 592 |
|
| 593 |
if not message or not str(message).strip():
|
|
@@ -733,7 +775,8 @@ with gr.Blocks(title="Provider Multi-Model Agent", theme=gr.themes.Soft()) as de
|
|
| 733 |
interactive=False,
|
| 734 |
)
|
| 735 |
|
| 736 |
-
# Populated by JavaScript on page load with
|
|
|
|
| 737 |
client_ip_box = gr.Textbox(visible=False, value="")
|
| 738 |
|
| 739 |
demo.load(
|
|
@@ -741,13 +784,26 @@ with gr.Blocks(title="Provider Multi-Model Agent", theme=gr.themes.Soft()) as de
|
|
| 741 |
inputs=None,
|
| 742 |
outputs=[client_ip_box],
|
| 743 |
js="""async () => {
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
|
| 748 |
-
|
| 749 |
-
|
| 750 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 751 |
}""",
|
| 752 |
)
|
| 753 |
|
|
|
|
| 407 |
|
| 408 |
@tool
|
| 409 |
def get_user_location(_: str = "") -> str:
|
| 410 |
+
"""Determine the user's precise physical location using browser GPS/WiFi coordinates or IP fallback."""
|
| 411 |
+
location_data = getattr(_request_context, "client_ip", "") or ""
|
| 412 |
+
|
| 413 |
+
# Precise coordinates from browser geolocation API
|
| 414 |
+
if location_data and not location_data.startswith("ip:"):
|
| 415 |
+
try:
|
| 416 |
+
lat_str, lon_str = location_data.split(",", 1)
|
| 417 |
+
lat, lon = float(lat_str), float(lon_str)
|
| 418 |
+
except ValueError:
|
| 419 |
+
return "Location lookup failed: invalid coordinate data."
|
| 420 |
+
try:
|
| 421 |
+
headers = {"User-Agent": "HFAgent/1.0 (location lookup)"}
|
| 422 |
+
resp = requests.get(
|
| 423 |
+
"https://nominatim.openstreetmap.org/reverse",
|
| 424 |
+
params={"lat": lat, "lon": lon, "format": "json", "addressdetails": 1},
|
| 425 |
+
headers=headers,
|
| 426 |
+
timeout=8,
|
| 427 |
+
)
|
| 428 |
+
resp.raise_for_status()
|
| 429 |
+
data = resp.json()
|
| 430 |
+
addr = data.get("address", {})
|
| 431 |
+
city = (
|
| 432 |
+
addr.get("city")
|
| 433 |
+
or addr.get("town")
|
| 434 |
+
or addr.get("village")
|
| 435 |
+
or addr.get("municipality")
|
| 436 |
+
or addr.get("county")
|
| 437 |
+
or "N/A"
|
| 438 |
+
)
|
| 439 |
+
return (
|
| 440 |
+
f"City: {city}\n"
|
| 441 |
+
f"County: {addr.get('county', 'N/A')}\n"
|
| 442 |
+
f"Region: {addr.get('state', 'N/A')}\n"
|
| 443 |
+
f"Country: {addr.get('country', 'N/A')} ({addr.get('country_code', 'N/A').upper()})\n"
|
| 444 |
+
f"Latitude: {lat}\n"
|
| 445 |
+
f"Longitude: {lon}\n"
|
| 446 |
+
f"Source: Browser GPS/WiFi (precise)"
|
| 447 |
+
)
|
| 448 |
+
except requests.RequestException as exc:
|
| 449 |
+
return f"Reverse geocoding failed: {exc}"
|
| 450 |
+
|
| 451 |
+
# IP-based fallback
|
| 452 |
+
client_ip = location_data[3:] if location_data.startswith("ip:") else ""
|
| 453 |
url = f"http://ip-api.com/json/{client_ip}" if client_ip else "http://ip-api.com/json/"
|
| 454 |
try:
|
| 455 |
response = requests.get(url, timeout=5)
|
|
|
|
| 464 |
f"Latitude: {data.get('lat', 'N/A')}\n"
|
| 465 |
f"Longitude: {data.get('lon', 'N/A')}\n"
|
| 466 |
f"Timezone: {data.get('timezone', 'N/A')}\n"
|
| 467 |
+
f"ISP: {data.get('isp', 'N/A')}\n"
|
| 468 |
+
f"Source: IP geolocation (approximate)"
|
| 469 |
)
|
| 470 |
except requests.RequestException as exc:
|
| 471 |
return f"Location lookup failed: {exc}"
|
|
|
|
| 629 |
def run_agent(message, history, selected_tools, model_id, client_ip: str = ""):
|
| 630 |
history = history or []
|
| 631 |
|
| 632 |
+
# Store location data in thread-local so get_user_location can read it
|
| 633 |
_request_context.client_ip = client_ip.strip() if client_ip else ""
|
| 634 |
|
| 635 |
if not message or not str(message).strip():
|
|
|
|
| 775 |
interactive=False,
|
| 776 |
)
|
| 777 |
|
| 778 |
+
# Populated by JavaScript on page load with precise browser coordinates (GPS/WiFi),
|
| 779 |
+
# stored as "lat,lon". Falls back to the public IP via ipify if geolocation is denied.
|
| 780 |
client_ip_box = gr.Textbox(visible=False, value="")
|
| 781 |
|
| 782 |
demo.load(
|
|
|
|
| 784 |
inputs=None,
|
| 785 |
outputs=[client_ip_box],
|
| 786 |
js="""async () => {
|
| 787 |
+
return new Promise((resolve) => {
|
| 788 |
+
if (navigator.geolocation) {
|
| 789 |
+
navigator.geolocation.getCurrentPosition(
|
| 790 |
+
(pos) => resolve(pos.coords.latitude + ',' + pos.coords.longitude),
|
| 791 |
+
async () => {
|
| 792 |
+
try {
|
| 793 |
+
const r = await fetch('https://api.ipify.org?format=json');
|
| 794 |
+
const d = await r.json();
|
| 795 |
+
resolve('ip:' + d.ip);
|
| 796 |
+
} catch(e) { resolve(''); }
|
| 797 |
+
},
|
| 798 |
+
{timeout: 8000, maximumAge: 60000}
|
| 799 |
+
);
|
| 800 |
+
} else {
|
| 801 |
+
fetch('https://api.ipify.org?format=json')
|
| 802 |
+
.then(r => r.json())
|
| 803 |
+
.then(d => resolve('ip:' + d.ip))
|
| 804 |
+
.catch(() => resolve(''));
|
| 805 |
+
}
|
| 806 |
+
});
|
| 807 |
}""",
|
| 808 |
)
|
| 809 |
|