xibecode 0.3.8 → 0.4.3

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 +270 -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 +2132 -0
  27. package/dist/webui/server.js.map +1 -0
  28. package/package.json +16 -6
  29. package/webui-dist/assets/index-BlYSY3Lp.js +338 -0
  30. package/webui-dist/assets/index-BlYSY3Lp.js.map +1 -0
  31. package/webui-dist/assets/index-DS6Gij8T.css +32 -0
  32. package/webui-dist/assets/xterm-BUw9jMN8.js +10 -0
  33. package/webui-dist/assets/xterm-BUw9jMN8.js.map +1 -0
  34. package/webui-dist/assets/xterm-addon-fit-CMYoGiLV.js +2 -0
  35. package/webui-dist/assets/xterm-addon-fit-CMYoGiLV.js.map +1 -0
  36. package/webui-dist/assets/xterm-addon-web-links-mCwMW5Oc.js +2 -0
  37. package/webui-dist/assets/xterm-addon-web-links-mCwMW5Oc.js.map +1 -0
  38. package/webui-dist/index.html +15 -0
package/README.md CHANGED
@@ -1,12 +1,23 @@
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.0
13
+
14
+ - **TUI-WebUI Sync** - Real-time bidirectional sync between terminal and browser
15
+ - **Slash Commands** - Type `/` in WebUI to switch between 13 agent modes
16
+ - **File References** - Type `@` to browse and reference project files
17
+ - **Custom Model Support** - Use any OpenAI-compatible API endpoint
18
+ - **Tool Execution Display** - See tool calls and results in real-time
19
+ - **Markdown Rendering** - Rich text formatting in chat responses
20
+ - **Minimalistic Design** - Clean, terminal-style interface
10
21
 
11
22
  ## Installation
12
23
 
@@ -19,15 +30,15 @@ From source:
19
30
  ```bash
20
31
  git clone https://github.com/iotserver24/xibecode
21
32
  cd xibecode
22
- npm install
23
- npm run build
33
+ pnpm install
34
+ pnpm run build
24
35
  npm link
25
36
  ```
26
37
 
27
38
  ## Requirements
28
39
 
29
40
  - Node.js 18+
30
- - Anthropic API key (or compatible provider/base URL)
41
+ - API key from Anthropic or OpenAI
31
42
 
32
43
  ## Quick Start
33
44
 
@@ -35,20 +46,45 @@ npm link
35
46
  # Configure once
36
47
  xibecode config --set-key YOUR_API_KEY
37
48
 
38
- # Interactive mode
49
+ # Interactive terminal mode
39
50
  xibecode chat
40
51
 
52
+ # Open WebUI in browser (recommended for beginners)
53
+ xibecode ui --open
54
+
41
55
  # Autonomous run
42
56
  xibecode run "Create an Express API with auth"
