@mmmbuto/nexuscrew 0.2.0 → 0.2.2

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 (41) hide show
  1. package/README.md +124 -56
  2. package/bin/nexuscrew.js +79 -152
  3. package/frontend/dist/assets/{index-8pw4eMB-.js → index-BsldfYnr.js} +1704 -1716
  4. package/frontend/dist/assets/index-DcQGg3dp.css +1 -0
  5. package/frontend/dist/index.html +2 -2
  6. package/lib/server/routes/hosts.js +3 -2
  7. package/lib/server/routes/launchers.js +12 -0
  8. package/lib/server/routes/models.js +16 -63
  9. package/lib/server/routes/runtime.js +10 -0
  10. package/lib/server/routes/send.js +97 -218
  11. package/lib/server/routes/sessions.js +7 -39
  12. package/lib/server/routes/status.js +16 -18
  13. package/lib/server/routes/tmux.js +88 -0
  14. package/lib/server/server.js +45 -65
  15. package/lib/services/engine-discovery.js +192 -445
  16. package/lib/services/session-store.js +86 -60
  17. package/lib/services/tmux-manager.js +103 -154
  18. package/package.json +3 -7
  19. package/frontend/dist/assets/index-BF0tdvNT.css +0 -1
  20. package/lib/config/manager.js +0 -362
  21. package/lib/config/models.js +0 -408
  22. package/lib/server/db/adapter.js +0 -274
  23. package/lib/server/db/drivers/sql-js.js +0 -75
  24. package/lib/server/db/migrate.js +0 -174
  25. package/lib/server/db/migrations/001_base_schema.sql +0 -70
  26. package/lib/server/middleware/auth.js +0 -134
  27. package/lib/server/middleware/rate-limit.js +0 -63
  28. package/lib/server/models/User.js +0 -128
  29. package/lib/server/routes/auth.js +0 -168
  30. package/lib/server/routes/keys.js +0 -15
  31. package/lib/server/routes/runtimes.js +0 -34
  32. package/lib/server/routes/speech.js +0 -75
  33. package/lib/server/routes/upload.js +0 -134
  34. package/lib/server/routes/wake-lock.js +0 -95
  35. package/lib/server/routes/workspaces.js +0 -101
  36. package/lib/server/services/context-bridge.js +0 -425
  37. package/lib/server/services/runtime-manager.js +0 -462
  38. package/lib/server/services/summary-generator.js +0 -309
  39. package/lib/server/services/workspace-manager.js +0 -79
  40. package/lib/utils/paths.js +0 -107
  41. package/lib/utils/termux.js +0 -145
@@ -10,34 +10,27 @@ const cors = require('cors');
10
10
  const path = require('path');
11
11
  const fs = require('fs');
12
12
  const http = require('http');
13
+ const os = require('os');
14
+ const packageJson = require('../../package.json');
13
15
 
14
- const { initDb, saveDb } = require('./db/adapter');
15
16
  const TmuxManager = require('../services/tmux-manager');
16
17
  const EngineDiscovery = require('../services/engine-discovery');
17
18
  const SessionStore = require('../services/session-store');
18
19
  const LogWatcher = require('../services/log-watcher');
19
20
 
20
- // Routes
21
21
  const sendRouter = require('./routes/send');
22
22
  const sessionsRouter = require('./routes/sessions');
23
23
  const modelsRouter = require('./routes/models');
24
- const runtimesRouter = require('./routes/runtimes');
25
24
  const statusRouter = require('./routes/status');
26
25
  const hostsRouter = require('./routes/hosts');
27
- const wakeLockRouter = require('./routes/wake-lock');
28
- const authRouter = require('./routes/auth');
29
- const speechRouter = require('./routes/speech');
30
- const keysRouter = require('./routes/keys');
31
- const uploadRouter = require('./routes/upload');
32
- const workspacesRouter = require('./routes/workspaces');
33
-
34
- // Middleware
35
- const { authMiddleware } = require('./middleware/auth');
26
+ const tmuxRouter = require('./routes/tmux');
27
+ const launchersRouter = require('./routes/launchers');
28
+ const runtimeRouter = require('./routes/runtime');
36
29
 
37
30
  class NexusCrewServer {
38
31
  constructor(config = {}) {
39
32
  this.port = config.port || process.env.PORT || 41820;
40
- this.configDir = config.configDir || path.join(process.env.HOME, '.nexuscrew');
33
+ this.configDir = config.configDir || path.join(os.homedir(), '.nexuscrew');
41
34
  this.config = this._loadConfig();
42
35
  this.app = express();
43
36
  this.server = null;
@@ -46,9 +39,18 @@ class NexusCrewServer {
46
39
  _loadConfig() {
47
40
  const configPath = path.join(this.configDir, 'config.json');
48
41
  if (fs.existsSync(configPath)) {
49
- return JSON.parse(fs.readFileSync(configPath, 'utf8'));
42
+ const loaded = JSON.parse(fs.readFileSync(configPath, 'utf8'));
43
+ if (loaded.providersPath && !loaded.extraShellSources) {
44
+ loaded.extraShellSources = [loaded.providersPath].filter(Boolean);
45
+ }
46
+ return loaded;
50
47
  }
51
- return { port: this.port, tmuxSession: 'nexuscrew', autoDiscovery: true };
48
+ return {
49
+ port: this.port,
50
+ autoDiscovery: true,
51
+ preferredShell: '',
52
+ extraShellSources: []
53
+ };
52
54
  }
53
55
 
54
56
  _loadHosts() {
@@ -60,60 +62,45 @@ class NexusCrewServer {
60
62
  }
61
63
 
62
64
  async start() {
63
- // 1. Init database
64
- await initDb();
65
-
66
- // 2. Seed admin user if no users exist
67
- const User = require('./models/User');
68
- if (User.count() === 0) {
69
- User.create('admin', 'admin', 'admin');
70
- console.log(' Created default admin user (admin/admin)');
71
- }
72
-
73
- // 3. Init services
74
65
  const hosts = this._loadHosts();
75
66
  const tmuxManager = new TmuxManager({
76
- tmuxSession: this.config.tmuxSession || 'nexuscrew',
77
67
  logDir: this.config.logDir || path.join(this.configDir, 'logs'),
68
+ preferredShell: this.config.preferredShell || process.env.SHELL || '/bin/sh',
78
69
  hosts
79
70
  });
80
71
 
81
- const engineDiscovery = new EngineDiscovery(this.config.providersPath);
82
- const sessionStore = new SessionStore();
83
- await sessionStore.init();
72
+ const engineDiscovery = new EngineDiscovery({
73
+ preferredShell: this.config.preferredShell,
74
+ extraShellSources: this.config.extraShellSources || []
75
+ });
76
+ const sessionStore = new SessionStore(path.join(this.configDir, 'nexuscrew.db'));
84
77
  const logWatcher = new LogWatcher();
85
78
 
86
- // Ensure tmux master session
87
- tmuxManager.ensureSession();
88
-
89
- // Sync DB with tmux reality
90
79
  sessionStore.syncWithTmux(tmuxManager);
91
80
 
92
- // Resume watching logs for active conversations
93
81
  const active = sessionStore.listConversations({ status: 'active' });
94
82
  for (const conv of active) {
95
83
  if (conv.log_path && fs.existsSync(conv.log_path)) {
96
- logWatcher.watch(conv.log_path, conv.engine, conv.id);
84
+ logWatcher.watch(conv.log_path, conv.engine || 'generic', conv.id);
97
85
  }
98
86
  }
99
87
 
100
- // 4. Middleware
88
+ // Middleware
101
89
  this.app.use(cors());
102
90
  this.app.use(express.json({ limit: '10mb' }));
103
91
 
104
- // 5. Health check (public)
92
+ // Health check
105
93
  this.app.get('/health', (req, res) => {
106
94
  res.json({
107
95
  status: 'ok',
108
96
  service: 'nexuscrew',
109
- version: '0.2.0',
110
- tmux: tmuxManager.hasSession(),
111
- windows: tmuxManager.listWindows().length,
97
+ version: packageJson.version,
98
+ tmuxSessions: tmuxManager.listSessions().length,
112
99
  uptime: process.uptime()
113
100
  });
114
101
  });
115
102
 
116
- // 6. Inject services into request
103
+ // Inject services into request
117
104
  this.app.use((req, res, next) => {
118
105
  req.tmux = tmuxManager;
119
106
  req.engines = engineDiscovery;
@@ -123,23 +110,17 @@ class NexusCrewServer {
123
110
  next();
124
111
  });
125
112
 
126
- // 7. Public routes
127
- this.app.use('/api/v1/auth', authRouter);
128
- this.app.use('/api/v1', wakeLockRouter);
129
- this.app.use('/api/v1/runtimes', runtimesRouter); // public for login screen
113
+ // API routes
114
+ this.app.use('/api/v1/send', sendRouter);
115
+ this.app.use('/api/v1/sessions', sessionsRouter);
130
116
  this.app.use('/api/v1/models', modelsRouter);
131
- this.app.use('/api/v1/keys', keysRouter); // public for STT key check
132
-
133
- // 8. Protected routes
134
- this.app.use('/api/v1/send', authMiddleware, sendRouter);
135
- this.app.use('/api/v1/sessions', authMiddleware, sessionsRouter);
136
- this.app.use('/api/v1/workspaces', authMiddleware, workspacesRouter);
137
- this.app.use('/api/v1/status', authMiddleware, statusRouter);
138
- this.app.use('/api/v1/hosts', authMiddleware, hostsRouter);
139
- this.app.use('/api/v1/speech', authMiddleware, speechRouter);
140
- this.app.use('/api/v1/upload', authMiddleware, uploadRouter);
141
-
142
- // 9. Serve frontend
117
+ this.app.use('/api/v1/status', statusRouter);
118
+ this.app.use('/api/v1/hosts', hostsRouter);
119
+ this.app.use('/api/v1/tmux', tmuxRouter);
120
+ this.app.use('/api/v1/launchers', launchersRouter);
121
+ this.app.use('/api/v1/runtime', runtimeRouter);
122
+
123
+ // Serve frontend
143
124
  const frontendDist = path.join(__dirname, '../../frontend/dist');
144
125
  if (fs.existsSync(frontendDist)) {
145
126
  this.app.use(express.static(frontendDist));
@@ -150,13 +131,13 @@ class NexusCrewServer {
150
131
  });
151
132
  }
152
133
 
153
- // 10. Error handler
134
+ // Error handler
154
135
  this.app.use((err, req, res, next) => {
155
136
  console.error('[Error]', err.message);
156
137
  res.status(500).json({ error: err.message });
157
138
  });
158
139
 
159
- // 11. Start HTTP server
140
+ // Start HTTP server
160
141
  this.server = http.createServer(this.app);
161
142
 
162
143
  return new Promise((resolve) => {
@@ -167,13 +148,13 @@ class NexusCrewServer {
167
148
  console.log('╚══════════════════════════════════════════════╝');
168
149
  console.log('');
169
150
  console.log(` HTTP: http://localhost:${this.port}`);
170
- console.log(` tmux: session "${tmuxManager.sessionName}" (${tmuxManager.listWindows().length} windows)`);
151
+ console.log(` tmux: ${tmuxManager.listSessions().length} active sessions`);
171
152
  console.log(` Hosts: ${hosts.map(h => h.name).join(', ')}`);
172
153
  console.log('');
173
154
 
174
- const engines = engineDiscovery.discover();
175
- for (const [name, info] of Object.entries(engines)) {
176
- console.log(` ${info.available ? 'OK' : ' '} ${name}${info.aliases.length ? ` (+${info.aliases.length} aliases)` : ''}`);
155
+ const discovery = engineDiscovery.discover();
156
+ for (const launcher of discovery.launchers) {
157
+ console.log(` OK ${launcher.label} [${launcher.kind}]`);
177
158
  }
178
159
  console.log('');
179
160
 
@@ -184,7 +165,6 @@ class NexusCrewServer {
184
165
 
185
166
  stop() {
186
167
  if (this.server) {
187
- saveDb();
188
168
  this.server.close();
189
169
  }
190
170
  }