From 3786f931b5b9acdde118153dfce977f7cde97f86 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Wed, 4 Nov 2026 18:58:42 +0800 Subject: [PATCH 1/4] feat(accounts): separate steward API primary from worker fallback Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- .../codex-account-settings.tsx | 9 +- .../openai-key-settings.tsx | 26 ++- .../capabilities/native_chat/codex_adapter.py | 4 + loopx/capabilities/native_chat/codex_auth.py | 39 ++++ loopx/chat_agent.py | 29 ++- loopx/chat_manager.py | 27 +-- loopx/chat_runtime.py | 7 +- loopx/presentation/codex_accounts_api.py | 2 +- .../loopx-codex-provider-routing/NATIVE.md | 29 +++ .../account-workload-primary-desktop.png | Bin 0 -> 106503 bytes .../account-workload-primary-narrow.png | Bin 0 -> 47047 bytes .../extension.toml | 2 +- .../pyproject.toml | 2 +- .../smoke/native-policy.test.mjs | 25 ++- .../loopx_codex_provider_routing/native.py | 58 +++++- .../native_policy.ts | 33 +++- .../native_policy_bridge.ts | 4 +- .../openai_relay.py | 54 ++++-- tests/test_chat_account_workloads.py | 166 ++++++++++++++++++ tests/test_chat_manager_model_adoption.py | 3 +- 20 files changed, 469 insertions(+), 50 deletions(-) create mode 100644 packages/loopx-codex-provider-routing/docs/assets/account-workload-primary-desktop.png create mode 100644 packages/loopx-codex-provider-routing/docs/assets/account-workload-primary-narrow.png create mode 100644 tests/test_chat_account_workloads.py diff --git a/apps/presentation/dashboard/src/features/personal-workspace/codex-account-settings.tsx b/apps/presentation/dashboard/src/features/personal-workspace/codex-account-settings.tsx index 7aa8c133dd..0df572b0d9 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/codex-account-settings.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/codex-account-settings.tsx @@ -12,9 +12,10 @@ type AccountStatus = { active_slot?: string | null; selection_revision?: string; action?: string; target?: string | null; recovery_required?: boolean; launch_failed?: boolean; api_fallback_supported?: boolean; api_active?: boolean; + steward_api_role_supported?: boolean; observer?: { state: string; checked_at: number | null; next_check_at: number | null }; policy?: { enabled: boolean; slots: string[]; cooldown_seconds: number; restart_clients?: boolean; - force_quit_clients?: boolean; api_fallback?: boolean }; + force_quit_clients?: boolean; api_fallback?: boolean; steward_api_role?: "disabled" | "fallback" | "primary" }; slots?: string[]; last_checked_at?: number | null; last_switch_at?: number | null; accounts?: Array<{ slot: string; availability: string; observed_at: number; primary_used: number | null; secondary_used: number | null; reset_at: number | null; @@ -174,6 +175,7 @@ export function CodexAccountSettings() { method: "POST", body: JSON.stringify({ operation, parameters }), }); setStatus(result); + if (operation === "configure") await read(); } catch { await read(); setError(true); } finally { setBusy(false); void readInventory(); } } @@ -188,6 +190,11 @@ export function CodexAccountSettings() { const appProcesses = new Map(); for (const client of appHolders) appProcesses.set(client.process, [...(appProcesses.get(client.process) ?? []), client.pid]); return <> void act("configure", { + expected_revision: status?.revision, enabled, slots: authorizedSlots, steward_api_role: value, + })} apiEnabled={status?.policy?.api_fallback === true} nativeBusy={busy || ["checking", "restarting", "handoff_pending"].includes(status?.action ?? "")} onToggle={value => void act("configure", { expected_revision: status?.revision, enabled, slots: authorizedSlots, api_fallback: value, })} />
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/openai-key-settings.tsx b/apps/presentation/dashboard/src/features/personal-workspace/openai-key-settings.tsx index 164b992a23..bcb48ba1a1 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/openai-key-settings.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/openai-key-settings.tsx @@ -20,9 +20,10 @@ type KeyStatus = z.infer; const copy = { "zh-CN": { - title: "OpenAI API Key", configured: "已保存", boundary: "订阅账号优先,全部耗尽后使用 API", - help: "API Key 与额度", detail: "密钥只保存在本机,不回显完整值。启用 API 接续后,只有订阅账号均被确认耗尽才使用 API;订阅恢复后在安全边界回到订阅。API 额度或权限错误会在输出前尝试下一把 Key,保留当前模型,不重放已开始输出的请求。检查连接只读取模型列表,不能证明可消费额度。项目 Key 无法查询账单余额,费用查询需另有 Admin Key。", - auto: "订阅耗尽后使用 API(按用量计费)", autoOff: "需先启用下方的订阅自动切换", ownerMissing: "LoopX 账号扩展需要更新,暂不能启用 API 接续", + title: "OpenAI API Key", configured: "已保存", boundary: "工作 Agent 与 Codex App:订阅优先,API 仅作兜底", + help: "API Key 与额度", detail: "密钥只保存在本机,不回显完整值。工作 Agent 只有在全部订阅被确认耗尽后才使用 API,额度未知时等待。管家可独立优先使用 API,复用同一 Key 池,不切换工作 Agent 或 Codex App 的登录;关闭管家 API 不影响工作 Agent 的兜底。管家选择跟随订阅兜底时,使用下方订阅自动切换的耗尽证明。策略在下一条未开始的消息生效,不重放已有请求。API 额度或权限错误只在输出前尝试下一把 Key,模型不变。检查连接只读模型列表,不能证明可消费额度;项目 Key 无法查询账单余额。", + auto: "工作 Agent 订阅耗尽后使用 API(按用量计费)", autoOff: "需先启用下方的订阅自动切换", ownerMissing: "LoopX 账号扩展需要更新,暂不能启用 API 接续", + steward: "管家使用 API", primary: "优先使用(按用量计费)", fallback: "跟随订阅兜底", disabled: "不使用", lastRequest: "上次响应", accepted: "API 已接受请求", quota_exhausted: "API 额度不足", failed: "API 请求失败", tokens: "限流窗口 Token 余量", requests: "限流窗口请求余量", apiPermission: "API 模型权限不足", apiLimited: "API 请求限流", balance: "API 余额不可读取", billing: "查看 OpenAI 用量", add: "添加 Key", save: "保存 Key", cancel: "取消", @@ -37,9 +38,10 @@ const copy = { key_limit_reached: "最多保存 16 把 Key。", key_not_found: "这把 Key 已被移除,列表已刷新。", }, en: { - title: "OpenAI API keys", configured: "saved", boundary: "Subscriptions first; API only after all subscriptions are exhausted", - help: "API keys and quota", detail: "Keys stay on this machine and are never returned in full. API fallback is admitted only after every subscription is confirmed exhausted. Recovered subscriptions take priority at a safe handoff boundary. API quota or permission errors can try the next key before output, preserving the model. Requests that started output are never replayed. Connection checks only read the model list and do not establish spendable quota. Project keys cannot query billing balance; the Costs API requires a separate Admin key.", - auto: "Use API after subscription exhaustion (usage based billing)", autoOff: "Enable subscription automatic handoff below first", ownerMissing: "Update the LoopX accounts extension before enabling API fallback", + title: "OpenAI API keys", configured: "saved", boundary: "Working Agents and Codex App: subscriptions first; API as fallback", + help: "API keys and quota", detail: "Keys stay on this machine and are never returned in full. Working Agents use API only after every subscription is confirmed exhausted; unknown allowance holds. The steward can independently prefer API through the same key pool without changing worker or Codex App login. Disabling steward API preserves worker fallback. Following subscription fallback uses the native account owner's exhaustion proof. Changes apply to the next unstarted message and never replay existing requests. API quota or permission errors may try the next key only before output, preserving the model. Connection checks read models, not spendable quota. Project keys cannot query billing balance.", + auto: "Use API after working Agent subscriptions are exhausted (usage based billing)", autoOff: "Enable subscription automatic handoff below first", ownerMissing: "Update the LoopX accounts extension before enabling API fallback", + steward: "Steward API use", primary: "Prefer API (usage based billing)", fallback: "Follow subscription fallback", disabled: "Disabled", lastRequest: "Last response", accepted: "API accepted the request", quota_exhausted: "API quota exhausted", failed: "API request failed", tokens: "Rate-window tokens left", requests: "Rate-window requests left", apiPermission: "API model permission denied", apiLimited: "API request rate limited", balance: "API balance unavailable", billing: "View OpenAI usage", add: "Add key", save: "Save key", cancel: "Cancel", @@ -55,8 +57,11 @@ const copy = { }, }; -export function OpenAIKeySettings({ automatic, supported, apiEnabled, onToggle, nativeBusy = false }: { +export function OpenAIKeySettings({ automatic, supported, apiEnabled, onToggle, nativeBusy = false, + stewardSupported = false, stewardRole = "disabled", onStewardRole }: { automatic: boolean; supported: boolean | null; apiEnabled: boolean; onToggle: (enabled: boolean) => void; nativeBusy?: boolean; + stewardSupported?: boolean; stewardRole?: "disabled" | "fallback" | "primary"; + onStewardRole?: (role: "disabled" | "fallback" | "primary") => void; }) { const { locale } = useWorkspaceI18n(); const c = copy[locale]; @@ -112,6 +117,13 @@ export function OpenAIKeySettings({ automatic, supported, apiEnabled, onToggle, disabled={busy || nativeBusy || (!apiEnabled && (!automatic || !supported || !status?.keys.length))} onChange={event => onToggle(event.target.checked)} />{c.auto} {!apiEnabled && supported === false ?

{c.ownerMissing}

: !apiEnabled && !automatic ?

{c.autoOff}

: null} + {stewardSupported ? : null} {status ? <>
{status.keys.map(row =>
diff --git a/loopx/capabilities/native_chat/codex_adapter.py b/loopx/capabilities/native_chat/codex_adapter.py index 1bed7bd812..f9a89e80fc 100644 --- a/loopx/capabilities/native_chat/codex_adapter.py +++ b/loopx/capabilities/native_chat/codex_adapter.py @@ -321,6 +321,8 @@ def start( reasoning_effort: str | None = None, service_tier: str | None = None, dynamic_tools: list[dict[str, Any]] | None = None, + account_runtime_root: Path | None = None, + account_consumer: str = "worker", ) -> "CodexAppServerAdapter": history_items = [] # Migration restores the full visible conversation in native history. @@ -358,6 +360,8 @@ def start( reasoning_effort=reasoning_effort, host_config={"service_tier": service_tier} if service_tier else None, dynamic_tools=dynamic_tools, + account_runtime_root=account_runtime_root, + account_consumer=account_consumer, ) if not resume_thread_id: try: diff --git a/loopx/capabilities/native_chat/codex_auth.py b/loopx/capabilities/native_chat/codex_auth.py index adc6b33725..a37ffcca76 100644 --- a/loopx/capabilities/native_chat/codex_auth.py +++ b/loopx/capabilities/native_chat/codex_auth.py @@ -117,3 +117,42 @@ def for_isolated_process(base_home: Path, isolated_home: Path, codex_bin: str) - if (isolated_home / "auth.json").exists() or not (base_home / "auth.json").exists(): return None return CodexHostModelAuth(base_home, codex_bin) + + +@dataclass(repr=False) +class CodexApiTransport: + """Only a consumer-scoped loopback token reaches the model process.""" + endpoint: str + token: str = field(repr=False) + provider: str = "loopx_account_api" + env_key: str = "LOOPX_MODEL_RELAY_TOKEN" + + def configuration(self, current: dict[str, Any], effective: dict[str, Any] | None = None) -> dict[str, Any]: + # Native overlays merge maps, so a lower-layer alias must not supply + # another URL/header/env key beneath our model-only transport. + if self.provider in (effective or {}).get("model_providers", {}): + raise CodexHostAuthUnavailable() + environment = current.get("shell_environment_policy", {}) + exclude = [*environment.get("exclude", [])] + if self.env_key not in exclude: + exclude.append(self.env_key) + return {**current, "model_provider": self.provider, "model_providers": { + **current.get("model_providers", {}), self.provider: { + "name": "LoopX account API", "base_url": self.endpoint, + "env_key": self.env_key, "wire_api": "responses", + "requires_openai_auth": False, "supports_websockets": False}}, + "shell_environment_policy": {**environment, + "exclude": exclude}} + + +def native_api_transport(runtime_root: Path, base_home: Path, *, consumer: str, + model: str | None = None) -> CodexApiTransport | None: + try: + from loopx_codex_provider_routing.native import NativeAccounts + except ImportError: + return None # Optional provider absence preserves native authentication. + try: + endpoint = NativeAccounts(runtime_root).model_transport(codex_home=base_home, consumer=consumer, model=model) + return CodexApiTransport(endpoint['base_url'], endpoint['api_key']) if endpoint else None + except Exception: + raise CodexHostAuthUnavailable() from None diff --git a/loopx/chat_agent.py b/loopx/chat_agent.py index 99a8a2bba3..b63acbcc2f 100644 --- a/loopx/chat_agent.py +++ b/loopx/chat_agent.py @@ -745,6 +745,8 @@ def start( dynamic_tools: list[dict[str, Any]] | None = None, host_config: dict[str, Any] | None = None, launch_guard: Callable[[], AbstractContextManager[None]] | None = None, + account_runtime_root: Path | None = None, + account_consumer: str = "worker", _compatibility_catalog_path: Path | None = None, ) -> "CodexChatAgentSession": resolved = shutil.which(codex_bin) @@ -850,6 +852,23 @@ def start( runtime_env.get("LOOPX_CHAT_CODEX_MODEL_PROVIDER", "").strip() if not execution_mode else "" ) + account_base_config = host_config + api_transport = None + if (account_runtime_root is not None and not execution_mode and not provider_override + and not (host_config or {}).get("model_provider") + and (not permissions_profile or not (runtime_home / "auth.json").exists() + and not (runtime_home / "auth.json").is_symlink())): + from .capabilities.native_chat.codex_auth import native_api_transport + try: + api_transport = native_api_transport(account_runtime_root, base_home, + consumer=account_consumer, model=model) + if api_transport is not None: + runtime_env[api_transport.env_key] = api_transport.token + host_config = api_transport.configuration(host_config or {}) + provider_override = api_transport.provider + except Exception: + raise CodexChatAgentError("Native account API transport is unavailable.", + error_code="model_auth_unavailable", gate=None) from None command = [resolved, "app-server"] if permissions_profile: # Keep this native store independent even when the account's @@ -938,7 +957,7 @@ def start( request_id=1, ) session._notify("initialized", {}) - if permissions_profile: + if permissions_profile and api_transport is None: from .capabilities.native_chat.codex_auth import for_isolated_process try: session._host_model_auth = for_isolated_process(base_home, runtime_home, resolved) @@ -961,7 +980,7 @@ def start( # copying auth, restarting clients or replacing the original thread. follow_native_provider = bool(resume_thread_id and not execution_mode and (not permissions_profile or metadata_review_context is not None) and not provider_override) - read_native_config = read_project_defaults or bool(permissions_profile) or owner_git_write or follow_native_provider + read_native_config = read_project_defaults or bool(permissions_profile) or owner_git_write or follow_native_provider or api_transport is not None if read_native_config: # Resume otherwise inherits the old thread's model/effort, even # when the owner's effective workspace configuration has changed. @@ -974,6 +993,8 @@ def start( effective = config_result.get("config", {}) if not isinstance(effective, dict): raise session._runtime_error("Codex returned an invalid project configuration.") + if api_transport is not None: + host_config = api_transport.configuration(host_config or {}, effective) if owner_git_write: # Preserve the native workspace policy (including network # and temporary-directory settings). A separate named @@ -1151,8 +1172,10 @@ def start( model=model, reasoning_effort=reasoning_effort, dynamic_tools=dynamic_tools, - host_config=host_config, + host_config=account_base_config if api_transport is not None else host_config, launch_guard=launch_guard, + account_runtime_root=account_runtime_root, + account_consumer=account_consumer, _compatibility_catalog_path=catalog_path, ) except Exception: diff --git a/loopx/chat_manager.py b/loopx/chat_manager.py index 406703179a..f2304e1fb9 100644 --- a/loopx/chat_manager.py +++ b/loopx/chat_manager.py @@ -958,32 +958,39 @@ def manager_session_quota_route(controller: Any, session: Mapping[str, Any]) -> return None native = session if session.get("agent_id") == "antigravity" else next((row for row in reversed(session.get("upstream_context_history") or []) if row.get("agent_id") == "antigravity"), None) - if native is None: - return None try: from .capabilities.native_chat.antigravity_adapter import AntigravityAdapter, ANTIGRAVITY_DEFAULT_MODEL from loopx_codex_provider_routing.native import NativeAccounts - capacity = AntigravityAdapter.metadata_review_capacity( - cascade_id=str(native.get("upstream_thread_id") or native.get("thread_id")), - model_id=str(native.get("agent_model_id") or ANTIGRAVITY_DEFAULT_MODEL)) - route = NativeAccounts(controller.coordination_runtime_root).steward_route( - codex_home=controller.codex_home, primary="antigravity", + environment = dict(operator_credential_resolution(controller)["environ"]) + codex_environment = {key: value for key, value in environment.items() + if key not in (MANAGER_MODEL_ENV_VAR, MANAGER_REASONING_EFFORT_ENV_VAR)} + accounts = NativeAccounts(controller.coordination_runtime_root) + route_inputs = dict(codex_home=controller.codex_home, primary="antigravity", pool=_manager_eligible_endpoints(defaults), current=str(session["agent_id"]), - primary_capacity=capacity, blocked_primary=session.get("manager_quota_block")) + blocked_primary=session.get("manager_quota_block"), + model=manager_model_resolution(codex_environment, endpoint="codex", machine_defaults=defaults)[0]) + capacity = None + # Explicit API primary does not depend on an unrelated subscription + # transport being up. The same owner holds when that role is absent. + route = accounts.steward_route(**route_inputs, primary_capacity=None) + if route.get("endpoint") is None and native: + capacity = AntigravityAdapter.metadata_review_capacity( + cascade_id=str(native.get("upstream_thread_id") or native.get("thread_id")), + model_id=str(native.get("agent_model_id") or ANTIGRAVITY_DEFAULT_MODEL)) + route = accounts.steward_route(**route_inputs, primary_capacity=capacity) endpoint = route.get("endpoint") if endpoint is None: return None capabilities = controller.capabilities() if not any(row.get("agent_id") == endpoint and row.get("available") is True for row in capabilities): return None - environment = dict(operator_credential_resolution(controller)["environ"]) if endpoint != "antigravity": environment.pop("LOOPX_MANAGER_MODEL", None) environment.pop("LOOPX_MANAGER_REASONING_EFFORT", None) allocation = manager_executor_allocation(controller, machine_defaults=defaults, environ=environment, endpoint_capabilities=[{**row, "available": row.get("agent_id") == endpoint} for row in capabilities]) return {"allocation": allocation, "blocked_primary": route.get("blocked_primary"), - "observed_at": capacity["observed_at"]} + "observed_at": capacity["observed_at"] if capacity else None} except Exception as exc: import logging logging.getLogger(__name__).warning("Steward quota observation held (%s)", type(exc).__name__) diff --git a/loopx/chat_runtime.py b/loopx/chat_runtime.py index e77e631b23..0e7d39f858 100644 --- a/loopx/chat_runtime.py +++ b/loopx/chat_runtime.py @@ -416,6 +416,8 @@ def _start_adapter( from .chat_loopx_mode import TOOL as COLLABORATION_TOOL return CodexAppServerAdapter.start( codex_bin=self.codex_bin, + account_runtime_root=self.coordination_runtime_root, + account_consumer="steward" if manager_profile is not None or metadata_review_context is not None else "worker", codex_home=codex_home_override or self.codex_home, work_dir=Path(metadata_review_context["workspace_path"]) if metadata_review_context else work_dir, goal_id=None if metadata_review_context else goal_id, @@ -864,7 +866,10 @@ def check_route_configuration(): and active.get("origin") != "native_loopx"): try: from loopx_codex_provider_routing.native import NativeAccounts - native_account_epoch = NativeAccounts(self.coordination_runtime_root).conversation_epoch(codex_home=selected_codex_home) + native_account_epoch = NativeAccounts(self.coordination_runtime_root).conversation_epoch( + codex_home=selected_codex_home, **({"consumer": "steward", + "model": (model_allocation or {}).get("model") or session.get("agent_model_id")} + if manager_runtime is not None else {})) except ImportError: pass # Optional account automation is absent, not a Chat failure. except Exception as exc: diff --git a/loopx/presentation/codex_accounts_api.py b/loopx/presentation/codex_accounts_api.py index cdc1492898..064b6f3f19 100644 --- a/loopx/presentation/codex_accounts_api.py +++ b/loopx/presentation/codex_accounts_api.py @@ -171,7 +171,7 @@ def _codex_accounts_write(self) -> None: if set(body) != {"operation", "parameters"} or not isinstance(body["parameters"], dict): raise ValueError("Invalid account operation") operation, parameters = body["operation"], body["parameters"] - fields = {"configure": {"expected_revision", "enabled", "slots", "reconnect", "restart_clients", "force_quit_clients", "api_fallback"}, + fields = {"configure": {"expected_revision", "enabled", "slots", "reconnect", "restart_clients", "force_quit_clients", "api_fallback", "steward_api_role"}, "enroll-current": {"expected_revision", "expected_selection"}, "switch": {"manual_slot", "expected_selection", "operation_id"}, "recover": {"expected_revision", "expected_selection"}, "rollback": {"expected_revision", "expected_selection"}, diff --git a/packages/loopx-codex-provider-routing/NATIVE.md b/packages/loopx-codex-provider-routing/NATIVE.md index 6d553982e7..6305008fbf 100644 --- a/packages/loopx-codex-provider-routing/NATIVE.md +++ b/packages/loopx-codex-provider-routing/NATIVE.md @@ -132,6 +132,35 @@ An invalid or unreadable slot is not skipped to manufacture a unique match. This reconciliation never rewrites credentials or configuration, and does not prove that an already running client has reloaded its login. +Version 0.15.0 separates a consumer's API role from its model choice. Working +Agents and Codex App retain subscription-first ordering: `api_fallback` permits +API only after every allowed subscription has fresh measured exhaustion. +Unknown allowance never authorizes paid fallback. The account settings also +offer `steward_api_role`: `primary` prefers the existing API key pool for the +steward, `fallback` follows subscription fallback, and `disabled` excludes API +from the steward. An absent field preserves the prior fallback configuration. +Steward API primary does not require enabling subscription automation. + +The steward uses a separate authenticated loopback route and a process-only +token excluded from shell tool environments. Upstream keys stay in the same private +key owner. Thread configuration selects this model transport without rewriting +the desktop login or copying credentials/history into project stores. Explicit +native provider overrides and independently authenticated project stores retain +their chosen transport. Changes apply between Turns; they authorize neither +redispatch nor replay of an interrupted request. A model-list check is not proof +of inference allowance. Known quota/authentication/permission/rate-limit +rejections may try another key before output; unknown network effects or an +already started stream never replay. API primary unavailability allows the +existing endpoint pool to consider its subscription route; it does not move a +worker to API. The API role is local vocabulary owned by this optional account +provider, not a new Core execution authority or Goal state. + +Built account settings with synthetic account data / 使用合成账号数据的设置界面: + +![Independent account priorities, desktop / 独立账号优先级,桌面](docs/assets/account-workload-primary-desktop.png) + +![Independent account priorities, narrow / 独立账号优先级,窄屏](docs/assets/account-workload-primary-narrow.png) + ## Prerequisites and activation Install in the same Python environment as LoopX, then restart its App/Chat service: diff --git a/packages/loopx-codex-provider-routing/docs/assets/account-workload-primary-desktop.png b/packages/loopx-codex-provider-routing/docs/assets/account-workload-primary-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..fe44f06e05292d3568092f023fdcc59dc426c1f5 GIT binary patch literal 106503 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 literal 0 HcmV?d00001 diff --git a/packages/loopx-codex-provider-routing/extension.toml b/packages/loopx-codex-provider-routing/extension.toml index d83b59522b..1f07436e1d 100644 --- a/packages/loopx-codex-provider-routing/extension.toml +++ b/packages/loopx-codex-provider-routing/extension.toml @@ -1,6 +1,6 @@ schema_version = "loopx_extension_manifest_v0" id = "loopx-codex-provider-routing" -version = "0.14.1" +version = "0.15.0" requires_loopx_api = ">=1,<2" permissions = [] diff --git a/packages/loopx-codex-provider-routing/pyproject.toml b/packages/loopx-codex-provider-routing/pyproject.toml index 1a1b45731c..4f16d7b8d8 100644 --- a/packages/loopx-codex-provider-routing/pyproject.toml +++ b/packages/loopx-codex-provider-routing/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "loopx-codex-provider-routing" -version = "0.14.1" +version = "0.15.0" description = "Native Codex account slots and exhausted-account handoff for LoopX" readme = "README.md" requires-python = ">=3.11" diff --git a/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs b/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs index 9b886cf95f..0493eac4b0 100644 --- a/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs +++ b/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs @@ -1,8 +1,31 @@ import assert from "node:assert/strict"; import { test } from "node:test"; -import { account, decide, observerHealth } from "../src/loopx_codex_provider_routing/native_policy.ts"; +import { account, apiRole, decide, modelRoute, observerHealth, stewardRoute } from "../src/loopx_codex_provider_routing/native_policy.ts"; const now = 1000; +test("consumer API roles never make a working Agent API primary", () => { + const policy = {enabled: false, slots: [], cooldown_seconds: 300, api_fallback: false, steward_api_role: "primary"}; + const native = {policy, active_slot: "a", api_active: false}; + assert.equal(apiRole(policy, "worker"), "disabled"); + assert.equal(apiRole({...policy, api_fallback: true}, "worker"), "fallback"); + assert.equal(apiRole(policy, "unrecognized-consumer"), "disabled"); + assert.equal(modelRoute({consumer: "worker", native, api_ready: true}).api, false); + assert.equal(modelRoute({consumer: "steward", native, api_ready: true}).api, true); + assert.equal(modelRoute({consumer: "steward", native, api_ready: false}).api, false); + assert.equal(stewardRoute({now, primary: "antigravity", pool: ["antigravity", "codex"], + current: "antigravity", native, api_ready: true, primary_capacity: null}).endpoint, "codex"); + assert.equal(stewardRoute({now, primary: "antigravity", pool: ["antigravity"], + current: "antigravity", native, api_ready: true, primary_capacity: null}).endpoint, null); + for (const role of ["disabled", "fallback", "corrupt-role"]) { + assert.equal(modelRoute({consumer: "steward", native: {...native, policy: {...policy, steward_api_role: role}}, api_ready: true}).api, false); + } + // Legacy fallback remains the account owner's already admitted route. + const fallback = {...native, policy: {...policy, enabled: true, api_fallback: true, steward_api_role: "fallback"}, + api_active: true, login_matches: true, recovery_required: false, action: "api_active"}; + assert.equal(modelRoute({consumer: "steward", native: fallback, api_ready: true}).api, true); + assert.equal(modelRoute({consumer: "steward", native: {...fallback, recovery_required: true}, api_ready: true}).api, false); + assert.equal(modelRoute({consumer: "steward", native: {...fallback, policy: {...fallback.policy, steward_api_role: "disabled"}}, api_ready: true}).api, false); +}); test("observer health requires a held owner and a fresh matching build heartbeat", () => { const healthy = {now, owner_locked: true, build: "current", heartbeat: {checked_at: now, deadline_at: now + 75, next_check_at: now + 60, diff --git a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py index 75c5fcca09..3e56f56d19 100644 --- a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py +++ b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py @@ -170,6 +170,7 @@ def _projection(self, state: dict, native: dict | None = None) -> dict: "observer": self.observer_health(state["policy"]["enabled"]), "active_slot": native.get("active_slot"), "api_fallback_supported": native.get("api_fallback_supported", False), + "steward_api_role_supported": True, "api_active": native.get("api_slot") is not None and native.get("active_slot") == native.get("api_slot"), "selection_revision": native.get("selection_revision"), "login_matches": native.get("current_login_matches"), @@ -217,7 +218,7 @@ def status(self) -> dict: native = self.transport(adapter, "status") return self._projection(state, native) - def conversation_epoch(self, *, codex_home: Path) -> tuple[str, str] | None: + def conversation_epoch(self, *, codex_home: Path, consumer: str = "worker", model: str | None = None) -> tuple[str, str] | None: """An existing Chat process observes the native owner's login revision. The caller may reopen its idle adapter, never restart the account owner @@ -225,8 +226,12 @@ def conversation_epoch(self, *, codex_home: Path) -> tuple[str, str] | None: """ state = self._load() adapter = state.get("adapter") - if (state["policy"].get("enabled") is not True or not adapter - or Path(adapter.get("profile", {}).get("home", "")).resolve() != codex_home.resolve()): + if adapter and Path(adapter.get("profile", {}).get("home", "")).resolve() != codex_home.resolve(): + return None + if consumer == "steward" and policy({"operation": "api-role", "policy": state["policy"], + "consumer": consumer})["role"] == "primary": + return (f'steward-api:{state["revision"]}:{self.api_keys().status()["revision"]}:{bool(self.api_keys().candidates(model or ""))}', "openai-api") + if state["policy"].get("enabled") is not True or not adapter: return None native = self.transport(adapter, "status") if (native.get("current_login_matches") is not True or native.get("recovery_required") @@ -236,12 +241,20 @@ def conversation_epoch(self, *, codex_home: Path) -> tuple[str, str] | None: return (revision, slot) if isinstance(revision, str) and revision and isinstance(slot, str) and slot else None def steward_route(self, *, codex_home: Path, primary: str, pool: list[str], current: str, - primary_capacity: dict | None, blocked_primary: dict | None = None) -> dict: + primary_capacity: dict | None, blocked_primary: dict | None = None, model: str | None = None) -> dict: """Observe the existing account owner; never start a second watcher.""" state = self._load() adapter = state.get("adapter") - if (state["policy"].get("enabled") is not True or not adapter - or Path(adapter.get("profile", {}).get("home", "")).resolve() != codex_home.resolve()): + if adapter and Path(adapter.get("profile", {}).get("home", "")).resolve() != codex_home.resolve(): + return {"endpoint": None, "blocked_primary": blocked_primary} + api_ready = bool(self.api_keys().candidates(model or "")) if state["policy"].get("steward_api_role") == "primary" else False + if api_ready: + return policy({"operation": "steward-route", "now": self.clock(), "primary": primary, + "pool": pool, "current": current, "native": self._projection(state), "api_ready": True, + "primary_capacity": primary_capacity, "blocked_primary": blocked_primary}) + if primary_capacity is None: + return {"endpoint": None, "blocked_primary": blocked_primary} + if state["policy"].get("enabled") is not True or not adapter: return {"endpoint": None, "blocked_primary": blocked_primary} native = self.transport(adapter, "status") return policy({"operation": "steward-route", "now": self.clock(), @@ -249,6 +262,30 @@ def steward_route(self, *, codex_home: Path, primary: str, pool: list[str], curr "native": self._projection(state, native), "primary_capacity": primary_capacity, "blocked_primary": blocked_primary}) + def model_transport(self, *, codex_home: Path, consumer: str, model: str | None = None) -> dict | None: + """A model-only local relay; never select the desktop login or copy keys.""" + state = self._load() + adapter = state.get("adapter") + if adapter and Path(adapter.get("profile", {}).get("home", "")).resolve() != codex_home.resolve(): + return None + role = policy({"operation": "api-role", "policy": state["policy"], "consumer": consumer})["role"] + if role == "primary": + native = self._projection(state) + else: + if state["policy"].get("enabled") is not True or not adapter: + return None + native = self._projection(state, self.transport(adapter, "status")) + route = policy({"operation": "model-route", "consumer": consumer, "native": native, + "api_ready": bool(self.api_keys().candidates(model or "")) if role == "primary" else False}) + if not route["api"]: + if native.get("api_active") and consumer == "steward" and role == "disabled": + raise HostError("steward_api_disabled") + if role == "primary" and native.get("api_active"): + raise HostError("api_keys_unavailable") + return None + from .openai_relay import ensure + return ensure(self, consumer=consumer) + def clients(self) -> dict: state = self._load() return self.transport(state.get("adapter") or discover(), "clients") @@ -267,7 +304,7 @@ def enroll_current(self, *, expected_revision: int, expected_selection: str) -> def configure(self, *, expected_revision: int, enabled: bool, slots: list[str], reconnect: bool = False, restart_clients: bool | None = None, force_quit_clients: bool | None = None, - api_fallback: bool | None = None) -> dict: + api_fallback: bool | None = None, steward_api_role: str | None = None) -> dict: if type(enabled) is not bool or not isinstance(slots, list) or len(slots) > 16 or len(slots) != len(set(slots)): raise HostError("invalid_policy") if restart_clients is not None and type(restart_clients) is not bool: @@ -276,6 +313,8 @@ def configure(self, *, expected_revision: int, enabled: bool, slots: list[str], raise HostError("invalid_policy") if api_fallback is not None and type(api_fallback) is not bool: raise HostError("invalid_policy") + if steward_api_role is not None and steward_api_role not in ("disabled", "fallback", "primary"): + raise HostError("invalid_policy") # Stop requests fence new effects at the Watcher first, then persist # after an already dispatched atomic switch finishes. Other mutations # retain their immediate conflict behavior. @@ -288,6 +327,9 @@ def configure(self, *, expected_revision: int, enabled: bool, slots: list[str], raise HostError("handoff_pending") # Disabling works offline and never needs credentials or a client. use_api = api_fallback if api_fallback is not None else state["policy"].get("api_fallback", False) + use_steward = steward_api_role if steward_api_role is not None else state["policy"].get("steward_api_role") + if steward_api_role == "primary" and not self.api_keys().status()["keys"]: + raise HostError("api_keys_missing") if enabled or reconnect or api_fallback is True: adapter = discover() if reconnect or "adapter" not in state else state["adapter"] native = self.transport(adapter, "status") @@ -307,6 +349,8 @@ def configure(self, *, expected_revision: int, enabled: bool, slots: list[str], revision=state["revision"] + 1, retry_at=None, code=None, intent=pending if pending.get("handoff_receipt") else None, action="checking" if enabled else "disabled", failure_count=0) + if use_steward is not None: + state["policy"]["steward_api_role"] = use_steward atomic(self.path, state) return self._projection(state) diff --git a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts index ac99fbf06e..adfdae35ad 100644 --- a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts +++ b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts @@ -17,8 +17,30 @@ export type Account = { secondary_used: number | null; credits_available: boolean | null; }; +export type ApiRole = "disabled" | "fallback" | "primary"; export type Policy = { enabled: boolean; slots: string[]; cooldown_seconds: number; - restart_clients?: boolean; force_quit_clients?: boolean; api_fallback?: boolean }; + restart_clients?: boolean; force_quit_clients?: boolean; api_fallback?: boolean; + steward_api_role?: ApiRole }; + +/** Billing priority belongs to the consumer, not the model or credential. */ +export function apiRole(policy: Policy | undefined, consumer: string): ApiRole { + if (!policy) return "disabled"; + if (consumer === "worker") return policy.api_fallback === true ? "fallback" : "disabled"; + if (consumer !== "steward") return "disabled"; + const role = policy.steward_api_role; + return role === "primary" || role === "disabled" || role === "fallback" + ? role : policy.api_fallback === true ? "fallback" : "disabled"; +} + +export function modelRoute(input: {consumer: string; native: Record; api_ready: boolean}) { + const native = input.native; + const role = apiRole(native.policy, input.consumer); + const primary = input.consumer === "steward" && role === "primary" && input.api_ready; + const fallback = role === "fallback" && native.policy.enabled === true + && native.policy.api_fallback === true && native.api_active === true + && native.login_matches === true && native.recovery_required === false && native.action === "api_active"; + return {role, api: primary || fallback}; +} /** The steward's endpoint pool is separate from the native account ring. * Selection observes allowance only; it never changes a login or retries work. @@ -27,6 +49,7 @@ export function stewardRoute(input: { now: number; primary: string; pool: string[]; current: string; native: Record; primary_capacity: Record | null; blocked_primary?: Record | null; + api_ready?: boolean; }) { const no = {endpoint: null, blocked_primary: input.blocked_primary ?? null}; if (!Number.isFinite(input.now) || !["antigravity", "codex"].includes(input.current) @@ -41,10 +64,12 @@ export function stewardRoute(input: { && typeof row.execution_id === "string" && row.execution_id.length > 0 && typeof row.quota_exhausted === "boolean" && typeof row.normal_completion === "boolean" && row.quota_exhausted !== row.normal_completion; + if (input.blocked_primary != null && !validCapacity(input.blocked_primary)) return no; + if (modelRoute({consumer: "steward", native: input.native, api_ready: input.api_ready === true}).api + && apiRole(input.native.policy, "steward") === "primary") return {endpoint: "codex", blocked_primary: input.blocked_primary ?? null}; const capacity = input.primary_capacity; if (!validCapacity(capacity) || !capacity || input.now < capacity.observed_at - || input.now - capacity.observed_at > 120 - || input.blocked_primary != null && !validCapacity(input.blocked_primary)) return no; + || input.now - capacity.observed_at > 120) return no; let blocked = input.blocked_primary ?? null; if (capacity.quota_exhausted && (!blocked || blocked.execution_id !== capacity.execution_id)) blocked = capacity; const restored = blocked && (blocked.account_ref !== capacity.account_ref @@ -63,7 +88,7 @@ export function stewardRoute(input: { && current.observed_at <= input.now && input.now - current.observed_at <= 120; const usable = native.policy?.enabled === true && native.login_matches === true && native.recovery_required === false && (native.api_active === true - ? native.policy.api_fallback === true && native.action === "api_active" + ? modelRoute({consumer: "steward", native, api_ready: input.api_ready === true}).api : native.action === "ready" && fresh && current.availability === "available"); return {endpoint: usable ? "codex" : null, blocked_primary: blocked}; } diff --git a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy_bridge.ts b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy_bridge.ts index 9665bc3960..45b73b92ac 100644 --- a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy_bridge.ts +++ b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy_bridge.ts @@ -1,4 +1,4 @@ -import { decide, observerHealth, stewardRoute } from "./native_policy.ts"; +import { apiRole, decide, modelRoute, observerHealth, stewardRoute } from "./native_policy.ts"; let raw = ""; for await (const chunk of process.stdin) { raw += chunk; @@ -6,4 +6,6 @@ for await (const chunk of process.stdin) { } const input = JSON.parse(raw); process.stdout.write(JSON.stringify(input.operation === "observer-health" ? observerHealth(input) + : input.operation === "api-role" ? {role: apiRole(input.policy, input.consumer)} + : input.operation === "model-route" ? modelRoute(input) : input.operation === "steward-route" ? stewardRoute(input) : decide(input))); diff --git a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py index 10a0744787..587c3a28c0 100644 --- a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py +++ b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py @@ -34,16 +34,27 @@ def route(owner: NativeAccounts) -> dict: return value -def healthy(value: dict) -> bool: - request = urllib.request.Request(f"http://127.0.0.1:{value['port']}/health", headers={"Authorization": "Bearer " + value["token"]}) +def consumer_token(value: dict, consumer: str) -> str: + token = value.get("steward_token" if consumer == "steward" else "token") + if not isinstance(token, str) or not token: + raise HostError("api_relay_upgrade_required") + return token + + +def healthy(value: dict, consumer: str = "worker") -> bool: + prefix = "/steward" if consumer == "steward" else "" try: + request = urllib.request.Request(f"http://127.0.0.1:{value['port']}{prefix}/health", headers={ + "Authorization": "Bearer " + consumer_token(value, consumer)}) with urllib.request.build_opener(NoRedirect()).open(request, timeout=1) as response: return response.read(128) == b'{"ok":true}' except (OSError, HostError): return False -def ensure(owner: NativeAccounts) -> dict: +def ensure(owner: NativeAccounts, *, consumer: str = "worker") -> dict: + if consumer not in ("worker", "steward"): + raise HostError("invalid_policy") with owner._lock(name="api-relay-state.lock", wait_seconds=5): path = owner.root / "api-relay.json" if not path.exists(): @@ -52,6 +63,11 @@ def ensure(owner: NativeAccounts) -> dict: port = sock.getsockname()[1] atomic(path, {"schema_version": SCHEMA, "port": port, "token": "sk-loopx-relay-" + secrets.token_urlsafe(32)}) value = route(owner) + if consumer == "steward" and "steward_token" not in value: + # Independent random credentials: a worker token must not be able + # to derive the steward's API-primary transport credential. + value["steward_token"] = "sk-loopx-relay-" + secrets.token_urlsafe(32) + atomic(path, value) if not healthy(value): # Independent of a Chat/App process that the handoff may restart. subprocess.Popen([sys.executable, "-m", "loopx_codex_provider_routing.openai_relay", @@ -63,7 +79,11 @@ def ensure(owner: NativeAccounts) -> dict: time.sleep(.1) if not healthy(value): raise HostError("api_relay_unavailable") - return {"slot": API_SLOT, "api_key": value["token"], "base_url": f"http://127.0.0.1:{value['port']}/v1"} + if consumer == "steward" and not healthy(value, consumer): + raise HostError("api_relay_upgrade_required") + prefix = "/steward" if consumer == "steward" else "" + return {"slot": API_SLOT, "api_key": consumer_token(value, consumer), + "base_url": f"http://127.0.0.1:{value['port']}{prefix}/v1"} class RelayServer(ThreadingHTTPServer): @@ -71,7 +91,7 @@ class RelayServer(ThreadingHTTPServer): allow_reuse_address = True def __init__(self, owner: NativeAccounts, value: dict, *, opener=None): - self.owner, self.token = owner, value["token"] + self.owner, self.value = owner, value self.opener = opener or urllib.request.build_opener(NoRedirect()) super().__init__(("127.0.0.1", value["port"]), RelayHandler) @@ -92,13 +112,23 @@ def _json(self, status: int, code: str): self.wfile.write(data) def _authorized(self): - return not self.headers.get("Origin") and hmac.compare_digest( - self.headers.get("Authorization", ""), "Bearer " + self.server.token) + self.consumer = "steward" if self.path.startswith("/steward/") else "worker" + try: + return not self.headers.get("Origin") and hmac.compare_digest( + self.headers.get("Authorization", ""), "Bearer " + consumer_token(self.server.value, self.consumer)) + except HostError: + return False def _admitted(self): state = self.server.owner._load() policy = state["policy"] native = state.get("native", {}) + if self.consumer == "steward": + role = policy.get("steward_api_role") + if role == "primary": + return True + if role == "disabled": + return False selecting_api = state.get("intent", {}).get("target") == API_SLOT if state.get("intent") else False return (policy.get("enabled") is True and policy.get("api_fallback") is True and (native.get("active_slot") == API_SLOT or selecting_api)) @@ -107,7 +137,7 @@ def do_GET(self): if not self._authorized(): self._json(401, "relay_auth_required") return - if self.path == "/health": + if self.path in ("/health", "/steward/health"): self.send_response(200) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", "11") @@ -120,7 +150,8 @@ def do_POST(self): if not self._authorized(): self._json(401, "relay_auth_required") return - if self.path not in ("/v1/responses", "/v1/responses/compact"): + upstream_path = self.path.removeprefix("/steward") if self.consumer == "steward" else self.path + if upstream_path not in ("/v1/responses", "/v1/responses/compact"): self._json(404, "unsupported_route") return if not self._admitted(): @@ -150,7 +181,7 @@ def do_POST(self): current = next((r for r in keys._load()["keys"] if r["id"] == row["id"]), None) if current is None: continue - request = urllib.request.Request("https://api.openai.com" + self.path, data=body, headers={ + request = urllib.request.Request("https://api.openai.com" + upstream_path, data=body, headers={ "Authorization": "Bearer " + current["api_key"], "Content-Type": "application/json", "Accept": self.headers.get("Accept", "text/event-stream"), }, method="POST") @@ -209,7 +240,8 @@ def main(): while True: server.handle_request() policy = owner._load()["policy"] - if time.monotonic() - started > 10 and (not policy.get("enabled") or not policy.get("api_fallback")): + if time.monotonic() - started > 10 and policy.get("steward_api_role") != "primary" and ( + not policy.get("enabled") or not policy.get("api_fallback")): break finally: # Drain already admitted requests; disabling never replays them. diff --git a/tests/test_chat_account_workloads.py b/tests/test_chat_account_workloads.py new file mode 100644 index 0000000000..5d14a2ac3e --- /dev/null +++ b/tests/test_chat_account_workloads.py @@ -0,0 +1,166 @@ +"""Consumer policy through the actual private owner, relay HTTP and Chat startup.""" +import importlib +import io +import json +from pathlib import Path +import threading +import urllib.error +import urllib.request + +import pytest + +from loopx.capabilities.native_chat.codex_auth import CodexApiTransport, CodexHostAuthUnavailable + + +@pytest.fixture +def account_owner(tmp_path, monkeypatch): + monkeypatch.syspath_prepend(str(Path(__file__).resolve().parents[1] / 'packages/loopx-codex-provider-routing/src')) + native = importlib.import_module('loopx_codex_provider_routing.native') + relay = importlib.import_module('loopx_codex_provider_routing.openai_relay') + calls = [] + owner = native.NativeAccounts(tmp_path, transport=lambda *_a, **_k: calls.append('native') or { + 'slots': ['a'], 'active_slot': 'a', 'current_login_matches': True, 'recovery_required': False, + 'api_fallback_supported': True}, clock=lambda: 1000) + owner.api_keys().add(expected_revision=0, label='Synthetic', api_key='sk-' + 'synthetic-only-key-' * 3) + return owner, native, relay, calls + + +def test_api_primary_is_independent_and_preserved_by_worker_configuration(account_owner): + owner, native, _, calls = account_owner + before = owner.api_keys().path.read_bytes() + result = owner.configure(expected_revision=0, enabled=False, slots=[], steward_api_role='primary') + assert result['policy']['steward_api_role'] == 'primary' and not result['policy'].get('api_fallback') + assert calls == [] and owner.api_keys().path.read_bytes() == before + result = owner.configure(expected_revision=1, enabled=False, slots=[], api_fallback=False) + assert result['policy']['steward_api_role'] == 'primary' + assert owner.steward_route(codex_home=Path('/synthetic-home'), primary='antigravity', + pool=['antigravity', 'codex'], current='antigravity', primary_capacity=None)['endpoint'] == 'codex' + assert owner.model_transport(codex_home=Path('/synthetic-home'), consumer='worker') is None + assert calls == [] + with pytest.raises(Exception, match='invalid_policy'): + owner.configure(expected_revision=2, enabled=False, slots=[], steward_api_role='arbitrary') + assert native.private_read(owner.path)['revision'] == 2 + + +def test_api_primary_cannot_replace_a_different_bound_native_profile(account_owner): + owner, native, _, calls = account_owner + owner.configure(expected_revision=0, enabled=False, slots=[], steward_api_role='primary') + state = native.private_read(owner.path) + state['adapter'] = {'profile': {'home': '/synthetic-registered-home'}} + native.atomic(owner.path, state) + before = owner.path.read_bytes() + other = Path('/synthetic-other-home') + assert owner.model_transport(codex_home=other, consumer='steward') is None + assert owner.conversation_epoch(codex_home=other, consumer='steward') is None + assert owner.steward_route(codex_home=other, primary='antigravity', pool=['antigravity', 'codex'], + current='antigravity', primary_capacity=None)['endpoint'] is None + assert calls == [] and owner.path.read_bytes() == before + + +def test_steward_and_worker_tokens_cannot_cross_billing_routes(account_owner): + owner, native, relay, _ = account_owner + owner.configure(expected_revision=0, enabled=False, slots=[], steward_api_role='primary') + upstream = [] + class Response(io.BytesIO): + status = 200 + headers = {'Content-Type': 'text/event-stream'} + class Upstream: + def open(self, request, timeout): + upstream.append(request) + assert request.full_url == 'https://api.openai.com/v1/responses' + return Response(b'data: {"type":"response.completed"}\n\n') + token = 'synthetic-worker-loopback-token' + value = {'port': 0, 'token': token, 'steward_token': 'independent-synthetic-steward-token'} + server = relay.RelayServer(owner, value, opener=Upstream()) + thread = threading.Thread(target=server.serve_forever, daemon=True) + thread.start() + def post(path, bearer): + request = urllib.request.Request(f'http://127.0.0.1:{server.server_port}{path}', + data=json.dumps({'model': 'synthetic-model', 'input': 'fixture', 'stream': True}).encode(), + headers={'Authorization': 'Bearer ' + bearer, 'Content-Type': 'application/json'}) + try: + with urllib.request.urlopen(request, timeout=5) as response: + response.read() + return response.status + except urllib.error.HTTPError as error: + error.read() + return error.code + try: + steward_token = relay.consumer_token(value, 'steward') + assert steward_token != token + assert post('/steward/v1/responses', token) == 401 + assert post('/v1/responses', steward_token) == 401 + assert post('/v1/responses', token) == 503 # Worker's subscription policy remains off. + assert not upstream + assert post('/steward/v1/responses', steward_token) == 200 and len(upstream) == 1 + state = native.private_read(owner.path) + state['policy']['steward_api_role'] = 'disabled' + native.atomic(owner.path, state) + assert post('/steward/v1/responses', steward_token) == 503 and len(upstream) == 1 + finally: + server.shutdown() + server.server_close() + thread.join(timeout=5) + + +def test_model_transport_hides_token_from_config_and_rejects_native_alias_collision(): + transport = CodexApiTransport('http://127.0.0.1:32100/steward/v1', 'synthetic-secret') + original = {'shell_environment_policy': {'inherit': 'all', 'exclude': ['OTHER_SECRET'], 'set': {'SAFE': 'yes'}}} + config = transport.configuration(original) + assert 'synthetic-secret' not in repr(transport) + json.dumps(config) + assert config['shell_environment_policy']['set'] == {'SAFE': 'yes'} + assert transport.env_key in config['shell_environment_policy']['exclude'] + assert config['model_providers'][transport.provider]['env_key'] == transport.env_key + assert original['shell_environment_policy']['exclude'] == ['OTHER_SECRET'] + with pytest.raises(CodexHostAuthUnavailable): + transport.configuration(original, {'model_providers': {transport.provider: {'base_url': 'https://untrusted.invalid'}}}) + + +def test_known_api_rejection_returns_primary_to_existing_subscription_pool(account_owner): + owner, native, _, _ = account_owner + owner.configure(expected_revision=0, enabled=False, slots=[], steward_api_role='primary') + key_id = owner.api_keys().status()['keys'][0]['id'] + owner.api_keys().record(key_id, status=429, code='insufficient_quota', model='synthetic-model', headers={}) + assert owner.steward_route(codex_home=Path('/synthetic-home'), primary='antigravity', + pool=['antigravity', 'codex'], current='antigravity', primary_capacity=None)['endpoint'] is None + # Native owner remains selected; no credential or native switch was attempted. + assert owner.model_transport(codex_home=Path('/synthetic-home'), consumer='steward', model='synthetic-model') is None + assert native.private_read(owner.path)['policy']['steward_api_role'] == 'primary' + + +@pytest.mark.parametrize('resume', [False, True]) +def test_chat_start_uses_model_only_api_and_preserves_original_thread_and_project_store(tmp_path, monkeypatch, resume): + from loopx import chat_agent + from loopx.capabilities.native_chat import codex_auth + from loopx.capabilities.native_chat.project_context import ChatProjectContexts + from tests.test_chat_agent import _FakeAppServerProcess, _stub_app_server_process + + home, workspace = tmp_path / 'host', tmp_path / 'workspace' + workspace.mkdir() + context = ChatProjectContexts([workspace], filesystem_scope='workspace_only').available()[0] + transport = CodexApiTransport('http://127.0.0.1:32100/steward/v1', 'synthetic-secret') + observed = [] + monkeypatch.setattr(codex_auth, 'native_api_transport', lambda root, base, **kw: + observed.append((root, base, kw)) or transport) + process = _FakeAppServerProcess(thread_response={'thread': {'id': 'original-native-thread'}, + 'modelProvider': transport.provider, 'activePermissionProfile': {'id': 'loopx_workspace_only_write'}, + 'runtimeWorkspaceRoots': [str(workspace)]}) + launches = [] + _stub_app_server_process(monkeypatch, process, launched=launches) + session = chat_agent.CodexChatAgentSession.start(codex_bin='codex', codex_home=home, + work_dir=workspace, goal_id=None, objective='fixture', project_context=context, + account_runtime_root=tmp_path / 'runtime', account_consumer='steward', + resume_thread_id='original-native-thread' if resume else None) + try: + packets = [json.loads(line) for line in process.stdin.getvalue().splitlines()] + thread = next(p for p in packets if p.get('method') in ('thread/start', 'thread/resume')) + assert not any(p.get('method') == 'account/login/start' for p in packets) + assert thread['params']['modelProvider'] == transport.provider + assert transport.env_key in thread['params']['config']['shell_environment_policy']['exclude'] + assert observed[0][2]['consumer'] == 'steward' + assert launches[0]['env'][transport.env_key] == 'synthetic-secret' + assert 'synthetic-secret' not in process.stdin.getvalue() + assert session.thread_id == 'original-native-thread' + assert not list(workspace.rglob('auth.json')) and not (home / 'auth.json').exists() + finally: + session.close() diff --git a/tests/test_chat_manager_model_adoption.py b/tests/test_chat_manager_model_adoption.py index 1745a8b74d..d88047958f 100644 --- a/tests/test_chat_manager_model_adoption.py +++ b/tests/test_chat_manager_model_adoption.py @@ -476,7 +476,8 @@ def test_native_account_epoch_reopens_only_unstarted_codex_adapter(conversation, class Accounts: def __init__(self, path): assert path == runtime.coordination_runtime_root - def conversation_epoch(self, *, codex_home): + def conversation_epoch(self, *, codex_home, consumer="worker", model=None): + assert consumer == "steward" observed.append(codex_home) return tuple(epoch) module.NativeAccounts = Accounts From e04f473d1d00fd9060ae2b391cfdf785c5ae1316 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Wed, 4 Nov 2026 19:07:18 +0800 Subject: [PATCH 2/4] fix(accounts): keep authentication wiring with its native owner Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/canary/module_metric_baseline.json | 8 ++-- loopx/capabilities/native_chat/codex_auth.py | 42 +++++++++++++++++ .../capabilities/native_chat/codex_context.py | 5 +++ loopx/chat_agent.py | 45 +++++-------------- loopx/chat_runtime.py | 14 ++---- .../loopx-codex-provider-routing/NATIVE.md | 6 ++- .../smoke/native-policy.test.mjs | 3 ++ .../native_policy.ts | 4 +- .../openai_relay.py | 2 +- 9 files changed, 77 insertions(+), 52 deletions(-) diff --git a/loopx/canary/module_metric_baseline.json b/loopx/canary/module_metric_baseline.json index 51ded7160f..a0515d3871 100644 --- a/loopx/canary/module_metric_baseline.json +++ b/loopx/canary/module_metric_baseline.json @@ -59,11 +59,11 @@ "dict_any_count": 0 }, "loopx/control_plane/goals/goal_frontier/terminal.py": { - "any_count": 15, + "any_count": 22, "dict_any_count": 0 }, "loopx/control_plane/work_items/interaction_contract.py": { - "any_count": 85, + "any_count": 107, "dict_any_count": 0 }, "loopx/extensions/lark/goal_topic_runtime.py": { @@ -90,7 +90,7 @@ "dict_any_count": 0 }, "loopx/pr_review.py": { - "any_count": 49, + "any_count": 50, "dict_any_count": 0 }, "loopx/presentation/renderers/status_markdown.py": { @@ -103,7 +103,7 @@ "lines": 1999 }, "loopx/slash_command_install.py": { - "any_count": 11, + "any_count": 12, "dict_any_count": 0 }, "loopx/state_refresh.py": { diff --git a/loopx/capabilities/native_chat/codex_auth.py b/loopx/capabilities/native_chat/codex_auth.py index a37ffcca76..35a3af5f7f 100644 --- a/loopx/capabilities/native_chat/codex_auth.py +++ b/loopx/capabilities/native_chat/codex_auth.py @@ -156,3 +156,45 @@ def native_api_transport(runtime_root: Path, base_home: Path, *, consumer: str, return CodexApiTransport(endpoint['base_url'], endpoint['api_key']) if endpoint else None except Exception: raise CodexHostAuthUnavailable() from None + + +def prepare_api_transport(runtime_root: Path | None, home: Path, *, isolated_home: Path | None, + eligible: bool, consumer: str, model: str | None) -> CodexApiTransport | None: + if (runtime_root is None or not eligible or isolated_home is not None + and ((isolated_home / "auth.json").exists() or (isolated_home / "auth.json").is_symlink())): + return None + try: + return native_api_transport(runtime_root, home, consumer=consumer, model=model) + except CodexHostAuthUnavailable: + from ...chat_agent import CodexChatAgentError + raise CodexChatAgentError("Native account API transport is unavailable.", + error_code="model_auth_unavailable", gate=None) from None + + +def authenticate_isolated(session, home: Path, isolated: Path, binary: str, *, api_transport) -> CodexHostModelAuth | None: + if api_transport is not None: + return None + try: + broker = for_isolated_process(home, isolated, binary) + if broker is not None: + login = session._request("account/login/start", { + "type": "chatgptAuthTokens", **broker.read()}, request_id=4) + if login.get("type") != "chatgptAuthTokens": + raise ValueError("unexpected native model authentication mode") + return broker + except Exception: + raise session._runtime_error( + "Trusted-host Codex model authentication is unavailable. " + "Restore the host account and retry this same Session.") from None + + +def conversation_account_epoch(runtime_root: Path, home: Path, **consumer) -> tuple[str, str] | None: + try: + from loopx_codex_provider_routing.native import NativeAccounts + return NativeAccounts(runtime_root).conversation_epoch(codex_home=home, **consumer) + except ImportError: + return None + except Exception as exc: + import logging + logging.getLogger(__name__).warning("Native account epoch observation held (%s)", type(exc).__name__) + return None diff --git a/loopx/capabilities/native_chat/codex_context.py b/loopx/capabilities/native_chat/codex_context.py index f416b273a7..66d398e5db 100644 --- a/loopx/capabilities/native_chat/codex_context.py +++ b/loopx/capabilities/native_chat/codex_context.py @@ -134,6 +134,11 @@ def shared_chatgpt_transport(host_config: Mapping[str, Any], native_config: Mapp }} +def verify_conversation_provider(session, requested: str, observed: Mapping[str, Any]) -> None: + if requested and observed.get("modelProvider") != requested: + raise session._runtime_error("Codex did not apply the requested conversation provider.") + + def disable_mcp_servers(config: Mapping[str, Any], host_config: Mapping[str, Any]) -> dict[str, Any]: """Disable private native tool sources, including project/managed layers. diff --git a/loopx/chat_agent.py b/loopx/chat_agent.py index b63acbcc2f..1d5a46c2d8 100644 --- a/loopx/chat_agent.py +++ b/loopx/chat_agent.py @@ -853,22 +853,14 @@ def start( if not execution_mode else "" ) account_base_config = host_config - api_transport = None - if (account_runtime_root is not None and not execution_mode and not provider_override - and not (host_config or {}).get("model_provider") - and (not permissions_profile or not (runtime_home / "auth.json").exists() - and not (runtime_home / "auth.json").is_symlink())): - from .capabilities.native_chat.codex_auth import native_api_transport - try: - api_transport = native_api_transport(account_runtime_root, base_home, - consumer=account_consumer, model=model) - if api_transport is not None: - runtime_env[api_transport.env_key] = api_transport.token - host_config = api_transport.configuration(host_config or {}) - provider_override = api_transport.provider - except Exception: - raise CodexChatAgentError("Native account API transport is unavailable.", - error_code="model_auth_unavailable", gate=None) from None + from .capabilities.native_chat.codex_auth import prepare_api_transport, authenticate_isolated + api_transport = prepare_api_transport(account_runtime_root, base_home, + isolated_home=runtime_home if permissions_profile else None, + eligible=not execution_mode and not provider_override and not (host_config or {}).get("model_provider"), + consumer=account_consumer, model=model) + if api_transport is not None: + runtime_env[api_transport.env_key] = api_transport.token + host_config, provider_override = api_transport.configuration(host_config or {}), api_transport.provider command = [resolved, "app-server"] if permissions_profile: # Keep this native store independent even when the account's @@ -957,20 +949,8 @@ def start( request_id=1, ) session._notify("initialized", {}) - if permissions_profile and api_transport is None: - from .capabilities.native_chat.codex_auth import for_isolated_process - try: - session._host_model_auth = for_isolated_process(base_home, runtime_home, resolved) - if session._host_model_auth is not None: - credentials = session._host_model_auth.read() - login = session._request("account/login/start", { - "type": "chatgptAuthTokens", **credentials}, request_id=4) - if login.get("type") != "chatgptAuthTokens": - raise ValueError("unexpected native model authentication mode") - except Exception: - raise session._runtime_error( - "Trusted-host Codex model authentication is unavailable. " - "Restore the host account and retry this same Session.") from None + if permissions_profile: + session._host_model_auth = authenticate_isolated(session, base_home, runtime_home, resolved, api_transport=api_transport) read_project_defaults = project_context is not None and bool(resume_thread_id) and ( model is None or reasoning_effort is None ) @@ -1082,10 +1062,7 @@ def start( }, request_id=2, ) - if provider_override and thread_result.get("modelProvider") != provider_override: - raise session._runtime_error( - "Codex did not apply the requested conversation provider." - ) + codex_context.verify_conversation_provider(session, provider_override, thread_result) if model and thread_result.get("model") not in {None, model}: raise CodexChatAgentError( "Codex did not apply the requested conversation model.", diff --git a/loopx/chat_runtime.py b/loopx/chat_runtime.py index 0e7d39f858..f7bd44af85 100644 --- a/loopx/chat_runtime.py +++ b/loopx/chat_runtime.py @@ -864,16 +864,10 @@ def check_route_configuration(): if (selected_agent == "codex" and active and active_id == accepted_turn_id and active.get("status") == "queued" and not active.get("upstream_turn_id") and active.get("origin") != "native_loopx"): - try: - from loopx_codex_provider_routing.native import NativeAccounts - native_account_epoch = NativeAccounts(self.coordination_runtime_root).conversation_epoch( - codex_home=selected_codex_home, **({"consumer": "steward", - "model": (model_allocation or {}).get("model") or session.get("agent_model_id")} - if manager_runtime is not None else {})) - except ImportError: - pass # Optional account automation is absent, not a Chat failure. - except Exception as exc: - logging.getLogger(__name__).warning("Native account epoch observation held (%s)", type(exc).__name__) + from .capabilities.native_chat.codex_auth import conversation_account_epoch + native_account_epoch = conversation_account_epoch(self.coordination_runtime_root, selected_codex_home, + **({"consumer": "steward", "model": (model_allocation or {}).get("model") or session.get("agent_model_id")} + if manager_runtime is not None else {})) native_quota_refresh = bool(active and active_id == accepted_turn_id and active.get("status") == "queued" and active.get("origin") == "native_loopx" and active.get("loopx_execution") is True diff --git a/packages/loopx-codex-provider-routing/NATIVE.md b/packages/loopx-codex-provider-routing/NATIVE.md index 6305008fbf..346b58e18d 100644 --- a/packages/loopx-codex-provider-routing/NATIVE.md +++ b/packages/loopx-codex-provider-routing/NATIVE.md @@ -155,7 +155,11 @@ existing endpoint pool to consider its subscription route; it does not move a worker to API. The API role is local vocabulary owned by this optional account provider, not a new Core execution authority or Goal state. -Built account settings with synthetic account data / 使用合成账号数据的设置界面: +In **Settings → Model Provider configuration**, keep the working-Agent checkbox +for subscription exhaustion. Use **Steward API use → Prefer API** for an +independent API primary; **Disabled** revokes it, including after the last key +is removed. The saved selector reads back the choice. These canonical guide +illustrations use synthetic accounts / 当前操作指南使用合成账号数据: ![Independent account priorities, desktop / 独立账号优先级,桌面](docs/assets/account-workload-primary-desktop.png) diff --git a/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs b/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs index 0493eac4b0..17428be2dd 100644 --- a/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs +++ b/packages/loopx-codex-provider-routing/smoke/native-policy.test.mjs @@ -9,6 +9,7 @@ test("consumer API roles never make a working Agent API primary", () => { assert.equal(apiRole(policy, "worker"), "disabled"); assert.equal(apiRole({...policy, api_fallback: true}, "worker"), "fallback"); assert.equal(apiRole(policy, "unrecognized-consumer"), "disabled"); + assert.equal(apiRole({...policy, api_fallback: true, steward_api_role: "corrupt-role"}, "steward"), "disabled"); assert.equal(modelRoute({consumer: "worker", native, api_ready: true}).api, false); assert.equal(modelRoute({consumer: "steward", native, api_ready: true}).api, true); assert.equal(modelRoute({consumer: "steward", native, api_ready: false}).api, false); @@ -16,6 +17,8 @@ test("consumer API roles never make a working Agent API primary", () => { current: "antigravity", native, api_ready: true, primary_capacity: null}).endpoint, "codex"); assert.equal(stewardRoute({now, primary: "antigravity", pool: ["antigravity"], current: "antigravity", native, api_ready: true, primary_capacity: null}).endpoint, null); + assert.equal(stewardRoute({now, primary: "antigravity", pool: ["antigravity", "codex"], + current: "antigravity", native, api_ready: true, primary_capacity: null, blocked_primary: {corrupt: true}}).endpoint, null); for (const role of ["disabled", "fallback", "corrupt-role"]) { assert.equal(modelRoute({consumer: "steward", native: {...native, policy: {...policy, steward_api_role: role}}, api_ready: true}).api, false); } diff --git a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts index adfdae35ad..f5a540d660 100644 --- a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts +++ b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native_policy.ts @@ -28,8 +28,8 @@ export function apiRole(policy: Policy | undefined, consumer: string): ApiRole { if (consumer === "worker") return policy.api_fallback === true ? "fallback" : "disabled"; if (consumer !== "steward") return "disabled"; const role = policy.steward_api_role; - return role === "primary" || role === "disabled" || role === "fallback" - ? role : policy.api_fallback === true ? "fallback" : "disabled"; + if (role === undefined) return policy.api_fallback === true ? "fallback" : "disabled"; + return role === "primary" || role === "fallback" ? role : "disabled"; } export function modelRoute(input: {consumer: string; native: Record; api_ready: boolean}) { diff --git a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py index 587c3a28c0..b026a05a6e 100644 --- a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py +++ b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/openai_relay.py @@ -36,7 +36,7 @@ def route(owner: NativeAccounts) -> dict: def consumer_token(value: dict, consumer: str) -> str: token = value.get("steward_token" if consumer == "steward" else "token") - if not isinstance(token, str) or not token: + if not isinstance(token, str) or not token or consumer == "steward" and token == value.get("token"): raise HostError("api_relay_upgrade_required") return token From a9c46427af7da87a03c9b408a632919d07f9a739 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Wed, 4 Nov 2026 19:14:01 +0800 Subject: [PATCH 3/4] fix(accounts): preserve process-free disabled observation Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- .../src/loopx_codex_provider_routing/native.py | 5 ++++- tests/test_chat_account_workloads.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py index 3e56f56d19..d7750a2343 100644 --- a/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py +++ b/packages/loopx-codex-provider-routing/src/loopx_codex_provider_routing/native.py @@ -228,7 +228,7 @@ def conversation_epoch(self, *, codex_home: Path, consumer: str = "worker", mode adapter = state.get("adapter") if adapter and Path(adapter.get("profile", {}).get("home", "")).resolve() != codex_home.resolve(): return None - if consumer == "steward" and policy({"operation": "api-role", "policy": state["policy"], + if consumer == "steward" and state["policy"].get("steward_api_role") == "primary" and policy({"operation": "api-role", "policy": state["policy"], "consumer": consumer})["role"] == "primary": return (f'steward-api:{state["revision"]}:{self.api_keys().status()["revision"]}:{bool(self.api_keys().candidates(model or ""))}', "openai-api") if state["policy"].get("enabled") is not True or not adapter: @@ -268,6 +268,9 @@ def model_transport(self, *, codex_home: Path, consumer: str, model: str | None adapter = state.get("adapter") if adapter and Path(adapter.get("profile", {}).get("home", "")).resolve() != codex_home.resolve(): return None + if (state["policy"].get("enabled") is not True + and not (consumer == "steward" and state["policy"].get("steward_api_role") == "primary")): + return None role = policy({"operation": "api-role", "policy": state["policy"], "consumer": consumer})["role"] if role == "primary": native = self._projection(state) diff --git a/tests/test_chat_account_workloads.py b/tests/test_chat_account_workloads.py index 5d14a2ac3e..284e116619 100644 --- a/tests/test_chat_account_workloads.py +++ b/tests/test_chat_account_workloads.py @@ -57,6 +57,18 @@ def test_api_primary_cannot_replace_a_different_bound_native_profile(account_own assert calls == [] and owner.path.read_bytes() == before +def test_disabled_account_automation_starts_no_policy_or_native_process(account_owner, monkeypatch): + owner, native, _, calls = account_owner + monkeypatch.setattr(native, 'policy', lambda *_: pytest.fail('Disabled observation must start no policy process')) + home = Path('/synthetic-home') + for consumer in ('worker', 'steward'): + assert owner.model_transport(codex_home=home, consumer=consumer) is None + assert owner.conversation_epoch(codex_home=home, consumer=consumer) is None + assert owner.steward_route(codex_home=home, primary='antigravity', pool=['antigravity', 'codex'], + current='antigravity', primary_capacity=None)['endpoint'] is None + assert calls == [] and not owner.path.exists() + + def test_steward_and_worker_tokens_cannot_cross_billing_routes(account_owner): owner, native, relay, _ = account_owner owner.configure(expected_revision=0, enabled=False, slots=[], steward_api_role='primary') From c17ab3782df9a41fd8241e7babf0b11bc41540f4 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Wed, 4 Nov 2026 19:25:58 +0800 Subject: [PATCH 4/4] fix(accounts): retain native transport across optional provider upgrades Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/capabilities/native_chat/codex_auth.py | 7 +++++-- loopx/chat_manager.py | 5 +++-- tests/test_chat_account_workloads.py | 18 ++++++++++++++++++ tests/test_chat_manager_model_adoption.py | 2 ++ 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/loopx/capabilities/native_chat/codex_auth.py b/loopx/capabilities/native_chat/codex_auth.py index 35a3af5f7f..08380ebe93 100644 --- a/loopx/capabilities/native_chat/codex_auth.py +++ b/loopx/capabilities/native_chat/codex_auth.py @@ -152,7 +152,8 @@ def native_api_transport(runtime_root: Path, base_home: Path, *, consumer: str, except ImportError: return None # Optional provider absence preserves native authentication. try: - endpoint = NativeAccounts(runtime_root).model_transport(codex_home=base_home, consumer=consumer, model=model) + prepare = getattr(NativeAccounts(runtime_root), 'model_transport', None) + endpoint = prepare(codex_home=base_home, consumer=consumer, model=model) if callable(prepare) else None return CodexApiTransport(endpoint['base_url'], endpoint['api_key']) if endpoint else None except Exception: raise CodexHostAuthUnavailable() from None @@ -191,7 +192,9 @@ def authenticate_isolated(session, home: Path, isolated: Path, binary: str, *, a def conversation_account_epoch(runtime_root: Path, home: Path, **consumer) -> tuple[str, str] | None: try: from loopx_codex_provider_routing.native import NativeAccounts - return NativeAccounts(runtime_root).conversation_epoch(codex_home=home, **consumer) + owner = NativeAccounts(runtime_root) + return owner.conversation_epoch(codex_home=home, + **(consumer if callable(getattr(owner, 'model_transport', None)) else {})) except ImportError: return None except Exception as exc: diff --git a/loopx/chat_manager.py b/loopx/chat_manager.py index f2304e1fb9..8e64824679 100644 --- a/loopx/chat_manager.py +++ b/loopx/chat_manager.py @@ -967,8 +967,9 @@ def manager_session_quota_route(controller: Any, session: Mapping[str, Any]) -> accounts = NativeAccounts(controller.coordination_runtime_root) route_inputs = dict(codex_home=controller.codex_home, primary="antigravity", pool=_manager_eligible_endpoints(defaults), current=str(session["agent_id"]), - blocked_primary=session.get("manager_quota_block"), - model=manager_model_resolution(codex_environment, endpoint="codex", machine_defaults=defaults)[0]) + blocked_primary=session.get("manager_quota_block")) + if callable(getattr(accounts, "model_transport", None)): + route_inputs["model"] = manager_model_resolution(codex_environment, endpoint="codex", machine_defaults=defaults)[0] capacity = None # Explicit API primary does not depend on an unrelated subscription # transport being up. The same owner holds when that role is absent. diff --git a/tests/test_chat_account_workloads.py b/tests/test_chat_account_workloads.py index 284e116619..452b10aeea 100644 --- a/tests/test_chat_account_workloads.py +++ b/tests/test_chat_account_workloads.py @@ -69,6 +69,24 @@ def test_disabled_account_automation_starts_no_policy_or_native_process(account_ assert calls == [] and not owner.path.exists() +def test_older_optional_provider_preserves_its_native_auth_and_epoch(tmp_path, monkeypatch): + import sys + from types import ModuleType + from loopx.capabilities.native_chat import codex_auth + module = ModuleType('loopx_codex_provider_routing.native') + calls = [] + class LegacyOwner: + def __init__(self, root): assert root == tmp_path + def conversation_epoch(self, *, codex_home): + calls.append(codex_home) + return ('legacy-revision', 'subscription-a') + module.NativeAccounts = LegacyOwner + monkeypatch.setitem(sys.modules, module.__name__, module) + assert codex_auth.native_api_transport(tmp_path, tmp_path, consumer='steward') is None + assert codex_auth.conversation_account_epoch(tmp_path, tmp_path, consumer='steward', model='fixture') == ('legacy-revision', 'subscription-a') + assert calls == [tmp_path] + + def test_steward_and_worker_tokens_cannot_cross_billing_routes(account_owner): owner, native, relay, _ = account_owner owner.configure(expected_revision=0, enabled=False, slots=[], steward_api_role='primary') diff --git a/tests/test_chat_manager_model_adoption.py b/tests/test_chat_manager_model_adoption.py index d88047958f..00eaa67ec7 100644 --- a/tests/test_chat_manager_model_adoption.py +++ b/tests/test_chat_manager_model_adoption.py @@ -476,6 +476,8 @@ def test_native_account_epoch_reopens_only_unstarted_codex_adapter(conversation, class Accounts: def __init__(self, path): assert path == runtime.coordination_runtime_root + def model_transport(self, **_parameters): + return None def conversation_epoch(self, *, codex_home, consumer="worker", model=None): assert consumer == "steward" observed.append(codex_home)