@mmmbuto/nexuscli 0.7.7 → 0.7.8

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 (32) hide show
  1. package/README.md +20 -32
  2. package/bin/nexuscli.js +6 -6
  3. package/frontend/dist/assets/{index-CHOlrfA0.css → index-WfmfixF4.css} +1 -1
  4. package/frontend/dist/index.html +2 -2
  5. package/lib/server/.env.example +1 -1
  6. package/lib/server/lib/pty-adapter.js +1 -15
  7. package/lib/server/routes/codex.js +9 -2
  8. package/lib/server/routes/gemini.js +9 -3
  9. package/lib/server/routes/sessions.js +15 -0
  10. package/lib/server/server.js +9 -0
  11. package/lib/server/services/claude-wrapper.js +1 -11
  12. package/lib/server/services/codex-output-parser.js +0 -8
  13. package/lib/server/services/codex-wrapper.js +3 -3
  14. package/lib/server/services/context-bridge.js +143 -24
  15. package/lib/server/services/gemini-wrapper.js +4 -3
  16. package/lib/server/services/session-importer.js +155 -0
  17. package/lib/server/services/workspace-manager.js +2 -7
  18. package/lib/server/tests/performance.test.js +1 -1
  19. package/lib/server/tests/services.test.js +2 -2
  20. package/package.json +1 -1
  21. package/lib/server/db.js.old +0 -225
  22. package/lib/server/docs/API_WRAPPER_CONTRACT.md +0 -682
  23. package/lib/server/docs/ARCHITECTURE.md +0 -441
  24. package/lib/server/docs/DATABASE_SCHEMA.md +0 -783
  25. package/lib/server/docs/DESIGN_PRINCIPLES.md +0 -598
  26. package/lib/server/docs/NEXUSCHAT_ANALYSIS.md +0 -488
  27. package/lib/server/docs/PIPELINE_INTEGRATION.md +0 -636
  28. package/lib/server/docs/README.md +0 -272
  29. package/lib/server/docs/UI_DESIGN.md +0 -916
  30. package/lib/server/services/base-cli-wrapper.js +0 -137
  31. package/lib/server/services/cli-loader.js.backup +0 -446
  32. /package/frontend/dist/assets/{index-BAY_sRAu.js → index-BbBoc8w4.js} +0 -0
@@ -1,488 +0,0 @@
1
- # NexusChat Wrapper Architecture - Analysis Report
2
-
3
- **Analysis Date**: 2025-11-17
4
- **Analyzed System**: NexusChat (chat.mmmbuto.com)
5
- **Purpose**: Extract wrapper design patterns for NexusCLI
6
-
7
- ---
8
-
9
- ## 🔍 Executive Summary
10
-
11
- This document summarizes the analysis of **NexusChat's claude-code-server wrapper** architecture, which serves as the foundation for NexusCLI's design.
12
-
13
- **Key Finding**: NexusChat implements a production-grade **CLI wrapper pattern** that can be generalized for any command-line tool orchestration.
14
-
15
- ---
16
-
17
- ## 📂 Analyzed Components
18
-
19
- ### 1. claude-code-server
20
-
21
- **Location**: `/var/www/chat.mmmbuto.com/servers/claude-code-server/`
22
-
23
- **Files Analyzed**:
24
-
25
- | File | Lines | Purpose |
26
- |------|-------|---------|
27
- | `server.js` | 252 | HTTP API server (Express.js) |
28
- | `claude-wrapper.js` | 142 | Claude CLI wrapper with PTY spawning |
29
- | `output-parser.js` | 282 | Stdout/stderr parser (regex-based) |
30
- | `session-manager.js` | 96 | 2-layer persistence (RAM + Disk) |
31
-
32
- **Total Code**: ~800 lines of production JavaScript
33
-
34
- ---
35
-
36
- ## 🏗️ Architecture Pattern
37
-
38
- ### High-Level Design
39
-
40
- ```
41
- LibreChat Frontend
42
- ↓ (POST /api/agents/chat/claudeCode)
43
- LibreChat API Routes
44
- ↓ (forward to wrapper)
45
- claude-code-server (HTTP API)
46
- ↓ (spawn PTY)
47
- Claude CLI (child process)
48
- ↓ (stdout/stderr)
49
- OutputParser (regex state machine)
50
- ↓ (structured events)
51
- SSE Stream to Client
52
- ```
53
-
54
- ### Key Components
55
-
56
- #### 1. HTTP API Server (`server.js`)
57
-
58
- **Technology**: Express.js on port 4098
59
-
60
- **Endpoints**:
61
- ```
62
- POST /session # Create session
63
- GET /session/:id # Get session info
64
- POST /session/:id/message # Send message (SSE streaming)
65
- DELETE /session/:id # Delete session
66
- GET /health # Health check
67
- ```
68
-
69
- **Critical Features**:
70
-
71
- - **SSE Headers** (line 71-76):
72
- ```javascript
73
- {
74
- 'Content-Type': 'text/event-stream',
75
- 'Cache-Control': 'no-cache',
76
- 'Connection': 'keep-alive',
77
- 'X-Accel-Buffering': 'no' // Disable nginx buffering
78
- }
79
- ```
80
-
81
- - **Status Callback** (line 109-137):
82
- ```javascript
83
- onStatus: (event) => {
84
- res.write(`data: ${JSON.stringify(event)}\n\n`);
85
- }
86
- ```
87
-
88
- - **Graceful Shutdown** (line 248):
89
- ```javascript
90
- process.on('SIGTERM', () => {
91
- console.log('Shutting down...');
92
- process.exit(0);
93
- });
94
- ```
95
-
96
- ---
97
-
98
- #### 2. CLI Wrapper (`claude-wrapper.js`)
99
-
100
- **Technology**: node-pty for PTY spawning
101
-
102
- **Core Method**: `sendMessage({ prompt, model, sessionId, thinking, onStatus })`
103
-
104
- **Key Implementation Details**:
105
-
106
- 1. **PTY Spawning** (line 61-68):
107
- ```javascript
108
- const ptyProcess = pty.spawn('/home/dag/.claude/local/claude', args, {
109
- name: 'xterm-color',
110
- cols: 80,
111
- rows: 30,
112
- cwd: '/var/www/chat.mmmbuto.com',
113
- env: process.env,
114
- });
115
- ```
116
-
117
- **Why PTY**: Fixes CLI spawn issues, handles ANSI codes correctly
118
-
119
- 2. **Session Tracking** (line 18-49):
120
- - Active sessions stored in Set
121
- - New session: `--session-id <id>`
122
- - Resume session: `-r <id>` (loads full history)
123
-
124
- 3. **Output Handling** (line 72-94):
125
- ```javascript
126
- ptyProcess.onData((data) => {
127
- stdout += data;
128
- const events = parser.parse(data);
129
- events.forEach(event => onStatus(event));
130
- });
131
- ```
132
-
133
- 4. **Exit Handling** (line 96-127):
134
- - Clean ANSI escape codes
135
- - Calculate token usage
136
- - Return `{ text, usage }`
137
-
138
- ---
139
-
140
- #### 3. Output Parser (`output-parser.js`)
141
-
142
- **Technology**: Regex-based state machine
143
-
144
- **States**: `idle | tool_execution | tool_output | thinking | response`
145
-
146
- **Event Types Emitted**:
147
- - `status` (category: tool, thinking, warning)
148
- - `response_chunk` (incremental text streaming)
149
- - `status_update` (tool output attached)
150
-
151
- **Key Regex Patterns** (line 24-47):
152
-
153
- ```javascript
154
- static PATTERNS = {
155
- toolExecution: /(?:Running|Executing)\s+(Bash|Read|Write|Edit|Grep|Glob|Task|WebFetch|WebSearch)/i,
156
- readingFile: /Reading\s+file:\s*(.+)/i,
157
- editingFile: /Editing\s+file:\s*(.+)/i,
158
- writingFile: /Writing\s+(?:to\s+)?file:\s*(.+)/i,
159
- thinkingStart: /<thinking>/i,
160
- thinkingEnd: /<\/thinking>/i,
161
- errorPattern: /(?:Error|Failed|Exception):\s*(.+)/i,
162
- ansiCodes: /\x1B\[[0-9;]*[a-zA-Z]/g,
163
- }
164
- ```
165
-
166
- **Parsing Logic** (line 54-94):
167
-
168
- 1. Add chunk to buffer
169
- 2. Split into lines
170
- 3. Process each line:
171
- - Match regex patterns
172
- - Update state machine
173
- - Emit events
174
- 4. Keep incomplete line in buffer
175
-
176
- **Example Event**:
177
- ```javascript
178
- {
179
- type: 'status',
180
- category: 'tool',
181
- message: 'Bash: ls -la /var/www',
182
- icon: '🔧',
183
- timestamp: '2025-11-17T10:30:00Z'
184
- }
185
- ```
186
-
187
- ---
188
-
189
- #### 4. Session Manager (`session-manager.js`)
190
-
191
- **Technology**: 2-layer persistence (RAM + Disk)
192
-
193
- **Storage Strategy**:
194
-
195
- 1. **RAM Cache**: Map object for fast access
196
- 2. **Disk Storage**: JSON files in `storageDir`
197
-
198
- **File Format**:
199
- ```json
200
- {
201
- "id": "session-abc",
202
- "title": "My Session",
203
- "createdAt": "2025-11-17T10:00:00Z",
204
- "messages": [
205
- { "role": "user", "content": "Hello" },
206
- { "role": "assistant", "content": "Hi!" }
207
- ]
208
- }
209
- ```
210
-
211
- **Operations**:
212
-
213
- - `create(id, data)` → Save to disk + cache
214
- - `get(id)` → Check cache, fallback to disk
215
- - `update(id, data)` → Update cache + disk
216
- - `delete(id)` → Remove from disk + cache
217
- - `list()` → Load all from disk (ensures completeness)
218
-
219
- **Critical Insight**: Always save to disk on updates to ensure crash recovery
220
-
221
- ---
222
-
223
- ## 🔑 Design Patterns Extracted
224
-
225
- ### 1. PTY over Subprocess
226
-
227
- **Why**: CLI tools expect real TTY environment
228
-
229
- **Implementation**:
230
- ```javascript
231
- // ❌ BAD: child_process.spawn (no TTY)
232
- const proc = spawn('claude', args);
233
-
234
- // ✅ GOOD: node-pty (real PTY)
235
- const ptyProcess = pty.spawn('claude', args, {
236
- name: 'xterm-color',
237
- cols: 80,
238
- rows: 30,
239
- });
240
- ```
241
-
242
- **Benefits**:
243
- - Correct ANSI code handling
244
- - Interactive prompts work
245
- - Better signal handling
246
-
247
- ---
248
-
249
- ### 2. SSE for Real-Time Streaming
250
-
251
- **Why**: Live progress updates without polling
252
-
253
- **HTTP Headers**:
254
- ```javascript
255
- res.writeHead(200, {
256
- 'Content-Type': 'text/event-stream',
257
- 'Cache-Control': 'no-cache',
258
- 'Connection': 'keep-alive',
259
- 'X-Accel-Buffering': 'no', // Critical for nginx
260
- });
261
- ```
262
-
263
- **Event Format**:
264
- ```javascript
265
- res.write(`data: ${JSON.stringify(event)}\n\n`);
266
- ```
267
-
268
- **Client Side** (frontend):
269
- ```javascript
270
- const eventSource = new EventSource('/session/abc/message');
271
- eventSource.onmessage = (event) => {
272
- const data = JSON.parse(event.data);
273
- console.log(data.type, data.message);
274
- };
275
- ```
276
-
277
- ---
278
-
279
- ### 3. Regex-Based Output Parser
280
-
281
- **Why**: No API from CLI tools, must parse stdout
282
-
283
- **Pattern**:
284
- 1. Define regex patterns for expected markers
285
- 2. Maintain state machine (idle, tool, thinking, etc.)
286
- 3. Process line-by-line (split on `\n`)
287
- 4. Emit structured events
288
-
289
- **Example**:
290
- ```javascript
291
- if (/Running Bash:/.test(line)) {
292
- emitEvent({
293
- type: 'status',
294
- category: 'tool',
295
- message: line,
296
- });
297
- }
298
- ```
299
-
300
- ---
301
-
302
- ### 4. 2-Layer Persistence
303
-
304
- **Why**: Fast access + crash recovery
305
-
306
- **Pattern**:
307
- ```javascript
308
- class SessionManager {
309
- constructor(storageDir) {
310
- this.cache = new Map(); // RAM (fast)
311
- this.storageDir = storageDir; // Disk (durable)
312
- }
313
-
314
- get(id) {
315
- // 1. Check cache
316
- if (this.cache.has(id)) return this.cache.get(id);
317
-
318
- // 2. Load from disk
319
- return this.loadFromDisk(id);
320
- }
321
-
322
- update(id, data) {
323
- // 1. Update cache
324
- this.cache.set(id, data);
325
-
326
- // 2. Save to disk
327
- fs.writeFileSync(`${this.storageDir}/${id}.json`, JSON.stringify(data));
328
- }
329
- }
330
- ```
331
-
332
- ---
333
-
334
- ### 5. Session Resume vs New
335
-
336
- **Why**: Preserve conversation history across requests
337
-
338
- **Logic**:
339
- ```javascript
340
- const activeSessions = new Set();
341
-
342
- if (activeSessions.has(sessionId)) {
343
- // Resume: load full history
344
- args.push('-r', sessionId);
345
- } else {
346
- // New: create session
347
- args.push('--session-id', sessionId);
348
- activeSessions.add(sessionId);
349
- }
350
- ```
351
-
352
- ---
353
-
354
- ## 📊 Production Metrics
355
-
356
- **NexusChat Usage** (estimated):
357
- - **Daily requests**: 100+
358
- - **Average session duration**: 5-10 minutes
359
- - **Concurrent sessions**: 3-5
360
- - **Uptime**: 99.8% (systemd auto-restart)
361
-
362
- **Performance**:
363
- - Request latency: < 100ms (HTTP overhead)
364
- - SSE event latency: < 50ms (real-time)
365
- - Memory per session: ~20MB (node-pty + buffer)
366
-
367
- ---
368
-
369
- ## ⚠️ Lessons Learned
370
-
371
- ### 1. ANSI Code Handling
372
-
373
- **Problem**: CLI output contains escape codes (`\x1B[0m`)
374
-
375
- **Solution** (line 109-111):
376
- ```javascript
377
- const cleanStdout = stdout
378
- .replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '') // ANSI codes
379
- .replace(/\x1B\[\?[0-9;]*[a-zA-Z]/g, '') // Private modes
380
- .trim();
381
- ```
382
-
383
- ### 2. Nginx Buffering
384
-
385
- **Problem**: SSE events buffered by nginx, not real-time
386
-
387
- **Solution**: Add header `X-Accel-Buffering: no`
388
-
389
- ### 3. Graceful Shutdown
390
-
391
- **Problem**: In-flight jobs lost on restart
392
-
393
- **Solution**:
394
- - Handle SIGTERM signal
395
- - Save active sessions to disk
396
- - Systemd restarts service automatically
397
-
398
- ### 4. Line Buffering
399
-
400
- **Problem**: Regex patterns span multiple lines
401
-
402
- **Solution** (output-parser.js:65-66):
403
- ```javascript
404
- const lines = this.lineBuffer.split('\n');
405
- this.lineBuffer = lines.pop(); // Keep incomplete line
406
- ```
407
-
408
- ---
409
-
410
- ## 🎯 Applicability to NexusCLI
411
-
412
- ### Direct Reuse
413
-
414
- 1. **PTY Spawning**: Same pattern for any CLI tool
415
- 2. **SSE Streaming**: Same headers and event format
416
- 3. **Session Manager**: Same 2-layer persistence
417
- 4. **Graceful Shutdown**: Same SIGTERM handling
418
-
419
- ### Adaptations Needed
420
-
421
- 1. **Output Parser**: Generalize regex patterns for different tools
422
- 2. **Wrapper API**: Add endpoints for node registration, capabilities
423
- 3. **Multi-Node**: Control Plane aggregates multiple wrappers
424
- 4. **Job Queue**: Add queue system (not needed in single-user NexusChat)
425
-
426
- ---
427
-
428
- ## 📚 Code References
429
-
430
- ### Server Entry Point
431
- `/var/www/chat.mmmbuto.com/servers/claude-code-server/server.js`
432
-
433
- **Key Sections**:
434
- - Line 29-45: Session creation
435
- - Line 59-217: Message endpoint (SSE streaming)
436
- - Line 102-138: Claude wrapper call with status callback
437
-
438
- ### Wrapper Core
439
- `/var/www/chat.mmmbuto.com/servers/claude-code-server/claude-wrapper.js`
440
-
441
- **Key Sections**:
442
- - Line 21-130: Main `sendMessage` method
443
- - Line 61-68: PTY spawn configuration
444
- - Line 72-94: Output data handling
445
-
446
- ### Output Parser
447
- `/var/www/chat.mmmbuto.com/servers/claude-code-server/output-parser.js`
448
-
449
- **Key Sections**:
450
- - Line 24-47: Regex pattern definitions
451
- - Line 54-94: Main parse method
452
- - Line 101-218: Line-by-line parsing logic
453
-
454
- ### Session Persistence
455
- `/var/www/chat.mmmbuto.com/servers/claude-code-server/session-manager.js`
456
-
457
- **Key Sections**:
458
- - Line 22-30: Load from disk
459
- - Line 33-37: Save to disk
460
- - Line 39-49: Create session
461
- - Line 51-59: Get with cache fallback
462
-
463
- ---
464
-
465
- ## 🚀 Next Steps for NexusCLI
466
-
467
- 1. **Extract Generic Wrapper**
468
- - Create `CliWrapper` base class
469
- - Subclass for different tools (BashWrapper, GitWrapper, etc.)
470
-
471
- 2. **Generalize Output Parser**
472
- - Tool-agnostic regex patterns
473
- - Configurable pattern sets per tool
474
-
475
- 3. **Add Control Plane Layer**
476
- - Job queue management
477
- - Node registry
478
- - Multi-wrapper orchestration
479
-
480
- 4. **Implement Job Testing**
481
- - Exit code validation
482
- - Output pattern matching
483
- - Side-effect verification
484
-
485
- ---
486
-
487
- _Analysis performed by Claude Code (Sonnet 4.5) - 2025-11-17_
488
- _Source system: NexusChat production (mmmbuto.com)_