43
57
  ```
44
58
 
45
59
  ## Main Commands
46
60
 
61
+ ### `xibecode ui`
62
+ **NEW** - Start the WebUI in your browser.
63
+
64
+ ```bash
65
+ xibecode ui # Start on localhost:3847
66
+ xibecode ui --open # Auto-open browser
67
+ xibecode ui -p 8080 # Custom port
68
+ ```
69
+
70
+ Features:
71
+ - **Dashboard** - Project stats, git status, test runner info
72
+ - **Chat Interface** - Real-time streaming responses
73
+ - **Visual Diff** - Colorized git diff viewer
74
+ - **AI Test Generator** - Generate tests with one click
75
+ - **Multi-Model Selector** - Switch models instantly
76
+ - **Configuration Panel** - Manage API keys and settings
77
+
47
78
  ### `xibecode run`
48
79
  Autonomous coding workflow.
49
80
 
50
- Useful options:
81
+ ```bash
82
+ xibecode run "Build a REST API with Express"
83
+ xibecode run "Fix the TypeScript errors" --verbose
84
+ xibecode run --file task.txt
85
+ ```
51
86
 
87
+ Options:
52
88
  - `-f, --file <path>` prompt from file
53
89
  - `-m, --model <model>` model override
54
90
  - `--mode <mode>` initial agent mode
@@ -61,10 +97,9 @@ Useful options:
61
97
  - `--changed-only`
62
98
 
63
99
  ### `xibecode chat`
64
- Interactive chat + tool use.
65
-
66
- Useful options:
100
+ Interactive terminal chat + tool use.
67
101
 
102
+ Options:
68
103
  - `-m, --model <model>`
69
104
  - `-b, --base-url <url>`
70
105
  - `-k, --api-key <key>`
@@ -87,31 +122,161 @@ MCP server management:
87
122
 
88
123
  ## Core Features
89
124
 
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
125
+ - **Autonomous multi-step agent loop** - Completes complex tasks automatically
126
+ - **Smart context gathering** - Understands related files and imports
127
+ - **Verified and line-based editing** - Reliable code modifications
128
+ - **Dry-run mode** - Preview changes safely before applying
129
+ - **Git-aware workflows** - `--changed-only`, checkpoints, and reverts
130
+ - **Test runner integration** - Auto-detects Vitest, Jest, pytest, Go test
131
+ - **MCP server integration** - Extend capabilities with external tools
132
+ - **Skill system** - Built-in + custom markdown skills
133
+ - **Session-aware chat** - Persistent conversation history
134
+ - **Themed terminal UI** - Beautiful, customizable interface
135
+
136
+ ## WebUI
137
+
138
+ The WebUI provides a browser-based interface that syncs in real-time with the terminal.
139
+
140
+ ```bash
141
+ # Start with both TUI and WebUI
142
+ xibecode chat
143
+
144
+ # WebUI opens automatically at http://localhost:3847
145
+ ```
146
+
147
+ ### TUI-WebUI Sync
148
+
149
+ When you run `xibecode chat`, both interfaces are connected:
150
+ - Messages sent from **TUI** appear in **WebUI** (marked with "TUI")
151
+ - Messages sent from **WebUI** are processed by **TUI**
152
+ - Streaming responses show in both simultaneously
153
+ - Tool executions display in real-time
154
+
155
+ ### Slash Commands (`/`)
156
+
157
+ Type `/` in the input to open the command palette:
158
+
159
+ **Commands:**
160
+
161
+ | Command | Description |
162
+ |---------|-------------|
163
+ | `/clear` | Clear chat messages |
164
+ | `/help` | Show available commands |
165
+ | `/diff` | Show git diff |
166
+ | `/status` | Show git status |
167
+ | `/test` | Run project tests |
168
+ | `/format` | Format code in project |
169
+ | `/reset` | Reset chat session |
170
+ | `/files` | List project files |
171
+
172
+ **Modes:**
173
+
174
+ | Mode | Icon | Description |
175
+ |------|------|-------------|
176
+ | `/mode agent` | 🤖 | Autonomous coding (default) |
177
+ | `/mode plan` | 📋 | Analyze without modifying |
178
+ | `/mode tester` | 🧪 | Testing and QA |
179
+ | `/mode debugger` | 🐛 | Bug investigation |
180
+ | `/mode security` | 🔒 | Security analysis |
181
+ | `/mode review` | 👀 | Code review |
182
+ | `/mode team_leader` | 👑 | Coordinate team |
183
+ | `/mode architect` | 🏛️ | System design |
184
+ | `/mode engineer` | 🛠️ | Implementation |
185
+ | `/mode seo` | 🌐 | SEO optimization |
186
+ | `/mode product` | 🔥 | Product strategy |
187
+ | `/mode data` | 📊 | Data analysis |
188
+ | `/mode researcher` | 📚 | Deep research |
189
+
190
+ ### File References (`@`)
191
+
192
+ Type `@` to browse and reference files:
193
+ - Shows project files and folders
194
+ - Filter by typing after `@`
195
+ - Select to include file path in message
196
+ - Helps AI understand which files to work with
197
+
198
+ ### Settings Panel
199
+
200
+ Click the ⚙️ Settings button to configure:
201
+ - **Provider** - Anthropic, OpenAI, or Custom
202
+ - **Model** - Select from available models
203
+ - **Custom Model ID** - For custom/local models
204
+ - **API Key** - Your provider API key
205
+ - **Base URL** - Custom API endpoint (for local LLMs)
206
+ - **Session Info** - Working directory, git branch
207
+
208
+ ### Features
209
+
210
+ - **Markdown Rendering** - Code blocks, bold, italic, lists, links
211
+ - **Tool Execution** - Shows each tool call with status (running/done/failed)
212
+ - **Thinking Indicator** - Spinner while AI is processing
213
+ - **Responsive Design** - Works on mobile and desktop
214
+ - **Real-time Streaming** - See responses as they're generated
215
+
216
+ ## AI Test Generation
217
+
218
+ XibeCode can automatically generate comprehensive test suites for your code:
219
+
220
+ ```bash
221
+ # Via CLI (in chat mode)
222
+ > generate tests for src/utils/helpers.ts
223
+
224
+ # Via WebUI
225
+ 1. Go to "Test Generator" tab
226
+ 2. Enter file path
227
+ 3. Select framework (auto-detected)
228
+ 4. Click "Generate Tests"
229
+ ```
230
+
231
+ ### Features
232
+
233
+ - **Multi-framework support** - Vitest, Jest, Mocha, pytest, Go test
234
+ - **Code analysis** - Understands functions, classes, types
235
+ - **Edge case generation** - Null checks, empty strings, boundaries
236
+ - **Mock setup** - Automatic mock configuration
237
+ - **Type checking tests** - Verifies return types
238
+ - **Error handling tests** - Tests for exceptions
239
+
240
+ ### Example Output
241
+
242
+ ```typescript
243
+ import { describe, it, expect, vi } from 'vitest';
244
+ import { calculateTotal } from '../utils/helpers';
245
+
246
+ describe('calculateTotal', () => {
247
+ it('should execute calculateTotal successfully', () => {
248
+ expect(calculateTotal([])).toBeDefined();
249
+ });
250
+
251
+ it('should return correct type from calculateTotal', () => {
252
+ expect(typeof calculateTotal([])).toBe('number');
253
+ });
254
+
255
+ it('should handle empty array', () => {
256
+ expect(calculateTotal([])).toBe(0);
257
+ });
258
+
259
+ it('should handle errors in calculateTotal', () => {
260
+ expect(() => calculateTotal(undefined)).toThrow();
261
+ });
262
+ });
263
+ ```
99
264
 
100
265
  ## Browser Testing (Playwright)
101
266
 
102
- XibeCode includes comprehensive browser automation and testing capabilities powered by Playwright:
267
+ XibeCode includes comprehensive browser automation and testing capabilities:
103
268
 
104
269
  - **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)
270
+ - **Console Logs** - Collect browser console output
271
+ - **Visual Regression** - Compare screenshots against baselines
272
+ - **Accessibility Audits** - Check WCAG compliance
108
273
  - **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
274
+ - **Responsive Testing** - Test across multiple viewports
275
+ - **Network Monitoring** - Capture all network requests
111
276
  - **E2E Tests** - Execute Playwright test files
112
277
 
113
278
  ```bash
