116 lines
3.6 KiB
TypeScript
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`]
|
|
]
|
|
}
|
|
])
|
|
}
|
|
}
|
|
]
|