opentui(phase3): launcher integration — HERMES_TUI_ENGINE dual-engine

hermes --tui launches the native OpenTUI engine (Bun) when
HERMES_TUI_ENGINE=opentui (env) or display.tui_engine=opentui (config);
Ink stays the default and the shipping path is untouched.

- _resolve_tui_engine() (env > config > ink); refuses opentui on
  Windows/Termux (no Bun) -> falls back to ink with a notice.
- _make_opentui_argv() -> [bun, src/entry.real.tsx] (no build step).
- _bun_bin() with HERMES_BUN override.
- Branch at top of _make_tui_argv BEFORE _ensure_tui_node (Bun-only host
  must not bootstrap Node).
- Gate _launch_tui NODE_OPTIONS/--max-old-space-size on engine==ink (Bun
  is JSC; the V8 flag errors/ignores).

Verified end-to-end via tmux: real hermes --tui -> Bun -> OpenTUI ->
real Python gateway streamed a real reply. No-flag default still ink.
This commit is contained in:
alt-glitch
2026-06-08 11:11:54 +00:00
parent 24f74eb888
commit 2bd9c9b881
741 changed files with 17733 additions and 79889 deletions
+1 -56
View File
@@ -533,17 +533,6 @@ skills:
When on, any flagged `skill_manage` write surfaces as an approval prompt with the scanner's rationale. Accepted writes land; denied writes return an explanatory error to the agent.
### Write approval for skill writes
Independent of the content scanner above, `skills.write_approval` gates **every** agent skill write (create / edit / patch / delete / supporting files) behind your explicit approval — the same approve/deny mechanism as dangerous commands:
```yaml
skills:
write_approval: false # false = write freely (default) | true = stage every write for review
```
When on, skill writes are staged under `~/.hermes/pending/skills/` and reviewed with `/skills pending`, `/skills diff <id>`, `/skills approve <id>`, `/skills reject <id>` — from the CLI or any messaging platform. Toggle at runtime with `/skills approval on|off`. Memory has the same gate (`memory.write_approval`, below). Full walkthrough: [Gating agent skill writes](/user-guide/features/skills#gating-agent-skill-writes-skillswrite_approval).
## Memory Configuration
```yaml
@@ -552,11 +541,8 @@ memory:
user_profile_enabled: true
memory_char_limit: 2200 # ~800 tokens
user_char_limit: 1375 # ~500 tokens
write_approval: false # true = require approval before any memory write
```
With `memory.write_approval: true`, memory writes need your approval before they land: interactive CLI turns prompt inline; messaging sessions and the background self-improvement review stage the write for `/memory pending``/memory approve <id>` / `/memory reject <id>` review. Toggle at runtime with `/memory approval on|off`. See [Controlling memory writes](/user-guide/features/memory#controlling-memory-writes-write_approval).
## File Read Safety
Controls how much content a single `read_file` call can return. Reads that exceed the limit are rejected with an error telling the agent to use `offset` and `limit` for a smaller range. This prevents a single read of a minified JS bundle or large data file from flooding the context window.
@@ -849,7 +835,6 @@ $ hermes model
[ ] vision currently: auto / main model
[ ] web_extract currently: auto / main model
[ ] title_generation currently: openrouter / google/gemini-3-flash-preview
[ ] tts_audio_tags currently: auto / main model
[ ] compression currently: auto / main model
[ ] approval currently: auto / main model
[ ] triage_specifier currently: auto / main model
@@ -926,14 +911,6 @@ auxiliary:
api_key: ""
timeout: 30 # seconds
# Gemini 3.1 TTS hidden audio-tag insertion
tts_audio_tags:
provider: "auto"
model: "" # empty = main chat model
base_url: ""
api_key: ""
timeout: 30
# Context compression timeout (separate from compression.* config)
compression:
timeout: 120 # seconds — compression summarizes long conversations, needs more time
@@ -1138,17 +1115,6 @@ agent:
When unset (default), reasoning effort defaults to "medium" — a balanced level that works well for most tasks. Setting a value overrides it — higher reasoning effort gives better results on complex tasks at the cost of more tokens and latency.
:::note Adaptive-thinking models (Claude 4.6+, Fable/Mythos-class) over OpenRouter
These models use *adaptive* thinking and don't accept the usual `reasoning.effort`
field — OpenRouter ignores it for them. Hermes transparently routes your
`reasoning_effort` to OpenRouter's `verbosity` parameter instead (which maps to
Anthropic's `output_config.effort`), so the same `low`/`medium`/`high`/`xhigh`
knob keeps working — no extra configuration needed. `none` (or unset) leaves the
model on its own adaptive default. (`max` is accepted on the wire but is not a
selectable `reasoning_effort` value; `xhigh` is the configurable ceiling.) The
native Anthropic provider already controls effort directly and is unaffected.
:::
You can also change the reasoning effort at runtime with the `/reasoning` command:
```
@@ -1220,10 +1186,8 @@ tts:
model: "voxtral-mini-tts-2603"
voice_id: "c69964a6-ab8b-4f8a-9465-ec0925096ec8" # Paul - Neutral (default)
gemini:
model: "gemini-2.5-flash-preview-tts" # or gemini-3.1-flash-tts-preview
model: "gemini-2.5-flash-preview-tts" # or gemini-2.5-pro-preview-tts
voice: "Kore" # 30 prebuilt voices: Zephyr, Puck, Kore, Enceladus, etc.
audio_tags: false # Hidden Gemini 3.1 TTS audio-tag insertion
persona_prompt_file: "" # Optional Markdown/text file with Gemini voice direction
xai:
voice_id: "eve" # xAI TTS voice
language: "en" # ISO 639-1
@@ -1453,25 +1417,6 @@ The master `streaming.enabled` switch is `false` by default — nothing streams
## Group Chat Session Isolation
Limit how many chat sessions can actively be open across CLI, TUI/dashboard,
and messaging gateway:
```yaml
max_concurrent_sessions: null # null/0 = unlimited; positive integer = active session cap
```
When the cap is reached, Hermes returns a direct limit message for new sessions.
Existing active sessions keep their normal behavior.
The canonical key is top-level `max_concurrent_sessions`. Hermes also accepts
`gateway.max_concurrent_sessions` as a fallback, but the top-level key wins when
both are set.
The cap is enforced with a local runtime lease file and is best-effort: Hermes
fails open if the registry cannot be read or locked so users are not stranded.
It is intended for a single host/profile runtime, not a shared `$HERMES_HOME`
mounted across multiple machines.
Control whether shared chats keep one conversation per room or one conversation per participant:
```yaml