Skip to content

feat(providers): add full Hermes agent support - #7168

Closed
eexxio wants to merge 6 commits into
pingdotgg:mainfrom
eexxio:feat/hermes-agent-provider
Closed

feat(providers): add full Hermes agent support#7168
eexxio wants to merge 6 commits into
pingdotgg:mainfrom
eexxio:feat/hermes-agent-provider

Conversation

@eexxio

@eexxio eexxio commented Aug 16, 2026

Copy link
Copy Markdown

What Changed

Adds Hermes Agent as a first-class Early Access provider. T3 Code connects to the Hermes Agent Protocol (ACP) server of a local Hermes Agent installation and uses Hermes' own models, credentials, tools, skills, rules, and session history.

Server

  • HermesDriver + HermesHome: built-in instance plus additional instances via HERMES_HOME — different homes keep configuration, credentials, and history isolated; shared homes can continue each other's sessions
  • HermesAdapter / HermesProvider over ACP: model list from Hermes, permission-mode mapping (Approval required / Auto → default, Auto-accept edits → accept_edits, Full access → dont_ask), session-scoped auto-approval (never a silent permanent grant), image support via ACP, slash commands advertised by the running CLI, MCP server startup
  • HermesAcpSupport + AcpRuntimeModel / AcpSessionRuntime updates: persisted ACP session ID for continuation, replay suppression on resume, updated approval-choices flow
  • HermesTextGeneration for source-control text generation (short-lived provider checks skip configured MCP startup)
  • Registration in builtInDrivers, provider contracts (HermesProviderSettings, ProviderKind), Cursor/Grok adapter alignment

Clients

  • Web + mobile: provider icon, provider card with detected CLI version + update action (hermes update), settings form, model options, context window entry, diagnostics flag

Docs

  • New docs/user/providers-hermes.md; updates to install.md, providers.md, overview.md, glossary.md

Tests

  • Units for driver, home, adapter, provider, ACP runtime/support, text generation, contracts, and web settings (9 new test files)

Why

Hermes Agent (hermes-agent.nousresearch.com) is an open-source, ACP-speaking agent runtime with its own provider, credentials, tools, skills, and session state. Because T3 Code already speaks ACP, the natural integration is a provider card that drives the real Hermes CLI instead of a separate adapter protocol — users get their existing Hermes setup (models, skills, MCP servers, session history) working inside T3 Code with no duplicate configuration. Requires Hermes Agent ≥ 0.20.0.

UI Changes

New Hermes provider card in Settings → Providers (CLI version detection, provider update action, model list) and the Hermes icon in the web/mobile provider pickers. Screenshots can be provided on request.

Checklist

  • I explained what changed and why
  • Unit tests cover the new driver, adapter, provider, ACP support, text generation, and settings
  • Before/after screenshots (available on request)

Note

Medium Risk
Large new provider adapter and ACP session/turn concurrency changes affect core agent runtime; mis-handling steer/interrupt or permission mapping could break threads, though coverage is mostly unit-tested.

Overview
Adds Hermes Agent as a first-class Early Access provider end-to-end: server driver (HermesDriver, HermesHome, provider snapshot/discovery), a large ACP adapter (hermes acp) for sessions, permissions, steering, images, token usage, and resume cursors, plus Hermes-backed text generation for git metadata jobs.

Contracts & settings: New HermesSettings (enabled by default, binaryPath, homePath, custom models), Hermes defaults in model maps, and registry/tests updated so Hermes boots alongside other shipped drivers.

ACP layer (shared): AcpRuntimeModel now emits reasoning text, usage, and available-commands updates; content deltas carry streamKind; AcpSessionRuntime supports concurrent prompts (used by Hermes). Cursor/Grok adapters pass streamKind and ignore the new notification types.

Clients & docs: Hermes icon, picker entry, model labels, thread settings (primary expanded provider), settings form, diagnostics agent detection; new providers-hermes.md and install/docs refresh.

Reviewed by Cursor Bugbot for commit f07fba0. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add full Hermes agent provider support across server, mobile, and web

  • Introduces a complete hermes provider driver including ACP session management, session lifecycle, turn steering, permission handling, model/mode configuration, and event streaming via HermesAdapter.ts and HermesDriver.ts
  • Adds provider health checks, version parsing, ACP-based model and slash command discovery, and settings schema (enabled, binaryPath, homePath, customModels) in HermesProvider.ts and settings.ts
  • Adds Hermes-backed text generation (commit messages, PR content, branch names, thread titles) with JSON schema validation and 180s timeouts in HermesTextGeneration.ts
  • Extends ACP runtime to support concurrent prompts and adds AvailableCommandsUpdated, UsageUpdated, and reasoning ContentDelta (streamKind) event types
  • Surfaces Hermes in the web settings UI, mobile provider icon, session provider picker, and thread settings sheet
  • Risk: Hermes is enabled by default (enabled: true) in server settings, which will trigger provider status checks on all existing deployments

Macroscope summarized f07fba0.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0287dd46-a90d-4991-adec-df5f8a7e4af0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Aug 16, 2026

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding in the web icon layer. The rest of the in-scope web changes (provider icon map, driver metadata, model placeholder, picker option, diagnostics regex, display-name switch) follow the existing per-provider registration patterns.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Icons.tsx
Comment thread apps/server/src/provider/Layers/HermesProvider.ts Outdated
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts Outdated
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts
@macroscopeapp

macroscopeapp Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

