hermes(agent): recognize CLI runtime and shorten restarts
All checks were successful
Tests / Declarative: Post Actions passed: 229
All checks were successful
Tests / Declarative: Post Actions passed: 229
This commit is contained in:
parent
e277e43633
commit
04bd50ca74
@ -131,7 +131,29 @@ spec:
|
|||||||
upsert_env GIT_ASKPASS /opt/coordinator/gitea_askpass.sh
|
upsert_env GIT_ASKPASS /opt/coordinator/gitea_askpass.sh
|
||||||
upsert_env GIT_TERMINAL_PROMPT 0
|
upsert_env GIT_TERMINAL_PROMPT 0
|
||||||
chmod 0600 "${env_file}"
|
chmod 0600 "${env_file}"
|
||||||
chown -R 10000:10000 /opt/data
|
# Existing owner data is already written as uid/gid 10000. A
|
||||||
|
# recursive chown made every routine rollout walk the full 20Gi
|
||||||
|
# workspace while the dashboard had no endpoint. Own only the
|
||||||
|
# paths this init container creates or updates.
|
||||||
|
chown 10000:10000 \
|
||||||
|
/opt/data \
|
||||||
|
/opt/data/home \
|
||||||
|
/opt/data/home/.claude \
|
||||||
|
/opt/data/home/.codex \
|
||||||
|
/opt/data/home/.kube \
|
||||||
|
/opt/data/cli-lanes \
|
||||||
|
/opt/data/logs \
|
||||||
|
/opt/data/tools \
|
||||||
|
/opt/data/tools/bin \
|
||||||
|
/opt/data/workspace \
|
||||||
|
/opt/data/workspace/coordinator \
|
||||||
|
/opt/data/workspace/projects \
|
||||||
|
/opt/data/workspace/skills \
|
||||||
|
/opt/data/config.yaml \
|
||||||
|
/opt/data/SOUL.md \
|
||||||
|
/opt/data/workspace/AGENTS.md \
|
||||||
|
/opt/data/workspace/START-HERE.md \
|
||||||
|
"${env_file}"
|
||||||
securityContext:
|
securityContext:
|
||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
runAsUser: 0
|
runAsUser: 0
|
||||||
|
|||||||
@ -6,6 +6,8 @@ from __future__ import annotations
|
|||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Iterable
|
from typing import Any, Iterable
|
||||||
@ -262,6 +264,28 @@ def _existing_model(config: dict[str, Any], provider: str, default: str) -> str:
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def codex_cli_authenticated() -> bool:
|
||||||
|
"""Return whether the installed Codex CLI has a usable local login."""
|
||||||
|
codex = shutil.which("codex")
|
||||||
|
if codex:
|
||||||
|
try:
|
||||||
|
status = subprocess.run(
|
||||||
|
[codex, "login", "status"],
|
||||||
|
capture_output=True,
|
||||||
|
check=False,
|
||||||
|
text=True,
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
detail = f"{status.stdout}\n{status.stderr}".lower()
|
||||||
|
if status.returncode == 0 and (
|
||||||
|
"logged in" in detail or "authenticated" in detail
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
except (OSError, subprocess.SubprocessError):
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def discover_codex_models() -> Catalog:
|
def discover_codex_models() -> Catalog:
|
||||||
"""Use the authenticated Codex endpoint; catalogs are status-only fallback."""
|
"""Use the authenticated Codex endpoint; catalogs are status-only fallback."""
|
||||||
token = ""
|
token = ""
|
||||||
@ -288,6 +312,20 @@ def discover_codex_models() -> Catalog:
|
|||||||
known = _unique_models(provider_model_ids("openai-codex", force_refresh=True))
|
known = _unique_models(provider_model_ids("openai-codex", force_refresh=True))
|
||||||
except Exception:
|
except Exception:
|
||||||
known = []
|
known = []
|
||||||
|
# The owner agent deliberately uses the local Codex app-server and the
|
||||||
|
# Codex CLI's ChatGPT login. That credential is not exported into Hermes'
|
||||||
|
# bearer-token store, so API discovery above may be empty even though the
|
||||||
|
# runtime is fully authenticated. Treat a successful CLI status check as a
|
||||||
|
# connected, degraded catalog: routing may use Codex while retaining the
|
||||||
|
# last-known working model names until app-server discovery is available.
|
||||||
|
if codex_cli_authenticated():
|
||||||
|
return Catalog(
|
||||||
|
"openai-codex",
|
||||||
|
known,
|
||||||
|
False,
|
||||||
|
True,
|
||||||
|
"connected-cli",
|
||||||
|
)
|
||||||
state = "degraded" if token else "not-configured"
|
state = "degraded" if token else "not-configured"
|
||||||
return Catalog("openai-codex", known, False, bool(token), state)
|
return Catalog("openai-codex", known, False, bool(token), state)
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import json
|
import json
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@ -64,6 +65,23 @@ def test_empty_catalog_retains_current_models():
|
|||||||
assert routing.choose_claude_model([], "claude-opus-5") == "claude-opus-5"
|
assert routing.choose_claude_model([], "claude-opus-5") == "claude-opus-5"
|
||||||
|
|
||||||
|
|
||||||
|
def test_codex_cli_login_counts_as_connected_runtime(monkeypatch):
|
||||||
|
"""AUTO routing must recognize the authenticated app-server CLI lane."""
|
||||||
|
monkeypatch.setattr(routing.shutil, "which", lambda name: "/usr/bin/codex")
|
||||||
|
monkeypatch.setattr(
|
||||||
|
routing.subprocess,
|
||||||
|
"run",
|
||||||
|
lambda *args, **kwargs: subprocess.CompletedProcess(
|
||||||
|
args[0],
|
||||||
|
0,
|
||||||
|
stdout="Logged in using ChatGPT\n",
|
||||||
|
stderr="",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
assert routing.codex_cli_authenticated() is True
|
||||||
|
|
||||||
|
|
||||||
def test_configure_routes_builds_cross_provider_fallback_profiles(tmp_path: Path):
|
def test_configure_routes_builds_cross_provider_fallback_profiles(tmp_path: Path):
|
||||||
(tmp_path / "config.yaml").write_text(
|
(tmp_path / "config.yaml").write_text(
|
||||||
yaml.safe_dump(_base_config()), encoding="utf-8"
|
yaml.safe_dump(_base_config()), encoding="utf-8"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user