feat: add 9 provider presets, latency indicator, fix _start_proxy bug, fix sandbox/approval flags, update Antigravity models
This commit is contained in:
@@ -444,18 +444,20 @@ PROVIDER_PRESETS = {
|
||||
"gemini-2.5-flash", "gemini-2.5-pro",
|
||||
],
|
||||
},
|
||||
"Google Antigravity (OAuth)": {
|
||||
"backend_type": "gemini-oauth-antigravity",
|
||||
"base_url": "https://cloudcode-pa.googleapis.com",
|
||||
"oauth_provider": "google-antigravity",
|
||||
"models": [
|
||||
"Gemini 3.5 Flash (High)", "Gemini 3.5 Flash (Medium)", "Gemini 3.5 Flash (Low)",
|
||||
"Gemini 3.1 Pro (High)", "Gemini 3.1 Pro (Low)",
|
||||
"Claude Sonnet 4.6 (Thinking)",
|
||||
"Claude Opus 4.6 (Thinking)",
|
||||
"GPT-OSS 120B (Medium)",
|
||||
],
|
||||
},
|
||||
"Google Antigravity (OAuth)": {
|
||||
"backend_type": "gemini-oauth-antigravity",
|
||||
"base_url": "https://cloudcode-pa.googleapis.com",
|
||||
"oauth_provider": "google-antigravity",
|
||||
"models": [
|
||||
"antigravity-gemini-3-flash",
|
||||
"antigravity-gemini-3-pro",
|
||||
"antigravity-gemini-3.1-pro",
|
||||
"antigravity-claude-sonnet-4-6",
|
||||
"antigravity-claude-opus-4-6-thinking",
|
||||
"gemini-2.5-flash", "gemini-2.5-pro",
|
||||
"gemini-3-flash-preview", "gemini-3-pro-preview", "gemini-3.1-pro-preview",
|
||||
],
|
||||
},
|
||||
"OpenAdapter": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "https://api.openadapter.in/v1",
|
||||
@@ -503,6 +505,46 @@ PROVIDER_PRESETS = {
|
||||
"moonshotai/kimi-k2.6", "minimax/minimax-m2.7",
|
||||
],
|
||||
},
|
||||
"Perplexity": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "https://api.perplexity.ai",
|
||||
"models": ["sonar", "sonar-pro", "sonar-reasoning-pro", "sonar-deep-research"],
|
||||
},
|
||||
"Cohere": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "https://api.cohere.ai/compatibility/v1",
|
||||
"models": [],
|
||||
},
|
||||
"Hugging Face": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "https://router.huggingface.co/v1",
|
||||
"models": [],
|
||||
},
|
||||
"Together AI": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "https://api.together.xyz/v1",
|
||||
"models": [],
|
||||
},
|
||||
"Groq": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "https://api.groq.com/openai/v1",
|
||||
"models": [],
|
||||
},
|
||||
"Fireworks AI": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "https://api.fireworks.ai/inference/v1",
|
||||
"models": [],
|
||||
},
|
||||
"LM Studio (local)": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "http://127.0.0.1:1234/v1",
|
||||
"models": [],
|
||||
},
|
||||
"vLLM / OpenAI-Compatible (self-hosted)": {
|
||||
"backend_type": "openai-compat",
|
||||
"base_url": "http://localhost:8000/v1",
|
||||
"models": [],
|
||||
},
|
||||
}
|
||||
|
||||
def safe_name(name):
|
||||
@@ -519,6 +561,7 @@ def label_for_backend(backend_type):
|
||||
"anthropic": "Anthropic",
|
||||
"command-code": "Command Code",
|
||||
"codebuff": "Codebuff (Free AI)",
|
||||
"freebuff": "Freebuff (Free AI)",
|
||||
"native": "Native",
|
||||
}.get(backend_type, backend_type)
|
||||
|
||||
@@ -569,6 +612,27 @@ def apply_provider_preset(endpoint, preset_name):
|
||||
updated["default_model"] = updated["models"][0]
|
||||
return updated
|
||||
|
||||
def _check_provider_latency(endpoint, timeout=5):
|
||||
import urllib.request
|
||||
base_url = (endpoint.get("base_url") or "").rstrip("/")
|
||||
api_key = endpoint.get("api_key", "")
|
||||
bt = endpoint.get("backend_type", "openai-compat")
|
||||
if not base_url or not api_key:
|
||||
return None
|
||||
url = base_url + "/models" if not base_url.endswith("/models") else base_url
|
||||
headers = {"Authorization": f"Bearer {api_key}"}
|
||||
if bt == "anthropic":
|
||||
headers = {"x-api-key": api_key, "anthropic-version": "2023-06-01"}
|
||||
url = base_url.replace("/v1", "") + "/v1/models" if "/v1" not in base_url else base_url + "/models"
|
||||
try:
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
t0 = time.time()
|
||||
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
||||
resp.read(1)
|
||||
return time.time() - t0
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _doctor_check_streaming(base_url, key, bt, model, add):
|
||||
if bt == "anthropic":
|
||||
test_url = f"{base_url}/v1/messages"
|
||||
@@ -2086,6 +2150,10 @@ class LauncherWin(Gtk.Window):
|
||||
self._combo.connect("changed", lambda c: self._on_endpoint_changed())
|
||||
sel_box.pack_start(self._combo, True, True, 0)
|
||||
|
||||
self._latency_label = Gtk.Label(label=" -- ")
|
||||
self._latency_label.set_opacity(0.7)
|
||||
sel_box.pack_start(self._latency_label, False, False, 4)
|
||||
|
||||
# model selector
|
||||
sel_box.pack_start(Gtk.Label(label="Model:"), False, False, 0)
|
||||
self._model_combo = Gtk.ComboBoxText()
|
||||
@@ -2288,10 +2356,11 @@ class LauncherWin(Gtk.Window):
|
||||
|
||||
def _on_endpoint_changed(self):
|
||||
name = self._combo.get_active_text()
|
||||
is_bgp = name and name.startswith("🔀 ")
|
||||
is_bgp = name and name.startswith("\U0001f500 ")
|
||||
bgp_name = name[2:] if is_bgp else None
|
||||
ep = get_endpoint(name) if name and not is_bgp else None
|
||||
self._model_combo.remove_all()
|
||||
self._check_latency(name)
|
||||
if is_bgp:
|
||||
pool = None
|
||||
for p in load_bgp_pools().get("pools", []):
|
||||
@@ -2320,6 +2389,34 @@ class LauncherWin(Gtk.Window):
|
||||
elif models:
|
||||
self._model_combo.set_active(0)
|
||||
|
||||
def _check_latency(self, ep_name):
|
||||
self._latency_label.set_text("...")
|
||||
is_bgp = ep_name and ep_name.startswith("\U0001f500 ")
|
||||
if is_bgp or not ep_name:
|
||||
self._latency_label.set_text(" -- ")
|
||||
return
|
||||
ep = get_endpoint(ep_name)
|
||||
if not ep:
|
||||
self._latency_label.set_text(" -- ")
|
||||
return
|
||||
|
||||
def _run():
|
||||
lat = _check_provider_latency(ep)
|
||||
def _update():
|
||||
if lat is None:
|
||||
self._latency_label.set_text(" -- ")
|
||||
self._latency_label.set_opacity(0.5)
|
||||
elif lat < 1.0:
|
||||
self._latency_label.set_text(f" {lat:.2f}s")
|
||||
self._latency_label.set_markup(f'<span foreground="#2ea043">{lat:.2f}s</span>')
|
||||
elif lat < 3.0:
|
||||
self._latency_label.set_markup(f'<span foreground="#d29922">{lat:.2f}s</span>')
|
||||
else:
|
||||
self._latency_label.set_markup(f'<span foreground="#e74c3c">{lat:.2f}s</span>')
|
||||
GLib.idle_add(_update)
|
||||
|
||||
threading.Thread(target=_run, daemon=True).start()
|
||||
|
||||
# ── endpoint mgr ─────────────────────────────────────────────
|
||||
|
||||
def _open_mgr(self):
|
||||
@@ -2406,7 +2503,7 @@ class LauncherWin(Gtk.Window):
|
||||
return
|
||||
for ep in load_endpoints().get("endpoints", []):
|
||||
if ep.get("name") == ep_name:
|
||||
self._start_proxy(ep)
|
||||
_start_proxy_for(ep, self.log)
|
||||
break
|
||||
except Exception as e:
|
||||
self.log(f"[AI Monitor] Proxy restart failed: {e}")
|
||||
@@ -2421,7 +2518,7 @@ class LauncherWin(Gtk.Window):
|
||||
return
|
||||
for ep in load_endpoints().get("endpoints", []):
|
||||
if ep.get("name") == ep_name:
|
||||
self._start_proxy(ep)
|
||||
_start_proxy_for(ep, self.log)
|
||||
self.log("Proxy restarted")
|
||||
break
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user