1 blocking correctness issue found. This PR introduces a complete new provider driver (Hermes) with ~2900 lines of new code including session management, turn handling, permissions, and text generation. New features of this scope require human review. Additionally, there are unresolved high-severity findings about error handling in the session/turn management logic.

You can customize Macroscope's approvability policy. Learn more.

Replace the U+2624 text glyph (which depends on host font coverage and
renders as a missing-glyph box on some platforms) with a hand-drawn
vector caduceus in both the web and mobile provider icons. Also drops
the hardcoded aria-hidden on the web icon so callers can override it.

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new Hermes Effect code (driver, adapter, ACP support, provider snapshot, text generation) against the service conventions.

Service definition, module layout, dependency acquisition (yield* Foo.Foo), namespace imports, catchTags usage, and predicate exports all look consistent with the conventions. Three findings, all the same error-modeling rule: the wrapper's detail (and therefore its message) is derived from cause.message instead of stable structural attributes. cause is already preserved in each case, so the underlying text stays available without being copied into the wrapper. ClaudeAdapter.ts (e.g. detail: "Failed to read attachment file.") shows the compliant form already used in this repo.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/provider/Layers/HermesAdapter.ts Outdated
Comment thread apps/server/src/provider/Drivers/HermesDriver.ts Outdated
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts Outdated
Address review findings on the Hermes provider:

- sendTurn accounting now runs under the per-thread lock (mirroring the
  hardened GrokAdapter path): the active turn id is bound atomically with
  the in-flight count, so concurrent steers can no longer both treat
  themselves as a fresh turn and emit duplicate turn.started events.
- image steers check interruptedTurnIds after cancelling and awaiting the
  superseded prompt, so a Stop arriving during steer preparation no longer
  submits a fresh prompt (interrupt guard equivalent to Grok's).
- interruptTurn registers the interrupted turn id under the same thread
  lock before cancelling the ACP session.
- model discovery keeps the built-in 'default' entry when Hermes reports
  currentModelId 'default', instead of forcing clients onto the first
  concrete model (adds regression test).
- error detail strings are stable and bounded; cause text and paths stay
  in the cause field, matching repo convention.
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts Outdated
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts
Validate prompt content before binding the session to the new turn id and
emitting turn.started, and clear the active turn id when a fresh turn is
rejected, so an empty sendTurn can no longer leave a phantom running turn.

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One finding on the new web provider icon: its color contract differs from every other entry in PROVIDER_ICON_BY_PROVIDER, which makes it the only provider glyph whose tone changes with the surrounding text color.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/Icons.tsx Outdated
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts
Comment thread apps/server/src/provider/Layers/HermesAdapter.ts Outdated
eexxio added 2 commits August 16, 2026 08:47
Match the other provider icons: explicit theme-aware fill instead of
fill-current, so the icon keeps full contrast in muted-foreground rows.
- emit turn.completed(cancelled) when an image steer is interrupted, so
  the superseded prompt's skipped completion cannot leave the thread
  running forever
- check interruptedTurnIds after prompt preparation on the normal path
  too, so a stop during attachment I/O/config cannot publish a late
  turn.started
- clear the active turn id on every fresh-turn preparation failure
  (invalid attachment, read error, empty prompt, interrupt), not just the
  empty-prompt path, so a concurrent sendTurn cannot misclassify itself
  as a steer
- drop the per-thread semaphore from threadLocksRef when a session is
  stopped, preventing unbounded map growth across sessions
});
}

const result = yield* ctx.acp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High Layers/HermesAdapter.ts:988

When ctx.acp.prompt(...) fails, sendTurn returns an error but the session remains marked as running: no turn.completed event is emitted, and ctx.session.activeTurnId and ctx.activeTurnId remain set. The ensuring block only decrements promptsInFlight, so transport or process failures leave consumers and listSessions observing a permanently active turn; handle this failure path by clearing the active-turn state and emitting a cancelled/completed event.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/Layers/HermesAdapter.ts around line 988:

When `ctx.acp.prompt(...)` fails, `sendTurn` returns an error but the session remains marked as running: no `turn.completed` event is emitted, and `ctx.session.activeTurnId` and `ctx.activeTurnId` remain set. The `ensuring` block only decrements `promptsInFlight`, so transport or process failures leave consumers and `listSessions` observing a permanently active turn; handle this failure path by clearing the active-turn state and emitting a cancelled/completed event.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f07fba0. Configure here.

method: "session/prompt",
detail: "Hermes prompt was interrupted during preparation.",
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Steer interrupt leaves turn open

High Severity

The new interrupt-during-preparation path returns without emitting turn.completed, unlike the image-steer wait path that just fixed the same gap. After a steer, the earlier prompt often already skipped completion because promptsInFlight was still above one, so aborting here can leave the thread running with no terminal turn event.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f07fba0. Configure here.

const next = new Map(current);
next.delete(ctx.threadId);
return next;
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lock map delete breaks exclusion

Medium Severity

Removing the thread entry from threadLocksRef inside stopSessionInternal can orphan the old semaphore while another fiber still waits on or holds it. A later getThreadSemaphore then creates a second lock for the same threadId, so stop/start/sendTurn ensuring no longer mutually exclude and can corrupt promptsInFlight on a replacement session.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f07fba0. Configure here.

@PedroL22

Copy link
Copy Markdown

Please merge this 🙏🏻🙏🏻🙏🏻

@t3dotgg

t3dotgg commented Aug 23, 2026

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing this PR after an automated pass over open pull requests. Adds an unsupported first-party provider or source-control host without a maintainer request.

@t3dotgg t3dotgg closed this Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants