@xopcai/xopc 0.0.28 → 0.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/agents-CkgFSiCY.js +216 -0
- package/dist/gateway/static/root/assets/agents-CkgFSiCY.js.map +1 -0
- package/dist/gateway/static/root/assets/{apps-page-Co95hLOJ.js → apps-page-Bmq19MS-.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-Co95hLOJ.js.map → apps-page-Bmq19MS-.js.map} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js +9 -0
- package/dist/gateway/static/root/assets/channels-settings-CE7jrdkO.js.map +1 -0
- package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js +2 -0
- package/dist/gateway/static/root/assets/cron-page-BpPPcykJ.js.map +1 -0
- package/dist/gateway/static/root/assets/{cron-utils-BmzF4m1y.js → cron-utils-N1PqD2DB.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-BmzF4m1y.js.map → cron-utils-N1PqD2DB.js.map} +1 -1
- package/dist/gateway/static/root/assets/{dist-Dn-ufXyc.js → dist--p2HQ2QF.js} +2 -2
- package/dist/gateway/static/root/assets/{dist-Dn-ufXyc.js.map → dist--p2HQ2QF.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BZ8xQ74_.js → extension-debug-page-DwHCB_6T.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-BZ8xQ74_.js.map → extension-debug-page-DwHCB_6T.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BlNgKxwW.js → extension-page-BsYwQIex.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-BlNgKxwW.js.map → extension-page-BsYwQIex.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-CWTdW_oY.js → extension-settings-page-nsisEgjB.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-CWTdW_oY.js.map → extension-settings-page-nsisEgjB.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-CR8zUHGR.js +4734 -0
- package/dist/gateway/static/root/assets/{index-lV8FGWlt.js.map → index-CR8zUHGR.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-Dnfha4O2.css +1 -0
- package/dist/gateway/static/root/assets/logs-page-CQwdV_Xw.js +2 -0
- package/dist/gateway/static/root/assets/{logs-page-DG31RpvG.js.map → logs-page-CQwdV_Xw.js.map} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js +2 -0
- package/dist/gateway/static/root/assets/sessions-page-Be5kIGl_.js.map +1 -0
- package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-PodSlNwr.js.map +1 -0
- package/dist/gateway/static/root/assets/skills-page-Clg8deH0.js +3 -0
- package/dist/gateway/static/root/assets/{skills-page-lb7vYtlP.js.map → skills-page-Clg8deH0.js.map} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/lifecycle/hook-handler.d.ts +2 -0
- package/dist/src/agent/lifecycle/hook-handler.js +24 -0
- package/dist/src/agent/lifecycle/hook-handler.js.map +1 -1
- package/dist/src/agent/messaging/command-handler.js +10 -2
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/service/process-direct-streaming.js +77 -20
- package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
- package/dist/src/agent/service.d.ts +15 -0
- package/dist/src/agent/service.js +21 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/channels/index.js +2 -2
- package/dist/src/channels/manager.js +2 -2
- package/dist/src/cli/agent-chat-log-level-preset.d.ts +3 -2
- package/dist/src/cli/agent-chat-log-level-preset.js +6 -3
- package/dist/src/cli/agent-chat-log-level-preset.js.map +1 -1
- package/dist/src/cli/index.js +4 -3
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/config/schema.js +5 -2
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/extensions/hooks.js +5 -1
- package/dist/src/extensions/hooks.js.map +1 -1
- package/dist/src/extensions/loader.d.ts +1 -0
- package/dist/src/extensions/loader.js +3 -1
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/sdk/index.d.ts +1 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +8 -0
- package/dist/src/extensions/types/hooks.d.ts +16 -1
- package/dist/src/extensions/types/hooks.js +1 -0
- package/dist/src/extensions/types/hooks.js.map +1 -1
- package/dist/src/gateway/agents-admin.d.ts +19 -1
- package/dist/src/gateway/agents-admin.js +164 -3
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/hono/app.js +1 -0
- package/dist/src/gateway/hono/app.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js +59 -5
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config.js +2 -2
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +1 -0
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +17 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/service.d.ts +2 -0
- package/dist/src/gateway/service.js +31 -4
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/session/client-history.d.ts +21 -0
- package/dist/src/session/client-history.js +89 -0
- package/dist/src/session/client-history.js.map +1 -0
- package/dist/src/session/index.d.ts +1 -0
- package/dist/src/session/index.js +2 -1
- package/dist/src/session/manager.d.ts +2 -0
- package/dist/src/session/manager.js +5 -0
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/thinking-resolve.js +1 -1
- package/dist/src/session/thinking-resolve.js.map +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +1 -1
- package/dist/src/tui/backends/embedded-backend.js +15 -2
- package/dist/src/tui/backends/embedded-backend.js.map +1 -1
- package/dist/src/tui/backends/gateway-sse-backend.d.ts +4 -0
- package/dist/src/tui/backends/gateway-sse-backend.js +34 -4
- package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
- package/dist/src/tui/chat-history.d.ts +4 -0
- package/dist/src/tui/chat-history.js +29 -0
- package/dist/src/tui/chat-history.js.map +1 -0
- package/dist/src/tui/components/chat-log.d.ts +3 -1
- package/dist/src/tui/components/chat-log.js +17 -3
- package/dist/src/tui/components/chat-log.js.map +1 -1
- package/dist/src/tui/components/custom-editor.d.ts +1 -0
- package/dist/src/tui/components/custom-editor.js +8 -2
- package/dist/src/tui/components/custom-editor.js.map +1 -1
- package/dist/src/tui/components/fuzzy-filter.d.ts +17 -0
- package/dist/src/tui/components/fuzzy-filter.js +85 -0
- package/dist/src/tui/components/fuzzy-filter.js.map +1 -0
- package/dist/src/tui/components/searchable-select-list.d.ts +39 -0
- package/dist/src/tui/components/searchable-select-list.js +257 -0
- package/dist/src/tui/components/searchable-select-list.js.map +1 -0
- package/dist/src/tui/theme.d.ts +2 -0
- package/dist/src/tui/theme.js +7 -1
- package/dist/src/tui/theme.js.map +1 -1
- package/dist/src/tui/tui-agent-events.d.ts +7 -0
- package/dist/src/tui/tui-agent-events.js +103 -0
- package/dist/src/tui/tui-agent-events.js.map +1 -0
- package/dist/src/tui/tui-backend.d.ts +8 -12
- package/dist/src/tui/tui-commands.d.ts +23 -0
- package/dist/src/tui/tui-commands.js +165 -0
- package/dist/src/tui/tui-commands.js.map +1 -0
- package/dist/src/tui/tui-lifecycle.d.ts +26 -0
- package/dist/src/tui/tui-lifecycle.js +57 -0
- package/dist/src/tui/tui-lifecycle.js.map +1 -0
- package/dist/src/tui/tui-local-shell.d.ts +28 -0
- package/dist/src/tui/tui-local-shell.js +147 -0
- package/dist/src/tui/tui-local-shell.js.map +1 -0
- package/dist/src/tui/tui-overlays.d.ts +8 -0
- package/dist/src/tui/tui-overlays.js +22 -0
- package/dist/src/tui/tui-overlays.js.map +1 -0
- package/dist/src/tui/tui-picker-overlay.d.ts +26 -0
- package/dist/src/tui/tui-picker-overlay.js +69 -0
- package/dist/src/tui/tui-picker-overlay.js.map +1 -0
- package/dist/src/tui/tui-stdio-filter.d.ts +17 -0
- package/dist/src/tui/tui-stdio-filter.js +96 -0
- package/dist/src/tui/tui-stdio-filter.js.map +1 -0
- package/dist/src/tui/tui-submit.d.ts +25 -0
- package/dist/src/tui/tui-submit.js +102 -0
- package/dist/src/tui/tui-submit.js.map +1 -0
- package/dist/src/tui/tui-suspend.d.ts +10 -0
- package/dist/src/tui/tui-suspend.js +18 -0
- package/dist/src/tui/tui-suspend.js.map +1 -0
- package/dist/src/tui/tui-types.d.ts +1 -0
- package/dist/src/tui/tui-types.js.map +1 -1
- package/dist/src/tui/tui.d.ts +2 -0
- package/dist/src/tui/tui.js +175 -312
- package/dist/src/tui/tui.js.map +1 -1
- package/package.json +2 -6
- package/dist/gateway/static/root/assets/agents-DplaQYS2.js +0 -216
- package/dist/gateway/static/root/assets/agents-DplaQYS2.js.map +0 -1
- package/dist/gateway/static/root/assets/channels-settings-CkfSST0k.js +0 -9
- package/dist/gateway/static/root/assets/channels-settings-CkfSST0k.js.map +0 -1
- package/dist/gateway/static/root/assets/cron-page-D9q6KqL8.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-D9q6KqL8.js.map +0 -1
- package/dist/gateway/static/root/assets/index-OT4cGzon.css +0 -1
- package/dist/gateway/static/root/assets/index-lV8FGWlt.js +0 -4734
- package/dist/gateway/static/root/assets/logs-page-DG31RpvG.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-CdmjxDEM.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-CdmjxDEM.js.map +0 -1
- package/dist/gateway/static/root/assets/settings-page-DU2XLf5s.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-DU2XLf5s.js.map +0 -1
- package/dist/gateway/static/root/assets/skills-page-lb7vYtlP.js +0 -3
package/dist/src/tui/tui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.js","names":[],"sources":["../../../src/tui/tui.ts"],"sourcesContent":["import {\n CombinedAutocompleteProvider,\n Container,\n Loader,\n ProcessTerminal,\n Text,\n TUI,\n} from '@mariozechner/pi-tui';\n\nimport type { TuiBackend, TuiEvent } from './tui-backend.js';\nimport { EmbeddedBackend } from './backends/embedded-backend.js';\nimport { GatewaySseBackend } from './backends/gateway-sse-backend.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { CustomEditor } from './components/custom-editor.js';\nimport { StreamAssembler } from './stream-assembler.js';\nimport { editorTheme, theme } from './theme.js';\nimport { createInitialState, type TuiOptions, type TuiResult, type TuiState } from './tui-types.js';\n\nexport type { TuiOptions, TuiResult };\n\n// ── Slash commands ──\n\ninterface SlashCommandDef {\n name: string;\n description: string;\n}\n\nfunction getSlashCommands(_isLocal: boolean): SlashCommandDef[] {\n return [\n // TUI-local commands\n { name: 'help', description: 'Show available commands' },\n { name: 'abort', description: 'Abort active run (or press Escape)' },\n { name: 'tools', description: 'Toggle tool output expanded/collapsed (or Ctrl+O)' },\n { name: 'thinking', description: 'Toggle thinking display (or Ctrl+T)' },\n { name: 'exit', description: 'Exit the TUI' },\n // Backend-delegated commands (handled by chat-command system)\n { name: 'models', description: 'List available models' },\n { name: 'switch', description: 'Switch model (e.g. /switch openai/gpt-4o)' },\n { name: 'usage', description: 'Show token usage statistics' },\n { name: 'new', description: 'Start a new session' },\n { name: 'clear', description: 'Clear current session' },\n { name: 'list', description: 'List sessions' },\n { name: 'compact', description: 'Compact session history' },\n { name: 'think', description: 'Set thinking level (e.g. /think high)' },\n { name: 'reasoning', description: 'Set reasoning visibility (e.g. /reasoning stream)' },\n { name: 'verbose', description: 'Toggle verbose mode' },\n { name: 'status', description: 'Show agent status' },\n { name: 'config', description: 'Show or update configuration' },\n { name: 'context', description: 'Show context budget' },\n { name: 'btw', description: 'Side question without saving to session' },\n { name: 'export', description: 'Export session (markdown/html/json)' },\n { name: 'settings', description: 'Show current settings' },\n { name: 'start', description: 'Show welcome message' },\n ];\n}\n\nfunction helpText(isLocal: boolean): string {\n const commands = getSlashCommands(isLocal);\n const lines = ['Available commands:'];\n for (const c of commands) {\n lines.push(` /${c.name} — ${c.description}`);\n }\n lines.push('', 'Keyboard shortcuts:');\n lines.push(' Escape — Abort active run');\n lines.push(' Ctrl+O — Toggle tool output');\n lines.push(' Ctrl+T — Toggle thinking display');\n lines.push(' Ctrl+C — Clear input / exit');\n lines.push(' Ctrl+D — Exit');\n return lines.join('\\n');\n}\n\n// ── Ctrl+C handling ──\n\ntype CtrlCAction = 'clear' | 'warn' | 'exit';\n\nfunction resolveCtrlCAction(hasInput: boolean, now: number, lastCtrlCAt: number): { action: CtrlCAction; nextLastCtrlCAt: number } {\n if (hasInput) return { action: 'clear', nextLastCtrlCAt: now };\n if (now - lastCtrlCAt <= 1000) return { action: 'exit', nextLastCtrlCAt: lastCtrlCAt };\n return { action: 'warn', nextLastCtrlCAt: now };\n}\n\n// ── SSE event dispatch ──\n\n// Track tool_start → tool_end matching when backend omits toolCallId.\n// Uses a per-toolName stack so concurrent tools of the same name still pair correctly.\nconst pendingToolCallIds = new Map<string, string[]>();\n\nfunction dispatchAgentSSE(\n event: string,\n data: Record<string, unknown>,\n state: TuiState,\n chatLog: ChatLog,\n assembler: StreamAssembler,\n tui: TUI,\n setActivityStatus: (status: string) => void,\n): void {\n const runId = state.activeRunId ?? 'default';\n\n switch (event) {\n case 'status': {\n const newRunId = typeof data.runId === 'string' ? data.runId : runId;\n state.activeRunId = newRunId;\n setActivityStatus('waiting');\n break;\n }\n case 'token': {\n const content =\n typeof data.content === 'string'\n ? data.content\n : typeof data.delta === 'string'\n ? data.delta\n : typeof data.text === 'string'\n ? data.text\n : '';\n if (!content) break;\n setActivityStatus('streaming');\n const display = assembler.ingestToken(runId, content, state.showThinking);\n if (display !== null) {\n chatLog.updateAssistant(display, runId);\n tui.requestRender();\n }\n break;\n }\n case 'thinking': {\n const thinkContent = String(data.content ?? '');\n const isDelta = Boolean(data.delta);\n if (data.status === 'started') break;\n setActivityStatus('streaming');\n const display = assembler.ingestThinking(runId, thinkContent, isDelta, state.showThinking);\n if (display !== null) {\n chatLog.updateAssistant(display, runId);\n tui.requestRender();\n }\n break;\n }\n case 'thinking_end':\n case 'message_end':\n break;\n case 'tool_start': {\n const toolName = String(data.toolName ?? 'unknown');\n const toolCallId = String(data.toolCallId || crypto.randomUUID());\n // Push onto the pending stack so tool_end can find this id by toolName\n const stack = pendingToolCallIds.get(toolName) ?? [];\n stack.push(toolCallId);\n pendingToolCallIds.set(toolName, stack);\n setActivityStatus('running');\n chatLog.startTool(toolCallId, toolName, data.args);\n tui.requestRender();\n break;\n }\n case 'tool_end': {\n const toolName = String(data.toolName ?? '');\n // Resolve toolCallId: prefer explicit value, then pop from pending stack by toolName\n let toolCallId = typeof data.toolCallId === 'string' && data.toolCallId ? data.toolCallId : '';\n if (!toolCallId && toolName) {\n const stack = pendingToolCallIds.get(toolName);\n if (stack && stack.length > 0) {\n toolCallId = stack.shift()!;\n if (stack.length === 0) pendingToolCallIds.delete(toolName);\n }\n }\n const resultText = String(data.result ?? '');\n const isError = Boolean(data.isError);\n if (toolCallId) {\n chatLog.updateToolResult(toolCallId, resultText, isError);\n }\n setActivityStatus('streaming');\n tui.requestRender();\n break;\n }\n case 'error': {\n const errorContent = String(data.content ?? 'Unknown error');\n const finalText = assembler.finalize(runId, state.showThinking);\n if (finalText) {\n chatLog.finalizeAssistant(finalText, runId);\n }\n chatLog.addSystem(`❌ ${errorContent}`);\n state.activeRunId = null;\n setActivityStatus('idle');\n tui.requestRender();\n break;\n }\n case 'result': {\n const finalText = assembler.finalize(runId, state.showThinking);\n if (finalText) {\n chatLog.finalizeAssistant(finalText, runId);\n }\n state.activeRunId = null;\n setActivityStatus('idle');\n tui.requestRender();\n break;\n }\n case 'progress': {\n setActivityStatus('running');\n break;\n }\n default:\n break;\n }\n}\n\n// ── Main entry ──\n\nexport async function runTui(opts: TuiOptions): Promise<TuiResult> {\n // Suppress pino JSON logs from polluting the terminal while pi-tui owns the screen.\n // We intercept stdout/stderr writes and swallow anything that looks like a JSON log line.\n const originalStdoutWrite = process.stdout.write.bind(process.stdout);\n const originalStderrWrite = process.stderr.write.bind(process.stderr);\n let suppressLogs = true;\n\n const logFilter = (\n original: typeof process.stdout.write,\n ): typeof process.stdout.write => {\n return function filteredWrite(chunk: unknown, ...rest: unknown[]): boolean {\n if (!suppressLogs) return (original as Function)(chunk, ...rest) as boolean;\n const text = typeof chunk === 'string' ? chunk : chunk instanceof Buffer ? chunk.toString() : '';\n if (text.startsWith('{\"level\":')) return true; // swallow JSON log lines\n return (original as Function)(chunk, ...rest) as boolean;\n } as typeof process.stdout.write;\n };\n\n process.stdout.write = logFilter(originalStdoutWrite);\n process.stderr.write = logFilter(originalStderrWrite);\n\n const restoreStdio = () => {\n suppressLogs = false;\n process.stdout.write = originalStdoutWrite;\n process.stderr.write = originalStderrWrite;\n };\n\n const isLocalMode = opts.local === true;\n const sessionKey = opts.session ?? 'cli:tui';\n const state = createInitialState(sessionKey);\n const assembler = new StreamAssembler();\n\n // Create backend\n const client: TuiBackend = isLocalMode\n ? new EmbeddedBackend()\n : new GatewaySseBackend({ url: opts.url ?? 'http://localhost:3120', token: opts.token });\n\n // Build UI tree\n const tui = new TUI(new ProcessTerminal());\n const header = new Text('', 1, 0);\n const statusContainer = new Container();\n const footer = new Text('', 1, 0);\n const chatLog = new ChatLog();\n const editor = new CustomEditor(tui, editorTheme);\n const root = new Container();\n root.addChild(header);\n root.addChild(chatLog);\n root.addChild(statusContainer);\n root.addChild(footer);\n root.addChild(editor);\n tui.addChild(root);\n tui.setFocus(editor);\n\n // Slash command autocomplete\n const slashCommands = getSlashCommands(isLocalMode);\n editor.setAutocompleteProvider(\n new CombinedAutocompleteProvider(\n slashCommands.map((c) => ({ name: c.name, description: c.description })),\n process.cwd(),\n ),\n );\n\n // Status management\n let statusText: Text | null = null;\n let statusLoader: Loader | null = null;\n let statusStartedAt: number | null = null;\n let lastActivityStatus = '';\n let elapsedTimerId: ReturnType<typeof setInterval> | null = null;\n const busyStates = new Set(['sending', 'waiting', 'streaming', 'running']);\n\n const formatElapsed = (startMs: number) => {\n const totalSeconds = Math.max(0, Math.floor((Date.now() - startMs) / 1000));\n if (totalSeconds < 60) return `${totalSeconds}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}m ${seconds}s`;\n };\n\n const renderStatus = () => {\n const isBusy = busyStates.has(state.activityStatus);\n if (isBusy) {\n if (!statusStartedAt || lastActivityStatus !== state.activityStatus) {\n statusStartedAt = Date.now();\n }\n // Show loader\n if (!statusLoader) {\n statusContainer.clear();\n statusText = null;\n statusLoader = new Loader(\n tui,\n (spinner) => theme.accent(spinner),\n (text) => theme.bold(theme.accentSoft(text)),\n '',\n );\n statusContainer.addChild(statusLoader);\n }\n const elapsed = formatElapsed(statusStartedAt);\n statusLoader.setMessage(`${state.activityStatus} • ${elapsed} | ${state.connectionStatus}`);\n // Tick every second to update elapsed time display\n if (!elapsedTimerId) {\n elapsedTimerId = setInterval(() => {\n if (statusStartedAt && statusLoader) {\n const el = formatElapsed(statusStartedAt);\n statusLoader.setMessage(`${state.activityStatus} • ${el} | ${state.connectionStatus}`);\n }\n }, 1000);\n }\n } else {\n statusStartedAt = null;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n statusLoader?.stop();\n statusLoader = null;\n if (!statusText) {\n statusContainer.clear();\n statusText = new Text('', 1, 0);\n statusContainer.addChild(statusText);\n }\n const text = state.activityStatus\n ? `${state.connectionStatus} | ${state.activityStatus}`\n : state.connectionStatus;\n statusText.setText(theme.dim(text));\n }\n lastActivityStatus = state.activityStatus;\n };\n\n const setActivityStatus = (status: string) => {\n state.activityStatus = status as TuiState['activityStatus'];\n renderStatus();\n };\n\n const setConnectionStatus = (text: string) => {\n state.connectionStatus = text;\n renderStatus();\n };\n\n const updateHeader = () => {\n const title = 'xopc tui';\n header.setText(\n theme.header(`${title} — ${client.connectionLabel} — session ${state.currentSessionKey}`),\n );\n };\n\n const updateFooter = () => {\n const modelLabel = state.sessionInfo.model\n ? state.sessionInfo.modelProvider\n ? `${state.sessionInfo.modelProvider}/${state.sessionInfo.model}`\n : state.sessionInfo.model\n : 'unknown';\n const tokens = state.sessionInfo.totalTokens != null\n ? `${state.sessionInfo.totalTokens} tokens`\n : '';\n const thinking = state.showThinking ? 'thinking:on' : '';\n const parts = [\n `session ${state.currentSessionKey}`,\n modelLabel,\n thinking,\n tokens,\n ].filter(Boolean);\n footer.setText(theme.dim(parts.join(' | ')));\n };\n\n // Load session info from backend\n const refreshSessionInfo = async () => {\n try {\n state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);\n updateFooter();\n tui.requestRender();\n } catch {\n // Ignore errors silently\n }\n };\n\n // Send message (fire-and-forget so the TUI event loop stays responsive)\n const sendMessage = (text: string) => {\n if (state.activeRunId) {\n chatLog.addSystem('A response is still in progress. Use /abort or press Escape to cancel.');\n tui.requestRender();\n return;\n }\n\n chatLog.addUser(text);\n setActivityStatus('sending');\n tui.requestRender();\n\n // Run in background — events arrive via client.onEvent callback\n void client\n .sendChat({\n sessionKey: state.currentSessionKey,\n message: text,\n thinking: opts.thinking,\n })\n .catch((error: unknown) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(`❌ Failed to send: ${errorMessage}`);\n setActivityStatus('idle');\n tui.requestRender();\n });\n };\n\n // Abort active run\n const abortActive = async () => {\n if (!state.activeRunId) return;\n const runId = state.activeRunId;\n state.activeRunId = null;\n assembler.drop(runId);\n chatLog.dropAssistant(runId);\n setActivityStatus('idle');\n tui.requestRender();\n await client.abortChat({ sessionKey: state.currentSessionKey, runId }).catch(() => {});\n };\n\n // Handle slash commands.\n // TUI-local commands are processed here; everything else is delegated to the\n // backend's chat-command system via sendMessage (processDirectStreaming handles\n // the commandRegistry lookup and returns results as SSE token events).\n const handleCommand = (input: string) => {\n const trimmed = input.replace(/^\\//, '').trim();\n const [commandName] = trimmed.split(/\\s+/);\n const normalizedCommand = (commandName ?? '').toLowerCase();\n\n // TUI-local commands (never sent to backend)\n switch (normalizedCommand) {\n case 'help':\n chatLog.addSystem(helpText(isLocalMode));\n tui.requestRender();\n return;\n case 'exit':\n case 'quit':\n requestExit();\n return;\n case 'abort':\n case 'stop':\n case 'cancel':\n void abortActive().then(() => {\n chatLog.addSystem('Aborted.');\n tui.requestRender();\n });\n return;\n case 'tools':\n state.toolsExpanded = !state.toolsExpanded;\n chatLog.setToolsExpanded(state.toolsExpanded);\n chatLog.addSystem(`Tools: ${state.toolsExpanded ? 'expanded' : 'collapsed'}`);\n tui.requestRender();\n return;\n case 'thinking':\n state.showThinking = !state.showThinking;\n chatLog.addSystem(`Thinking display: ${state.showThinking ? 'on' : 'off'}`);\n updateFooter();\n tui.requestRender();\n return;\n default:\n break;\n }\n\n // Commands that need TUI-side state cleanup before delegating to backend\n switch (normalizedCommand) {\n case 'new':\n case 'reset':\n case 'restart':\n case 'clear': {\n void abortActive().then(() => {\n assembler.clear();\n chatLog.clearAll();\n tui.requestRender();\n // Delegate to backend so session store is actually cleared/reset\n sendMessage(input);\n });\n return;\n }\n default:\n break;\n }\n\n // Everything else is delegated to the backend chat-command system — send the\n // raw slash command so processDirectStreaming's commandRegistry handles it.\n sendMessage(input);\n };\n\n // Editor submit\n editor.onSubmit = (text: string) => {\n const value = text.trim();\n editor.setText('');\n if (!value) return;\n editor.addToHistory(value);\n if (value.startsWith('/')) {\n void handleCommand(value);\n } else {\n void sendMessage(value);\n }\n };\n\n // Keyboard shortcuts\n editor.onEscape = () => void abortActive();\n editor.onCtrlD = () => requestExit();\n editor.onCtrlO = () => {\n state.toolsExpanded = !state.toolsExpanded;\n chatLog.setToolsExpanded(state.toolsExpanded);\n setActivityStatus(state.toolsExpanded ? 'tools expanded' : 'tools collapsed');\n tui.requestRender();\n };\n editor.onCtrlT = () => {\n state.showThinking = !state.showThinking;\n updateFooter();\n tui.requestRender();\n };\n\n const handleCtrlC = () => {\n const now = Date.now();\n const decision = resolveCtrlCAction(\n editor.getText().trim().length > 0,\n now,\n state.lastCtrlCAt,\n );\n state.lastCtrlCAt = decision.nextLastCtrlCAt;\n if (decision.action === 'clear') {\n editor.setText('');\n setActivityStatus('cleared input; press ctrl+c again to exit');\n tui.requestRender();\n } else if (decision.action === 'exit') {\n requestExit();\n } else {\n setActivityStatus('press ctrl+c again to exit');\n tui.requestRender();\n }\n };\n editor.onCtrlC = handleCtrlC;\n\n // Exit\n let finishTui: (() => void) | null = null;\n let exitResult: TuiResult = { exitReason: 'exit' };\n\n const requestExit = () => {\n if (state.exitRequested) return;\n state.exitRequested = true;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n client.stop();\n try {\n tui.stop();\n } catch {\n // Ignore terminal cleanup errors\n }\n restoreStdio();\n finishTui?.();\n };\n\n // Wire backend events\n client.onEvent = (evt: TuiEvent) => {\n const data = (evt.data ?? {}) as Record<string, unknown>;\n dispatchAgentSSE(evt.event, data, state, chatLog, assembler, tui, setActivityStatus);\n };\n\n client.onConnected = () => {\n state.isConnected = true;\n setConnectionStatus(isLocalMode ? 'local ready' : 'gateway connected');\n void (async () => {\n await refreshSessionInfo();\n updateHeader();\n updateFooter();\n tui.requestRender();\n // Auto-send message if provided\n if (!state.autoMessageSent && opts.message) {\n state.autoMessageSent = true;\n sendMessage(opts.message);\n }\n })();\n };\n\n client.onDisconnected = (reason: string) => {\n const wasConnected = state.isConnected;\n state.isConnected = false;\n if (isLocalMode) {\n setConnectionStatus(`local stopped: ${reason}`);\n } else {\n setConnectionStatus(`disconnected: ${reason}`);\n if (!wasConnected && !state.historyLoaded) {\n const gatewayUrl = opts.url ?? 'http://localhost:3120';\n chatLog.addSystem(\n `Cannot reach gateway at ${gatewayUrl}.\\n` +\n 'Make sure the gateway is running (xopc gateway), or use --local for embedded mode.',\n );\n }\n }\n tui.requestRender();\n };\n\n // Signal handlers\n const sigintHandler = () => handleCtrlC();\n const sigtermHandler = () => requestExit();\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n // Boot\n updateHeader();\n setConnectionStatus(isLocalMode ? 'starting local runtime' : 'connecting');\n updateFooter();\n tui.start();\n client.start();\n\n // Wait for exit\n await new Promise<void>((resolve) => {\n finishTui = () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n finishTui = null;\n resolve();\n };\n });\n\n return exitResult;\n}\n"],"mappings":";;;;;;;;;AA2BA,SAAS,iBAAiB,UAAsC;AAC9D,QAAO;EAEL;GAAE,MAAM;GAAQ,aAAa;GAA2B;EACxD;GAAE,MAAM;GAAS,aAAa;GAAsC;EACpE;GAAE,MAAM;GAAS,aAAa;GAAqD;EACnF;GAAE,MAAM;GAAY,aAAa;GAAuC;EACxE;GAAE,MAAM;GAAQ,aAAa;GAAgB;EAE7C;GAAE,MAAM;GAAU,aAAa;GAAyB;EACxD;GAAE,MAAM;GAAU,aAAa;GAA6C;EAC5E;GAAE,MAAM;GAAS,aAAa;GAA+B;EAC7D;GAAE,MAAM;GAAO,aAAa;GAAuB;EACnD;GAAE,MAAM;GAAS,aAAa;GAAyB;EACvD;GAAE,MAAM;GAAQ,aAAa;GAAiB;EAC9C;GAAE,MAAM;GAAW,aAAa;GAA2B;EAC3D;GAAE,MAAM;GAAS,aAAa;GAAyC;EACvE;GAAE,MAAM;GAAa,aAAa;GAAqD;EACvF;GAAE,MAAM;GAAW,aAAa;GAAuB;EACvD;GAAE,MAAM;GAAU,aAAa;GAAqB;EACpD;GAAE,MAAM;GAAU,aAAa;GAAgC;EAC/D;GAAE,MAAM;GAAW,aAAa;GAAuB;EACvD;GAAE,MAAM;GAAO,aAAa;GAA2C;EACvE;GAAE,MAAM;GAAU,aAAa;GAAuC;EACtE;GAAE,MAAM;GAAY,aAAa;GAAyB;EAC1D;GAAE,MAAM;GAAS,aAAa;GAAwB;EACvD;;AAGH,SAAS,SAAS,SAA0B;CAC1C,MAAM,WAAW,iBAAiB,QAAQ;CAC1C,MAAM,QAAQ,CAAC,sBAAsB;AACrC,MAAK,MAAM,KAAK,SACd,OAAM,KAAK,MAAM,EAAE,KAAK,KAAK,EAAE,cAAc;AAE/C,OAAM,KAAK,IAAI,sBAAsB;AACrC,OAAM,KAAK,8BAA8B;AACzC,OAAM,KAAK,gCAAgC;AAC3C,OAAM,KAAK,qCAAqC;AAChD,OAAM,KAAK,gCAAgC;AAC3C,OAAM,KAAK,kBAAkB;AAC7B,QAAO,MAAM,KAAK,KAAK;;AAOzB,SAAS,mBAAmB,UAAmB,KAAa,aAAuE;AACjI,KAAI,SAAU,QAAO;EAAE,QAAQ;EAAS,iBAAiB;EAAK;AAC9D,KAAI,MAAM,eAAe,IAAM,QAAO;EAAE,QAAQ;EAAQ,iBAAiB;EAAa;AACtF,QAAO;EAAE,QAAQ;EAAQ,iBAAiB;EAAK;;AAOjD,MAAM,qCAAqB,IAAI,KAAuB;AAEtD,SAAS,iBACP,OACA,MACA,OACA,SACA,WACA,KACA,mBACM;CACN,MAAM,QAAQ,MAAM,eAAe;AAEnC,SAAQ,OAAR;EACE,KAAK;AAEH,SAAM,cADW,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAE/D,qBAAkB,UAAU;AAC5B;EAEF,KAAK,SAAS;GACZ,MAAM,UACJ,OAAO,KAAK,YAAY,WACpB,KAAK,UACL,OAAO,KAAK,UAAU,WACpB,KAAK,QACL,OAAO,KAAK,SAAS,WACnB,KAAK,OACL;AACV,OAAI,CAAC,QAAS;AACd,qBAAkB,YAAY;GAC9B,MAAM,UAAU,UAAU,YAAY,OAAO,SAAS,MAAM,aAAa;AACzE,OAAI,YAAY,MAAM;AACpB,YAAQ,gBAAgB,SAAS,MAAM;AACvC,QAAI,eAAe;;AAErB;;EAEF,KAAK,YAAY;GACf,MAAM,eAAe,OAAO,KAAK,WAAW,GAAG;GAC/C,MAAM,UAAU,QAAQ,KAAK,MAAM;AACnC,OAAI,KAAK,WAAW,UAAW;AAC/B,qBAAkB,YAAY;GAC9B,MAAM,UAAU,UAAU,eAAe,OAAO,cAAc,SAAS,MAAM,aAAa;AAC1F,OAAI,YAAY,MAAM;AACpB,YAAQ,gBAAgB,SAAS,MAAM;AACvC,QAAI,eAAe;;AAErB;;EAEF,KAAK;EACL,KAAK,cACH;EACF,KAAK,cAAc;GACjB,MAAM,WAAW,OAAO,KAAK,YAAY,UAAU;GACnD,MAAM,aAAa,OAAO,KAAK,cAAc,OAAO,YAAY,CAAC;GAEjE,MAAM,QAAQ,mBAAmB,IAAI,SAAS,IAAI,EAAE;AACpD,SAAM,KAAK,WAAW;AACtB,sBAAmB,IAAI,UAAU,MAAM;AACvC,qBAAkB,UAAU;AAC5B,WAAQ,UAAU,YAAY,UAAU,KAAK,KAAK;AAClD,OAAI,eAAe;AACnB;;EAEF,KAAK,YAAY;GACf,MAAM,WAAW,OAAO,KAAK,YAAY,GAAG;GAE5C,IAAI,aAAa,OAAO,KAAK,eAAe,YAAY,KAAK,aAAa,KAAK,aAAa;AAC5F,OAAI,CAAC,cAAc,UAAU;IAC3B,MAAM,QAAQ,mBAAmB,IAAI,SAAS;AAC9C,QAAI,SAAS,MAAM,SAAS,GAAG;AAC7B,kBAAa,MAAM,OAAO;AAC1B,SAAI,MAAM,WAAW,EAAG,oBAAmB,OAAO,SAAS;;;GAG/D,MAAM,aAAa,OAAO,KAAK,UAAU,GAAG;GAC5C,MAAM,UAAU,QAAQ,KAAK,QAAQ;AACrC,OAAI,WACF,SAAQ,iBAAiB,YAAY,YAAY,QAAQ;AAE3D,qBAAkB,YAAY;AAC9B,OAAI,eAAe;AACnB;;EAEF,KAAK,SAAS;GACZ,MAAM,eAAe,OAAO,KAAK,WAAW,gBAAgB;GAC5D,MAAM,YAAY,UAAU,SAAS,OAAO,MAAM,aAAa;AAC/D,OAAI,UACF,SAAQ,kBAAkB,WAAW,MAAM;AAE7C,WAAQ,UAAU,KAAK,eAAe;AACtC,SAAM,cAAc;AACpB,qBAAkB,OAAO;AACzB,OAAI,eAAe;AACnB;;EAEF,KAAK,UAAU;GACb,MAAM,YAAY,UAAU,SAAS,OAAO,MAAM,aAAa;AAC/D,OAAI,UACF,SAAQ,kBAAkB,WAAW,MAAM;AAE7C,SAAM,cAAc;AACpB,qBAAkB,OAAO;AACzB,OAAI,eAAe;AACnB;;EAEF,KAAK;AACH,qBAAkB,UAAU;AAC5B;EAEF,QACE;;;AAMN,eAAsB,OAAO,MAAsC;CAGjE,MAAM,sBAAsB,QAAQ,OAAO,MAAM,KAAK,QAAQ,OAAO;CACrE,MAAM,sBAAsB,QAAQ,OAAO,MAAM,KAAK,QAAQ,OAAO;CACrE,IAAI,eAAe;CAEnB,MAAM,aACJ,aACgC;AAChC,SAAO,SAAS,cAAc,OAAgB,GAAG,MAA0B;AACzE,OAAI,CAAC,aAAc,QAAQ,SAAsB,OAAO,GAAG,KAAK;AAEhE,QADa,OAAO,UAAU,WAAW,QAAQ,iBAAiB,SAAS,MAAM,UAAU,GAAG,IACrF,WAAW,cAAY,CAAE,QAAO;AACzC,UAAQ,SAAsB,OAAO,GAAG,KAAK;;;AAIjD,SAAQ,OAAO,QAAQ,UAAU,oBAAoB;AACrD,SAAQ,OAAO,QAAQ,UAAU,oBAAoB;CAErD,MAAM,qBAAqB;AACzB,iBAAe;AACf,UAAQ,OAAO,QAAQ;AACvB,UAAQ,OAAO,QAAQ;;CAGzB,MAAM,cAAc,KAAK,UAAU;CAEnC,MAAM,QAAQ,mBADK,KAAK,WAAW,UACS;CAC5C,MAAM,YAAY,IAAI,iBAAiB;CAGvC,MAAM,SAAqB,cACvB,IAAI,iBAAiB,GACrB,IAAI,kBAAkB;EAAE,KAAK,KAAK,OAAO;EAAyB,OAAO,KAAK;EAAO,CAAC;CAG1F,MAAM,MAAM,IAAI,IAAI,IAAI,iBAAiB,CAAC;CAC1C,MAAM,SAAS,IAAI,KAAK,IAAI,GAAG,EAAE;CACjC,MAAM,kBAAkB,IAAI,WAAW;CACvC,MAAM,SAAS,IAAI,KAAK,IAAI,GAAG,EAAE;CACjC,MAAM,UAAU,IAAI,SAAS;CAC7B,MAAM,SAAS,IAAI,aAAa,KAAK,YAAY;CACjD,MAAM,OAAO,IAAI,WAAW;AAC5B,MAAK,SAAS,OAAO;AACrB,MAAK,SAAS,QAAQ;AACtB,MAAK,SAAS,gBAAgB;AAC9B,MAAK,SAAS,OAAO;AACrB,MAAK,SAAS,OAAO;AACrB,KAAI,SAAS,KAAK;AAClB,KAAI,SAAS,OAAO;CAGpB,MAAM,gBAAgB,iBAAiB,YAAY;AACnD,QAAO,wBACL,IAAI,6BACF,cAAc,KAAK,OAAO;EAAE,MAAM,EAAE;EAAM,aAAa,EAAE;EAAa,EAAE,EACxE,QAAQ,KAAK,CACd,CACF;CAGD,IAAI,aAA0B;CAC9B,IAAI,eAA8B;CAClC,IAAI,kBAAiC;CACrC,IAAI,qBAAqB;CACzB,IAAI,iBAAwD;CAC5D,MAAM,aAAa,IAAI,IAAI;EAAC;EAAW;EAAW;EAAa;EAAU,CAAC;CAE1E,MAAM,iBAAiB,YAAoB;EACzC,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,KAAK,GAAG,WAAW,IAAK,CAAC;AAC3E,MAAI,eAAe,GAAI,QAAO,GAAG,aAAa;AAG9C,SAAO,GAFS,KAAK,MAAM,eAAe,GAEzB,CAAC,IADF,eAAe,GACD;;CAGhC,MAAM,qBAAqB;AAEzB,MADe,WAAW,IAAI,MAAM,eAC1B,EAAE;AACV,OAAI,CAAC,mBAAmB,uBAAuB,MAAM,eACnD,mBAAkB,KAAK,KAAK;AAG9B,OAAI,CAAC,cAAc;AACjB,oBAAgB,OAAO;AACvB,iBAAa;AACb,mBAAe,IAAI,OACjB,MACC,YAAY,MAAM,OAAO,QAAQ,GACjC,SAAS,MAAM,KAAK,MAAM,WAAW,KAAK,CAAC,EAC5C,GACD;AACD,oBAAgB,SAAS,aAAa;;GAExC,MAAM,UAAU,cAAc,gBAAgB;AAC9C,gBAAa,WAAW,GAAG,MAAM,eAAe,KAAK,QAAQ,KAAK,MAAM,mBAAmB;AAE3F,OAAI,CAAC,eACH,kBAAiB,kBAAkB;AACjC,QAAI,mBAAmB,cAAc;KACnC,MAAM,KAAK,cAAc,gBAAgB;AACzC,kBAAa,WAAW,GAAG,MAAM,eAAe,KAAK,GAAG,KAAK,MAAM,mBAAmB;;MAEvF,IAAK;SAEL;AACL,qBAAkB;AAClB,OAAI,gBAAgB;AAClB,kBAAc,eAAe;AAC7B,qBAAiB;;AAEnB,iBAAc,MAAM;AACpB,kBAAe;AACf,OAAI,CAAC,YAAY;AACf,oBAAgB,OAAO;AACvB,iBAAa,IAAI,KAAK,IAAI,GAAG,EAAE;AAC/B,oBAAgB,SAAS,WAAW;;GAEtC,MAAM,OAAO,MAAM,iBACf,GAAG,MAAM,iBAAiB,KAAK,MAAM,mBACrC,MAAM;AACV,cAAW,QAAQ,MAAM,IAAI,KAAK,CAAC;;AAErC,uBAAqB,MAAM;;CAG7B,MAAM,qBAAqB,WAAmB;AAC5C,QAAM,iBAAiB;AACvB,gBAAc;;CAGhB,MAAM,uBAAuB,SAAiB;AAC5C,QAAM,mBAAmB;AACzB,gBAAc;;CAGhB,MAAM,qBAAqB;AAEzB,SAAO,QACL,MAAM,OAAO,cAAc,OAAO,gBAAgB,aAAa,MAAM,oBAAoB,CAC1F;;CAGH,MAAM,qBAAqB;EACzB,MAAM,aAAa,MAAM,YAAY,QACjC,MAAM,YAAY,gBAChB,GAAG,MAAM,YAAY,cAAc,GAAG,MAAM,YAAY,UACxD,MAAM,YAAY,QACpB;EACJ,MAAM,SAAS,MAAM,YAAY,eAAe,OAC5C,GAAG,MAAM,YAAY,YAAY,WACjC;EACJ,MAAM,WAAW,MAAM,eAAe,gBAAgB;EACtD,MAAM,QAAQ;GACZ,WAAW,MAAM;GACjB;GACA;GACA;GACD,CAAC,OAAO,QAAQ;AACjB,SAAO,QAAQ,MAAM,IAAI,MAAM,KAAK,MAAM,CAAC,CAAC;;CAI9C,MAAM,qBAAqB,YAAY;AACrC,MAAI;AACF,SAAM,cAAc,MAAM,OAAO,eAAe,MAAM,kBAAkB;AACxE,iBAAc;AACd,OAAI,eAAe;UACb;;CAMV,MAAM,eAAe,SAAiB;AACpC,MAAI,MAAM,aAAa;AACrB,WAAQ,UAAU,yEAAyE;AAC3F,OAAI,eAAe;AACnB;;AAGF,UAAQ,QAAQ,KAAK;AACrB,oBAAkB,UAAU;AAC5B,MAAI,eAAe;AAGd,SACF,SAAS;GACR,YAAY,MAAM;GAClB,SAAS;GACT,UAAU,KAAK;GAChB,CAAC,CACD,OAAO,UAAmB;GACzB,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,WAAQ,UAAU,qBAAqB,eAAe;AACtD,qBAAkB,OAAO;AACzB,OAAI,eAAe;IACnB;;CAIN,MAAM,cAAc,YAAY;AAC9B,MAAI,CAAC,MAAM,YAAa;EACxB,MAAM,QAAQ,MAAM;AACpB,QAAM,cAAc;AACpB,YAAU,KAAK,MAAM;AACrB,UAAQ,cAAc,MAAM;AAC5B,oBAAkB,OAAO;AACzB,MAAI,eAAe;AACnB,QAAM,OAAO,UAAU;GAAE,YAAY,MAAM;GAAmB;GAAO,CAAC,CAAC,YAAY,GAAG;;CAOxF,MAAM,iBAAiB,UAAkB;EAEvC,MAAM,CAAC,eADS,MAAM,QAAQ,OAAO,GAAG,CAAC,MACZ,CAAC,MAAM,MAAM;EAC1C,MAAM,qBAAqB,eAAe,IAAI,aAAa;AAG3D,UAAQ,mBAAR;GACE,KAAK;AACH,YAAQ,UAAU,SAAS,YAAY,CAAC;AACxC,QAAI,eAAe;AACnB;GACF,KAAK;GACL,KAAK;AACH,iBAAa;AACb;GACF,KAAK;GACL,KAAK;GACL,KAAK;AACE,iBAAa,CAAC,WAAW;AAC5B,aAAQ,UAAU,WAAW;AAC7B,SAAI,eAAe;MACnB;AACF;GACF,KAAK;AACH,UAAM,gBAAgB,CAAC,MAAM;AAC7B,YAAQ,iBAAiB,MAAM,cAAc;AAC7C,YAAQ,UAAU,UAAU,MAAM,gBAAgB,aAAa,cAAc;AAC7E,QAAI,eAAe;AACnB;GACF,KAAK;AACH,UAAM,eAAe,CAAC,MAAM;AAC5B,YAAQ,UAAU,qBAAqB,MAAM,eAAe,OAAO,QAAQ;AAC3E,kBAAc;AACd,QAAI,eAAe;AACnB;GACF,QACE;;AAIJ,UAAQ,mBAAR;GACE,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK;AACE,iBAAa,CAAC,WAAW;AAC5B,eAAU,OAAO;AACjB,aAAQ,UAAU;AAClB,SAAI,eAAe;AAEnB,iBAAY,MAAM;MAClB;AACF;GAEF,QACE;;AAKJ,cAAY,MAAM;;AAIpB,QAAO,YAAY,SAAiB;EAClC,MAAM,QAAQ,KAAK,MAAM;AACzB,SAAO,QAAQ,GAAG;AAClB,MAAI,CAAC,MAAO;AACZ,SAAO,aAAa,MAAM;AAC1B,MAAI,MAAM,WAAW,IAAI,CAClB,eAAc,MAAM;MAEpB,aAAY,MAAM;;AAK3B,QAAO,iBAAiB,KAAK,aAAa;AAC1C,QAAO,gBAAgB,aAAa;AACpC,QAAO,gBAAgB;AACrB,QAAM,gBAAgB,CAAC,MAAM;AAC7B,UAAQ,iBAAiB,MAAM,cAAc;AAC7C,oBAAkB,MAAM,gBAAgB,mBAAmB,kBAAkB;AAC7E,MAAI,eAAe;;AAErB,QAAO,gBAAgB;AACrB,QAAM,eAAe,CAAC,MAAM;AAC5B,gBAAc;AACd,MAAI,eAAe;;CAGrB,MAAM,oBAAoB;EACxB,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,WAAW,mBACf,OAAO,SAAS,CAAC,MAAM,CAAC,SAAS,GACjC,KACA,MAAM,YACP;AACD,QAAM,cAAc,SAAS;AAC7B,MAAI,SAAS,WAAW,SAAS;AAC/B,UAAO,QAAQ,GAAG;AAClB,qBAAkB,4CAA4C;AAC9D,OAAI,eAAe;aACV,SAAS,WAAW,OAC7B,cAAa;OACR;AACL,qBAAkB,6BAA6B;AAC/C,OAAI,eAAe;;;AAGvB,QAAO,UAAU;CAGjB,IAAI,YAAiC;CACrC,IAAI,aAAwB,EAAE,YAAY,QAAQ;CAElD,MAAM,oBAAoB;AACxB,MAAI,MAAM,cAAe;AACzB,QAAM,gBAAgB;AACtB,MAAI,gBAAgB;AAClB,iBAAc,eAAe;AAC7B,oBAAiB;;AAEnB,SAAO,MAAM;AACb,MAAI;AACF,OAAI,MAAM;UACJ;AAGR,gBAAc;AACd,eAAa;;AAIf,QAAO,WAAW,QAAkB;EAClC,MAAM,OAAQ,IAAI,QAAQ,EAAE;AAC5B,mBAAiB,IAAI,OAAO,MAAM,OAAO,SAAS,WAAW,KAAK,kBAAkB;;AAGtF,QAAO,oBAAoB;AACzB,QAAM,cAAc;AACpB,sBAAoB,cAAc,gBAAgB,oBAAoB;AACtE,GAAM,YAAY;AAChB,SAAM,oBAAoB;AAC1B,iBAAc;AACd,iBAAc;AACd,OAAI,eAAe;AAEnB,OAAI,CAAC,MAAM,mBAAmB,KAAK,SAAS;AAC1C,UAAM,kBAAkB;AACxB,gBAAY,KAAK,QAAQ;;MAEzB;;AAGN,QAAO,kBAAkB,WAAmB;EAC1C,MAAM,eAAe,MAAM;AAC3B,QAAM,cAAc;AACpB,MAAI,YACF,qBAAoB,kBAAkB,SAAS;OAC1C;AACL,uBAAoB,iBAAiB,SAAS;AAC9C,OAAI,CAAC,gBAAgB,CAAC,MAAM,eAAe;IACzC,MAAM,aAAa,KAAK,OAAO;AAC/B,YAAQ,UACN,2BAA2B,WAAW,uFAEvC;;;AAGL,MAAI,eAAe;;CAIrB,MAAM,sBAAsB,aAAa;CACzC,MAAM,uBAAuB,aAAa;AAC1C,SAAQ,GAAG,UAAU,cAAc;AACnC,SAAQ,GAAG,WAAW,eAAe;AAGrC,eAAc;AACd,qBAAoB,cAAc,2BAA2B,aAAa;AAC1E,eAAc;AACd,KAAI,OAAO;AACX,QAAO,OAAO;AAGd,OAAM,IAAI,SAAe,YAAY;AACnC,oBAAkB;AAChB,WAAQ,eAAe,UAAU,cAAc;AAC/C,WAAQ,eAAe,WAAW,eAAe;AACjD,eAAY;AACZ,YAAS;;GAEX;AAEF,QAAO"}
|
|
1
|
+
{"version":3,"file":"tui.js","names":[],"sources":["../../../src/tui/tui.ts"],"sourcesContent":["import {\n CombinedAutocompleteProvider,\n Container,\n getKeybindings,\n isKeyRelease,\n Key,\n Loader,\n matchesKey,\n parseKey,\n ProcessTerminal,\n Text,\n TUI,\n} from '@mariozechner/pi-tui';\n\nimport type { TuiBackend, TuiEvent } from './tui-backend.js';\nimport { EmbeddedBackend } from './backends/embedded-backend.js';\nimport { GatewaySseBackend } from './backends/gateway-sse-backend.js';\nimport {\n clearPendingToolCallIds,\n DEFAULT_STREAMING_WATCHDOG_MS,\n dispatchAgentSSE,\n} from './tui-agent-events.js';\nimport { ChatLog } from './components/chat-log.js';\nimport { CustomEditor } from './components/custom-editor.js';\nimport { StreamAssembler } from './stream-assembler.js';\nimport { createTuiCommandHandler, getSlashCommands } from './tui-commands.js';\nimport { createLocalShellRunner } from './tui-local-shell.js';\nimport {\n createBackspaceDeduper,\n drainAndStopTuiSafely,\n resolveCtrlCAction,\n} from './tui-lifecycle.js';\nimport { openModelPickerOverlay, openSessionPickerOverlay } from './tui-picker-overlay.js';\nimport { createOverlayHandlers } from './tui-overlays.js';\nimport {\n createEditorSubmitHandler,\n createSubmitBurstCoalescer,\n shouldEnableWindowsGitBashPasteFallback,\n} from './tui-submit.js';\nimport { appendHistoryToChatLog } from './chat-history.js';\nimport { installTuiStdioFilter } from './tui-stdio-filter.js';\nimport { withTuiSuspended } from './tui-suspend.js';\nimport { editorTheme, theme } from './theme.js';\nimport { createInitialState, type TuiOptions, type TuiResult, type TuiState } from './tui-types.js';\n\nexport type { TuiOptions, TuiResult };\n\nexport {\n createBackspaceDeduper,\n drainAndStopTuiSafely,\n type DrainableTui,\n isIgnorableTuiStopError,\n resolveCtrlCAction,\n stopTuiSafely,\n} from './tui-lifecycle.js';\n\nexport { withTuiSuspended } from './tui-suspend.js';\n\nfunction matchesCtrlCSequence(data: string): boolean {\n if (isKeyRelease(data)) return false;\n if (data === '\\x03') return true;\n if (parseKey(data) === 'ctrl+c') return true;\n const kb = getKeybindings();\n return matchesKey(data, Key.ctrl('c')) || kb.matches(data, 'tui.input.copy');\n}\n\nexport async function runTui(opts: TuiOptions): Promise<TuiResult> {\n const stdioFilter = installTuiStdioFilter();\n const restoreStdio = () => stdioFilter.restore();\n\n const isLocalMode = opts.local === true;\n const sessionKey = opts.session ?? 'cli:tui';\n const state = createInitialState(sessionKey);\n const assembler = new StreamAssembler();\n\n const client: TuiBackend = isLocalMode\n ? new EmbeddedBackend()\n : new GatewaySseBackend({ url: opts.url ?? 'http://localhost:3120', token: opts.token });\n\n const tui = new TUI(new ProcessTerminal());\n const dedupeBackspace = createBackspaceDeduper();\n tui.addInputListener((data) => {\n const next = dedupeBackspace(data);\n if (next.length === 0) {\n return { consume: true };\n }\n return { data: next };\n });\n\n const header = new Text('', 1, 0);\n const statusContainer = new Container();\n const footer = new Text('', 1, 0);\n const chatLog = new ChatLog();\n const editor = new CustomEditor(tui, editorTheme);\n const root = new Container();\n root.addChild(header);\n root.addChild(chatLog);\n root.addChild(statusContainer);\n root.addChild(footer);\n root.addChild(editor);\n tui.addChild(root);\n tui.setFocus(editor);\n\n const { openOverlay, closeOverlay } = createOverlayHandlers(tui, editor);\n\n const slashCommands = getSlashCommands(isLocalMode);\n editor.setAutocompleteProvider(\n new CombinedAutocompleteProvider(\n slashCommands.map((c) => ({ name: c.name, description: c.description })),\n process.cwd(),\n ),\n );\n\n let statusText: Text | null = null;\n let statusLoader: Loader | null = null;\n let statusStartedAt: number | null = null;\n let lastActivityStatus = '';\n let elapsedTimerId: ReturnType<typeof setInterval> | null = null;\n const busyStates = new Set(['sending', 'waiting', 'streaming', 'running']);\n\n let lastStreamActivityAt = Date.now();\n let streamWatchdogId: ReturnType<typeof setInterval> | null = null;\n\n const touchStreamingActivity = () => {\n lastStreamActivityAt = Date.now();\n };\n\n const formatElapsed = (startMs: number) => {\n const totalSeconds = Math.max(0, Math.floor((Date.now() - startMs) / 1000));\n if (totalSeconds < 60) return `${totalSeconds}s`;\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}m ${seconds}s`;\n };\n\n const renderStatus = () => {\n const isBusy = busyStates.has(state.activityStatus);\n if (isBusy) {\n if (!statusStartedAt || lastActivityStatus !== state.activityStatus) {\n statusStartedAt = Date.now();\n }\n if (!statusLoader) {\n statusContainer.clear();\n statusText = null;\n statusLoader = new Loader(\n tui,\n (spinner) => theme.accent(spinner),\n (text) => theme.bold(theme.accentSoft(text)),\n '',\n );\n statusContainer.addChild(statusLoader);\n }\n const elapsed = formatElapsed(statusStartedAt);\n statusLoader.setMessage(`${state.activityStatus} • ${elapsed} | ${state.connectionStatus}`);\n if (!elapsedTimerId) {\n elapsedTimerId = setInterval(() => {\n if (statusStartedAt && statusLoader) {\n const el = formatElapsed(statusStartedAt);\n statusLoader.setMessage(`${state.activityStatus} • ${el} | ${state.connectionStatus}`);\n }\n }, 1000);\n }\n } else {\n statusStartedAt = null;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n statusLoader?.stop();\n statusLoader = null;\n if (!statusText) {\n statusContainer.clear();\n statusText = new Text('', 1, 0);\n statusContainer.addChild(statusText);\n }\n const text = state.activityStatus\n ? `${state.connectionStatus} | ${state.activityStatus}`\n : state.connectionStatus;\n statusText.setText(theme.dim(text));\n }\n lastActivityStatus = state.activityStatus;\n };\n\n const setActivityStatus = (status: string) => {\n state.activityStatus = status as TuiState['activityStatus'];\n renderStatus();\n };\n\n const setConnectionStatus = (text: string) => {\n state.connectionStatus = text;\n renderStatus();\n };\n\n const updateHeader = () => {\n const title = 'xopc tui';\n header.setText(\n theme.header(`${title} — ${client.connectionLabel} — session ${state.currentSessionKey}`),\n );\n };\n\n const updateFooter = () => {\n const modelLabel = state.sessionInfo.model\n ? state.sessionInfo.modelProvider\n ? `${state.sessionInfo.modelProvider}/${state.sessionInfo.model}`\n : state.sessionInfo.model\n : 'unknown';\n const tokens =\n state.sessionInfo.totalTokens != null ? `${state.sessionInfo.totalTokens} tokens` : '';\n const thinking = state.showThinking ? 'thinking:on' : '';\n const parts = [`session ${state.currentSessionKey}`, modelLabel, thinking, tokens].filter(\n Boolean,\n );\n footer.setText(theme.dim(parts.join(' | ')));\n };\n\n const refreshSessionInfo = async () => {\n try {\n state.sessionInfo = await client.getSessionInfo(state.currentSessionKey);\n updateFooter();\n tui.requestRender();\n } catch {\n // ignore\n }\n };\n\n let finishTui: (() => void) | null = null;\n let exitResult: TuiResult = { exitReason: 'exit' };\n\n const requestExit = () => {\n if (state.exitRequested) return;\n state.exitRequested = true;\n if (elapsedTimerId) {\n clearInterval(elapsedTimerId);\n elapsedTimerId = null;\n }\n if (streamWatchdogId) {\n clearInterval(streamWatchdogId);\n streamWatchdogId = null;\n }\n client.stop();\n void drainAndStopTuiSafely(tui).then(() => {\n restoreStdio();\n finishTui?.();\n });\n };\n\n const abortActive = async () => {\n if (!state.activeRunId) return;\n const runId = state.activeRunId;\n state.activeRunId = null;\n assembler.drop(runId);\n chatLog.dropAssistant(runId);\n setActivityStatus('idle');\n tui.requestRender();\n await client.abortChat({ sessionKey: state.currentSessionKey, runId }).catch(() => {});\n };\n\n const sendMessage = (text: string) => {\n if (state.activeRunId) {\n chatLog.addSystem('A response is still in progress. Use /abort or press Escape to cancel.');\n tui.requestRender();\n return;\n }\n\n chatLog.addUser(text);\n setActivityStatus('sending');\n touchStreamingActivity();\n tui.requestRender();\n\n void client\n .sendChat({\n sessionKey: state.currentSessionKey,\n message: text,\n thinking: opts.thinking,\n })\n .catch((error: unknown) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n chatLog.addSystem(`❌ Failed to send: ${errorMessage}`);\n setActivityStatus('idle');\n tui.requestRender();\n });\n };\n\n const handleCommand = createTuiCommandHandler({\n state,\n chatLog,\n tui,\n assembler,\n isLocalMode,\n abortActive,\n sendMessage,\n requestExit,\n updateFooter,\n });\n\n const { runLocalShellLine } = createLocalShellRunner({\n chatLog,\n tui,\n editor,\n openOverlay,\n closeOverlay,\n pauseStdioFilter: () => stdioFilter.pause(),\n resumeStdioFilter: () => stdioFilter.resume(),\n runWithInheritedStdio: async (work) => {\n await withTuiSuspended(tui, work);\n },\n });\n\n const submitCore = createEditorSubmitHandler({\n editor,\n handleCommand,\n sendMessage,\n handleBangLine: runLocalShellLine,\n });\n\n editor.onSubmit = createSubmitBurstCoalescer({\n submit: submitCore,\n enabled: shouldEnableWindowsGitBashPasteFallback(),\n });\n\n const setSessionKey = (key: string) => {\n state.currentSessionKey = key;\n };\n\n const clearChatForSessionSwitch = () => {\n assembler.clear();\n chatLog.clearAll();\n clearPendingToolCallIds();\n state.historyLoaded = false;\n };\n\n const loadSessionHistory = async () => {\n try {\n const { messages } = await client.loadHistory({\n sessionKey: state.currentSessionKey,\n limit: 200,\n });\n appendHistoryToChatLog(chatLog, messages, state.toolsExpanded);\n } catch {\n // ignore; footer already hints on disconnect\n } finally {\n state.historyLoaded = true;\n tui.requestRender();\n }\n };\n\n const pickerSvc = {\n tui,\n editor,\n openOverlay,\n closeOverlay,\n chatLog,\n client,\n sendMessage,\n refreshSessionInfo,\n updateHeader,\n state,\n setSessionKey,\n clearChatForSessionSwitch,\n loadSessionHistory,\n };\n\n editor.onEscape = () => void abortActive();\n editor.onCtrlD = () => requestExit();\n editor.onCtrlL = () => void openModelPickerOverlay(pickerSvc);\n editor.onCtrlP = () => void openSessionPickerOverlay(pickerSvc);\n editor.onCtrlO = () => {\n state.toolsExpanded = !state.toolsExpanded;\n chatLog.setToolsExpanded(state.toolsExpanded);\n setActivityStatus(state.toolsExpanded ? 'tools expanded' : 'tools collapsed');\n tui.requestRender();\n };\n editor.onCtrlT = () => {\n state.showThinking = !state.showThinking;\n updateFooter();\n tui.requestRender();\n };\n\n const handleCtrlC = () => {\n const now = Date.now();\n const decision = resolveCtrlCAction({\n hasInput: editor.getText().trim().length > 0,\n now,\n lastCtrlCAt: state.lastCtrlCAt,\n });\n state.lastCtrlCAt = decision.nextLastCtrlCAt;\n if (decision.action === 'clear') {\n editor.setText('');\n setActivityStatus('cleared input; press ctrl+c again to exit');\n tui.requestRender();\n return;\n }\n if (decision.action === 'exit') {\n requestExit();\n return;\n }\n setActivityStatus('press ctrl+c again to exit');\n tui.requestRender();\n };\n editor.onCtrlC = handleCtrlC;\n\n tui.addInputListener((data) => {\n if (!matchesCtrlCSequence(data)) return undefined;\n handleCtrlC();\n return { consume: true };\n });\n\n streamWatchdogId = setInterval(() => {\n if (!state.activeRunId) return;\n if (!busyStates.has(state.activityStatus)) return;\n if (Date.now() - lastStreamActivityAt < DEFAULT_STREAMING_WATCHDOG_MS) return;\n\n const rid = state.activeRunId;\n const finalText = assembler.finalize(rid, state.showThinking);\n if (finalText) {\n chatLog.finalizeAssistant(finalText, rid);\n }\n chatLog.addSystem(\n '⚠️ No stream activity for 30s; UI reset (connection may have stalled). Retry or check gateway.',\n );\n state.activeRunId = null;\n setActivityStatus('idle');\n tui.requestRender();\n }, 5000);\n\n client.onEvent = (evt: TuiEvent) => {\n const data = (evt.data ?? {}) as Record<string, unknown>;\n dispatchAgentSSE(evt.event, data, state, chatLog, assembler, tui, setActivityStatus, touchStreamingActivity);\n };\n\n client.onConnected = () => {\n state.isConnected = true;\n setConnectionStatus(isLocalMode ? 'local ready' : 'gateway connected');\n touchStreamingActivity();\n void (async () => {\n await refreshSessionInfo();\n await loadSessionHistory();\n updateHeader();\n updateFooter();\n tui.requestRender();\n if (!state.autoMessageSent && opts.message) {\n state.autoMessageSent = true;\n sendMessage(opts.message);\n }\n })();\n };\n\n client.onDisconnected = (reason: string) => {\n const wasConnected = state.isConnected;\n state.isConnected = false;\n touchStreamingActivity();\n if (isLocalMode) {\n setConnectionStatus(`local stopped: ${reason}`);\n } else {\n const hint =\n wasConnected || state.historyLoaded\n ? ` (${reason}). Reconnecting broadcast stream…`\n : `. Ensure gateway is running (xopc gateway) or use --local.`;\n setConnectionStatus(`disconnected${hint}`);\n if (!wasConnected && !state.historyLoaded) {\n const gatewayUrl = opts.url ?? 'http://localhost:3120';\n chatLog.addSystem(\n `Cannot reach gateway at ${gatewayUrl}.\\n` +\n 'Start the gateway (`xopc gateway`) or run `xopc tui --local` for embedded mode.',\n );\n }\n }\n tui.requestRender();\n };\n\n client.onGap = (info) => {\n chatLog.addSystem(\n `⚠️ Event gap: expected ${info.expected}, received ${info.received}. Some updates may be missing.`,\n );\n setConnectionStatus(`event gap: expected ${info.expected}, got ${info.received}`);\n tui.requestRender();\n };\n\n const sigintHandler = () => handleCtrlC();\n const sigtermHandler = () => requestExit();\n process.on('SIGINT', sigintHandler);\n process.on('SIGTERM', sigtermHandler);\n\n updateHeader();\n setConnectionStatus(isLocalMode ? 'starting local runtime' : 'connecting');\n updateFooter();\n tui.start();\n client.start();\n\n await new Promise<void>((resolve) => {\n finishTui = () => {\n process.removeListener('SIGINT', sigintHandler);\n process.removeListener('SIGTERM', sigtermHandler);\n if (streamWatchdogId) {\n clearInterval(streamWatchdogId);\n streamWatchdogId = null;\n }\n finishTui = null;\n resolve();\n };\n });\n\n return exitResult;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xopcai/xopc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.29",
|
|
4
4
|
"description": "Personal AI assistant: CLI, gateway (HTTP/WebSocket + React console), Telegram and WeChat (Weixin) channels — TypeScript, 20+ LLM providers via pi-ai, extensions and skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -129,10 +129,6 @@
|
|
|
129
129
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
130
130
|
"build:web": "pnpm -C web run build",
|
|
131
131
|
"dev:web": "pnpm -C web run dev",
|
|
132
|
-
"dev:mobile": "pnpm -C mobile run start",
|
|
133
|
-
"mobile:lint": "pnpm -C mobile run lint",
|
|
134
|
-
"mobile:typecheck": "pnpm -C mobile run typecheck",
|
|
135
|
-
"test:gateway-sse-client": "vitest run packages/gateway-sse-client",
|
|
136
132
|
"dev": "tsx src/cli/index.ts",
|
|
137
133
|
"start": "node dist/src/cli/index.js",
|
|
138
134
|
"test": "vitest run src extensions/telegram/src extensions/feishu/src",
|
|
@@ -142,7 +138,7 @@
|
|
|
142
138
|
"skills:test": "tsx src/cli/index.ts skills test",
|
|
143
139
|
"skills:validate": "tsx src/cli/index.ts skills test validate",
|
|
144
140
|
"skills:security": "tsx src/cli/index.ts skills test security",
|
|
145
|
-
"lint": "eslint && pnpm -C web run lint
|
|
141
|
+
"lint": "eslint && pnpm -C web run lint",
|
|
146
142
|
"docs:dev": "vitepress dev docs",
|
|
147
143
|
"docs:build": "vitepress build docs",
|
|
148
144
|
"docs:preview": "vitepress preview docs",
|