Files
aiturk-hermes-ide/ui-tui/src/app/slash/commands/debug.ts
T

116 lines
3.6 KiB
TypeScript

// 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`]
]
}
])
}
}
]