114
- # Example: Test a page's performance
279
+ # Example: Test performance
115
280
  xibecode run "Measure the performance of http://localhost:3000"
116
281
 
117
282
  # Example: Check accessibility
@@ -121,12 +286,91 @@ xibecode run "Run an accessibility audit on the homepage"
121
286
  xibecode run "Take a screenshot and compare against baseline"
122
287
  ```
123
288
 
289
+ ## Configuration
290
+
291
+ ### Environment Variables
292
+
293
+ ```bash
294
+ ANTHROPIC_API_KEY=sk-ant-... # Anthropic API key
295
+ OPENAI_API_KEY=sk-... # OpenAI API key
296
+ XIBECODE_MODEL=claude-sonnet-4-5-20250929 # Default model
297
+ ```
298
+
299
+ ### Config File
300
+
301
+ Located at `~/.xibecode/config.json`:
302
+
303
+ ```json
304
+ {
305
+ "apiKey": "sk-ant-...",
306
+ "model": "claude-sonnet-4-5-20250929",
307
+ "provider": "anthropic",
308
+ "maxIterations": 50,
309
+ "theme": "default"
310
+ }
311
+ ```
312
+
313
+ ### Available Models
314
+
315
+ | Model | Provider | Best For |
316
+ |-------|----------|----------|
317
+ | `claude-sonnet-4-5-20250929` | Anthropic | General coding (default) |
318
+ | `claude-opus-4-5-20251101` | Anthropic | Complex reasoning |
319
+ | `claude-haiku-4-5-20251015` | Anthropic | Fast responses |
320
+ | `gpt-4o` | OpenAI | General coding |
321
+ | `gpt-4o-mini` | OpenAI | Fast responses |
322
+ | `o1-preview` | OpenAI | Complex reasoning |
323
+
324
+ ## API
325
+
326
+ XibeCode provides a REST API when running the WebUI:
327
+
328
+ ```bash
329
+ # Start the server
330
+ xibecode ui
331
+
332
+ # API endpoints
333
+ GET /api/health # Health check
334
+ GET /api/config # Get configuration
335
+ PUT /api/config # Update configuration
336
+ GET /api/models # List available models
337
+ GET /api/project # Get project info
338
+ GET /api/git/status # Get git status
339
+ GET /api/git/diff # Get git diff
340
+ POST /api/files/list # List directory contents
341
+ POST /api/files/read # Read file contents
342
+ POST /api/session/create # Create chat session
343
+ POST /api/tests/generate # Generate tests for file
344
+ POST /api/tests/analyze # Analyze file for testable code
345
+ POST /api/tests/run # Run project tests
346
+ ```
347
+
348
+ ## Project Structure
349
+
350
+ ```
351
+ xibecode/
352
+ ├── src/
353
+ │ ├── core/ # Agent, tools, context
354
+ │ ├── commands/ # CLI commands
355
+ │ ├── utils/ # Config, git, safety
356
+ │ ├── tools/ # Test generator, browser
357
+ │ ├── webui/ # WebUI server
358
+ │ └── index.ts # CLI entry point
359
+ ├── site/ # Documentation site
360
+ └── tests/ # Test suites
361
+ ```
362
+
124
363
  ## Project Docs
125
364
 
126
365
  - `CHANGELOG.md` — release history
127
366
  - `FEATURES.md` — feature deep dive
128
367
  - `PUBLISHING.md` — npm release process
129
368
 
369
+ ## Support
370
+
371
+ - [GitHub Issues](https://github.com/iotserver24/xibecode/issues)
372
+ - [Donate](https://www.anishkumar.tech/donate)
373
+
130
374
  ## License
131
375
 
132
376
  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