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.
- package/README.md +282 -26
- package/dist/commands/chat.d.ts +1 -0
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +106 -8
- package/dist/commands/chat.js.map +1 -1
- package/dist/core/modes.d.ts +1 -1
- package/dist/core/modes.d.ts.map +1 -1
- package/dist/core/modes.js +7 -8
- package/dist/core/modes.js.map +1 -1
- package/dist/core/session-bridge.d.ts +105 -0
- package/dist/core/session-bridge.d.ts.map +1 -0
- package/dist/core/session-bridge.js +243 -0
- package/dist/core/session-bridge.js.map +1 -0
- package/dist/core/tools.d.ts +4 -0
- package/dist/core/tools.d.ts.map +1 -1
- package/dist/core/tools.js +171 -0
- package/dist/core/tools.js.map +1 -1
- package/dist/index.js +42 -35
- package/dist/index.js.map +1 -1
- package/dist/tools/test-generator.d.ts +157 -0
- package/dist/tools/test-generator.d.ts.map +1 -0
- package/dist/tools/test-generator.js +893 -0
- package/dist/tools/test-generator.js.map +1 -0
- package/dist/webui/server.d.ts +96 -0
- package/dist/webui/server.d.ts.map +1 -0
- package/dist/webui/server.js +2304 -0
- package/dist/webui/server.js.map +1 -0
- package/package.json +16 -6
- package/webui-dist/assets/index-BXqucsdn.js +353 -0
- package/webui-dist/assets/index-BXqucsdn.js.map +1 -0
- package/webui-dist/assets/index-D1NjcKN3.css +32 -0
- package/webui-dist/assets/xterm-BjznWQZK.js +10 -0
- package/webui-dist/assets/xterm-BjznWQZK.js.map +1 -0
- package/webui-dist/assets/xterm-addon-fit-CPOtr3CW.js +2 -0
- package/webui-dist/assets/xterm-addon-fit-CPOtr3CW.js.map +1 -0
- package/webui-dist/assets/xterm-addon-web-links-z5RYd3SS.js +2 -0
- package/webui-dist/assets/xterm-addon-web-links-z5RYd3SS.js.map +1 -0
- 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
|
[](https://www.anishkumar.tech/donate)
|
|
6
|
+
[](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
|
-
|
|
23
|
-
|
|
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
|
-
-
|
|
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
|
-
|
|
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
|
|
92
|
-
- Verified and line-based editing
|
|
93
|
-
- Dry-run mode
|
|
94
|
-
- Git-aware workflows
|
|
95
|
-
- Test runner integration
|
|
96
|
-
- MCP server integration
|
|
97
|
-
- Skill system
|
|
98
|
-
- Session-aware chat
|
|
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
|
|
279
|
+
XibeCode includes comprehensive browser automation and testing capabilities:
|
|
103
280
|
|
|
104
281
|
- **Screenshots** - Capture webpage screenshots
|
|
105
|
-
- **Console Logs** - Collect browser console output
|
|
106
|
-
- **Visual Regression** - Compare screenshots against baselines
|
|
107
|
-
- **Accessibility Audits** - Check WCAG compliance
|
|
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
|
|
110
|
-
- **Network Monitoring** - Capture all network requests
|
|
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
|
|
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
|
package/dist/commands/chat.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/commands/chat.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/commands/chat.js
CHANGED
|
@@ -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
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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
|