mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-23 10:42:00 +00:00
docs(ui-tui): fix file paths, add billing command, update file map
This commit is contained in:
parent
d164ed0326
commit
d7737bfd97
1 changed files with 231 additions and 89 deletions
320
ui-tui/README.md
320
ui-tui/README.md
|
|
@ -70,14 +70,38 @@ npm run test:watch
|
|||
|
||||
`src/app.tsx` is the center of the UI. Heavy logic is split into `src/app/`:
|
||||
|
||||
- `createGatewayEventHandler.ts` — maps gateway events to state updates
|
||||
- `createSlashHandler.ts` — local slash command dispatch
|
||||
- `useComposerState.ts` — draft, multiline buffer, queue editing
|
||||
- `useInputHandlers.ts` — keypress routing
|
||||
- `useTurnState.ts` — agent turn lifecycle
|
||||
- `overlayStore.ts` / `uiStore.ts` — nanostores for overlay and UI state
|
||||
- `gatewayContext.tsx` — React context for the gateway client
|
||||
- `constants.ts`, `helpers.ts`, `interfaces.ts`
|
||||
- `src/app/createGatewayEventHandler.ts` — maps gateway events to state updates
|
||||
- `src/app/createSlashHandler.ts` — local slash command dispatch
|
||||
- `src/app/useComposerState.ts` — draft, multiline buffer, queue editing
|
||||
- `src/app/useInputHandlers.ts` — keypress routing
|
||||
- `src/app/useMainApp.ts` — top-level composition hook: wires all sub-hooks, manages transcript history, session polling, and exposes props consumed by `app.tsx`
|
||||
- `src/app/useSessionLifecycle.ts` — session create / resume / activate / close and visible-history reset
|
||||
- `src/app/useSubmission.ts` — message send, shell exec (`!cmd`), inline interpolation (`{!cmd}`), and busy-input-mode dispatch (queue / steer / interrupt)
|
||||
- `src/app/turnController.ts` — stateful class that drives the turn lifecycle: buffers streaming deltas, manages tool/reasoning state, handles interrupt and message-complete transitions
|
||||
- `src/app/turnStore.ts` — nanostore for turn state (streaming text, tools, reasoning, subagents, todos, activity trail)
|
||||
- `src/app/useConfigSync.ts` — fetches `config.get full` on session start and polls config mtime every 5 s; applies display settings and triggers MCP reload on change
|
||||
- `src/app/useLongRunToolCharms.ts` — fires ambient activity messages for tools running longer than 8 s
|
||||
- `src/app/overlayStore.ts` / `src/app/uiStore.ts` — nanostores for overlay and UI state
|
||||
- `src/app/delegationStore.ts` — nanostore for subagent spawning caps and overlay accordion state
|
||||
- `src/app/spawnHistoryStore.ts` — in-memory ring (last 10) of finished subagent fan-out snapshots; populated at turn end for `/replay`
|
||||
- `src/app/inputSelectionStore.ts` — nanostore exposing the active text-input selection handle
|
||||
- `src/app/gatewayContext.tsx` — React context for the gateway client
|
||||
- `src/app/gatewayRecovery.ts` — pure function that decides whether to respawn and resume after a gateway crash, with a 3-attempt / 60 s budget
|
||||
- `src/app/setupHandoff.ts` — launches external `hermes setup`, suspends Ink while it runs, opens a new session on success
|
||||
- `src/app/scroll.ts` — scrolls the viewport while keeping the text selection anchor in sync
|
||||
- `src/app/interfaces.ts` — internal interfaces (ComposerActions, GatewayRpc, etc.)
|
||||
|
||||
### Slash command subsystem (`src/app/slash/`)
|
||||
|
||||
- `types.ts` — `SlashCommand` interface and `SlashRunCtx` execution context (gateway rpc, transcript helpers, session refs, stale-guard)
|
||||
- `registry.ts` — assembles `SLASH_COMMANDS` from all command files in registration order (core → billing → credits → session → ops → setup → debug) and exposes `findSlashCommand(name)` for case-insensitive lookup
|
||||
- `commands/core.ts` — general TUI commands
|
||||
- `commands/billing.ts` — `/billing`: manage Nous terminal billing — buy credits, auto-reload, limits
|
||||
- `commands/credits.ts` — `/credits`
|
||||
- `commands/session.ts` — session and agent commands
|
||||
- `commands/ops.ts` — operations commands
|
||||
- `commands/setup.ts` — `/setup`
|
||||
- `commands/debug.ts` — `/heapdump`, `/mem`
|
||||
|
||||
The top-level `app.tsx` composes these into the Ink tree with `Static` transcript output, a live streaming assistant row, prompt overlays, queue preview, status rule, input line, and completion list.
|
||||
|
||||
|
|
@ -197,32 +221,41 @@ These are stateful UI branches in `app.tsx`, not separate screens.
|
|||
|
||||
## Commands
|
||||
|
||||
The local slash handler covers the built-ins that need direct client behavior:
|
||||
The following commands are handled directly by the TUI client. Unrecognized commands fall through to the Python gateway via `slash.exec` and `command.dispatch`.
|
||||
|
||||
- `/help`
|
||||
- `/quit`, `/exit`, `/q`
|
||||
- `/clear`
|
||||
- `/new`
|
||||
- `/compact`
|
||||
- `/resume`
|
||||
- `/copy`
|
||||
- `/paste`
|
||||
- `/details`
|
||||
- `/logs`
|
||||
- `/statusbar`, `/sb`
|
||||
- `/queue`
|
||||
- `/undo`
|
||||
- `/retry`
|
||||
### Core (`core.ts`)
|
||||
`/help`, `/quit` (alias `/exit`), `/update`, `/clear` (alias `/new`),
|
||||
`/compact`, `/copy`, `/paste`, `/details` (alias `/detail`),
|
||||
`/statusbar` (alias `/sb`), `/queue` (alias `/q`), `/logs`, `/history`,
|
||||
`/save`, `/undo`, `/retry`, `/steer`, `/mouse` (alias `/scroll`),
|
||||
`/status`, `/title`, `/fortune`, `/redraw`, `/terminal-setup`
|
||||
|
||||
Notes:
|
||||
### Billing (`billing.ts`)
|
||||
`/billing` — manage Nous terminal billing — buy credits, auto-reload, limits
|
||||
|
||||
- `/copy` sends the selected assistant response through OSC 52.
|
||||
- `/paste` with no args asks the gateway to attach a clipboard image.
|
||||
- Text paste remains inline-only; `Cmd+V` / `Ctrl+V` handle layered text/OSC52/image fallback before `/paste` is needed.
|
||||
- `/details [hidden|collapsed|expanded|cycle]` controls thinking/tool-detail visibility.
|
||||
- `/statusbar` toggles the status rule on/off.
|
||||
### Session (`session.ts`)
|
||||
`/model`, `/sessions` (aliases `/switch`, `/session`, `/resume`),
|
||||
`/background` (aliases `/bg`, `/btw`), `/image`, `/personality`,
|
||||
`/compress`, `/branch` (alias `/fork`), `/voice`, `/skin`,
|
||||
`/indicator`, `/yolo`, `/reasoning`, `/fast`, `/busy`, `/verbose`, `/usage`
|
||||
|
||||
Anything else falls through to:
|
||||
### Ops (`ops.ts`)
|
||||
`/stop`, `/reload-mcp` (alias `/reload_mcp`), `/reload`, `/browser`,
|
||||
`/rollback`, `/agents` (alias `/tasks`), `/replay`, `/replay-diff`,
|
||||
`/skills`, `/reload-skills` (alias `/reload_skills`), `/plugins`, `/tools`
|
||||
|
||||
### Credits (`credits.ts`)
|
||||
`/credits` — Nous credit balance and browser top-up
|
||||
|
||||
### Setup (`setup.ts`)
|
||||
`/setup` — launches external `hermes setup` wizard, suspends Ink while it runs
|
||||
|
||||
### Debug (`debug.ts`)
|
||||
`/heapdump`, `/mem` — V8 memory diagnostics
|
||||
|
||||
---
|
||||
|
||||
Anything not matched above falls through to:
|
||||
|
||||
1. `slash.exec`
|
||||
2. `command.dispatch`
|
||||
|
|
@ -233,28 +266,43 @@ That lets Python own aliases, plugins, skills, and registry-backed commands with
|
|||
|
||||
Primary event types the client handles today:
|
||||
|
||||
| Event | Payload |
|
||||
| ------------------------ | ----------------------------------------------- |
|
||||
| `gateway.ready` | `{ skin? }` |
|
||||
| `session.info` | session metadata for banner + tool/skill panels |
|
||||
| `message.start` | start assistant streaming |
|
||||
| `message.delta` | `{ text, rendered? }` |
|
||||
| `message.complete` | `{ text, rendered?, usage, status }` |
|
||||
| `thinking.delta` | `{ text }` |
|
||||
| `reasoning.delta` | `{ text }` |
|
||||
| `reasoning.available` | `{ text }` |
|
||||
| `status.update` | `{ kind, text }` |
|
||||
| `tool.start` | `{ tool_id, name, context? }` |
|
||||
| `tool.progress` | `{ name, preview }` |
|
||||
| `tool.complete` | `{ tool_id, name }` |
|
||||
| `clarify.request` | `{ question, choices?, request_id }` |
|
||||
| `approval.request` | `{ command, description }` |
|
||||
| `sudo.request` | `{ request_id }` |
|
||||
| `secret.request` | `{ prompt, env_var, request_id }` |
|
||||
| `background.complete` | `{ task_id, text }` |
|
||||
| `error` | `{ message }` |
|
||||
| `gateway.stderr` | synthesized from child stderr |
|
||||
| `gateway.protocol_error` | synthesized from malformed stdout |
|
||||
| Event | Payload |
|
||||
| -------------------------- | --------------------------------------------------------------------------- |
|
||||
| `gateway.ready` | `{ skin? }` |
|
||||
| `skin.changed` | `{ skin }` |
|
||||
| `session.info` | session metadata for banner + tool/skill panels |
|
||||
| `message.start` | start assistant streaming |
|
||||
| `message.delta` | `{ text, rendered? }` |
|
||||
| `message.complete` | `{ text, rendered?, usage, status }` |
|
||||
| `thinking.delta` | `{ text }` |
|
||||
| `reasoning.delta` | `{ text, verbose? }` |
|
||||
| `reasoning.available` | `{ text, verbose? }` |
|
||||
| `status.update` | `{ kind, text }` |
|
||||
| `notification.show` | `{ id, key, kind, level, text, ttl_ms? }` |
|
||||
| `notification.clear` | `{ key }` |
|
||||
| `tool.start` | `{ tool_id, name, context?, args_text? }` |
|
||||
| `tool.generating` | `{ name }` |
|
||||
| `tool.progress` | `{ name, preview }` |
|
||||
| `tool.complete` | `{ tool_id, name, error?, summary?, duration_s?, inline_diff?, todos? }` |
|
||||
| `clarify.request` | `{ question, choices?, request_id }` |
|
||||
| `approval.request` | `{ command, description, allow_permanent? }` |
|
||||
| `sudo.request` | `{ request_id }` |
|
||||
| `secret.request` | `{ prompt, env_var, request_id }` |
|
||||
| `background.complete` | `{ task_id, text }` |
|
||||
| `review.summary` | `{ text }` |
|
||||
| `browser.progress` | `{ message }` |
|
||||
| `voice.status` | `{ state }` |
|
||||
| `voice.transcript` | `{ text, no_speech_limit? }` |
|
||||
| `subagent.spawn_requested` | `{ subagent_id?, task_index, goal?, depth?, parent_id? }` |
|
||||
| `subagent.start` | `{ subagent_id?, task_index, goal?, depth?, parent_id? }` |
|
||||
| `subagent.thinking` | `{ text }` |
|
||||
| `subagent.tool` | `{ tool_name?, tool_preview?, text? }` |
|
||||
| `subagent.progress` | `{ text }` |
|
||||
| `subagent.complete` | `{ status, summary?, text?, duration_seconds? }` |
|
||||
| `error` | `{ message }` |
|
||||
| `gateway.stderr` | synthesized from child stderr |
|
||||
| `gateway.protocol_error` | synthesized from malformed stdout |
|
||||
| `gateway.start_timeout` | `{ cwd?, python?, stderr_tail? }` |
|
||||
|
||||
## Theme model
|
||||
|
||||
|
|
@ -283,56 +331,150 @@ ui-tui/
|
|||
entry.tsx TTY gate + render()
|
||||
app.tsx top-level Ink tree, composes src/app/*
|
||||
gatewayClient.ts child process + JSON-RPC bridge
|
||||
theme.ts default palette + skin merge
|
||||
constants.ts display constants, hotkeys, tool labels
|
||||
types.ts shared client-side types
|
||||
banner.ts ASCII art data
|
||||
gatewayTypes.ts gateway event and RPC response type definitions
|
||||
theme.ts theme colors and skin merge
|
||||
banner.ts ASCII art renderer (parses Rich color tags)
|
||||
types.ts shared client-side types (ActiveTool, Msg, etc.)
|
||||
|
||||
app/
|
||||
createGatewayEventHandler.ts event → state mapping
|
||||
createSlashHandler.ts local slash dispatch
|
||||
useComposerState.ts draft + multiline + queue editing
|
||||
delegationStore.ts nanostore for subagent spawning caps and overlay accordion state
|
||||
gatewayContext.tsx React context for gateway client
|
||||
gatewayRecovery.ts crash-recovery budget: respawn+resume capped to 3 attempts / 60 s
|
||||
inputSelectionStore.ts nanostore exposing the active text-input selection handle
|
||||
interfaces.ts internal interfaces (ComposerActions, GatewayRpc, etc.)
|
||||
overlayStore.ts nanostores for overlay state
|
||||
scroll.ts viewport scroll with text-selection anchor sync
|
||||
setupHandoff.ts launches external hermes setup, suspends Ink while it runs
|
||||
spawnHistoryStore.ts ring buffer of finished subagent fan-out snapshots
|
||||
turnController.ts stateful turn lifecycle driver (streaming, tools, reasoning)
|
||||
turnStore.ts nanostore for turn state (streaming, tools, reasoning, subagents)
|
||||
uiStore.ts nanostores for UI flags (busy, sid, mouseTracking, etc.)
|
||||
useComposerState.ts draft + multiline buffer + queue editing
|
||||
useConfigSync.ts config polling and MCP reload on mtime change
|
||||
useInputHandlers.ts keypress routing
|
||||
useTurnState.ts agent turn lifecycle
|
||||
overlayStore.ts nanostores for overlays
|
||||
uiStore.ts nanostores for UI flags
|
||||
gatewayContext.tsx React context for gateway client
|
||||
constants.ts app-level constants
|
||||
helpers.ts pure helpers
|
||||
interfaces.ts internal interfaces
|
||||
useLongRunToolCharms.ts ambient activity messages for tools running longer than 8 s
|
||||
useMainApp.ts top-level composition hook
|
||||
useSessionLifecycle.ts session create / resume / activate / close
|
||||
useSubmission.ts message send, shell exec, interpolation, busy-input-mode dispatch
|
||||
|
||||
slash/
|
||||
types.ts SlashCommand interface and SlashRunCtx execution context
|
||||
registry.ts SLASH_COMMANDS assembly and findSlashCommand lookup
|
||||
commands/
|
||||
billing.ts /billing — manage Nous terminal billing
|
||||
core.ts general TUI commands
|
||||
credits.ts /credits
|
||||
debug.ts /heapdump, /mem
|
||||
ops.ts operations commands
|
||||
session.ts session and agent commands
|
||||
setup.ts /setup wizard
|
||||
|
||||
components/
|
||||
appChrome.tsx status bar, input row, completions
|
||||
appLayout.tsx top-level layout composition
|
||||
appOverlays.tsx overlay routing (pickers, prompts)
|
||||
branding.tsx banner + session summary
|
||||
markdown.tsx Markdown-to-Ink renderer
|
||||
maskedPrompt.tsx masked input for sudo / secrets
|
||||
messageLine.tsx transcript rows
|
||||
modelPicker.tsx model switch picker
|
||||
prompts.tsx approval + clarify flows
|
||||
queuedMessages.tsx queued input preview
|
||||
sessionPicker.tsx session resume picker
|
||||
textInput.tsx custom line editor
|
||||
thinking.tsx spinner, reasoning, tool activity
|
||||
activeSessionSwitcher.tsx active session switch overlay
|
||||
agentsOverlay.tsx subagent delegation overlay
|
||||
appChrome.tsx status bar, input row, completions
|
||||
appLayout.tsx top-level layout composition
|
||||
appOverlays.tsx overlay routing (pickers, prompts)
|
||||
billingOverlay.tsx billing overlay
|
||||
branding.tsx banner + session summary
|
||||
fpsOverlay.tsx FPS debug overlay
|
||||
helpHint.tsx contextual help hint
|
||||
markdown.tsx Markdown-to-Ink renderer
|
||||
maskedPrompt.tsx masked input for sudo / secrets
|
||||
messageLine.tsx transcript rows
|
||||
modelPicker.tsx model switch picker
|
||||
overlayControls.tsx shared overlay control buttons
|
||||
pluginsHub.tsx plugins hub overlay
|
||||
prompts.tsx approval + clarify flows
|
||||
queuedMessages.tsx queued input preview
|
||||
skillsHub.tsx skills hub overlay
|
||||
streamingAssistant.tsx live streaming assistant row
|
||||
streamingMarkdown.tsx streaming Markdown renderer
|
||||
textInput.tsx custom line editor
|
||||
themed.tsx theme-aware wrapper
|
||||
thinking.tsx spinner, reasoning, tool activity
|
||||
todoPanel.tsx todo list panel
|
||||
|
||||
config/
|
||||
env.ts environment variable resolution and Termux/mouse defaults
|
||||
limits.ts paste size, live-render and history limits
|
||||
timing.ts streaming batch and debounce timing constants
|
||||
|
||||
content/
|
||||
charms.ts ambient activity strings for long-running tools
|
||||
faces.ts agent face / kaomoji pool
|
||||
fortunes.ts /fortune quote pool
|
||||
hotkeys.ts platform-aware hotkey display strings
|
||||
placeholders.ts rotating input placeholder strings
|
||||
setup.ts setup-required panel content
|
||||
verbs.ts tool activity verb map (browser → browsing, etc.)
|
||||
|
||||
domain/
|
||||
blockLayout.ts block layout and lead-gap helpers
|
||||
details.ts details visibility mode resolution (hidden/collapsed/expanded)
|
||||
messages.ts message formatting and transcript helpers
|
||||
paths.ts cwd shortening and path display helpers
|
||||
providers.ts provider display name helpers
|
||||
roles.ts message role color and label helpers
|
||||
slash.ts slash command parsing and TUI session model flag
|
||||
usage.ts token usage zero value and helpers
|
||||
viewport.ts viewport height estimation helpers
|
||||
|
||||
hooks/
|
||||
useCompletion.ts tab completion (slash + path)
|
||||
useInputHistory.ts persistent history navigation
|
||||
useQueue.ts queued message management
|
||||
useVirtualHistory.ts in-memory history for pickers
|
||||
useCompletion.ts tab completion (slash + path)
|
||||
useGitBranch.ts current git branch via child_process execFile
|
||||
useInputHistory.ts persistent history navigation
|
||||
useQueue.ts queued message management
|
||||
useVirtualHistory.ts virtual list scroll and height tracking
|
||||
|
||||
lib/
|
||||
history.ts persistent input history
|
||||
messages.ts message formatting helpers
|
||||
osc52.ts OSC 52 clipboard copy
|
||||
rpc.ts JSON-RPC type helpers
|
||||
text.ts text helpers, ANSI detection, previews
|
||||
circularBuffer.ts fixed-size generic ring buffer
|
||||
clipboard.ts clipboard read / write via child_process
|
||||
editor.ts $EDITOR launch, PATH resolution, and Ink suspend
|
||||
emoji.ts emoji and variation selector width helpers
|
||||
externalCli.ts external CLI subprocess launcher
|
||||
externalLink.ts open URLs in the system browser
|
||||
forceTruecolor.ts 24-bit truecolor override before chalk imports
|
||||
fpsStore.ts Ink frame FPS tracker nanostore
|
||||
fuzzy.ts lightweight fuzzy subsequence scorer
|
||||
gracefulExit.ts clean shutdown with failsafe timeout
|
||||
history.ts persistent input history (read/append to disk)
|
||||
inputMetrics.ts input width and wrap metrics
|
||||
liveProgress.ts todo helpers and tool-shelf message assembly
|
||||
mathUnicode.ts best-effort LaTeX → Unicode for inline math
|
||||
memory.ts V8 heap snapshot and diagnostics helpers
|
||||
memoryMonitor.ts automatic heap-dump trigger on high usage
|
||||
messages.ts transcript message append helpers
|
||||
openExternalUrl.ts platform-aware URL opener (macOS/Linux/Windows)
|
||||
osc52.ts OSC 52 terminal clipboard copy sequence
|
||||
parentLog.ts append-only log to ~/.hermes/tui-parent.log
|
||||
platform.ts platform-aware keybinding and SSH detection helpers
|
||||
precisionWheel.ts high-precision scroll wheel with sticky-frame budget
|
||||
prompt.ts composer prompt text helpers (Termux-safe)
|
||||
reasoning.ts reasoning tag detection and split helpers
|
||||
rpc.ts JSON-RPC result and command dispatch helpers
|
||||
subagentTree.ts subagent tree flattening and aggregate helpers
|
||||
syntax.ts syntax token types and theme-aware highlighting
|
||||
terminalModes.ts terminal mode reset sequences (kitty, mouse, etc.)
|
||||
terminalParity.ts VSCode-like terminal detection and hint helpers
|
||||
terminalSetup.ts IDE keybinding config file install helpers
|
||||
termux.ts Termux platform detection helpers
|
||||
text.ts text helpers, ANSI detection, tool trail builders
|
||||
todo.ts todo item tone and display helpers
|
||||
viewportStore.ts viewport height nanostore via ScrollBoxHandle
|
||||
virtualHeights.ts virtual list row height estimation
|
||||
wheelAccel.ts scroll wheel acceleration state machine
|
||||
|
||||
protocol/
|
||||
interpolation.ts {!cmd} inline shell interpolation regex and helpers
|
||||
paste.ts bracketed paste snippet token regex
|
||||
|
||||
types/
|
||||
hermes-ink.d.ts type declarations for @hermes/ink
|
||||
hermes-ink.d.ts type declarations for @hermes/ink
|
||||
|
||||
__tests__/ vitest suite
|
||||
__tests__/ vitest suite
|
||||
```
|
||||
|
||||
Related Python side:
|
||||
|
|
@ -343,4 +485,4 @@ tui_gateway/
|
|||
server.py RPC handlers and session logic
|
||||
render.py optional rich/ANSI bridge
|
||||
slash_worker.py persistent HermesCLI subprocess for slash commands
|
||||
```
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue