diff --git a/build.ts b/build.ts index 149be76..78ae422 100644 --- a/build.ts +++ b/build.ts @@ -3,7 +3,7 @@ import { $ } from 'bun' await $`rm -rf dist` await Bun.build({ - entrypoints: ['src/index.ts'], + entrypoints: ['src/index.ts', 'src/tui.ts'], outdir: './dist', format: 'esm', target: 'node', diff --git a/package.json b/package.json index 5f1b8c4..027b582 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,16 @@ "type": "module", "main": "./dist/index.js", "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./tui": { + "types": "./dist/tui.d.ts", + "default": "./dist/tui.js" + } + }, "files": ["dist"], "scripts": { "build": "bun run build.ts && tsc --emitDeclarationOnly", diff --git a/src/tui.ts b/src/tui.ts new file mode 100644 index 0000000..6b5bc73 --- /dev/null +++ b/src/tui.ts @@ -0,0 +1,56 @@ +import type { TuiPlugin } from '@opencode-ai/plugin' +import { getMode } from './state' + +const MODE_LABELS: Record = { + 'lite': { icon: '💎', label: 'Caveman Lite' }, + 'full': { icon: 'ðŸ”Ĩ', label: 'Caveman Full' }, + 'ultra': { icon: '⚡', label: 'Caveman Ultra' }, + 'wenyan-lite': { icon: '📜', label: '文čĻ€ Lite' }, + 'wenyan-full': { icon: '📜', label: '文čĻ€ Full' }, + 'wenyan-ultra': { icon: '📜', label: '文čĻ€ Ultra' }, +} + +function formatMode(mode: string): string { + const info = MODE_LABELS[mode] + return info ? `${info.icon} ${info.label}` : `ðŸĶī ${mode}` +} + +export const tui: TuiPlugin = async (api, _options, _meta) => { + // Maintain a Set of session IDs that have caveman active + const activeSessions = new Set() + + // Listen for events to know when caveman mode changes + api.event.on('chat.message', (event) => { + const sessionID = event.sessionID + if (!sessionID) return + + const mode = getMode(sessionID) + const isActive = mode && mode !== 'off' + if (isActive) { + activeSessions.add(sessionID) + // Trigger a re-render of our slots + api.renderer.render() + } else { + if (activeSessions.has(sessionID)) { + activeSessions.delete(sessionID) + api.renderer.render() + } + } + }) + + // Register slots for each session + const dispose = api.slots.register({ + sidebar_footer: ({ session_id }) => { + const mode = getMode(session_id) + if (!mode || mode === 'off') return null + + return ( + + {' '}{formatMode(mode)}{' '} + + ) + }, + }) + + api.lifecycle.onDispose(dispose) +}