Files
hermes-agent/ui-tui/src/types.ts

205 lines
4.3 KiB
TypeScript
Raw Normal View History

2026-04-02 20:39:52 -05:00
export interface ActiveTool {
refactor(tui): /clean pass across ui-tui — 49 files, −217 LOC Full codebase pass using the /clean doctrine (KISS/DRY, no one-off helpers, no variables-used-once, pure functional where natural, inlined obvious one-liners, killed dead exports, narrowed types, spaced JSX). All contracts preserved — no RPC method, event name, or exported type shape changed. app/ — 15 files, -134 LOC - inlined 4 one-off helpers (titleCase, isLong, statusToneFrom, focusOutside predicate) - stores to arrow-const style (buildUiState, buildTurnState, buildOverlayState plus get/patch/reset triplets) - functional slash/registry byName map (flatMap over for-loops) - dropped dead param `live` in cancelOverlayFromCtrlC - DRY'd duplicate shift() call in scrollWithSelection - consolidated sections.push calls in /help components/ — 12 files, -40 LOC - extracted inline prop types to interfaces at file bottom (13×) - inlined 6 one-off vars (pctLabel, logoW, heroW, cwd, title, hint) - promoted HEART_COLORS + OPTS/LABELS to module scope - JSX sibling spacing across 9 files - un-shadowed `raw` in textInput - components/thinking.tsx + components/markdown.tsx untouched (structurally load-bearing / edge-case-heavy) config content domain protocol/ — 8 files, -77 LOC - tightened 3 regexes (MOUSE_TRACKING, looksLikeSlashCommand, hasInterpolation — dropped stateful lastIndex dance) - dead export ParsedSlashCommand removed - MODES narrowed to `as const`, `.find(m => m === s)` replaces `.includes() ? (as cast) : null` - fortunes.ts hash via reduce - fmtDuration ternary chain - inlined aboveViewport predicate in viewport.ts hooks/ + lib/ — 9 files, -38 LOC - ANSI_RE via String.fromCharCode(27) + WS_RE lifted to module scope (no more eslint-disable no-control-regex) - compactPreview/edgePreview/thinkingPreview → ternary arrows - useCompletion: hoisted pathReplace, moved stale-ref guard earlier - useInputHistory: dropped useCallback wrapper (append is stable) - useVirtualHistory: replaced 4× any with unknown + narrow MeasuredNode interface + one cast site root TS — 3 files, -63 LOC - banner.ts: parseRichMarkup via matchAll instead of exec/lastIndex, artWidth via reduce - gatewayClient.ts: resolvePython candidate list collapse, inlined one-branch guards in dispatch/pushLog/drain/request - types.ts: alpha-sorted ActiveTool / Msg / SudoReq / SecretReq members eslint config - disabled react-hooks/exhaustive-deps on packages/hermes-ink/** (compiled by react/compiler, deps live in $[N] memo arrays that eslint can't introspect) and removed the now-orphan in-file disable directive in ScrollBox.tsx fixes (not from the cleaner pass) - useComposerState: unlinkSync(file) + try/catch → rmSync(file, { force: true }) — kills the no-empty lint error and is more idiomatic - useConfigSync: added setBellOnComplete + setVoiceEnabled to the two useEffect dep arrays (they're stable React setState setters; adding is safe and silences exhaustive-deps) verification - npx eslint src/ packages/ → 0 errors, 0 warnings - npm run type-check → clean - npm test → 50/50 - npm run build → 394.8kb ink-bundle.js, 11ms esbuild - pytest tests/tui_gateway/ tests/test_tui_gateway_server.py tests/hermes_cli/test_tui_resume_flow.py tests/hermes_cli/test_tui_npm_install.py → 57/57
2026-04-16 22:32:53 -05:00
context?: string
2026-04-02 20:39:52 -05:00
id: string
name: string
2026-04-11 14:02:36 -05:00
startedAt?: number
2026-04-02 20:39:52 -05:00
}
export interface TodoItem {
content: string
id: string
status: 'cancelled' | 'completed' | 'in_progress' | 'pending'
}
2026-04-08 13:45:34 -05:00
export interface ActivityItem {
id: number
text: string
tone: 'error' | 'info' | 'warn'
}
2026-04-15 14:14:01 -05:00
export interface SubagentProgress {
feat(tui): subagent spawn observability overlay Adds a live + post-hoc audit surface for recursive delegate_task fan-out. None of cc/oc/oclaw tackle nested subagent trees inside an Ink overlay; this ships a view-switched dashboard that handles arbitrary depth + width. Python - delegate_tool: every subagent event now carries subagent_id, parent_id, depth, model, tool_count; subagent.complete also ships input/output/ reasoning tokens, cost, api_calls, files_read/files_written, and a tail of tool-call outputs - delegate_tool: new subagent.spawn_requested event + _active_subagents registry so the overlay can kill a branch by id and pause new spawns - tui_gateway: new RPCs delegation.status, delegation.pause, subagent.interrupt, spawn_tree.save/list/load (disk under \$HERMES_HOME/spawn-trees/<session>/<ts>.json) TUI - /agents overlay: full-width list mode (gantt strip + row picker) and Enter-to-drill full-width scrollable detail mode; inverse+amber selection, heat-coloured branch markers, wall-clock gantt with tick ruler, per-branch rollups - Detail pane: collapsible accordions (Budget, Files, Tool calls, Output, Progress, Summary); open-state persists across agents + mode switches via a shared atom - /replay [N|last|list|load <path>] for in-memory + disk history; /replay-diff <a> <b> for side-by-side tree comparison - Status-bar SpawnHud warns as depth/concurrency approaches caps; overlay auto-follows the just-finished turn onto history[1] - Theme: bump DARK dim #B8860B → #CC9B1F for readable secondary text globally; keep LIGHT untouched Tests: +29 new subagentTree unit tests; 215/215 passing.
2026-04-22 10:38:17 -05:00
apiCalls?: number
costUsd?: number
depth: number
2026-04-15 14:14:01 -05:00
durationSeconds?: number
feat(tui): subagent spawn observability overlay Adds a live + post-hoc audit surface for recursive delegate_task fan-out. None of cc/oc/oclaw tackle nested subagent trees inside an Ink overlay; this ships a view-switched dashboard that handles arbitrary depth + width. Python - delegate_tool: every subagent event now carries subagent_id, parent_id, depth, model, tool_count; subagent.complete also ships input/output/ reasoning tokens, cost, api_calls, files_read/files_written, and a tail of tool-call outputs - delegate_tool: new subagent.spawn_requested event + _active_subagents registry so the overlay can kill a branch by id and pause new spawns - tui_gateway: new RPCs delegation.status, delegation.pause, subagent.interrupt, spawn_tree.save/list/load (disk under \$HERMES_HOME/spawn-trees/<session>/<ts>.json) TUI - /agents overlay: full-width list mode (gantt strip + row picker) and Enter-to-drill full-width scrollable detail mode; inverse+amber selection, heat-coloured branch markers, wall-clock gantt with tick ruler, per-branch rollups - Detail pane: collapsible accordions (Budget, Files, Tool calls, Output, Progress, Summary); open-state persists across agents + mode switches via a shared atom - /replay [N|last|list|load <path>] for in-memory + disk history; /replay-diff <a> <b> for side-by-side tree comparison - Status-bar SpawnHud warns as depth/concurrency approaches caps; overlay auto-follows the just-finished turn onto history[1] - Theme: bump DARK dim #B8860B → #CC9B1F for readable secondary text globally; keep LIGHT untouched Tests: +29 new subagentTree unit tests; 215/215 passing.
2026-04-22 10:38:17 -05:00
filesRead?: string[]
filesWritten?: string[]
2026-04-15 14:14:01 -05:00
goal: string
id: string
index: number
feat(tui): subagent spawn observability overlay Adds a live + post-hoc audit surface for recursive delegate_task fan-out. None of cc/oc/oclaw tackle nested subagent trees inside an Ink overlay; this ships a view-switched dashboard that handles arbitrary depth + width. Python - delegate_tool: every subagent event now carries subagent_id, parent_id, depth, model, tool_count; subagent.complete also ships input/output/ reasoning tokens, cost, api_calls, files_read/files_written, and a tail of tool-call outputs - delegate_tool: new subagent.spawn_requested event + _active_subagents registry so the overlay can kill a branch by id and pause new spawns - tui_gateway: new RPCs delegation.status, delegation.pause, subagent.interrupt, spawn_tree.save/list/load (disk under \$HERMES_HOME/spawn-trees/<session>/<ts>.json) TUI - /agents overlay: full-width list mode (gantt strip + row picker) and Enter-to-drill full-width scrollable detail mode; inverse+amber selection, heat-coloured branch markers, wall-clock gantt with tick ruler, per-branch rollups - Detail pane: collapsible accordions (Budget, Files, Tool calls, Output, Progress, Summary); open-state persists across agents + mode switches via a shared atom - /replay [N|last|list|load <path>] for in-memory + disk history; /replay-diff <a> <b> for side-by-side tree comparison - Status-bar SpawnHud warns as depth/concurrency approaches caps; overlay auto-follows the just-finished turn onto history[1] - Theme: bump DARK dim #B8860B → #CC9B1F for readable secondary text globally; keep LIGHT untouched Tests: +29 new subagentTree unit tests; 215/215 passing.
2026-04-22 10:38:17 -05:00
inputTokens?: number
iteration?: number
model?: string
2026-04-15 14:14:01 -05:00
notes: string[]
feat(tui): subagent spawn observability overlay Adds a live + post-hoc audit surface for recursive delegate_task fan-out. None of cc/oc/oclaw tackle nested subagent trees inside an Ink overlay; this ships a view-switched dashboard that handles arbitrary depth + width. Python - delegate_tool: every subagent event now carries subagent_id, parent_id, depth, model, tool_count; subagent.complete also ships input/output/ reasoning tokens, cost, api_calls, files_read/files_written, and a tail of tool-call outputs - delegate_tool: new subagent.spawn_requested event + _active_subagents registry so the overlay can kill a branch by id and pause new spawns - tui_gateway: new RPCs delegation.status, delegation.pause, subagent.interrupt, spawn_tree.save/list/load (disk under \$HERMES_HOME/spawn-trees/<session>/<ts>.json) TUI - /agents overlay: full-width list mode (gantt strip + row picker) and Enter-to-drill full-width scrollable detail mode; inverse+amber selection, heat-coloured branch markers, wall-clock gantt with tick ruler, per-branch rollups - Detail pane: collapsible accordions (Budget, Files, Tool calls, Output, Progress, Summary); open-state persists across agents + mode switches via a shared atom - /replay [N|last|list|load <path>] for in-memory + disk history; /replay-diff <a> <b> for side-by-side tree comparison - Status-bar SpawnHud warns as depth/concurrency approaches caps; overlay auto-follows the just-finished turn onto history[1] - Theme: bump DARK dim #B8860B → #CC9B1F for readable secondary text globally; keep LIGHT untouched Tests: +29 new subagentTree unit tests; 215/215 passing.
2026-04-22 10:38:17 -05:00
outputTail?: SubagentOutputEntry[]
outputTokens?: number
parentId: null | string
reasoningTokens?: number
startedAt?: number
status: 'completed' | 'failed' | 'interrupted' | 'queued' | 'running'
2026-04-15 14:14:01 -05:00
summary?: string
taskCount: number
thinking: string[]
feat(tui): subagent spawn observability overlay Adds a live + post-hoc audit surface for recursive delegate_task fan-out. None of cc/oc/oclaw tackle nested subagent trees inside an Ink overlay; this ships a view-switched dashboard that handles arbitrary depth + width. Python - delegate_tool: every subagent event now carries subagent_id, parent_id, depth, model, tool_count; subagent.complete also ships input/output/ reasoning tokens, cost, api_calls, files_read/files_written, and a tail of tool-call outputs - delegate_tool: new subagent.spawn_requested event + _active_subagents registry so the overlay can kill a branch by id and pause new spawns - tui_gateway: new RPCs delegation.status, delegation.pause, subagent.interrupt, spawn_tree.save/list/load (disk under \$HERMES_HOME/spawn-trees/<session>/<ts>.json) TUI - /agents overlay: full-width list mode (gantt strip + row picker) and Enter-to-drill full-width scrollable detail mode; inverse+amber selection, heat-coloured branch markers, wall-clock gantt with tick ruler, per-branch rollups - Detail pane: collapsible accordions (Budget, Files, Tool calls, Output, Progress, Summary); open-state persists across agents + mode switches via a shared atom - /replay [N|last|list|load <path>] for in-memory + disk history; /replay-diff <a> <b> for side-by-side tree comparison - Status-bar SpawnHud warns as depth/concurrency approaches caps; overlay auto-follows the just-finished turn onto history[1] - Theme: bump DARK dim #B8860B → #CC9B1F for readable secondary text globally; keep LIGHT untouched Tests: +29 new subagentTree unit tests; 215/215 passing.
2026-04-22 10:38:17 -05:00
toolCount: number
2026-04-15 14:14:01 -05:00
tools: string[]
feat(tui): subagent spawn observability overlay Adds a live + post-hoc audit surface for recursive delegate_task fan-out. None of cc/oc/oclaw tackle nested subagent trees inside an Ink overlay; this ships a view-switched dashboard that handles arbitrary depth + width. Python - delegate_tool: every subagent event now carries subagent_id, parent_id, depth, model, tool_count; subagent.complete also ships input/output/ reasoning tokens, cost, api_calls, files_read/files_written, and a tail of tool-call outputs - delegate_tool: new subagent.spawn_requested event + _active_subagents registry so the overlay can kill a branch by id and pause new spawns - tui_gateway: new RPCs delegation.status, delegation.pause, subagent.interrupt, spawn_tree.save/list/load (disk under \$HERMES_HOME/spawn-trees/<session>/<ts>.json) TUI - /agents overlay: full-width list mode (gantt strip + row picker) and Enter-to-drill full-width scrollable detail mode; inverse+amber selection, heat-coloured branch markers, wall-clock gantt with tick ruler, per-branch rollups - Detail pane: collapsible accordions (Budget, Files, Tool calls, Output, Progress, Summary); open-state persists across agents + mode switches via a shared atom - /replay [N|last|list|load <path>] for in-memory + disk history; /replay-diff <a> <b> for side-by-side tree comparison - Status-bar SpawnHud warns as depth/concurrency approaches caps; overlay auto-follows the just-finished turn onto history[1] - Theme: bump DARK dim #B8860B → #CC9B1F for readable secondary text globally; keep LIGHT untouched Tests: +29 new subagentTree unit tests; 215/215 passing.
2026-04-22 10:38:17 -05:00
toolsets?: string[]
}
export interface SubagentOutputEntry {
isError: boolean
preview: string
tool: string
}
export interface SubagentNode {
aggregate: SubagentAggregate
children: SubagentNode[]
item: SubagentProgress
}
export interface SubagentAggregate {
activeCount: number
costUsd: number
descendantCount: number
filesTouched: number
hotness: number
inputTokens: number
maxDepthFromHere: number
outputTokens: number
totalDuration: number
totalTools: number
}
export interface DelegationStatus {
active: {
depth?: number
goal?: string
model?: null | string
parent_id?: null | string
started_at?: number
status?: string
subagent_id?: string
tool_count?: number
}[]
max_concurrent_children?: number
max_spawn_depth?: number
paused: boolean
2026-04-15 14:14:01 -05:00
}
2026-04-02 20:39:52 -05:00
export interface ApprovalReq {
command: string
description: string
}
export interface ConfirmReq {
cancelLabel?: string
confirmLabel?: string
danger?: boolean
detail?: string
onConfirm: () => void
title: string
}
2026-04-02 20:39:52 -05:00
export interface ClarifyReq {
choices: string[] | null
question: string
requestId: string
}
export interface Msg {
2026-04-07 20:10:33 -05:00
info?: SessionInfo
kind?: 'diff' | 'intro' | 'panel' | 'slash' | 'trail'
2026-04-11 14:29:24 -04:00
panelData?: PanelData
refactor(tui): /clean pass across ui-tui — 49 files, −217 LOC Full codebase pass using the /clean doctrine (KISS/DRY, no one-off helpers, no variables-used-once, pure functional where natural, inlined obvious one-liners, killed dead exports, narrowed types, spaced JSX). All contracts preserved — no RPC method, event name, or exported type shape changed. app/ — 15 files, -134 LOC - inlined 4 one-off helpers (titleCase, isLong, statusToneFrom, focusOutside predicate) - stores to arrow-const style (buildUiState, buildTurnState, buildOverlayState plus get/patch/reset triplets) - functional slash/registry byName map (flatMap over for-loops) - dropped dead param `live` in cancelOverlayFromCtrlC - DRY'd duplicate shift() call in scrollWithSelection - consolidated sections.push calls in /help components/ — 12 files, -40 LOC - extracted inline prop types to interfaces at file bottom (13×) - inlined 6 one-off vars (pctLabel, logoW, heroW, cwd, title, hint) - promoted HEART_COLORS + OPTS/LABELS to module scope - JSX sibling spacing across 9 files - un-shadowed `raw` in textInput - components/thinking.tsx + components/markdown.tsx untouched (structurally load-bearing / edge-case-heavy) config content domain protocol/ — 8 files, -77 LOC - tightened 3 regexes (MOUSE_TRACKING, looksLikeSlashCommand, hasInterpolation — dropped stateful lastIndex dance) - dead export ParsedSlashCommand removed - MODES narrowed to `as const`, `.find(m => m === s)` replaces `.includes() ? (as cast) : null` - fortunes.ts hash via reduce - fmtDuration ternary chain - inlined aboveViewport predicate in viewport.ts hooks/ + lib/ — 9 files, -38 LOC - ANSI_RE via String.fromCharCode(27) + WS_RE lifted to module scope (no more eslint-disable no-control-regex) - compactPreview/edgePreview/thinkingPreview → ternary arrows - useCompletion: hoisted pathReplace, moved stale-ref guard earlier - useInputHistory: dropped useCallback wrapper (append is stable) - useVirtualHistory: replaced 4× any with unknown + narrow MeasuredNode interface + one cast site root TS — 3 files, -63 LOC - banner.ts: parseRichMarkup via matchAll instead of exec/lastIndex, artWidth via reduce - gatewayClient.ts: resolvePython candidate list collapse, inlined one-branch guards in dispatch/pushLog/drain/request - types.ts: alpha-sorted ActiveTool / Msg / SudoReq / SecretReq members eslint config - disabled react-hooks/exhaustive-deps on packages/hermes-ink/** (compiled by react/compiler, deps live in $[N] memo arrays that eslint can't introspect) and removed the now-orphan in-file disable directive in ScrollBox.tsx fixes (not from the cleaner pass) - useComposerState: unlinkSync(file) + try/catch → rmSync(file, { force: true }) — kills the no-empty lint error and is more idiomatic - useConfigSync: added setBellOnComplete + setVoiceEnabled to the two useEffect dep arrays (they're stable React setState setters; adding is safe and silences exhaustive-deps) verification - npx eslint src/ packages/ → 0 errors, 0 warnings - npm run type-check → clean - npm test → 50/50 - npm run build → 394.8kb ink-bundle.js, 11ms esbuild - pytest tests/tui_gateway/ tests/test_tui_gateway_server.py tests/hermes_cli/test_tui_resume_flow.py tests/hermes_cli/test_tui_npm_install.py → 57/57
2026-04-16 22:32:53 -05:00
role: Role
text: string
thinking?: string
thinkingTokens?: number
toolTokens?: number
tools?: string[]
2026-04-26 15:55:38 -05:00
todos?: TodoItem[]
todoIncomplete?: boolean
todoCollapsedByDefault?: boolean
2026-04-02 20:39:52 -05:00
}
export type Role = 'assistant' | 'system' | 'tool' | 'user'
2026-04-13 21:20:55 -05:00
export type DetailsMode = 'hidden' | 'collapsed' | 'expanded'
export type ThinkingMode = 'collapsed' | 'truncated' | 'full'
2026-04-02 20:39:52 -05:00
// Per-section overrides for the agent details accordion. Resolution order
// at lookup time is: explicit `display.sections.<name>` → built-in
// SECTION_DEFAULTS → global `details_mode`. Today the built-in defaults
// expand `thinking`/`tools` and hide `activity`; `subagents` falls through
// to the global mode. Any explicit value still wins for that one section.
feat(tui): per-section visibility for the details accordion Adds optional per-section overrides on top of the existing global details_mode (hidden | collapsed | expanded). Lets users keep the accordion collapsed by default while auto-expanding tools, or hide the activity panel entirely without touching thinking/tools/subagents. Config (~/.hermes/config.yaml): display: details_mode: collapsed sections: thinking: expanded tools: expanded activity: hidden Slash command: /details show current global + overrides /details [hidden|collapsed|expanded] set global mode (existing) /details <section> <mode|reset> per-section override (new) /details <section> reset clear override Sections: thinking, tools, subagents, activity. Implementation: - ui-tui/src/types.ts SectionName + SectionVisibility - ui-tui/src/domain/details.ts parseSectionMode / resolveSections / sectionMode + SECTION_NAMES - ui-tui/src/app/uiStore.ts + app/interfaces.ts + app/useConfigSync.ts sections threaded into UiState - ui-tui/src/components/ thinking.tsx ToolTrail consults per-section mode for hidden/expanded behaviour; expandAll skips hidden sections; floating-alert fallback respects activity:hidden - ui-tui/src/components/ messageLine.tsx + appLayout.tsx pass sections through render tree - ui-tui/src/app/slash/ commands/core.ts /details <section> <mode|reset> syntax - tui_gateway/server.py config.set details_mode.<section> writes to display.sections.<section> (empty value clears the override) - website/docs/user-guide/tui.md documented Tests: 14 new (4 domain, 4 useConfigSync, 3 slash, 3 gateway). Total: 269/269 vitest, all gateway tests pass.
2026-04-24 02:34:32 -05:00
export type SectionName = 'thinking' | 'tools' | 'subagents' | 'activity'
export type SectionVisibility = Partial<Record<SectionName, DetailsMode>>
export interface McpServerStatus {
connected: boolean
name: string
tools: number
transport: string
}
2026-04-02 20:39:52 -05:00
export interface SessionInfo {
2026-04-07 20:10:33 -05:00
cwd?: string
fast?: boolean
perf(tui): defer agent construction until first prompt Match classic CLI perceived startup behavior: show the TUI shell and composer before constructing the full AIAgent. session.create now returns a lightweight placeholder session with lazy=true and no longer starts _make_agent eagerly. The first method that needs the agent triggers _start_agent_build() via _sess(); prompt.submit is routed through the RPC worker pool so that the initial wait for agent construction does not block the stdio dispatcher. The intro panel renders skeleton rows for tools/skills while the real session.info payload is absent, then hydrates to the real tools/skills panel once AIAgent initialization completes. Also skip the startup /voice status probe and avoid the input.detect_drop RPC for ordinary plain-text prompts to keep early startup/first-submit paths cheap. Measurements on macOS Terminal.app: - Previous full ready p50 after earlier PR commits: ~1537ms - Lazy skeleton panel p50: ~794ms - Original baseline full ready p50: ~1843ms So the visible startup surface is now ~743ms faster than the prior PR state and ~1.05s faster than the original baseline. First prompt still pays the same agent construction cost if it races the background/skeleton state, matching classic CLI's deferred behavior. Tests: - python -m py_compile tui_gateway/server.py - cd ui-tui && npm run type-check && npm run build - scripts/run_tests.sh tests/tui_gateway/test_protocol.py::test_sess_found tests/tools/test_code_execution_modes.py tests/tools/test_code_execution.py - cd ui-tui && npm test -- --run src/__tests__/useSessionLifecycle.test.ts src/__tests__/useConfigSync.test.ts
2026-04-28 23:32:02 -05:00
lazy?: boolean
mcp_servers?: McpServerStatus[]
2026-04-02 20:39:52 -05:00
model: string
reasoning_effort?: string
2026-04-07 20:10:33 -05:00
release_date?: string
perf(tui): defer agent construction until first prompt Match classic CLI perceived startup behavior: show the TUI shell and composer before constructing the full AIAgent. session.create now returns a lightweight placeholder session with lazy=true and no longer starts _make_agent eagerly. The first method that needs the agent triggers _start_agent_build() via _sess(); prompt.submit is routed through the RPC worker pool so that the initial wait for agent construction does not block the stdio dispatcher. The intro panel renders skeleton rows for tools/skills while the real session.info payload is absent, then hydrates to the real tools/skills panel once AIAgent initialization completes. Also skip the startup /voice status probe and avoid the input.detect_drop RPC for ordinary plain-text prompts to keep early startup/first-submit paths cheap. Measurements on macOS Terminal.app: - Previous full ready p50 after earlier PR commits: ~1537ms - Lazy skeleton panel p50: ~794ms - Original baseline full ready p50: ~1843ms So the visible startup surface is now ~743ms faster than the prior PR state and ~1.05s faster than the original baseline. First prompt still pays the same agent construction cost if it races the background/skeleton state, matching classic CLI's deferred behavior. Tests: - python -m py_compile tui_gateway/server.py - cd ui-tui && npm run type-check && npm run build - scripts/run_tests.sh tests/tui_gateway/test_protocol.py::test_sess_found tests/tools/test_code_execution_modes.py tests/tools/test_code_execution.py - cd ui-tui && npm test -- --run src/__tests__/useSessionLifecycle.test.ts src/__tests__/useConfigSync.test.ts
2026-04-28 23:32:02 -05:00
service_tier?: string
2026-04-02 20:39:52 -05:00
skills: Record<string, string[]>
tools: Record<string, string[]>
2026-04-07 20:10:33 -05:00
update_behind?: number | null
update_command?: string
usage?: Usage
2026-04-07 20:10:33 -05:00
version?: string
2026-04-02 20:39:52 -05:00
}
export interface Usage {
calls: number
context_max?: number
context_percent?: number
context_used?: number
cost_usd?: number
2026-04-02 20:39:52 -05:00
input: number
output: number
total: number
}
2026-04-03 14:44:50 -05:00
export interface SudoReq {
requestId: string
}
refactor(tui): /clean pass across ui-tui — 49 files, −217 LOC Full codebase pass using the /clean doctrine (KISS/DRY, no one-off helpers, no variables-used-once, pure functional where natural, inlined obvious one-liners, killed dead exports, narrowed types, spaced JSX). All contracts preserved — no RPC method, event name, or exported type shape changed. app/ — 15 files, -134 LOC - inlined 4 one-off helpers (titleCase, isLong, statusToneFrom, focusOutside predicate) - stores to arrow-const style (buildUiState, buildTurnState, buildOverlayState plus get/patch/reset triplets) - functional slash/registry byName map (flatMap over for-loops) - dropped dead param `live` in cancelOverlayFromCtrlC - DRY'd duplicate shift() call in scrollWithSelection - consolidated sections.push calls in /help components/ — 12 files, -40 LOC - extracted inline prop types to interfaces at file bottom (13×) - inlined 6 one-off vars (pctLabel, logoW, heroW, cwd, title, hint) - promoted HEART_COLORS + OPTS/LABELS to module scope - JSX sibling spacing across 9 files - un-shadowed `raw` in textInput - components/thinking.tsx + components/markdown.tsx untouched (structurally load-bearing / edge-case-heavy) config content domain protocol/ — 8 files, -77 LOC - tightened 3 regexes (MOUSE_TRACKING, looksLikeSlashCommand, hasInterpolation — dropped stateful lastIndex dance) - dead export ParsedSlashCommand removed - MODES narrowed to `as const`, `.find(m => m === s)` replaces `.includes() ? (as cast) : null` - fortunes.ts hash via reduce - fmtDuration ternary chain - inlined aboveViewport predicate in viewport.ts hooks/ + lib/ — 9 files, -38 LOC - ANSI_RE via String.fromCharCode(27) + WS_RE lifted to module scope (no more eslint-disable no-control-regex) - compactPreview/edgePreview/thinkingPreview → ternary arrows - useCompletion: hoisted pathReplace, moved stale-ref guard earlier - useInputHistory: dropped useCallback wrapper (append is stable) - useVirtualHistory: replaced 4× any with unknown + narrow MeasuredNode interface + one cast site root TS — 3 files, -63 LOC - banner.ts: parseRichMarkup via matchAll instead of exec/lastIndex, artWidth via reduce - gatewayClient.ts: resolvePython candidate list collapse, inlined one-branch guards in dispatch/pushLog/drain/request - types.ts: alpha-sorted ActiveTool / Msg / SudoReq / SecretReq members eslint config - disabled react-hooks/exhaustive-deps on packages/hermes-ink/** (compiled by react/compiler, deps live in $[N] memo arrays that eslint can't introspect) and removed the now-orphan in-file disable directive in ScrollBox.tsx fixes (not from the cleaner pass) - useComposerState: unlinkSync(file) + try/catch → rmSync(file, { force: true }) — kills the no-empty lint error and is more idiomatic - useConfigSync: added setBellOnComplete + setVoiceEnabled to the two useEffect dep arrays (they're stable React setState setters; adding is safe and silences exhaustive-deps) verification - npx eslint src/ packages/ → 0 errors, 0 warnings - npm run type-check → clean - npm test → 50/50 - npm run build → 394.8kb ink-bundle.js, 11ms esbuild - pytest tests/tui_gateway/ tests/test_tui_gateway_server.py tests/hermes_cli/test_tui_resume_flow.py tests/hermes_cli/test_tui_npm_install.py → 57/57
2026-04-16 22:32:53 -05:00
2026-04-03 14:44:50 -05:00
export interface SecretReq {
envVar: string
prompt: string
requestId: string
}
2026-04-03 20:14:57 -05:00
2026-04-11 14:29:24 -04:00
export interface PanelData {
sections: PanelSection[]
title: string
}
export interface PanelSection {
items?: string[]
rows?: [string, string][]
text?: string
title?: string
}
2026-04-03 20:14:57 -05:00
export interface SlashCatalog {
canon: Record<string, string>
2026-04-10 00:01:37 -04:00
categories: SlashCategory[]
2026-04-03 20:14:57 -05:00
pairs: [string, string][]
2026-04-10 00:01:37 -04:00
skillCount: number
2026-04-03 20:14:57 -05:00
sub: Record<string, string[]>
}
2026-04-10 00:01:37 -04:00
export interface SlashCategory {
name: string
pairs: [string, string][]
}