mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 01:21:43 +00:00
refactor(tui): store-driven turn state + slash registry + module split
Hoist turn state from a 286-line hook into $turnState atom + turnController
singleton. createGatewayEventHandler becomes a typed dispatch over the
controller; its ctx shrinks from 30 fields to 5. Event-handler refs and 16
threaded actions are gone.
Fold three createSlash*Handler factories into a data-driven SlashCommand[]
registry under slash/commands/{core,session,ops}.ts. Aliases are data;
findSlashCommand does name+alias lookup. Shared guarded/guardedErr combinator
in slash/guarded.ts.
Split constants.ts + app/helpers.ts into config/ (timing/limits/env),
content/ (faces/placeholders/hotkeys/verbs/charms/fortunes), domain/ (roles/
details/messages/paths/slash/viewport/usage), protocol/ (interpolation/paste).
Type every RPC response in gatewayTypes.ts (26 new interfaces); drop all
`(r: any)` across slash + main app.
Shrink useMainApp from 1216 -> 646 lines by extracting useSessionLifecycle,
useSubmission, useConfigSync. Add <Fg> themed primitive and strip ~50
`as any` color casts.
Tests: 50 passing. Build + type-check clean.
This commit is contained in:
parent
9c71f3a6ea
commit
68ecdb6e26
56 changed files with 3666 additions and 4117 deletions
|
|
@ -2,10 +2,10 @@ import { AlternateScreen, Box, NoSelect, ScrollBox, Text } from '@hermes/ink'
|
|||
import { useStore } from '@nanostores/react'
|
||||
import { memo } from 'react'
|
||||
|
||||
import { PLACEHOLDER } from '../app/constants.js'
|
||||
import type { AppLayoutProps } from '../app/interfaces.js'
|
||||
import { $isBlocked } from '../app/overlayStore.js'
|
||||
import { $uiState } from '../app/uiStore.js'
|
||||
import { PLACEHOLDER } from '../content/placeholders.js'
|
||||
|
||||
import { GoodVibesHeart, StatusRule, StickyPromptTracker, TranscriptScrollbar } from './appChrome.js'
|
||||
import { AppOverlays } from './appOverlays.js'
|
||||
|
|
@ -119,14 +119,14 @@ const ComposerPane = memo(function ComposerPane({
|
|||
/>
|
||||
|
||||
{ui.bgTasks.size > 0 && (
|
||||
<Text color={ui.theme.color.dim as any}>
|
||||
<Text color={ui.theme.color.dim}>
|
||||
{ui.bgTasks.size} background {ui.bgTasks.size === 1 ? 'task' : 'tasks'} running
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{status.showStickyPrompt ? (
|
||||
<Text color={ui.theme.color.dim as any} wrap="truncate-end">
|
||||
<Text color={ui.theme.color.label as any}>↳ </Text>
|
||||
<Text color={ui.theme.color.dim} wrap="truncate-end">
|
||||
<Text color={ui.theme.color.label}>↳ </Text>
|
||||
|
||||
{status.stickyPrompt}
|
||||
</Text>
|
||||
|
|
@ -169,19 +169,19 @@ const ComposerPane = memo(function ComposerPane({
|
|||
{composer.inputBuf.map((line, i) => (
|
||||
<Box key={i}>
|
||||
<Box width={3}>
|
||||
<Text color={ui.theme.color.dim as any}>{i === 0 ? `${ui.theme.brand.prompt} ` : ' '}</Text>
|
||||
<Text color={ui.theme.color.dim}>{i === 0 ? `${ui.theme.brand.prompt} ` : ' '}</Text>
|
||||
</Box>
|
||||
|
||||
<Text color={ui.theme.color.cornsilk as any}>{line || ' '}</Text>
|
||||
<Text color={ui.theme.color.cornsilk}>{line || ' '}</Text>
|
||||
</Box>
|
||||
))}
|
||||
|
||||
<Box position="relative">
|
||||
<Box width={pw}>
|
||||
{sh ? (
|
||||
<Text color={ui.theme.color.shellDollar as any}>$ </Text>
|
||||
<Text color={ui.theme.color.shellDollar}>$ </Text>
|
||||
) : (
|
||||
<Text bold color={ui.theme.color.gold as any}>
|
||||
<Text bold color={ui.theme.color.gold}>
|
||||
{composer.inputBuf.length ? ' ' : `${ui.theme.brand.prompt} `}
|
||||
</Text>
|
||||
)}
|
||||
|
|
@ -204,7 +204,7 @@ const ComposerPane = memo(function ComposerPane({
|
|||
</Box>
|
||||
)}
|
||||
|
||||
{!composer.empty && !ui.sid && <Text color={ui.theme.color.dim as any}>⚕ {ui.status}</Text>}
|
||||
{!composer.empty && !ui.sid && <Text color={ui.theme.color.dim}>⚕ {ui.status}</Text>}
|
||||
</NoSelect>
|
||||
)
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue