Lines 1, 400, and 533 contained literal backslash-n sequences that caused
SyntaxError on import. Replace each with actual newlines and correct the
surrounding indentation so the code structure is preserved.
Fixes#1040
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add TestAIAgentConcurrentExecution with 8 integration tests exercising
_execute_tool_calls_concurrent through AIAgent for 2/3/4-tool batches,
pass-rate reporting, and Gemma 4-style read patterns.
- Fix test_malformed_json_args_forces_sequential: use JSON array '[1,2,3]'
instead of unrepairable garbage now that repair_and_load_json handles
most malformed input.
- Fix test_concurrent_handles_tool_error: replace racy call_count list
with deterministic failure based on tool_call_id to eliminate flaky
failures under ThreadPoolExecutor.
Closes#798
Brings hooks/pre-commit-path-guard.py from burn/921-poka-yoke-hardcoded-paths
to complete QA verification of all guard layers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the action button lifecycle described in #961:
- POST /api/actions/restart-gateway — sends SIGTERM to the gateway PID
- POST /api/actions/update-hermes — runs pip upgrade in a background job
- GET /api/actions/jobs/{job_id} — polls job status/output
Frontend (StatusPage.tsx):
- "Restart Gateway" button with spinning icon while running, then
success/error message that clears after 5–8 s
- "Update Hermes" button that polls the job endpoint every 2 s;
shows collapsible pip output on completion
- Page remains responsive (buttons disabled only during their own action)
Also adds i18n strings to en.ts, zh.ts, and the shared types.ts interface.
Fixes#961
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add TestActionEndpoints class to test_web_server.py covering:
- POST /api/actions/restart-gateway sends SIGUSR1 to gateway PID
- 409 when gateway is not running
- 500 when os.kill raises a signal error
- POST /api/actions/update-hermes returns ok=true on zero exit
- ok=false on non-zero exit code with stderr in detail
- ok=false on timeout
- Both endpoints reject unauthenticated requests
All 7 new tests pass (83 total in the file).
Refs #961
Implements the update/restart action buttons called out in issue #961:
- Backend (web_server.py): two new POST endpoints
- /api/actions/restart-gateway — sends SIGUSR1 to the running gateway PID
- /api/actions/update-hermes — runs `hermes update --yes` in a subprocess
- Frontend (api.ts): restartGateway() / updateHermes() API helpers + ActionResponse type
- UI (StatusPage.tsx): "Actions" card with Restart Gateway and Update Hermes buttons
- idle → running (spinner) → success/failure states
- feedback detail text; auto-resets to idle after 8 s
- i18n: new status.actions / restartGateway / updateHermes strings in en, zh, and types
Refs #961
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cherry-picks tools/path_guard.py and tests/test_path_guard.py from
burn/921-poka-yoke-hardcoded-paths (commit 5dcb905). All 21 tests pass:
- hardcoded /Users/<name>/ paths are rejected at runtime
- hardcoded /home/<name>/ paths are rejected at runtime
- ~/.hermes/... via expanduser() passes (safe, expanded at runtime)
- valid relative and /tmp/ absolute paths pass
- static scanner catches violations and respects # noqa: hardcoded-path-ok
- comments are skipped by scanner
- directory scanner skips test files and __pycache__
Refs #962
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_get_vision_model() now resolves via a layered priority chain:
1. BROWSER_VISION_MODEL env var (browser-specific override)
2. config.yaml browser.vision_model
3. AUXILIARY_VISION_MODEL env var (backward-compat shared override)
4. google/gemma-4-27b-it — Gemma 4 native multimodal default
Add browser.vision_model config key to hermes_cli/config.py defaults
with inline documentation.
call_kwargs["model"] is now always set (model is never None), and a
debug log line records which model is in use for each screenshot.
Fixes#816
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Building on the Gemma 4 default already on this branch:
- Change call_llm() task from "vision" to "browser_vision" in browser_vision()
so auxiliary.browser_vision.* config is consulted for provider/model/timeout
- Route call_llm(task="browser_vision") through the vision provider resolution
path in auxiliary_client.py (same as task="vision")
- Fix timeout resolution: check auxiliary.browser_vision.timeout before
auxiliary.vision.timeout (allows browser-specific timeout override)
- Add timeout option to auxiliary.browser_vision in cli-config.yaml.example
- Add test_browser_vision_gemma4.py covering: task routing assertions,
call_llm() vision branch routing, and timeout config key ordering
Refs #816
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merge remote claude/issue-816 which contains the full Gemma 4 browser
vision implementation. Resolved conflicts by taking the remote's cleaner
variable names and docstrings while keeping the same 4-tier resolution
logic. All 12 tests pass.
Refs #816
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extends `_get_vision_model()` with a 5-level resolution chain:
1. `BROWSER_VISION_MODEL` env var — browser-specific override
2. `auxiliary.browser.vision_model` config key — per-install default
3. `AUXILIARY_VISION_MODEL` env var — backward-compat shared override
4. Auto-select `gemma-4-27b-it` when the main provider is Gemini/Google
5. `None` — fall through to `call_llm` vision router
Adds `_BROWSER_VISION_DEFAULT_MODEL = "gemma-4-27b-it"` constant and
registers `gemma-4-27b-it` in the Gemini provider model catalog.
16 new tests in `tests/tools/test_browser_vision_model.py` cover each
priority level, edge cases (empty env, config exceptions, wrong provider).
Fixes#816
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements mTLS for securing agent-to-agent communication in the Hermes
fleet. Fixes#806.
Changes:
- scripts/gen_fleet_ca.sh: generate a self-signed Fleet CA (4096-bit RSA,
10-year validity) that signs all agent certificates
- scripts/gen_agent_cert.sh: generate per-agent certs (Timmy, Allegro,
Ezra) signed by the fleet CA with SAN entries and clientAuth/serverAuth
extended key usage
- agent/mtls.py: new module providing:
- build_server_ssl_context() — TLS_SERVER context with CERT_REQUIRED,
enforces client cert against Fleet CA
- build_client_ssl_context() — TLS_CLIENT context for outbound A2A calls
- MTLSMiddleware — ASGI middleware that rejects unauthenticated requests
to A2A routes (/.well-known/agent-card*, /api/agent-card, /a2a/) with
HTTP 403 when mTLS is enabled
- is_mtls_configured() — checks HERMES_MTLS_CERT/KEY/CA env vars
- hermes_cli/web_server.py: wire MTLSMiddleware into the FastAPI app;
pass SSL context to uvicorn when HERMES_MTLS_* env vars are set so
the server runs TLS with mandatory client cert verification
- ansible/roles/hermes_mtls/: Ansible role to distribute Fleet CA cert,
agent cert, and agent key to fleet nodes; writes an env file with
HERMES_MTLS_* vars and restarts the hermes-gateway service
- ansible/fleet_mtls.yml: fleet-wide playbook referencing the role for
Timmy, Allegro, and Ezra nodes
- tests/test_mtls.py: 15 tests covering is_mtls_configured, SSL context
creation with real cryptography-generated certs, and MTLSMiddleware
(unauthorized agent rejected → 403, authorized agent accepted → 200)
mTLS is opt-in: set HERMES_MTLS_CERT, HERMES_MTLS_KEY, and HERMES_MTLS_CA
to enable. When unset, the server behaves exactly as before.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Default browser_vision screenshots to google/gemma-4-27b-it (Gemma 4
native multimodal) for reduced latency and unified text+vision model.
Resolution order for _get_vision_model():
1. BROWSER_VISION_MODEL env var (new, browser-specific override)
2. auxiliary.browser_vision.model in config.yaml (new config key)
3. AUXILIARY_VISION_MODEL env var (existing global vision override)
4. Default: google/gemma-4-27b-it
Backward compatibility: existing AUXILIARY_VISION_MODEL users are
unaffected — their override still flows through to browser_vision.
Also documents the new auxiliary.browser_vision config section in
cli-config.yaml.example and adds 14 unit tests covering the full
priority chain.
Fixes#816
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>