16 Commits
Author SHA1 Message Date
Mike McHargueandClaude Opus 5 1f7e5e78da fix: resolve Hermes Agent names moved by the Sep 2026 decomposition
Hermes Agent moved several names the WebUI uses into sibling modules
(tools.approval_context, tools.mcp_tool_discovery/_lifecycle,
hermes_cli.kanban_db_connect/_dispatch, hermes_cli.models_local,
agent.anthropic_credentials). The old paths only resolved through
PLUGIN-COMPAT __getattr__ pointers that warn on every use and are removed
on schedule by reverting one commit.

With the pointers removed, every affected WebUI call site is wrapped in a
broad except, so nothing crashes; features silently degrade instead:
per-turn approval session-key binding is skipped, MCP discovery/status
return nothing, /reload-mcp reports "MCP runtime unavailable", Claude Code
credential linking returns None, every kanban connection raises
AttributeError, and the dispatcher reports "unavailable".

Add api.agent_compat.agent_attr, which resolves a moved name from the
original module's own namespace first (pre-split Agents and existing test
stubs), then from its new home (split Agents, with or without pointers),
then plain attribute access (non-module doubles). Importing only the new
modules would have broken pre-split Agents and bypassed the sys.modules
stubs the test suite installs on the original modules.

Names still native to their original module (_servers, _lock,
has_blocking_approval, is_session_yolo_enabled, register/unregister
gateway notify, the rest of kanban_db) are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 21:26:50 +00:00
seanxgao ab4d64f157 perf(providers): invalidate cache on oauth credential changes 2026-07-13 19:58:41 +08:00
d6e5dc302d Release Batch D: terminal resource-leak fix + fsync atomic writers (#5835, #5843) (#5848)
Phase 2 backend reliability/data-integrity batch. Each byte-verified vs PR head,
Codex SAFE, 20 own + 355 regression tests pass, disjoint files.

- #5835 (ai-ag2026): stop leaking fd + reader thread + shell on client/shell exit (#4633 family)
- #5843 (ai-ag2026): fsync atomic JSON writers (oauth/passkeys/discoverability) + thread-safe temp

Co-authored-by: t <a@b>
Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-07-09 10:54:06 -07:00
hinotoi-agent 3c1b7392ba Avoid blocking OAuth flow lock during Codex start 2026-06-17 00:20:49 +00:00
hinotoi-agent a700e8e0d3 fix(security): reuse pending onboarding oauth flows 2026-06-17 00:20:49 +00:00
nesquena-hermes cf07c0a02d Release v0.51.330 — Release KT (#3716 api docstring backfill, partial) (#3841)
Backfill docstrings for api/oauth.py + api/kanban_bridge.py (51 functions, verified accurate to current behavior). Conflicted files dropped for follow-up. Docstring-only, no behavior change. Full suite 8275, CI 11/11. Co-authored-by: camr <camr@users.noreply.github.com>
2026-06-08 12:22:22 -07:00
Frank Song 91f99d8194 fix(oauth): serialize Anthropic env fallback reads 2026-05-07 02:47:19 +00:00
Michael Lam e509faec44 feat: link Claude Code OAuth in onboarding 2026-05-06 06:26:43 +00:00
Nathan EsquenaziandClaude Opus 4.7 b34ce63c97 fix(oauth): honor cancel during Codex device-token exchange (follow-up to #1652)
The Codex OAuth onboarding worker introduced in #1652 had a cancel-vs-worker
race: a `cancel_onboarding_oauth_flow` request that arrived while the worker
was mid-network-call (between the `live = dict(...)` snapshot and the next
status check) would be silently overridden:

  1. User clicks Cancel → server sets flow.status = "cancelled" and drops
     sensitive lifecycle fields under the lock.
  2. Worker is mid-`_poll_codex_authorization` / `_exchange_codex_authorization`
     using the local `live` snapshot it captured before the cancel.
  3. Worker calls `_persist_codex_credentials(...)` — auth.json gets written.
  4. Worker calls `_set_flow_status(flow_id, "success")` — overrides the
     cancelled status.

Net effect: the user's explicit cancel is ignored, credentials are persisted,
and the UI reports success. Reproduced with a behavioural harness that drove
a real worker thread against patched network helpers and confirmed:

  pre-fix : flow status `success`, auth.json written despite cancel
  post-fix: flow status `cancelled`, auth.json NOT written

The fix re-checks the flow status under `_OAUTH_FLOWS_LOCK` after the token
exchange completes and before persisting. If the status is no longer
`pending`, the worker exits without persisting credentials and without
overwriting the terminal status.

Regression test `test_cancel_during_token_exchange_does_not_persist_credentials`
drives the worker against threading.Event-gated network stubs to reproduce
the race deterministically and lock the new invariant.

Trace verified against fresh hermes-agent tarball — credential_pool entry
shape (`auth_type=oauth`, `source=manual:device_code`, `priority=0`, base_url)
remains compatible with `agent.credential_pool.load_pool("openai-codex")` and
the agent CLI's `_save_codex_tokens` legacy fallback path.

Tests:
- 10/10 in tests/test_issue1362_codex_oauth_onboarding.py
- Full suite: 4230 passed, 57 skipped, 3 xpassed, 0 failed in 33.82s

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 14:49:38 -07:00
Hermes Agent db54dc594e chore(release): stamp v0.50.296 — 3-PR batch + Opus pass + 2 follow-ups absorbed
Constituent PRs (all by @Michaelyklam):
  #1640 — show TPS in assistant message headers (closes #1617) — Aaron UX APPROVED
  #1648 — session save mode config (closes #1406)
  #1650 — Codex OAuth onboarding flow (refs #1362)

Opus advisor SHIP verdict on stage-296. 14-question audit passed including
focused OAuth security review on #1650. Two minor follow-ups absorbed:
- _get_active_hermes_home() exception fallback now logs warning
- Codex credential pool find-loop accepts both legacy and current source values

#1640 has @aronprins UX gate APPROVED (default-off TPS toggle in Preferences).
#1650 ships first in-app OAuth flow — server-owned device-code lifecycle,
profile-scoped credential storage, atomic chmod-before-rename writes.

4255 → 4284 tests passing (+29).
2026-05-04 21:38:26 +00:00
Michael Lam 259c5c4afb feat: add Codex OAuth onboarding flow 2026-05-04 14:07:16 -07:00
bergeouss 8fe593fa38 feat: silent credential self-heal on 401 errors (#1401) 2026-05-03 18:32:53 +00:00
nesquena-hermes f8007d43f3 v0.50.257: 4 Opus pre-release follow-ups + CHANGELOG + test fixes for #1415
stage-257 batch (PRs #1402 + #1415):

Opus pre-release advisor caught 4 issues in stage-257:

1. MUST-FIX (security): api/oauth.py::_write_auth_json — tmp.replace()
   preserves the temp file umask (0644 default), so OAuth access/refresh
   tokens landed world-readable on shared systems. Fix: tmp.chmod(0o600)
   BEFORE rename, with try/except OSError that warns but does not abort.

2. SHOULD-FIX: _handle_cron_history and _handle_cron_run_detail accepted
   job_id as a path component without validation. Mirrors the rollback
   path-traversal vector caught in v0.50.255 (#1405). Path() / .. does NOT
   normalize. New regex ^[A-Za-z0-9_-][A-Za-z0-9_.-]{0,63}$ with explicit
   . / .. rejection.

3. SHOULD-FIX: _handle_cron_history int(offset)/int(limit) raised
   ValueError on malformed input → confusing 500. Now try/except + clamp
   to (max(0, offset), max(1, min(500, limit))).

4. NIT: same regex applied to _handle_cron_run_detail (defense-in-depth
   even though path-resolve check would catch it downstream).

PR #1415 follow-up: 8 pre-existing tests in test_issue1106 and
test_custom_provider_display_name asserted bare model IDs but #1415
changes named-custom-provider IDs to @custom:NAME:model form when active
provider differs. Tests updated to use _strip_at_prefix helper to keep
checking the same invariant in the new shape.

4 regression tests in test_v050257_opus_followups.py + 8 fixed pre-existing
tests. Full suite: 3602 passed, 0 failed.
2026-05-01 18:30:41 +00:00
bergeouss 3bff26037f fix: improve auth.json warning message and prevent credential ID collision
- Include file path and exception details in _read_auth_json warning log
- Add retry-on-collision (up to 3 attempts) for credential UUID generation

Addresses PR #1402 review feedback points 1 and 2.
2026-05-01 15:46:50 +00:00
bergeouss f4bfd9dca7 fix: address PR #1402 review feedback — cron sort, path traversal, OAuth robustness
- Cron history: sort by mtime instead of lexicographic filename (more robust)
- Path traversal: use resolve() + is_relative_to() instead of brittle string checks
- _cron_output_snippet: document the contract for response heading extraction
- _read_auth_json: catch JSONDecodeError specifically, log warning instead of silent swallow
- OAuth timestamps: use ISO strings consistently (created_at, updated_at)
- Credential id: use uuid4 instead of time-based truncated int (collision-safe)
2026-05-01 13:38:14 +00:00
bergeouss 8ae198e88c feat: P2 improvements — cron history, toolsets per session, Codex OAuth
- #468: Cron run history — GET /api/crons/history (metadata listing)
  + GET /api/crons/run (full output), lazy-load on click in Tasks panel
- #493: Per-session toolset override — Session.enabled_toolsets field,
  POST /api/session/toolsets endpoint, streaming handler override,
  composer chip UI with dropdown (matches reasoning chip pattern)
- #1362: In-app Codex OAuth — device-code flow (stdlib only, no httpx),
  SSE polling endpoint, onboarding wizard login button
- #1240: Design proposal comment for provider/model source-of-truth
2026-05-01 12:42:21 +00:00