xibecode 0.3.8 → 0.4.4

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.
Files changed (38) hide show
  1. package/README.md +282 -26
  2. package/dist/commands/chat.d.ts +1 -0
  3. package/dist/commands/chat.d.ts.map +1 -1
  4. package/dist/commands/chat.js +106 -8
  5. package/dist/commands/chat.js.map +1 -1
  6. package/dist/core/modes.d.ts +1 -1
  7. package/dist/core/modes.d.ts.map +1 -1
  8. package/dist/core/modes.js +7 -8
  9. package/dist/core/modes.js.map +1 -1
  10. package/dist/core/session-bridge.d.ts +105 -0
  11. package/dist/core/session-bridge.d.ts.map +1 -0
  12. package/dist/core/session-bridge.js +243 -0
  13. package/dist/core/session-bridge.js.map +1 -0
  14. package/dist/core/tools.d.ts +4 -0
  15. package/dist/core/tools.d.ts.map +1 -1
  16. package/dist/core/tools.js +171 -0
  17. package/dist/core/tools.js.map +1 -1
  18. package/dist/index.js +42 -35
  19. package/dist/index.js.map +1 -1
  20. package/dist/tools/test-generator.d.ts +157 -0
  21. package/dist/tools/test-generator.d.ts.map +1 -0
  22. package/dist/tools/test-generator.js +893 -0
  23. package/dist/tools/test-generator.js.map +1 -0
  24. package/dist/webui/server.d.ts +96 -0
  25. package/dist/webui/server.d.ts.map +1 -0
  26. package/dist/webui/server.js +2304 -0
  27. package/dist/webui/server.js.map +1 -0
  28. package/package.json +16 -6
  29. package/webui-dist/assets/index-BXqucsdn.js +353 -0
  30. package/webui-dist/assets/index-BXqucsdn.js.map +1 -0
  31. package/webui-dist/assets/index-D1NjcKN3.css +32 -0
  32. package/webui-dist/assets/xterm-BjznWQZK.js +10 -0
  33. package/webui-dist/assets/xterm-BjznWQZK.js.map +1 -0
  34. package/webui-dist/assets/xterm-addon-fit-CPOtr3CW.js +2 -0
  35. package/webui-dist/assets/xterm-addon-fit-CPOtr3CW.js.map +1 -0
  36. package/webui-dist/assets/xterm-addon-web-links-z5RYd3SS.js +2 -0
  37. package/webui-dist/assets/xterm-addon-web-links-z5RYd3SS.js.map +1 -0
  38. package/webui-dist/index.html +15 -0
package/README.md CHANGED
@@ -1,12 +1,27 @@
1
1
  # XibeCode
2
2
 
3
- AI-powered autonomous coding assistant for your terminal.
3
+ AI-powered autonomous coding assistant for your terminal and browser.
4
4
 
