diff --git a/ui-tui/src/app.tsx b/ui-tui/src/app.tsx index 740e0ffcd7..e18adba99a 100644 --- a/ui-tui/src/app.tsx +++ b/ui-tui/src/app.tsx @@ -1031,14 +1031,25 @@ export function App({ gw }: { gw: GatewayClient }) { const dbl = now - lastEmptyAt.current < 450 lastEmptyAt.current = now - if (dbl && queueRef.current.length) { - if (busy && sid) { - gw.request('session.interrupt', { session_id: sid }).catch(() => {}) - setStatus('interrupting…') + if (dbl && busy && sid) { + interruptedRef.current = true + gw.request('session.interrupt', { session_id: sid }).catch(() => {}) - return + const partial = (streaming || buf.current).trimStart() + if (partial) { + appendMessage({ role: 'assistant' as const, text: partial + '\n\n*[interrupted]*' }) + } else { + sys('interrupted') } + idle() + setStatus('interrupted') + setTimeout(() => setStatus('ready'), 1500) + + return + } + + if (dbl && queueRef.current.length) { const next = dequeue() if (next && sid) { diff --git a/ui-tui/src/components/markdown.tsx b/ui-tui/src/components/markdown.tsx index 2abb5bf41b..9a75952f54 100644 --- a/ui-tui/src/components/markdown.tsx +++ b/ui-tui/src/components/markdown.tsx @@ -111,15 +111,22 @@ export function Md({ compact, t, text }: { compact?: boolean; t: Theme; text: st nodes.push( {lang && !isDiff && {'─ ' + lang}} - {block.map((l, j) => ( - - {l} - - ))} + {block.map((l, j) => { + const add = isDiff && l.startsWith('+') + const del = isDiff && l.startsWith('-') + const hunk = isDiff && l.startsWith('@@') + + return ( + + {l} + + ) + })} ) diff --git a/ui-tui/src/theme.ts b/ui-tui/src/theme.ts index 29db1480ff..37f1d5bde7 100644 --- a/ui-tui/src/theme.ts +++ b/ui-tui/src/theme.ts @@ -16,6 +16,11 @@ export interface ThemeColors { statusWarn: string statusBad: string statusCritical: string + + diffAdded: string + diffRemoved: string + diffAddedWord: string + diffRemovedWord: string } export interface ThemeBrand { @@ -52,7 +57,12 @@ export const DEFAULT_THEME: Theme = { statusGood: '#8FBC8F', statusWarn: '#FFD700', statusBad: '#FF8C00', - statusCritical: '#FF6B6B' + statusCritical: '#FF6B6B', + + diffAdded: 'rgb(220,255,220)', + diffRemoved: 'rgb(255,220,220)', + diffAddedWord: 'rgb(36,138,61)', + diffRemovedWord: 'rgb(207,34,46)', }, brand: { @@ -95,7 +105,12 @@ export function fromSkin( statusGood: c('ui_ok') ?? d.color.statusGood, statusWarn: c('ui_warn') ?? d.color.statusWarn, statusBad: d.color.statusBad, - statusCritical: d.color.statusCritical + statusCritical: d.color.statusCritical, + + diffAdded: d.color.diffAdded, + diffRemoved: d.color.diffRemoved, + diffAddedWord: d.color.diffAddedWord, + diffRemovedWord: d.color.diffRemovedWord, }, brand: {