mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
feat: add slash commands to the history so it doesnt get lost
This commit is contained in:
parent
7e813a30e0
commit
17ecdce936
5 changed files with 52 additions and 10 deletions
|
|
@ -709,7 +709,10 @@ export function App({ gw }: { gw: GatewayClient }) {
|
|||
historyDraftRef.current = ''
|
||||
}
|
||||
|
||||
if (full.startsWith('/') && slashRef.current(full)) {
|
||||
if (full.startsWith('/')) {
|
||||
appendMessage({ role: 'system', text: full, kind: 'slash' })
|
||||
pushHistory(full)
|
||||
slashRef.current(full)
|
||||
clearInput()
|
||||
|
||||
return
|
||||
|
|
@ -793,7 +796,7 @@ export function App({ gw }: { gw: GatewayClient }) {
|
|||
send(full)
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[busy, enqueue, gw, listPasteIds, pastes, resolvePasteTokens, sid]
|
||||
[appendMessage, busy, enqueue, gw, listPasteIds, pastes, pushHistory, resolvePasteTokens, sid]
|
||||
)
|
||||
|
||||
// ── Input handling ───────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ export const MessageLine = memo(function MessageLine({
|
|||
const { body, glyph, prefix } = ROLE[msg.role](t)
|
||||
|
||||
const content = (() => {
|
||||
if (msg.kind === 'slash') {
|
||||
return <Text color={t.color.dim}>{msg.text}</Text>
|
||||
}
|
||||
|
||||
if (msg.role === 'assistant') {
|
||||
return hasAnsi(msg.text) ? <Text wrap="wrap">{msg.text}</Text> : <Md compact={compact} t={t} text={msg.text} />
|
||||
}
|
||||
|
|
@ -41,9 +45,11 @@ export const MessageLine = memo(function MessageLine({
|
|||
return (
|
||||
<Text color={body}>
|
||||
{head}
|
||||
|
||||
<Text color={t.color.dim} dimColor>
|
||||
[long message]
|
||||
</Text>
|
||||
|
||||
{rest.join('')}
|
||||
</Text>
|
||||
)
|
||||
|
|
@ -53,7 +59,7 @@ export const MessageLine = memo(function MessageLine({
|
|||
})()
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" marginTop={msg.role === 'user' ? 1 : 0}>
|
||||
<Box flexDirection="column" marginTop={msg.role === 'user' || msg.kind === 'slash' ? 1 : 0}>
|
||||
{msg.thinking && (
|
||||
<Text color={t.color.dim} dimColor wrap="truncate-end">
|
||||
💭 {msg.thinking.replace(/\n/g, ' ').slice(0, 200)}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,21 @@ import { memo, useEffect, useState } from 'react'
|
|||
import spinners, { type BrailleSpinnerName } from 'unicode-animations'
|
||||
|
||||
import { FACES, TOOL_VERBS, VERBS } from '../constants.js'
|
||||
import { isToolTrailResultLine, lastCotTrailIndex } from '../lib/text.js'
|
||||
import {
|
||||
isToolTrailResultLine,
|
||||
lastCotTrailIndex,
|
||||
pick,
|
||||
scaleHex,
|
||||
THINKING_COT_FADE,
|
||||
THINKING_COT_MAX,
|
||||
thinkingCotTail
|
||||
} from '../lib/text.js'
|
||||
import type { Theme } from '../theme.js'
|
||||
import type { ActiveTool, ActivityItem } from '../types.js'
|
||||
|
||||
const THINK: BrailleSpinnerName[] = ['helix', 'breathe', 'orbit', 'dna', 'waverows', 'snake', 'pulse']
|
||||
const TOOL: BrailleSpinnerName[] = ['cascade', 'scan', 'diagswipe', 'fillsweep', 'rain', 'columns', 'sparkle']
|
||||
|
||||
const pick = <T,>(a: T[]) => a[Math.floor(Math.random() * a.length)]!
|
||||
|
||||
const tone = (item: ActivityItem, t: Theme) =>
|
||||
item.tone === 'error' ? t.color.error : item.tone === 'warn' ? t.color.warn : t.color.dim
|
||||
|
||||
|
|
@ -128,7 +134,8 @@ export const Thinking = memo(function Thinking({ reasoning, t }: { reasoning: st
|
|||
return () => clearInterval(id)
|
||||
}, [])
|
||||
|
||||
const tail = reasoning.slice(-160).replace(/\n/g, ' ')
|
||||
const tail = thinkingCotTail(reasoning)
|
||||
const clipped = reasoning.length > THINKING_COT_MAX
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -138,8 +145,17 @@ export const Thinking = memo(function Thinking({ reasoning, t }: { reasoning: st
|
|||
</Text>
|
||||
|
||||
{tail ? (
|
||||
<Text color={t.color.dim} dimColor wrap="truncate-end">
|
||||
💭 {tail}
|
||||
<Text wrap="truncate-end">
|
||||
{clipped &&
|
||||
Array.from({ length: Math.min(THINKING_COT_FADE, tail.length) }, (_, i) => (
|
||||
<Text color={scaleHex(t.color.dim, (i + 1) / (THINKING_COT_FADE + 1))} key={i}>
|
||||
{tail[i]}
|
||||
</Text>
|
||||
))}
|
||||
|
||||
<Text color={t.color.dim} dimColor>
|
||||
{clipped ? tail.slice(THINKING_COT_FADE) : tail}
|
||||
</Text>
|
||||
</Text>
|
||||
) : null}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -53,6 +53,23 @@ export const lastCotTrailIndex = (trail: readonly string[]) => {
|
|||
return -1
|
||||
}
|
||||
|
||||
export const THINKING_COT_MAX = 160
|
||||
export const THINKING_COT_FADE = 5
|
||||
|
||||
export const thinkingCotTail = (reasoning: string) => reasoning.replace(/\n/g, ' ').slice(-THINKING_COT_MAX)
|
||||
|
||||
/** Scale #RRGGBB by k ∈ [0,1] — used for left-edge fade toward terminal bg. */
|
||||
export const scaleHex = (hex: string, k: number) => {
|
||||
const h = hex.replace('#', '')
|
||||
|
||||
const ch = (o: number) =>
|
||||
Math.round(parseInt(h.slice(o, o + 2), 16) * k)
|
||||
.toString(16)
|
||||
.padStart(2, '0')
|
||||
|
||||
return `#${ch(0)}${ch(2)}${ch(4)}`
|
||||
}
|
||||
|
||||
export const estimateRows = (text: string, w: number, compact = false) => {
|
||||
let inCode = false
|
||||
let rows = 0
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export interface ClarifyReq {
|
|||
export interface Msg {
|
||||
role: Role
|
||||
text: string
|
||||
kind?: 'intro'
|
||||
kind?: 'intro' | 'slash'
|
||||
info?: SessionInfo
|
||||
thinking?: string
|
||||
tools?: string[]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue