mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-17 14:42:06 +00:00
Merge remote-tracking branch 'origin/main' into pr48275-rebase
# Conflicts: # cron/scheduler.py
This commit is contained in:
commit
a58287afcb
162 changed files with 8521 additions and 634 deletions
|
|
@ -743,7 +743,7 @@ Upload a debug report (system info + recent logs) to a paste service and get a s
|
|||
| `--expire <days>` | Paste expiry in days (default: 7). |
|
||||
| `--local` | Print the report locally instead of uploading. |
|
||||
|
||||
The report includes system info (OS, Python version, Hermes version), recent agent and gateway logs (512 KB limit per file), and redacted API key status. Keys are always redacted — no secrets are uploaded.
|
||||
The report includes system info (OS, Python version, Hermes version), recent agent, gateway, GUI/dashboard, and desktop logs (512 KB limit per file), and redacted API key status. Keys are always redacted — no secrets are uploaded.
|
||||
|
||||
Paste services tried in order: paste.rs, dpaste.com.
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ The **Chat** tab embeds the full Hermes TUI (the same interface you get from `he
|
|||
|
||||
**Resume an existing session:** from the **Sessions** tab, click the play icon (▶) next to any session. That jumps to `/chat?resume=<id>` and launches the TUI with `--resume`, loading the full history.
|
||||
|
||||
**Session switcher (right rail):** the Chat tab carries its own ChatGPT-style conversation list in a thin right rail beside the terminal, so you can swap conversations without leaving the page. The rail stacks the model picker on top and the session list directly below it; the terminal takes up most of the screen. The list shows your most recent sessions for the active profile — title (falling back to a message preview), relative last-active time, message count, and the source channel for non-CLI sessions. Click any row to resume it in place (the terminal respawns with that conversation's history); the active session is highlighted. **New chat** starts a fresh session, and a refresh control re-pulls the list. The rail is read-only for switching — delete, rename, export, and bulk cleanup still live on the **Sessions** tab. On narrow screens it folds into a slide-over panel.
|
||||
|
||||
**Prerequisites:**
|
||||
|
||||
- Node.js (same requirement as `hermes --tui`; the TUI bundle is built on first launch)
|
||||
|
|
|
|||
|
|
@ -56,6 +56,139 @@ research gateway start
|
|||
That's it — three independent agents, each on its own process, restarting
|
||||
automatically on crash and on user login.
|
||||
|
||||
## Alternative: one gateway for all profiles (multiplexing)
|
||||
|
||||
The model above runs **one process per profile**. That is the default and is
|
||||
the right choice for most setups. But on a host with many profiles — or a
|
||||
container deployment where one process per profile is operationally heavy — you
|
||||
can instead run a **single multiplexing gateway**: the default profile's gateway
|
||||
becomes the sole inbound process and serves messages for *every* profile on the
|
||||
box.
|
||||
|
||||
This is **opt-in** and **off by default**. When it's off, nothing on this page
|
||||
changes — every behavior below is inert.
|
||||
|
||||
### When to prefer multiplexing
|
||||
|
||||
- A container/VPS deployment where N supervisor units, N ports, and N PID files
|
||||
are a burden.
|
||||
- Many low-traffic profiles that don't each justify a full process.
|
||||
- You want a single thing to start, monitor, and restart.
|
||||
|
||||
Stick with one-process-per-profile when you want hard process-level isolation
|
||||
between profiles (separate memory footprints, independent crash domains, the
|
||||
ability to restart one profile without touching the others).
|
||||
|
||||
### How to opt in
|
||||
|
||||
Set the flag on the **default profile** (it owns the multiplexer) and restart
|
||||
its gateway:
|
||||
|
||||
```bash
|
||||
hermes config set gateway.multiplex_profiles true
|
||||
hermes gateway restart
|
||||
```
|
||||
|
||||
Equivalently, in the default profile's `~/.hermes/config.yaml`:
|
||||
|
||||
```yaml
|
||||
gateway:
|
||||
multiplex_profiles: true
|
||||
```
|
||||
|
||||
(The flag is also accepted as a top-level `multiplex_profiles: true` for
|
||||
convenience.) On the next start the default gateway enumerates every profile,
|
||||
brings up each profile's enabled platforms under that profile's own
|
||||
credentials, and routes each inbound message to the profile it belongs to. Each
|
||||
turn resolves the routed profile's config, skills, memory, SOUL, **and provider
|
||||
keys** — credentials are never shared across profiles.
|
||||
|
||||
You do **not** run `hermes gateway start` for the secondary profiles — the
|
||||
default gateway serves them. See the contract changes below.
|
||||
|
||||
### What changes when multiplexing is on
|
||||
|
||||
Enabling the flag changes how a few things behave. All of these revert the
|
||||
moment the flag is off.
|
||||
|
||||
#### 1. Secondary profiles must not start their own gateway
|
||||
|
||||
With a multiplexer running, a named-profile `hermes gateway start` / `run` is a
|
||||
**hard error**, pointing you back at the multiplexer:
|
||||
|
||||
```
|
||||
The default gateway is running as a profile multiplexer and already serves
|
||||
profile 'coder'. ...
|
||||
```
|
||||
|
||||
The multiplexer is the single inbound process; a second profile gateway would
|
||||
double-bind that profile's platforms. Pass `--force` only if you deliberately
|
||||
want a separate process for that profile (not recommended while the multiplexer
|
||||
is running). The cross-profile lifecycle wrapper script earlier on this page is
|
||||
therefore **not** used in multiplex mode — you only manage the default gateway.
|
||||
|
||||
#### 2. HTTP-inbound platforms are reached via a `/p/<profile>/` URL prefix
|
||||
|
||||
Webhook (and other HTTP-inbound) traffic for a secondary profile arrives on the
|
||||
default listener under a profile prefix, **not** a second port:
|
||||
|
||||
```
|
||||
# default profile
|
||||
POST http://host:8644/webhooks/<route>
|
||||
# the "coder" profile, same listener
|
||||
POST http://host:8644/p/coder/webhooks/<route>
|
||||
```
|
||||
|
||||
An unknown or unconfigured profile in the prefix returns `404`. Because the one
|
||||
shared listener already serves every profile this way, a **secondary profile
|
||||
must not enable a port-binding platform itself** — doing so is a config error
|
||||
and the gateway refuses to start, naming the profile and platform:
|
||||
|
||||
```
|
||||
Profile 'coder' enables the port-binding platform 'webhook', but
|
||||
gateway.multiplex_profiles is on. ... Remove platforms.webhook from profile
|
||||
'coder's config.yaml (configure it only on the default profile).
|
||||
```
|
||||
|
||||
Port-binding platforms covered by this rule: `webhook`, `api_server`,
|
||||
`msgraph_webhook`, `feishu`, `wecom_callback`, `bluebubbles`, `sms`. Configure
|
||||
any of these **only on the default profile**; every profile is reachable through
|
||||
its `/p/<profile>/` prefix.
|
||||
|
||||
#### 3. Per-credential platforms still need their own token per profile
|
||||
|
||||
Polling/connection platforms (Telegram, Discord, Slack, Matrix, Signal, …) work
|
||||
fine multiplexed, but each profile that enables one must supply its **own** bot
|
||||
token — the same token cannot be polled by two profiles at once. If two profiles
|
||||
configure the same `(platform, token)`, startup fails fast naming both profiles
|
||||
(see [Token-conflict safety](#token-conflict-safety) — the rule is unchanged,
|
||||
it's just enforced inside the one process now).
|
||||
|
||||
#### 4. Session keys are namespaced by profile
|
||||
|
||||
Each profile's sessions live under an `agent:<profile>:…` namespace so two
|
||||
profiles on the same platform/chat never collide in the shared session store.
|
||||
The **default** profile keeps the historical `agent:main:…` namespace
|
||||
byte-for-byte, so existing default-profile sessions are unaffected — no
|
||||
migration, no orphaned history.
|
||||
|
||||
#### 5. One PID/lock and one status surface
|
||||
|
||||
There is a single process-level PID and lock (the multiplexer, under the default
|
||||
home). `hermes status` reports the multiplexer and the profiles it serves;
|
||||
`hermes status -p <name>` slices to one profile. Each profile still writes its
|
||||
own `runtime_status.json` under its own home, so existing per-profile readers
|
||||
keep working.
|
||||
|
||||
#### What does **not** change
|
||||
|
||||
Per-profile `.env` credential isolation is preserved and, if anything,
|
||||
stricter: a profile's keys are resolved from its own scope and are never unioned
|
||||
into a shared environment (this also means subprocesses like MCP servers and
|
||||
Kanban workers only ever see their own profile's secrets). Kanban,
|
||||
profile-scoped skills/memory/SOUL, and model routing all behave per-profile
|
||||
exactly as they do with separate gateways.
|
||||
|
||||
## Start, stop, or restart all gateways at once
|
||||
|
||||
The CLI ships with single-profile lifecycle commands. To act across every
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue