refactor(tui): stop shadowing python — slash fallback inherits worker output

Python's slash worker already prints every echo/panel command through Rich.
TS was reformatting the same data client-side for 23 commands. Delete those
shadows; let the `slash.exec` fallback in `createSlashHandler` route the
worker's text (via `<Ansi>`) and page-wrap long output.

TS registry now contains 23 commands (down from 45) — only those that:
  - mutate React-local state (composer, transcript, overlays, uiStore)
  - touch the terminal (OSC52 copy, `$EDITOR`, clipboard)
  - open pickers (`/model`, `/resume`)
  - trigger history surgery (`/undo`, `/retry`, `/compress`, `/personality`)
  - need TS-only composition (`/help` merges HOTKEYS + catalog)

Deleted shadows:
  session: yolo, skin, verbose, reasoning, provider, stop, reload-mcp,
           save, title, insights, debug, fast, platforms, snapshot,
           usage, history, profile
  ops:     plugins, rollback, agents, tasks, cron, config, toolsets,
           browser, skills (list/browse only; `/tools configure` kept
           for its history-reset side effect)

Side effects:
- Drops `slash/shared.ts` + `SlashShared` + `shared`/`SLASH_OUTPUT_PAGE` —
  generic slash.exec fallback handles titled paging via `createSlashHandler`.
- Prunes 17 now-unreferenced `*Response` interfaces from gatewayTypes.ts.
- `createSlashHandler` fallback now pages long output (len>180 || lines>2)
  and uses the command name as title.

session.ts: 670 -> 199  (-70%)
ops.ts:     460 ->  52  (-88%)
gatewayTypes.ts: 450 -> 302  (-33%)
This commit is contained in:
Brooklyn Nicholson 2026-04-16 14:26:15 -05:00
parent beccd1bc04
commit 0478266831
6 changed files with 69 additions and 835 deletions

View file

@ -4,15 +4,17 @@ import { asCommandDispatch, rpcErrorMessage } from '../lib/rpc.js'
import type { SlashHandlerContext } from './interfaces.js'
import { findSlashCommand } from './slash/registry.js'
import { createSlashShared } from './slash/shared.js'
import type { SlashRunCtx } from './slash/types.js'
import { getUiState } from './uiStore.js'
const titleCase = (name: string) => name.charAt(0).toUpperCase() + name.slice(1)
const isLong = (text: string) => text.length > 180 || text.split('\n').filter(Boolean).length > 2
export function createSlashHandler(ctx: SlashHandlerContext): (cmd: string) => boolean {
const { gw } = ctx.gateway
const { catalog } = ctx.local
const { send, sys } = ctx.transcript
const shared = createSlashShared({ ...ctx.transcript, gw, slashFlightRef: ctx.slashFlightRef })
const { page, send, sys } = ctx.transcript
const handler = (cmd: string): boolean => {
const flight = ++ctx.slashFlightRef.current
@ -37,7 +39,7 @@ export function createSlashHandler(ctx: SlashHandlerContext): (cmd: string) => b
}
}
const runCtx: SlashRunCtx = { ...ctx, flight, guarded, guardedErr, shared, sid, stale, ui }
const runCtx: SlashRunCtx = { ...ctx, flight, guarded, guardedErr, sid, stale, ui }
const found = findSlashCommand(parsed.name)
@ -75,11 +77,10 @@ export function createSlashHandler(ctx: SlashHandlerContext): (cmd: string) => b
return
}
sys(
r?.warning
? `warning: ${r.warning}\n${r?.output || `/${parsed.name}: no output`}`
: r?.output || `/${parsed.name}: no output`
)
const body = r?.output || `/${parsed.name}: no output`
const text = r?.warning ? `warning: ${r.warning}\n${body}` : body
isLong(text) ? page(text, titleCase(parsed.name)) : sys(text)
})
.catch(() => {
gw.request('command.dispatch', { arg: parsed.arg, name: parsed.name, session_id: sid })