5
5
  [![Donate](https://img.shields.io/badge/Donate-Support%20XibeCode-ff69b4?style=for-the-badge)](https://www.anishkumar.tech/donate)
6
+ [![Version](https://img.shields.io/npm/v/xibecode?style=for-the-badge)](https://www.npmjs.com/package/xibecode)
6
7
 
7
8
  ## Overview
8
9
 
9
- XibeCode is a CLI agent that can read and edit code, run commands, and iterate on tasks from your terminal using LLMs.
10
+ XibeCode is a CLI agent that can read and edit code, run commands, and iterate on tasks from your terminal using LLMs. It now includes a **WebUI** for a browser-based experience, **AI-powered test generation**, and **multi-model support** for both Anthropic and OpenAI models.
11
+
12
+ ## What's New in v0.4.4
13
+
14
+ - **v0.dev-inspired UI** - Modern split-panel layout with resizable chat and code areas
15
+ - **Multi-Terminal Support** - Create/manage multiple terminal tabs with + and X buttons
16
+ - **Monaco Code Editor** - Full syntax highlighting and IntelliSense in the browser
17
+ - **Settings Modal** - Configure AI provider, display, dev settings, and MCP servers
18
+ - **MCP JSON Editor** - Edit mcp-servers.json directly with Monaco syntax highlighting
19
+ - **Git History Graph** - Visual commit timeline with branch/tag indicators
20
+ - **Custom Model Support** - Add any model (Claude, GPT, DeepSeek, etc.) via WebUI or CLI
21
+ - **Real PTY Terminal** - Fully interactive shell with colors, tab-completion, and all terminal features
22
+ - **File Tree Explorer** - Browse and open files with recursive directory tree
23
+ - **Current Model Display** - Status bar shows active AI model
24
+ - **Drag-to-Resize Panels** - Adjustable chat/code split layout
10
25
 
11
26
  ## Installation
12
27
 
@@ -19,15 +34,15 @@ From source:
19
34
  ```bash
20
35
  git clone https://github.com/iotserver24/xibecode
21
36
  cd xibecode
22
- npm install
23
- npm run build
37
+ pnpm install
38
+ pnpm run build
24
39
  npm link
25
40
  ```
26
41
 
27
42
  ## Requirements
28
43
 
29
44
  - Node.js 18+
30
- - Anthropic API key (or compatible provider/base URL)
45
+ - API key from Anthropic or OpenAI
31
46
 
32
47
  ## Quick Start
33
48
 
@@ -35,20 +50,53 @@ npm link
35
50
  # Configure once
36
51
  xibecode config --set-key YOUR_API_KEY
37
52
 
38
- # Interactive mode
53
+ # Interactive terminal mode
39
54
  xibecode chat
40
55
 
56
+ # Open WebUI in browser (recommended for beginners)
57
+ xibecode ui --open
58
+
41
59
  # Autonomous run
42
60
  xibecode run "Create an Express API with auth"
43
61
  ```
44
62
 
45
63
  ## Main Commands
46
64
 
65
+ ### `xibecode ui`
66
+ **NEW** - Start the WebUI in your browser.
67
+
68
+ ```bash
69
+ xibecode ui # Start on localhost:3847
70
+ xibecode ui --open # Auto-open browser
71
+ xibecode ui -p 8080 # Custom port
72
+ ```
73
+
74
+ Features:
75
+ - **v0.dev-style Layout** - Activity bar (left) → Chat panel (resizable) → Code editor (right)
76
+ - **Monaco Code Editor** - Professional code editor with syntax highlighting and IntelliSense
77
+ - **File Tree Explorer** - Browse and open project files with recursive directory tree
78
+ - **Multi-Terminal Tabs** - Create/manage multiple shell sessions with + and X buttons
79
+ - **Real PTY Terminal** - Fully interactive bash/zsh with colors, tab-completion, vim/nano support
80
+ - **Git Integration** - Commit history graph, stage/unstage files, view diffs, write commits
81
+ - **Settings Modal** - Configure AI provider, display preferences, dev tools, and MCP servers
82
+ - **MCP JSON Editor** - Edit mcp-servers.json directly with Monaco syntax highlighting
83
+ - **Custom Models** - Add any AI model (Claude, GPT-4, DeepSeek, Llama) via dropdown + text input
84
+ - **Real-time Chat** - Streaming AI responses with markdown rendering
85
+ - **Status Bar** - Connection status, current mode, active AI model, cursor position
86
+ - **Resizable Panels** - Drag the divider between chat and code areas to adjust layout
87
+ - **Slash Commands** - Type `/` for commands and mode switching, `@` for file references
88
+ - **New Chat Button** - Clear conversation with + button in chat input
89
+
47
90
  ### `xibecode run`
48
91
  Autonomous coding workflow.
49
92
 
50
- Useful options:
93
+ ```bash
94
+ xibecode run "Build a REST API with Express"
95
+ xibecode run "Fix the TypeScript errors" --verbose
96
+ xibecode run --file task.txt
97
+ ```
51
98
 
99
+ Options:
52
100
  - `-f, --file <path>` prompt from file
53
101
  - `-m, --model <model>` model override
54
102
  - `--mode <mode>` initial agent mode
@@ -61,10 +109,9 @@ Useful options:
61
109
  - `--changed-only`
62
110
 
63
111
  ### `xibecode chat`
64
- Interactive chat + tool use.
65
-
66
- Useful options:
112
+ Interactive terminal chat + tool use.
67
113
 
114
+ Options:
68
115
  - `-m, --model <model>`
69
116
  - `-b, --base-url <url>`
70
117
  - `-k, --api-key <key>`
@@ -87,31 +134,161 @@ MCP server management:
87
134
 
88
135
  ## Core Features
89
136
 
90
- - Autonomous multi-step agent loop
91
- - Smart context gathering across related files
92
- - Verified and line-based editing workflows
93
- - Dry-run mode for safe previews
94
- - Git-aware workflows (`--changed-only`, checkpoints/reverts)
95
- - Test runner integration support
96
- - MCP server integration
97
- - Skill system (built-in + custom markdown skills)
98
- - Session-aware chat and themed terminal UI
137
+ - **Autonomous multi-step agent loop** - Completes complex tasks automatically
138
+ - **Smart context gathering** - Understands related files and imports
139
+ - **Verified and line-based editing** - Reliable code modifications
140
+ - **Dry-run mode** - Preview changes safely before applying
141
+ - **Git-aware workflows** - `--changed-only`, checkpoints, and reverts
142
+ - **Test runner integration** - Auto-detects Vitest, Jest, pytest, Go test
143
+ - **MCP server integration** - Extend capabilities with external tools
144
+ - **Skill system** - Built-in + custom markdown skills
145
+ - **Session-aware chat** - Persistent conversation history
146
+ - **Themed terminal UI** - Beautiful, customizable interface
147
+
148
+ ## WebUI
149
+
150
+ The WebUI provides a browser-based interface that syncs in real-time with the terminal.
151
+
152
+ ```bash
153
+ # Start with both TUI and WebUI
154
+ xibecode chat
155
+
156
+ # WebUI opens automatically at http://localhost:3847
157
+ ```
158
+
159
+ ### TUI-WebUI Sync
160
+
161
+ When you run `xibecode chat`, both interfaces are connected:
162
+ - Messages sent from **TUI** appear in **WebUI** (marked with "TUI")
163
+ - Messages sent from **WebUI** are processed by **TUI**
164
+ - Streaming responses show in both simultaneously
165
+ - Tool executions display in real-time
166
+
167
+ ### Slash Commands (`/`)
168
+
169
+ Type `/` in the input to open the command palette:
170
+
171
+ **Commands:**
172
+
173
+ | Command | Description |
174
+ |---------|-------------|
175
+ | `/clear` | Clear chat messages |
176
+ | `/help` | Show available commands |
177
+ | `/diff` | Show git diff |
178
+ | `/status` | Show git status |
179
+ | `/test` | Run project tests |
180
+ | `/format` | Format code in project |
181
+ | `/reset` | Reset chat session |
182
+ | `/files` | List project files |
183
+
184
+ **Modes:**
185
+
186
+ | Mode | Icon | Description |
187
+ |------|------|-------------|
188
+ | `/mode agent` | 🤖 | Autonomous coding (default) |
189
+ | `/mode plan` | 📋 | Analyze without modifying |
190
+ | `/mode tester` | 🧪 | Testing and QA |
191
+ | `/mode debugger` | 🐛 | Bug investigation |
192
+ | `/mode security` | 🔒 | Security analysis |
193
+ | `/mode review` | 👀 | Code review |
194
+ | `/mode team_leader` | 👑 | Coordinate team |
195
+ | `/mode architect` | 🏛️ | System design |
196
+ | `/mode engineer` | 🛠️ | Implementation |
197
+ | `/mode seo` | 🌐 | SEO optimization |
198
+ | `/mode product` | 🔥 | Product strategy |
199
+ | `/mode data` | 📊 | Data analysis |
200
+ | `/mode researcher` | 📚 | Deep research |
201
+
202
+ ### File References (`@`)
203
+
204
+ Type `@` to browse and reference files:
205
+ - Shows project files and folders
206
+ - Filter by typing after `@`
207
+ - Select to include file path in message
208
+ - Helps AI understand which files to work with
209
+
210
+ ### Settings Panel
211
+
212
+ Click the ⚙️ Settings button to configure:
213
+ - **Provider** - Anthropic, OpenAI, or Custom
214
+ - **Model** - Select from available models
215
+ - **Custom Model ID** - For custom/local models
216
+ - **API Key** - Your provider API key
217
+ - **Base URL** - Custom API endpoint (for local LLMs)
218
+ - **Session Info** - Working directory, git branch
219
+
220
+ ### Features
221
+
222
+ - **Markdown Rendering** - Code blocks, bold, italic, lists, links
223
+ - **Tool Execution** - Shows each tool call with status (running/done/failed)
224
+ - **Thinking Indicator** - Spinner while AI is processing
225
+ - **Responsive Design** - Works on mobile and desktop
226
+ - **Real-time Streaming** - See responses as they're generated
227
+
228
+ ## AI Test Generation
229
+
230
+ XibeCode can automatically generate comprehensive test suites for your code:
231
+
232
+ ```bash
233
+ # Via CLI (in chat mode)
234
+ > generate tests for src/utils/helpers.ts
235
+
236
+ # Via WebUI
237
+ 1. Go to "Test Generator" tab
238
+ 2. Enter file path
239
+ 3. Select framework (auto-detected)
240
+ 4. Click "Generate Tests"
241
+ ```
242
+
243
+ ### Features
244
+
245
+ - **Multi-framework support** - Vitest, Jest, Mocha, pytest, Go test
246
+ - **Code analysis** - Understands functions, classes, types
247
+ - **Edge case generation** - Null checks, empty strings, boundaries
248
+ - **Mock setup** - Automatic mock configuration
249
+ - **Type checking tests** - Verifies return types
250
+ - **Error handling tests** - Tests for exceptions
251
+
252
+ ### Example Output
253
+
254
+ ```typescript
255
+ import { describe, it, expect, vi } from 'vitest';
256
+ import { calculateTotal } from '../utils/helpers';
257
+
258
+ describe('calculateTotal', () => {
259
+ it('should execute calculateTotal successfully', () => {
260
+ expect(calculateTotal([])).toBeDefined();
261
+ });
262
+
263
+ it('should return correct type from calculateTotal', () => {
264
+ expect(typeof calculateTotal([])).toBe('number');
265
+ });
266
+
267
+ it('should handle empty array', () => {
268
+ expect(calculateTotal([])).toBe(0);
269
+ });
270
+
271
+ it('should handle errors in calculateTotal', () => {
272
+ expect(() => calculateTotal(undefined)).toThrow();
273
+ });
274
+ });
275
+ ```
99
276
 
100
277
  ## Browser Testing (Playwright)
101
278
 
102
- XibeCode includes comprehensive browser automation and testing capabilities powered by Playwright:
279
+ XibeCode includes comprehensive browser automation and testing capabilities:
103
280
 
104
281
  - **Screenshots** - Capture webpage screenshots
105
- - **Console Logs** - Collect browser console output for debugging
106
- - **Visual Regression** - Compare screenshots against baselines to detect UI changes
107
- - **Accessibility Audits** - Check WCAG compliance (alt text, labels, heading hierarchy)
282
+ - **Console Logs** - Collect browser console output
283
+ - **Visual Regression** - Compare screenshots against baselines
284
+ - **Accessibility Audits** - Check WCAG compliance
108
285
  - **Performance Metrics** - Measure Core Web Vitals (FCP, LCP, CLS, TTI)
109
- - **Responsive Testing** - Test across multiple viewports (mobile, tablet, desktop)
110
- - **Network Monitoring** - Capture all network requests during page load
286
+ - **Responsive Testing** - Test across multiple viewports
287
+ - **Network Monitoring** - Capture all network requests
111
288
  - **E2E Tests** - Execute Playwright test files
112
289
 
113
290
  ```bash
114
- # Example: Test a page's performance
291
+ # Example: Test performance
115
292
  xibecode run "Measure the performance of http://localhost:3000"
116
293
 
117
294
  # Example: Check accessibility
@@ -121,12 +298,91 @@ xibecode run "Run an accessibility audit on the homepage"
121
298
  xibecode run "Take a screenshot and compare against baseline"
122
299
  ```
123
300
 
301
+ ## Configuration
302
+
303
+ ### Environment Variables
304
+
305
+ ```bash
306
+ ANTHROPIC_API_KEY=sk-ant-... # Anthropic API key
307
+ OPENAI_API_KEY=sk-... # OpenAI API key
308
+ XIBECODE_MODEL=claude-sonnet-4-5-20250929 # Default model
309
+ ```
310
+
311
+ ### Config File
312
+
313
+ Located at `~/.xibecode/config.json`:
314
+
315
+ ```json
316
+ {
317
+ "apiKey": "sk-ant-...",
318
+ "model": "claude-sonnet-4-5-20250929",
319
+ "provider": "anthropic",
320
+ "maxIterations": 50,
321
+ "theme": "default"
322
+ }
323
+ ```
324
+
325
+ ### Available Models
326
+
327
+ | Model | Provider | Best For |
328
+ |-------|----------|----------|
329
+ | `claude-sonnet-4-5-20250929` | Anthropic | General coding (default) |
330
+ | `claude-opus-4-5-20251101` | Anthropic | Complex reasoning |
331
+ | `claude-haiku-4-5-20251015` | Anthropic | Fast responses |
332
+ | `gpt-4o` | OpenAI | General coding |
333
+ | `gpt-4o-mini` | OpenAI | Fast responses |
334
+ | `o1-preview` | OpenAI | Complex reasoning |
335
+
336
+ ## API
337
+
338
+ XibeCode provides a REST API when running the WebUI:
339
+
340
+ ```bash
341
+ # Start the server
342
+ xibecode ui
343
+
344
+ # API endpoints
345
+ GET /api/health # Health check
346
+ GET /api/config # Get configuration
347
+ PUT /api/config # Update configuration
348
+ GET /api/models # List available models
349
+ GET /api/project # Get project info
350
+ GET /api/git/status # Get git status
351
+ GET /api/git/diff # Get git diff
352
+ POST /api/files/list # List directory contents
353
+ POST /api/files/read # Read file contents
354
+ POST /api/session/create # Create chat session
355
+ POST /api/tests/generate # Generate tests for file
356
+ POST /api/tests/analyze # Analyze file for testable code
357
+ POST /api/tests/run # Run project tests
358
+ ```
359
+
360
+ ## Project Structure
361
+
362
+ ```
363
+ xibecode/
364
+ ├── src/
365
+ │ ├── core/ # Agent, tools, context
366
+ │ ├── commands/ # CLI commands
367
+ │ ├── utils/ # Config, git, safety
368
+ │ ├── tools/ # Test generator, browser
369
+ │ ├── webui/ # WebUI server
370
+ │ └── index.ts # CLI entry point
371
+ ├── site/ # Documentation site
372
+ └── tests/ # Test suites
373
+ ```
374
+
124
375
  ## Project Docs
125
376
 
126
377
  - `CHANGELOG.md` — release history
127
378
  - `FEATURES.md` — feature deep dive
128
379
  - `PUBLISHING.md` — npm release process
129
380
 
381
+ ## Support
382
+
383
+ - [GitHub Issues](https://github.com/iotserver24/xibecode/issues)
384
+ - [Donate](https://www.anishkumar.tech/donate)
385
+
130
386
  ## License
131
387
 
132
388
  Apache-2.0
@@ -5,6 +5,7 @@ interface ChatOptions {
5
5
  provider?: string;
6
6
  theme?: string;
7
7
  session?: string;
8
+ noWebui?: boolean;
8
9
  }
9
10
  export declare function chatCommand(options: ChatOptions): Promise<void>;
10
11
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"AAmBA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,iBAsrCrD"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"AAqBA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,iBAmyCrD"}
@@ -13,6 +13,8 @@ import { TodoManager } from '../utils/todoManager.js';
13
13
  import { getAllModes, MODE_CONFIG } from '../core/modes.js';
14
14
  import { isThemeName, THEME_NAMES } from '../ui/themes.js';
15
15
  import { SkillManager } from '../core/skills.js';
16
+ import { startWebUI } from '../webui/server.js';
17
+ import { SessionBridge } from '../core/session-bridge.js';
16
18
  import chalk from 'chalk';
17
19
  import * as fs from 'fs/promises';
18
20
  import * as path from 'path';
@@ -26,10 +28,27 @@ export async function chatCommand(options) {
26
28
  const sessionManager = new SessionManager(config.getSessionDirectory());
27
29
  const contextManager = new ContextManager(process.cwd());
28
30
  let skillManager;
31
+ let webUIServer = null;
29
32
  ui.clear();
30
33
  if (!config.isHeaderMinimal()) {
31
34
  ui.header('1.0.0');
32
35
  }
36
+ // Start WebUI server in background (unless disabled)
37
+ const webUIPort = 3847;
38
+ if (!options.noWebui) {
39
+ try {
40
+ webUIServer = await startWebUI({ port: webUIPort, host: 'localhost', workingDir: process.cwd() });
41
+ console.log(chalk.hex('#6B6B7B')(` WebUI: `) + chalk.hex('#00D4FF')(`http://localhost:${webUIPort}`) + chalk.hex('#6B6B7B')(` (open in browser for visual interface)`));
42
+ console.log('');
43
+ }
44
+ catch (error) {
45
+ // Silently continue if WebUI fails to start (port might be in use)
46
+ if (error.code !== 'EADDRINUSE') {
47
+ console.log(chalk.hex('#6B6B7B')(` WebUI: `) + chalk.yellow(`failed to start (${error.message})`));
48
+ console.log('');
49
+ }
50
+ }
51
+ }
33
52
  // Get API key
34
53
  const apiKey = options.apiKey || config.getApiKey();
35
54
  if (!apiKey) {
@@ -81,23 +100,28 @@ export async function chatCommand(options) {
81
100
  case 'thinking':
82
101
  if (!hasResponse) {
83
102
  ui.thinking(event.data.message || 'Analyzing your request...');
103
+ SessionBridge.onThinking(event.data.message || 'Analyzing your request...');
84
104
  }
85
105
  break;
86
106
  // ── Streaming ──
87
107
  case 'stream_start':
88
108
  ui.startAssistantResponse(event.data.persona);
109
+ SessionBridge.onStreamStart(event.data.persona);
89
110
  hasResponse = true;
90
111
  break;
91
112
  case 'stream_text':
92
113
  ui.streamText(event.data.text);
114
+ SessionBridge.onStreamText(event.data.text);
93
115
  break;
94
116
  case 'stream_end':
95
117
  ui.endAssistantResponse();
118
+ SessionBridge.onStreamEnd();
96
119
  break;
97
120
  // ── Non-streaming fallback ──
98
121
  case 'response':
99
122
  if (!hasResponse) {
100
123
  ui.response(event.data.text, event.data.persona);
124
+ SessionBridge.onAssistantMessage(event.data.text, event.data.persona);
101
125
  hasResponse = true;
102
126
  }
103
127
  break;
@@ -105,11 +129,13 @@ export async function chatCommand(options) {
105
129
  case 'tool_call':
106
130
  if (enableTools) {
107
131
  ui.toolCall(event.data.name, event.data.input);
132
+ SessionBridge.onToolCall(event.data.name, event.data.input);
108
133
  }
109
134
  break;
110
135
  case 'tool_result':
111
136
  if (enableTools) {
112
137
  ui.toolResult(event.data.name, event.data.result, event.data.success);
138
+ SessionBridge.onToolResult(event.data.name, event.data.result, event.data.success);
113
139
  const r = event.data.result;
114
140
  if (r?.success && event.data.name === 'write_file') {
115
141
  ui.fileChanged('created', r.path, r.lines ? `${r.lines} lines` : undefined);
@@ -139,6 +165,7 @@ export async function chatCommand(options) {
139
165
  // ── Errors / Warnings ──
140
166
  case 'error':
141
167
  ui.error(event.data.message || event.data.error);
168
+ SessionBridge.onError(event.data.message || event.data.error);
142
169
  break;
143
170
  case 'warning':
144
171
  ui.warning(event.data.message);
@@ -146,6 +173,7 @@ export async function chatCommand(options) {
146
173
  case 'mode_changed':
147
174
  currentMode = event.data.to;
148
175
  ui.info(`Mode: ${currentMode}`);
176
+ SessionBridge.updateState({ mode: currentMode });
149
177
  break;
150
178
  }
151
179
  });
@@ -168,6 +196,62 @@ export async function chatCommand(options) {
168
196
  else {
169
197
  currentSession = await sessionManager.createSession({ model, cwd: process.cwd() });
170
198
  }
199
+ // Update SessionBridge with initial state
200
+ SessionBridge.updateState({
201
+ sessionId: currentSession.id,
202
+ model,
203
+ mode: currentMode,
204
+ messages: agent.getMessages(),
205
+ isProcessing: false,
206
+ });
207
+ // Queue for WebUI messages and resolver for interrupting TUI input
208
+ let pendingWebUIMessage = null;
209
+ let webUIMessageResolver = null;
210
+ // Listen for messages from WebUI
211
+ SessionBridge.on('user_message', async (content, source) => {
212
+ if (source === 'webui') {
213
+ pendingWebUIMessage = content;
214
+ // If TUI is waiting for input, resolve immediately with WebUI message
215
+ if (webUIMessageResolver) {
216
+ webUIMessageResolver(content);
217
+ webUIMessageResolver = null;
218
+ pendingWebUIMessage = null;
219
+ }
220
+ }
221
+ });
222
+ /**
223
+ * Get input from either TUI or WebUI (whichever comes first)
224
+ */
225
+ async function getInput() {
226
+ // Check if there's already a pending WebUI message
227
+ if (pendingWebUIMessage) {
228
+ const msg = pendingWebUIMessage;
229
+ pendingWebUIMessage = null;
230
+ return { message: msg, source: 'webui' };
231
+ }
232
+ return new Promise((resolve) => {
233
+ // Set up resolver for WebUI messages
234
+ webUIMessageResolver = (msg) => {
235
+ rl.close();
236
+ resolve({ message: msg, source: 'webui' });
237
+ };
238
+ // Create readline interface for TUI input
239
+ const rl = readline.createInterface({
240
+ input: process.stdin,
241
+ output: process.stdout,
242
+ });
243
+ // Show prompt
244
+ process.stdout.write(chalk.hex('#00E676').bold('❯ You ') + '');
245
+ rl.on('line', (line) => {
246
+ webUIMessageResolver = null;
247
+ rl.close();
248
+ resolve({ message: line, source: 'tui' });
249
+ });
250
+ rl.on('close', () => {
251
+ webUIMessageResolver = null;
252
+ });
253
+ });
254
+ }
171
255
  async function showPathSuggestions(raw) {
172
256
  const input = raw.trim().slice(1).trim(); // drop leading '@'
173
257
  const target = input ? path.resolve(process.cwd(), input) : process.cwd();
@@ -498,14 +582,14 @@ export async function chatCommand(options) {
498
582
  }
499
583
  // ── Chat loop ──
500
584
  while (true) {
501
- let { message } = await inquirer.prompt([
502
- {
503
- type: 'input',
504
- name: 'message',
505
- message: chalk.hex('#00E676').bold('❯ You '),
506
- prefix: '',
507
- },
508
- ]);
585
+ // Get input from either TUI or WebUI
586
+ const input = await getInput();
587
+ let message = input.message;
588
+ const messageSource = input.source; // Track where the message came from
589
+ // Show indicator for WebUI messages
590
+ if (messageSource === 'webui') {
591
+ console.log(chalk.hex('#00D4FF').bold('❯ WebUI ') + chalk.white(message));
592
+ }
509
593
  // Special interactive flow when user types just "@"
510
594
  if (message.trim() === '@') {
511
595
  try {
@@ -988,6 +1072,10 @@ export async function chatCommand(options) {
988
1072
  messages: agent.getMessages(),
989
1073
  stats,
990
1074
  });
1075
+ // Stop WebUI server
1076
+ if (webUIServer) {
1077
+ await webUIServer.stop();
1078
+ }
991
1079
  break;
992
1080
  }
993
1081
  if (lowerMessage === 'clear') {
@@ -1048,11 +1136,17 @@ export async function chatCommand(options) {
1048
1136
  if (undoStack.length > MAX_UNDO)
1049
1137
  undoStack.shift();
1050
1138
  redoStack.length = 0; // clear redo on new action
1139
+ // Broadcast user message to WebUI (only if from TUI, WebUI already has it)
1140
+ if (messageSource === 'tui') {
1141
+ SessionBridge.onTUIUserMessage(message);
1142
+ }
1051
1143
  // agent.run() resets its iteration/tool counters but KEEPS
1052
1144
  // the conversation history (this.messages), so the AI has
1053
1145
  // full context of everything discussed in this session.
1054
1146
  await agent.run(message, tools, toolExecutor);
1055
1147
  const stats = agent.getStats();
1148
+ // Update SessionBridge with latest messages
1149
+ SessionBridge.updateState({ messages: agent.getMessages() });
1056
1150
  // Build tokens label for status bar
1057
1151
  const tokensLabel = stats.totalTokens > 0
1058
1152
  ? `${(stats.totalTokens / 1000).toFixed(1)}k${stats.costLabel ? ` · ${stats.costLabel}` : ''}`
@@ -1083,5 +1177,9 @@ export async function chatCommand(options) {
1083
1177
  }
1084
1178
  // Cleanup: disconnect from any MCP servers connected during this session
1085
1179
  await mcpClientManager.disconnectAll();
1180
+ // Stop WebUI server if running
1181
+ if (webUIServer) {
1182
+ await webUIServer.stop();
1183
+ }
1086
1184
  }
1087
1185
  //# sourceMappingURL=chat.js.map