@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,682 +0,0 @@
1
- # NexusCLI API & Wrapper Contract Specification
2
-
3
- **Version**: 0.1.0
4
- **Created**: 2025-11-17
5
- **Based on**: NexusChat wrapper architecture
6
- **Purpose**: Official API contract for NexusCLI control plane and nexus-wrapper node agents
7
-
8
- ---
9
-
10
- ## 📋 Table of Contents
11
-
12
- 1. [Architecture Overview](#architecture-overview)
13
- 2. [Control Plane API (NexusCLI)](#control-plane-api-nexuscli)
14
- 3. [Node Agent API (nexus-wrapper)](#node-agent-api-nexus-wrapper)
15
- 4. [Data Structures](#data-structures)
16
- 5. [Event Streaming](#event-streaming)
17
- 6. [Error Handling](#error-handling)
18
- 7. [Pipeline Integration](#pipeline-integration)
19
-
20
- ---
21
-
22
- ## 🏗️ Architecture Overview
23
-
24
- ### Philosophy: Separation of Concerns
25
-
26
- **NexusChat Pattern** (adapted from analysis):
27
- ```
28
- User Request → LibreChat API → Wrapper → Claude CLI → PTY Output → Parser → SSE Events → Client
29
- ```
30
-
31
- **NexusCLI Pattern** (generalized):
32
- ```
33
- Control Plane → Job API → nexus-wrapper → Remote CLI → Stdout/Stderr → Parser → SSE Events → Dashboard
34
- ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
35
- Orchestrator REST API HTTP Agent Local Tools Raw Output Structured Real-time UI/Logs
36
- ```
37
-
38
- ### Key Principles (from NexusChat)
39
-
40
- 1. **Stateless Wrappers**: Each wrapper is a lightweight HTTP server that spawns CLI processes
41
- 2. **Session Persistence**: 2-layer (RAM cache + Disk storage) for crash recovery
42
- 3. **Event-Driven Streaming**: SSE (Server-Sent Events) for real-time progress
43
- 4. **Output Parsing**: Regex-based parsing of stdout/stderr into structured events
44
- 5. **Tool Abstraction**: Generic tool interface (Bash, Read, Write, etc.)
45
-
46
- ---
47
-
48
- ## 🎛️ Control Plane API (NexusCLI)
49
-
50
- ### Base URL
51
- ```
52
- http://localhost:4000/api/v1
53
- ```
54
-
55
- ### Authentication
56
- ```
57
- Authorization: Bearer <jwt_token>
58
- ```
59
-
60
- ---
61
-
62
- ### 1. Node Management
63
-
64
- #### `POST /nodes/register`
65
- Register a new node with the control plane.
66
-
67
- **Request**:
68
- ```json
69
- {
70
- "nodeId": "node-001",
71
- "hostname": "server-prod-1",
72
- "ipAddress": "192.168.1.10",
73
- "capabilities": {
74
- "tools": ["bash", "python", "git", "docker"],
75
- "maxConcurrentJobs": 5,
76
- "platform": "linux",
77
- "arch": "x86_64"
78
- },
79
- "wrapperVersion": "1.0.0",
80
- "wrapperEndpoint": "http://192.168.1.10:5000"
81
- }
82
- ```
83
-
84
- **Response** (200 OK):
85
- ```json
86
- {
87
- "nodeId": "node-001",
88
- "status": "registered",
89
- "token": "<node_auth_token>",
90
- "heartbeatInterval": 30000
91
- }
92
- ```
93
-
94
- #### `GET /nodes`
95
- List all registered nodes.
96
-
97
- **Response** (200 OK):
98
- ```json
99
- {
100
- "nodes": [
101
- {
102
- "nodeId": "node-001",
103
- "hostname": "server-prod-1",
104
- "status": "online",
105
- "lastHeartbeat": "2025-11-17T10:30:00Z",
106
- "activeJobs": 2,
107
- "capabilities": { "tools": ["bash", "python"] }
108
- }
109
- ]
110
- }
111
- ```
112
-
113
- #### `POST /nodes/:nodeId/heartbeat`
114
- Update node status (sent by wrapper every N seconds).
115
-
116
- **Request**:
117
- ```json
118
- {
119
- "status": "online",
120
- "activeJobs": 2,
121
- "systemLoad": 0.45,
122
- "timestamp": "2025-11-17T10:30:00Z"
123
- }
124
- ```
125
-
126
- **Response** (200 OK):
127
- ```json
128
- {
129
- "acknowledged": true
130
- }
131
- ```
132
-
133
- ---
134
-
135
- ### 2. Job Management
136
-
137
- #### `POST /jobs`
138
- Create a new job for execution on a node.
139
-
140
- **Request**:
141
- ```json
142
- {
143
- "nodeId": "node-001",
144
- "tool": "bash",
145
- "command": "ls -la /var/www",
146
- "workingDir": "/tmp",
147
- "timeout": 30000,
148
- "metadata": {
149
- "userId": "user-123",
150
- "requestId": "req-456"
151
- }
152
- }
153
- ```
154
-
155
- **Response** (201 Created):
156
- ```json
157
- {
158
- "jobId": "job-789",
159
- "nodeId": "node-001",
160
- "status": "queued",
161
- "createdAt": "2025-11-17T10:30:00Z",
162
- "streamEndpoint": "/jobs/job-789/stream"
163
- }
164
- ```
165
-
166
- #### `GET /jobs/:jobId`
167
- Get job status and results.
168
-
169
- **Response** (200 OK):
170
- ```json
171
- {
172
- "jobId": "job-789",
173
- "nodeId": "node-001",
174
- "status": "completed",
175
- "tool": "bash",
176
- "command": "ls -la /var/www",
177
- "result": {
178
- "exitCode": 0,
179
- "stdout": "total 24\ndrwxr-xr-x 6 root root...",
180
- "stderr": "",
181
- "duration": 123
182
- },
183
- "createdAt": "2025-11-17T10:30:00Z",
184
- "completedAt": "2025-11-17T10:30:01Z"
185
- }
186
- ```
187
-
188
- #### `GET /jobs/:jobId/stream` (SSE)
189
- Real-time event stream for job execution.
190
-
191
- **SSE Events**:
192
- ```javascript
193
- // Event: status
194
- data: {"type":"status","category":"queued","message":"Job queued on node-001","timestamp":"..."}
195
-
196
- // Event: status (execution started)
197
- data: {"type":"status","category":"executing","message":"Running bash command...","icon":"🔧","timestamp":"..."}
198
-
199
- // Event: output_chunk (incremental stdout)
200
- data: {"type":"output_chunk","stream":"stdout","text":"total 24\n","isIncremental":true}
201
-
202
- // Event: status (tool execution)
203
- data: {"type":"status","category":"tool","message":"Bash: ls -la /var/www","icon":"🔧","toolOutput":"..."}
204
-
205
- // Event: response_done
206
- data: {"type":"response_done","exitCode":0,"duration":123}
207
-
208
- // Event: done
209
- data: {"type":"done","jobId":"job-789","status":"completed"}
210
- ```
211
-
212
- #### `DELETE /jobs/:jobId`
213
- Cancel a running job.
214
-
215
- **Response** (200 OK):
216
- ```json
217
- {
218
- "jobId": "job-789",
219
- "status": "cancelled"
220
- }
221
- ```
222
-
223
- ---
224
-
225
- ### 3. Batch Operations
226
-
227
- #### `POST /batch`
228
- Execute a job on multiple nodes.
229
-
230
- **Request**:
231
- ```json
232
- {
233
- "nodeIds": ["node-001", "node-002", "node-003"],
234
- "tool": "bash",
235
- "command": "systemctl status nginx",
236
- "parallel": true
237
- }
238
- ```
239
-
240
- **Response** (201 Created):
241
- ```json
242
- {
243
- "batchId": "batch-abc",
244
- "jobs": [
245
- {"jobId": "job-001", "nodeId": "node-001"},
246
- {"jobId": "job-002", "nodeId": "node-002"},
247
- {"jobId": "job-003", "nodeId": "node-003"}
248
- ]
249
- }
250
- ```
251
-
252
- ---
253
-
254
- ## 🤖 Node Agent API (nexus-wrapper)
255
-
256
- ### Base URL (on each node)
257
- ```
258
- http://<node-ip>:5000/api/v1
259
- ```
260
-
261
- ### Authentication
262
- ```
263
- Authorization: Bearer <node_auth_token>
264
- ```
265
-
266
- ---
267
-
268
- ### 1. Health & Capabilities
269
-
270
- #### `GET /health`
271
- Health check endpoint.
272
-
273
- **Response** (200 OK):
274
- ```json
275
- {
276
- "status": "ok",
277
- "nodeId": "node-001",
278
- "wrapperVersion": "1.0.0",
279
- "uptime": 86400,
280
- "activeJobs": 2
281
- }
282
- ```
283
-
284
- #### `GET /capabilities`
285
- List available tools and capabilities.
286
-
287
- **Response** (200 OK):
288
- ```json
289
- {
290
- "tools": [
291
- {
292
- "name": "bash",
293
- "version": "5.1.16",
294
- "available": true
295
- },
296
- {
297
- "name": "python",
298
- "version": "3.11.5",
299
- "available": true
300
- },
301
- {
302
- "name": "git",
303
- "version": "2.39.2",
304
- "available": true
305
- }
306
- ],
307
- "platform": "linux",
308
- "arch": "x86_64",
309
- "maxConcurrentJobs": 5
310
- }
311
- ```
312
-
313
- ---
314
-
315
- ### 2. Job Execution
316
-
317
- #### `POST /jobs`
318
- Execute a job locally on this node.
319
-
320
- **Request**:
321
- ```json
322
- {
323
- "jobId": "job-789",
324
- "tool": "bash",
325
- "command": "ls -la /var/www",
326
- "workingDir": "/tmp",
327
- "timeout": 30000,
328
- "env": {
329
- "PATH": "/usr/local/bin:/usr/bin"
330
- }
331
- }
332
- ```
333
-
334
- **Response** (202 Accepted):
335
- ```json
336
- {
337
- "jobId": "job-789",
338
- "status": "accepted",
339
- "streamEndpoint": "/jobs/job-789/stream"
340
- }
341
- ```
342
-
343
- #### `GET /jobs/:jobId/stream` (SSE)
344
- Real-time output stream (like NexusChat claude-wrapper).
345
-
346
- **SSE Events** (same format as Control Plane):
347
- ```javascript
348
- // status events
349
- data: {"type":"status","category":"executing","message":"Running command..."}
350
-
351
- // stdout chunks
352
- data: {"type":"output_chunk","stream":"stdout","text":"line 1\n"}
353
-
354
- // stderr chunks
355
- data: {"type":"output_chunk","stream":"stderr","text":"warning: ...\n"}
356
-
357
- // completion
358
- data: {"type":"response_done","exitCode":0,"duration":123}
359
- data: {"type":"done"}
360
- ```
361
-
362
- #### `GET /jobs/:jobId`
363
- Get job result (after completion).
364
-
365
- **Response** (200 OK):
366
- ```json
367
- {
368
- "jobId": "job-789",
369
- "status": "completed",
370
- "exitCode": 0,
371
- "stdout": "total 24\ndrwxr-xr-x...",
372
- "stderr": "",
373
- "duration": 123,
374
- "startedAt": "2025-11-17T10:30:00Z",
375
- "completedAt": "2025-11-17T10:30:01Z"
376
- }
377
- ```
378
-
379
- #### `DELETE /jobs/:jobId`
380
- Kill a running job.
381
-
382
- **Response** (200 OK):
383
- ```json
384
- {
385
- "jobId": "job-789",
386
- "status": "killed",
387
- "signal": "SIGTERM"
388
- }
389
- ```
390
-
391
- ---
392
-
393
- ## 📦 Data Structures
394
-
395
- ### Node
396
- ```typescript
397
- interface Node {
398
- nodeId: string; // Unique node identifier
399
- hostname: string; // Node hostname
400
- ipAddress: string; // Node IP address
401
- status: 'online' | 'offline' | 'error';
402
- capabilities: {
403
- tools: string[]; // Available CLI tools
404
- maxConcurrentJobs: number;
405
- platform: string; // 'linux' | 'darwin' | 'windows'
406
- arch: string; // 'x86_64' | 'arm64'
407
- };
408
- wrapperVersion: string;
409
- wrapperEndpoint: string;
410
- lastHeartbeat: string; // ISO 8601 timestamp
411
- activeJobs: number;
412
- }
413
- ```
414
-
415
- ### Job
416
- ```typescript
417
- interface Job {
418
- jobId: string;
419
- nodeId: string;
420
- status: 'queued' | 'executing' | 'completed' | 'failed' | 'cancelled' | 'killed';
421
- tool: string; // 'bash' | 'python' | 'git' | etc.
422
- command: string; // Command to execute
423
- workingDir?: string; // Working directory (optional)
424
- timeout?: number; // Timeout in milliseconds
425
- env?: Record<string, string>; // Environment variables
426
- result?: {
427
- exitCode: number;
428
- stdout: string;
429
- stderr: string;
430
- duration: number; // Milliseconds
431
- };
432
- metadata?: Record<string, any>; // Custom metadata
433
- createdAt: string;
434
- startedAt?: string;
435
- completedAt?: string;
436
- }
437
- ```
438
-
439
- ### Event (SSE)
440
- ```typescript
441
- interface Event {
442
- type: 'status' | 'output_chunk' | 'response_done' | 'done' | 'error';
443
-
444
- // For type: 'status'
445
- category?: 'queued' | 'executing' | 'tool' | 'streaming' | 'complete' | 'warning';
446
- message?: string;
447
- icon?: string; // Emoji icon
448
-
449
- // For type: 'output_chunk'
450
- stream?: 'stdout' | 'stderr';
451
- text?: string;
452
- isIncremental?: boolean;
453
-
454
- // For type: 'response_done'
455
- exitCode?: number;
456
- duration?: number;
457
-
458
- // For type: 'error'
459
- error?: string;
460
- details?: string;
461
-
462
- timestamp?: string; // ISO 8601
463
- }
464
- ```
465
-
466
- ---
467
-
468
- ## 🌊 Event Streaming
469
-
470
- ### SSE (Server-Sent Events)
471
-
472
- **Inspired by NexusChat**: Real-time streaming via SSE for live job progress.
473
-
474
- **Headers**:
475
- ```http
476
- Content-Type: text/event-stream
477
- Cache-Control: no-cache
478
- Connection: keep-alive
479
- X-Accel-Buffering: no
480
- ```
481
-
482
- **Event Flow** (based on NexusChat output-parser.js):
483
-
484
- 1. **Queued**:
485
- ```javascript
486
- data: {"type":"status","category":"queued","message":"Job queued","icon":"⏱️"}
487
- ```
488
-
489
- 2. **Executing**:
490
- ```javascript
491
- data: {"type":"status","category":"executing","message":"Running bash command...","icon":"🔧"}
492
- ```
493
-
494
- 3. **Output Streaming** (incremental):
495
- ```javascript
496
- data: {"type":"output_chunk","stream":"stdout","text":"line 1\n","isIncremental":true}
497
- data: {"type":"output_chunk","stream":"stdout","text":"line 2\n","isIncremental":true}
498
- ```
499
-
500
- 4. **Tool Events** (if detected):
501
- ```javascript
502
- data: {"type":"status","category":"tool","message":"Git: clone repository","icon":"🔀"}
503
- ```
504
-
505
- 5. **Completion**:
506
- ```javascript
507
- data: {"type":"response_done","exitCode":0,"duration":123}
508
- data: {"type":"done","jobId":"job-789"}
509
- ```
510
-
511
- 6. **Error**:
512
- ```javascript
513
- data: {"type":"error","error":"Command failed","details":"...\n"}
514
- ```
515
-
516
- ---
517
-
518
- ## ⚠️ Error Handling
519
-
520
- ### Error Response Format
521
-
522
- **HTTP Error Response**:
523
- ```json
524
- {
525
- "error": "Error message",
526
- "code": "ERROR_CODE",
527
- "details": "Additional details...",
528
- "timestamp": "2025-11-17T10:30:00Z"
529
- }
530
- ```
531
-
532
- ### Common Error Codes
533
-
534
- | Code | HTTP Status | Description |
535
- |------|-------------|-------------|
536
- | `NODE_NOT_FOUND` | 404 | Node ID does not exist |
537
- | `NODE_OFFLINE` | 503 | Node is offline or unreachable |
538
- | `JOB_NOT_FOUND` | 404 | Job ID does not exist |
539
- | `JOB_TIMEOUT` | 408 | Job exceeded timeout limit |
540
- | `TOOL_NOT_AVAILABLE` | 400 | Requested tool not available on node |
541
- | `AUTHENTICATION_FAILED` | 401 | Invalid or missing auth token |
542
- | `RATE_LIMIT_EXCEEDED` | 429 | Too many requests |
543
- | `INTERNAL_ERROR` | 500 | Internal server error |
544
-
545
- ### Retry Strategy (inspired by NexusChat wrapper)
546
-
547
- - **Connection errors**: Retry up to 3 times with exponential backoff
548
- - **Timeout errors**: No retry (user-initiated cancellation)
549
- - **Tool errors**: No retry (fix command and resubmit)
550
-
551
- ---
552
-
553
- ## 🔄 Pipeline Integration
554
-
555
- ### Workflow: Analysis → Coordination → Execution → Test → Deploy
556
-
557
- **Based on NexusChat CLAUDE.md pipeline**, adapted for distributed CLI:
558
-
559
- ```
560
- ┌─────────────────────────────────────────────────────────────────┐
561
- │ CONTROL PLANE │
562
- │ │
563
- │ 1. ANALYSIS │
564
- │ - User submits job request │
565
- │ - Validate command, tool, node availability │
566
- │ │
567
- │ 2. COORDINATION │
568
- │ - Select target node(s) │
569
- │ - Queue job │
570
- │ - Establish SSE stream │
571
- │ │
572
- │ 3. EXECUTION (delegated to nexus-wrapper) │
573
- │ - POST /jobs to wrapper API │
574
- │ - Wrapper spawns PTY process │
575
- │ - Output parser streams events │
576
- │ │
577
- │ 4. TEST (optional - automated verification) │
578
- │ - Check exit code │
579
- │ - Validate output format │
580
- │ - Assert expected results │
581
- │ │
582
- │ 5. DEPLOY (future - chained jobs) │
583
- │ - Trigger dependent jobs │
584
- │ - Update deployment status │
585
- │ │
586
- └─────────────────────────────────────────────────────────────────┘
587
-
588
- ┌─────────────────────────────────────────────────────────────────┐
589
- │ NEXUS-WRAPPER (Node) │
590
- │ │
591
- │ - Receive job request │
592
- │ - Spawn PTY process (like NexusChat claude-wrapper) │
593
- │ - Parse stdout/stderr with OutputParser │
594
- │ - Emit SSE events (status, output_chunk, done) │
595
- │ - Store result in local job storage │
596
- │ │
597
- └─────────────────────────────────────────────────────────────────┘
598
- ```
599
-
600
- ### Session Persistence (NexusChat pattern)
601
-
602
- **2-Layer Storage**:
603
- 1. **RAM Cache** (Map): Fast access for active jobs
604
- 2. **Disk Storage** (JSON files): Persistence across restarts
605
-
606
- **File Structure** (per wrapper):
607
- ```
608
- /var/lib/nexus-wrapper/jobs/
609
- ├── job-001.json
610
- ├── job-002.json
611
- └── job-003.json
612
- ```
613
-
614
- **Job File Format**:
615
- ```json
616
- {
617
- "jobId": "job-001",
618
- "status": "completed",
619
- "command": "ls -la",
620
- "result": {
621
- "exitCode": 0,
622
- "stdout": "...",
623
- "stderr": "",
624
- "duration": 123
625
- },
626
- "createdAt": "2025-11-17T10:30:00Z",
627
- "completedAt": "2025-11-17T10:30:01Z"
628
- }
629
- ```
630
-
631
- ---
632
-
633
- ## 🎯 Implementation Notes
634
-
635
- ### From NexusChat Analysis
636
-
637
- 1. **PTY over Subprocess** (claude-wrapper.js:61)
638
- - Use `node-pty` for real PTY (fixes CLI spawn issues)
639
- - Handles ANSI escape codes correctly
640
- - Better signal handling (SIGTERM, SIGKILL)
641
-
642
- 2. **Output Parser State Machine** (output-parser.js:13)
643
- - States: `idle | tool_execution | tool_output | thinking | response`
644
- - Regex patterns for detecting tool markers
645
- - Line-by-line parsing for accuracy
646
-
647
- 3. **SSE Streaming** (server.js:71-76)
648
- - Set correct headers (`text/event-stream`, `no-cache`)
649
- - Disable nginx buffering (`X-Accel-Buffering: no`)
650
- - Emit events as `data: {JSON}\n\n`
651
-
652
- 4. **Session Manager** (session-manager.js)
653
- - Load from disk on cache miss (lazy loading)
654
- - Save to disk on every update (durability)
655
- - List() loads all from disk (ensure completeness)
656
-
657
- 5. **Graceful Shutdown** (server.js:248)
658
- - Handle SIGTERM for systemd compatibility
659
- - Clean up active PTY processes
660
- - Save in-flight jobs to disk
661
-
662
- ---
663
-
664
- ## 📚 References
665
-
666
- - **NexusChat Source**: `/var/www/chat.mmmbuto.com/servers/claude-code-server/`
667
- - **NexusChat CLAUDE.md**: Development workflow and pipeline
668
- - **LibreChat API**: Upstream reference for agents/chat routes
669
- - **Model**: Based on production wrapper serving 100+ daily requests
670
-
671
- ---
672
-
673
- **Next Steps**:
674
- 1. Implement Control Plane API endpoints (Express.js)
675
- 2. Create nexus-wrapper reference implementation
676
- 3. Adapt OutputParser for generic CLI tools
677
- 4. Add WebSocket support (alternative to SSE)
678
- 5. Implement authentication & rate limiting
679
-
680
- ---
681
-
682
- _Generated by Claude Code (Sonnet 4.5) - 2025-11-17_