mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-12 20:57:42 +02:00
[eric] free-trial: hand the wheel back when a real model is connected mid-trial (key or 9router sub)
This commit is contained in:
@@ -1602,7 +1602,7 @@ class AgentManager:
|
||||
"ANTHROPIC_BASE_URL": proxy_url,
|
||||
# Pin subagent ids; CLI default 'claude-haiku-4-5-20251001'
|
||||
# gets rejected by Pro's surface as "No credentials for provider: anthropic".
|
||||
# (Free-trial down-routes all of these to Haiku server-side.)
|
||||
# (Free-trial clamps to its allowed Claude set + weights credits server-side.)
|
||||
"CLAUDE_CODE_SUBAGENT_MODEL": "claude-sonnet-4-6",
|
||||
"ANTHROPIC_SMALL_FAST_MODEL": "claude-haiku-4-5-20251001",
|
||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5-20251001",
|
||||
|
||||
@@ -143,6 +143,23 @@ async def update_settings(body: AppSettings):
|
||||
for k in SERVER_OWNED_FIELDS:
|
||||
setattr(body, k, getattr(old, k, None))
|
||||
|
||||
# If the user connects their own model while the free trial is armed, hand
|
||||
# the wheel back to their provider. Without this, connection_mode (server-
|
||||
# owned, so the loop above just restored it to "free-trial") would keep them
|
||||
# pinned to the forced Haiku lane even though they pasted a real key.
|
||||
if getattr(old, "connection_mode", "own_key") == "free-trial":
|
||||
from backend.apps.subscription.free_trial import _has_own_model
|
||||
if _has_own_model(body):
|
||||
body.connection_mode = "own_key"
|
||||
body.free_trial_token = None
|
||||
body.free_trial_remaining = None
|
||||
try:
|
||||
import asyncio as _aio
|
||||
from backend.apps.nine_router import sync_pro_routing as _spr
|
||||
_aio.create_task(_spr(body)) # drop the now-stale free-trial 9router node
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
secret_keys = {"anthropic_api_key", "openai_api_key", "google_api_key", "openrouter_api_key",
|
||||
"claude_subscription_token", "openai_subscription_token", "gemini_subscription_token",
|
||||
"openswarm_bearer_token", "free_trial_token", "installation_id"}
|
||||
|
||||
@@ -74,7 +74,7 @@ def _fingerprint(settings_obj) -> str | None:
|
||||
|
||||
|
||||
def _has_own_model(s) -> bool:
|
||||
"""True if the user already has any real model path; never shadow it."""
|
||||
"""True if the user already has any real model path in settings; never shadow it."""
|
||||
if any(getattr(s, k, None) for k in (
|
||||
"anthropic_api_key", "openai_api_key", "google_api_key", "openrouter_api_key",
|
||||
"claude_subscription_token", "openai_subscription_token", "gemini_subscription_token",
|
||||
@@ -90,6 +90,23 @@ def _has_own_model(s) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
async def _has_connected_subscription() -> bool:
|
||||
"""True if 9Router holds a live Claude/ChatGPT/Gemini subscription. Those
|
||||
connections live in 9Router, not settings, so the sync check above misses
|
||||
them; this catches a sub connected while the trial was armed."""
|
||||
try:
|
||||
from backend.apps.nine_router import is_running as _9r_running, get_providers as _9r_providers
|
||||
if not _9r_running():
|
||||
return False
|
||||
conns = await _9r_providers()
|
||||
return any(
|
||||
c.get("isActive") and c.get("provider") in ("claude", "codex", "gemini-cli")
|
||||
for c in conns
|
||||
)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _proxy_base(settings_obj) -> str:
|
||||
return (getattr(settings_obj, "openswarm_proxy_url", None) or OPENSWARM_DEFAULT_PROXY_URL).rstrip("/")
|
||||
|
||||
@@ -117,9 +134,14 @@ async def arm_free_trial(settings_obj) -> dict:
|
||||
free-trial mode. Guarded: never arms over a real key/subscription."""
|
||||
if not _enabled():
|
||||
return {"armed": False, "reason": "disabled"}
|
||||
if getattr(settings_obj, "connection_mode", "own_key") not in ("own_key", "free-trial"):
|
||||
mode = getattr(settings_obj, "connection_mode", "own_key")
|
||||
if mode not in ("own_key", "free-trial"):
|
||||
return {"armed": False, "reason": "other_mode"}
|
||||
if _has_own_model(settings_obj):
|
||||
if _has_own_model(settings_obj) or await _has_connected_subscription():
|
||||
# A real model exists now (key, custom provider, or a 9Router sub). If we
|
||||
# were on the free lane, hand the wheel back instead of re-arming.
|
||||
if mode == "free-trial":
|
||||
await clear_free_trial(settings_obj)
|
||||
return {"armed": False, "reason": "has_model"}
|
||||
|
||||
fp = _fingerprint(settings_obj)
|
||||
|
||||
Reference in New Issue
Block a user