mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-14 14:12:44 +00:00
@opentui/core@0.4.0 bundles only 5 grammars (ts/js/markdown/markdown_inline/ zig) and Hermes registered none of its own — Python/Rust/Go/bash/JSON/C/HTML/ CSS/YAML/TOML tool bodies and fences rendered plain text (never a regression: no addDefaultParsers existed anywhere in branch history). Now: parsers/manifest.json curates the 10 grammars (cpp deliberately dropped — 3.28MB alone); scripts/update-parsers.mjs vendors wasm+highlights.scm with magic/content validation (plain Node fetch — core's update-assets generator is Bun-flavored and its import-module won't bundle under esbuild, so registration skips it and points at the vendored files by runtime-resolved path instead); boundary/parsers.ts registers via the public addDefaultParsers() at entry module load, before the first <code>/<markdown> mount initializes the global tree-sitter client. ~4MB vendored, committed (build inputs, offline-safe). Markdown fence injections need no infoStringMap: fence labels resolve as filetype ids and core's ext maps already normalize py→python, zsh→bash, h→c. Live-smoked in a real renderer: python tool body draws 6 distinct token colors; ```python and ```yaml fences inside markdown highlight too. 6 new tests pin the wiring (vendored assets valid, registration set, filetype routing); visuals stay live-smoke territory per codeBlock.tsx.
56 lines
2.2 KiB
TypeScript
56 lines
2.2 KiB
TypeScript
/**
|
|
* DEV DEMO — NOT a test, NOT production. Renders the bench fixture (lorem-ipsum +
|
|
* fat tool-turns from ./fixture.ts) in a REAL CliRenderer so you can attach over
|
|
* tmux, scroll, and eyeball the transcript + the rolling-cap truncation notice.
|
|
* No gateway is spawned (purely the fixture seeded into the store via the resume
|
|
* path), so typing won't reach a backend — it's for viewing/scrolling.
|
|
*
|
|
* Run (Node 26 — needs the esbuild/Solid transform, then --experimental-ffi):
|
|
* node scripts/build.mjs scripts/demo.tsx .demo
|
|
* node --experimental-ffi --no-warnings .demo/demo.js # inside tmux (needs a TTY)
|
|
* DEMO_TOTAL=200 fixture messages to seed (default 200)
|
|
* HERMES_TUI_MAX_MESSAGES=80 cap → the "⤒ N earlier messages" notice fires
|
|
* Quit: Ctrl+C.
|
|
*/
|
|
import { createCliRenderer } from '@opentui/core'
|
|
import { render } from '@opentui/solid'
|
|
|
|
import { installMultiClickSelection } from '../src/boundary/multiClickSelect.ts'
|
|
import { registerVendoredParsers } from '../src/boundary/parsers.ts'
|
|
import { createSessionStore } from '../src/logic/store.ts'
|
|
import { App } from '../src/view/App.tsx'
|
|
import { ThemeProvider } from '../src/view/theme.tsx'
|
|
import { materialize } from './fixture.ts'
|
|
|
|
// Same grammar registration as the live entry so fixture code blocks highlight.
|
|
registerVendoredParsers()
|
|
|
|
const TOTAL = Number.parseInt(process.env.DEMO_TOTAL ?? '', 10) || 200
|
|
|
|
const store = createSessionStore()
|
|
store.apply({ type: 'gateway.ready' })
|
|
store.setSessionId('demo-fixture-20260609')
|
|
// Seed via the resume path so the cap slices + the `dropped` counter is set
|
|
// (drives the truncation notice) exactly as a real `session.resume` would.
|
|
store.beginBuffer()
|
|
store.commitSnapshot(materialize(TOTAL))
|
|
|
|
const renderer = await createCliRenderer({
|
|
externalOutputMode: 'passthrough',
|
|
targetFps: 60,
|
|
exitOnCtrlC: true,
|
|
useKittyKeyboard: {},
|
|
useMouse: true
|
|
})
|
|
// Same seam the live entry installs (boundary/renderer.ts) so the demo smokes
|
|
// double-click word / triple-click line / drag-extend too.
|
|
installMultiClickSelection(renderer)
|
|
|
|
void render(
|
|
() => (
|
|
<ThemeProvider theme={() => store.state.theme}>
|
|
<App store={store} />
|
|
</ThemeProvider>
|
|
),
|
|
renderer
|
|
)
|