// Importing the apps barrel registers the reference apps before launch. import '../../../sdk/apps/index.js' import { terminalBackgroundHex } from '@hermes/ink' import { formatBytes, performHeapDump } from '../../../lib/memory.js' import { launchWidget } from '../../../sdk/host.js' import { listWidgetApps } from '../../../sdk/registry.js' import { loadUserWidgets } from '../../../sdk/userWidgets.js' import { detectLightMode } from '../../../theme.js' import { getUiState } from '../../uiStore.js' import type { SlashCommand } from '../types.js' /** The registry IS the catalog: every registered widget app becomes a slash * command carrying the app's own help/usage — nothing hardcoded per app. * The app owns parsing (init), keybindings (reduce), placement (render). */ export const widgetAppCommands: SlashCommand[] = listWidgetApps().map(app => ({ help: app.help, name: app.id, run: (arg, ctx) => { const err = launchWidget(app.id, arg) if (err) { ctx.transcript.sys(err) } } })) export const debugCommands: SlashCommand[] = [ ...widgetAppCommands, { help: 'rescan $HERMES_HOME/tui-widgets and (re)register user widget apps', name: 'widgets-reload', run: (_arg, ctx) => { void loadUserWidgets().then(({ errors, loaded }) => { const parts = [ loaded.length ? `loaded: ${loaded.join(', ')}` : 'no user widgets found', ...errors.map(e => `${e.file}: ${e.message}`) ] ctx.transcript.sys(`widgets — ${parts.join(' · ')}`) }) } }, { help: 'write a V8 heap snapshot + memory diagnostics (see HERMES_HEAPDUMP_DIR)', name: 'heapdump', run: (_arg, ctx) => { const { heapUsed, rss } = process.memoryUsage() ctx.transcript.sys(`writing heap dump (heap ${formatBytes(heapUsed)} · rss ${formatBytes(rss)})…`) void performHeapDump('manual').then(r => { if (ctx.stale()) { return } if (!r.success) { return ctx.transcript.sys(`heapdump failed: ${r.error ?? 'unknown error'}`) } ctx.transcript.sys(`heapdump: ${r.heapPath}`) ctx.transcript.sys(`diagnostics: ${r.diagPath}`) }) } }, { help: 'print live theme diagnostics (background probe, light mode, palette)', name: 'theme-info', run: (_arg, ctx) => { const { theme } = getUiState() ctx.transcript.panel('Theme', [ { rows: [ ['OSC-11 background', terminalBackgroundHex() ?? '(no reply)'], ['HERMES_TUI_BACKGROUND', process.env.HERMES_TUI_BACKGROUND ?? '(unset)'], ['HERMES_TUI_THEME', process.env.HERMES_TUI_THEME ?? '(unset)'], ['COLORFGBG', process.env.COLORFGBG ?? '(unset)'], ['TERM_PROGRAM', process.env.TERM_PROGRAM ?? '(unset)'], ['detected mode', detectLightMode() ? 'light' : 'dark'], ['text', theme.color.text], ['completionBg', theme.color.completionBg], ['selectionBg', theme.color.selectionBg], ['statusBg', theme.color.statusBg] ] } ]) } }, { help: 'print live V8 heap + rss numbers', name: 'mem', run: (_arg, ctx) => { const { arrayBuffers, external, heapTotal, heapUsed, rss } = process.memoryUsage() ctx.transcript.panel('Memory', [ { rows: [ ['heap used', formatBytes(heapUsed)], ['heap total', formatBytes(heapTotal)], ['external', formatBytes(external)], ['array buffers', formatBytes(arrayBuffers)], ['rss', formatBytes(rss)], ['uptime', `${process.uptime().toFixed(0)}s`] ] } ]) } } ]