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,16 +1,14 @@
---
sidebar_position: 15
title: "Automation Blueprints"
description: "Ready-to-use automation blueprints — scheduled tasks, GitHub event triggers, API webhooks, and multi-skill workflows"
title: "Automation Templates"
description: "Ready-to-use automation recipes — scheduled tasks, GitHub event triggers, API webhooks, and multi-skill workflows"
---
# Automation Blueprints
# Automation Templates
Copy-paste blueprints for common automation patterns. Each blueprint uses Hermes's built-in [cron scheduler](/user-guide/features/cron) for time-based triggers and [webhook platform](/user-guide/messaging/webhooks) for event-driven triggers.
Copy-paste recipes for common automation patterns. Each template uses Hermes's built-in [cron scheduler](/user-guide/features/cron) for time-based triggers and [webhook platform](/user-guide/messaging/webhooks) for event-driven triggers.
Every blueprint works with **any model** — not locked to a single provider.
For parameterized blueprints with forms instead of cron syntax, see the [Automation Blueprints Catalog](/reference/automation-blueprints-catalog).
Every template works with **any model** — not locked to a single provider.
:::tip Three Trigger Types
| Trigger | How | Tool |
@@ -488,53 +488,6 @@ When `security.allow_lazy_installs: false` is set globally, `ensure()` raises `F
### Thread-safe lazy singletons
Plugins often cache an expensive object — an SDK client, an HTTP session, a connection pool — in a module-level variable built on first use:
```python
_client = None
def get_client():
global _client
if _client is not None:
return _client
_client = ExpensiveClient(...) # ← TOCTOU race
return _client
```
This is a footgun. Hermes runs multiple threads in one process (delegated tool calls, background workers, the self-improvement fork), so two threads can hit `get_client()` before `_client` is set, **both** pass the `is not None` check, **both** run the expensive build, and the second write clobbers the first — leaking whatever resource the loser opened (connection, file handle, background thread).
Don't hand-roll the lock. Use the helpers in `plugins/plugin_utils.py`:
```python
from plugins.plugin_utils import lazy_singleton, SingletonSlot
# Zero-arg accessor → decorate it:
@lazy_singleton
def get_client():
return ExpensiveClient(load_config()) # runs exactly once
client = get_client() # safe across threads
get_client.reset() # drop the instance (tests / teardown)
# Accessor that takes a build argument → use a slot:
_slot: SingletonSlot = SingletonSlot()
def get_client(config=None):
return _slot.get(lambda: ExpensiveClient(resolve(config)))
def reset_client():
_slot.reset()
```
Both serialize concurrent first calls with double-checked locking and run the factory at most once. If the factory raises, nothing is cached and the next call retries. The honcho memory plugin (`plugins/memory/honcho/client.py`) is the reference consumer.
> Rule of thumb: any time you write `global _something` followed by a `is None` check and a build, reach for one of these instead.
### Conditional tool availability
For tools that depend on optional libraries: