@mmmbuto/nexuscli 0.7.5 → 0.7.7

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 (33) hide show
  1. package/README.md +12 -4
  2. package/bin/nexuscli.js +6 -6
  3. package/frontend/dist/assets/{index-CikJbUR5.js → index-BAY_sRAu.js} +1704 -1704
  4. package/frontend/dist/assets/{index-Bn_l1e6e.css → index-CHOlrfA0.css} +1 -1
  5. package/frontend/dist/index.html +2 -2
  6. package/lib/server/.env.example +1 -1
  7. package/lib/server/db.js.old +225 -0
  8. package/lib/server/docs/API_WRAPPER_CONTRACT.md +682 -0
  9. package/lib/server/docs/ARCHITECTURE.md +441 -0
  10. package/lib/server/docs/DATABASE_SCHEMA.md +783 -0
  11. package/lib/server/docs/DESIGN_PRINCIPLES.md +598 -0
  12. package/lib/server/docs/NEXUSCHAT_ANALYSIS.md +488 -0
  13. package/lib/server/docs/PIPELINE_INTEGRATION.md +636 -0
  14. package/lib/server/docs/README.md +272 -0
  15. package/lib/server/docs/UI_DESIGN.md +916 -0
  16. package/lib/server/lib/pty-adapter.js +15 -1
  17. package/lib/server/routes/chat.js +70 -8
  18. package/lib/server/routes/codex.js +61 -7
  19. package/lib/server/routes/gemini.js +66 -12
  20. package/lib/server/routes/sessions.js +7 -2
  21. package/lib/server/server.js +2 -0
  22. package/lib/server/services/base-cli-wrapper.js +137 -0
  23. package/lib/server/services/claude-wrapper.js +11 -1
  24. package/lib/server/services/cli-loader.js.backup +446 -0
  25. package/lib/server/services/codex-output-parser.js +8 -0
  26. package/lib/server/services/codex-wrapper.js +13 -4
  27. package/lib/server/services/context-bridge.js +24 -20
  28. package/lib/server/services/gemini-wrapper.js +26 -8
  29. package/lib/server/services/session-manager.js +20 -0
  30. package/lib/server/services/workspace-manager.js +1 -1
  31. package/lib/server/tests/performance.test.js +1 -1
  32. package/lib/server/tests/services.test.js +2 -2
  33. package/package.json +1 -1
@@ -10,13 +10,14 @@
10
10
  * - -o stream-json: JSON streaming output
11
11
  * - --include-directories: Workspace access
12
12
  *
13
- * @version 0.4.0 - TRI CLI Support
13
+ * @version 0.5.0 - Extended BaseCliWrapper for interrupt support
14
14
  */
15
15
 
16
16
  const fs = require('fs');
17
17
  const path = require('path');
18
18
  const pty = require('../lib/pty-adapter');
19
19
  const GeminiOutputParser = require('./gemini-output-parser');
20
+ const BaseCliWrapper = require('./base-cli-wrapper');
20
21
 
21
22
  // Default model - Gemini 3 Pro Preview
22
23
  const DEFAULT_MODEL = 'gemini-3-pro-preview';
@@ -24,8 +25,9 @@ const DEFAULT_MODEL = 'gemini-3-pro-preview';
24
25
  // CLI timeout (10 minutes)
25
26
  const CLI_TIMEOUT_MS = 600000;
26
27
 
27
- class GeminiWrapper {
28
+ class GeminiWrapper extends BaseCliWrapper {
28
29
  constructor(options = {}) {
30
+ super(); // Initialize activeProcesses from BaseCliWrapper
29
31
  this.geminiPath = this._resolveGeminiPath(options.geminiPath);
30
32
  this.workspaceDir = options.workspaceDir || process.cwd();
31
33
 
@@ -67,15 +69,15 @@ class GeminiWrapper {
67
69
  *
68
70
  * @param {Object} params
69
71
  * @param {string} params.prompt - User message/prompt
70
- * @param {string} params.sessionId - Session UUID (for logging)
72
+ * @param {string} params.threadId - Native Gemini session ID for resume
71
73
  * @param {string} [params.model='gemini-3-pro-preview'] - Model name
72
74
  * @param {string} [params.workspacePath] - Workspace directory
73
75
  * @param {Function} [params.onStatus] - Callback for status events (SSE streaming)
74
- * @returns {Promise<{text: string, usage: Object}>}
76
+ * @returns {Promise<{text: string, usage: Object, sessionId: string}>}
75
77
  */
76
78
  async sendMessage({
77
79
  prompt,
78
- sessionId,
80
+ threadId,
79
81
  model = DEFAULT_MODEL,
80
82
  workspacePath,
81
83
  onStatus
@@ -87,16 +89,23 @@ class GeminiWrapper {
87
89
  const cwd = workspacePath || this.workspaceDir;
88
90
 
89
91
  // Build CLI arguments
90
- // Note: cwd is set in pty.spawn() options, no need for --include-directories
92
+ // If threadId exists, use --resume to continue native session
91
93
  const args = [
92
94
  '-y', // YOLO mode - auto-approve all actions
93
95
  '-m', model, // Model selection
94
96
  '-o', 'stream-json', // JSON streaming for structured events
95
- prompt // Prompt as positional argument
96
97
  ];
97
98
 
99
+ // Add resume flag if continuing existing session
100
+ if (threadId) {
101
+ args.push('--resume', threadId);
102
+ }
103
+
104
+ // Add prompt as positional argument
105
+ args.push(prompt);
106
+
98
107
  console.log(`[GeminiWrapper] Model: ${model}`);
99
- console.log(`[GeminiWrapper] Session: ${sessionId}`);
108
+ console.log(`[GeminiWrapper] ThreadId: ${threadId || '(new session)'}`);
100
109
  console.log(`[GeminiWrapper] CWD: ${cwd}`);
101
110
  console.log(`[GeminiWrapper] Prompt length: ${prompt.length}`);
102
111
 
@@ -117,6 +126,11 @@ class GeminiWrapper {
117
126
  return reject(new Error(`Failed to spawn Gemini CLI: ${spawnError.message}`));
118
127
  }
119
128
 
129
+ // Register process for interrupt capability
130
+ // Use threadId if available, otherwise generate temp ID
131
+ const processId = threadId || `gemini-${Date.now()}`;
132
+ this.registerProcess(processId, ptyProcess, 'pty');
133
+
120
134
  let stdout = '';
121
135
 
122
136
  // Handle PTY data
@@ -145,6 +159,9 @@ class GeminiWrapper {
145
159
 
146
160
  // Handle PTY exit
147
161
  ptyProcess.onExit(({ exitCode }) => {
162
+ // Unregister process on exit
163
+ this.unregisterProcess(processId);
164
+
148
165
  if (promiseSettled) return;
149
166
  promiseSettled = true;
150
167
 
@@ -170,6 +187,7 @@ class GeminiWrapper {
170
187
 
171
188
  resolve({
172
189
  text: finalResponse,
190
+ sessionId: parser.getSessionId(), // Native Gemini session ID for resume
173
191
  usage: {
174
192
  prompt_tokens: promptTokens,
175
193
  completion_tokens: completionTokens,
@@ -442,6 +442,26 @@ class SessionManager {
442
442
  }
443
443
  }
444
444
 
445
+ /**
446
+ * Bump session activity counters (message_count, last_used_at)
447
+ * @param {string} sessionId
448
+ * @param {number} increment
449
+ */
450
+ bumpSessionActivity(sessionId, increment = 1) {
451
+ if (!sessionId) return;
452
+ try {
453
+ const stmt = prepare(`
454
+ UPDATE sessions
455
+ SET message_count = COALESCE(message_count, 0) + ?, last_used_at = ?
456
+ WHERE id = ?
457
+ `);
458
+ stmt.run(increment, Date.now(), sessionId);
459
+ saveDb();
460
+ } catch (error) {
461
+ console.warn(`[SessionManager] Failed to bump activity for ${sessionId}:`, error.message);
462
+ }
463
+ }
464
+
445
465
  /**
446
466
  * Get all sessions for a conversation
447
467
  */
@@ -396,7 +396,7 @@ class WorkspaceManager {
396
396
  * @returns {string}
397
397
  */
398
398
  getSessionPath(workspacePath) {
399
- // Convert /home/user/myproject → -home-user-myproject
399
+ // Convert /var/www/myapp → -var-www-myapp
400
400
  const projectDir = workspacePath.replace(/\//g, '-').replace(/^-/, '');
401
401
  return path.join(this.claudePath, 'projects', projectDir);
402
402
  }
@@ -45,7 +45,7 @@ describe('Performance Benchmarks', () => {
45
45
 
46
46
  test('Workspace validation should be fast', async () => {
47
47
  const manager = new WorkspaceManager();
48
- const testPath = '/home/user/myproject';
48
+ const testPath = '/var/www/myapp';
49
49
 
50
50
  const start = Date.now();
51
51
  const validated = await manager.validateWorkspace(testPath);
@@ -16,7 +16,7 @@ describe('WorkspaceManager', () => {
16
16
 
17
17
  test('should validate workspace path', async () => {
18
18
  // Test with allowed path
19
- const validPath = '/home/user/myproject';
19
+ const validPath = '/var/www/myapp';
20
20
  const result = await manager.validateWorkspace(validPath);
21
21
  expect(result).toBe(validPath);
22
22
  });
@@ -147,7 +147,7 @@ describe('SummaryGenerator', () => {
147
147
  describe('Integration - Service Interactions', () => {
148
148
  test('WorkspaceManager should use consistent path resolution', async () => {
149
149
  const manager = new WorkspaceManager();
150
- const testPath = '/home/user/myproject';
150
+ const testPath = '/var/www/myapp';
151
151
  const validated = await manager.validateWorkspace(testPath);
152
152
  expect(validated).toBe(testPath);
153
153
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmmbuto/nexuscli",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
4
4
  "description": "NexusCLI - TRI CLI Control Plane (Claude/Codex/Gemini)",
5
5
  "main": "lib/server/server.js",
6
6
  "bin": {