mstro-app 0.1.58 → 0.3.0
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/PRIVACY.md +126 -0
- package/README.md +24 -23
- package/bin/commands/login.js +85 -42
- package/bin/commands/logout.js +35 -1
- package/bin/commands/status.js +1 -1
- package/bin/mstro.js +231 -131
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker.js +550 -115
- package/dist/server/cli/headless/claude-invoker.js.map +1 -1
- package/dist/server/cli/headless/index.d.ts +2 -1
- package/dist/server/cli/headless/index.d.ts.map +1 -1
- package/dist/server/cli/headless/index.js +2 -0
- package/dist/server/cli/headless/index.js.map +1 -1
- package/dist/server/cli/headless/prompt-utils.d.ts +5 -8
- package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -1
- package/dist/server/cli/headless/prompt-utils.js +40 -5
- package/dist/server/cli/headless/prompt-utils.js.map +1 -1
- package/dist/server/cli/headless/runner.d.ts +1 -1
- package/dist/server/cli/headless/runner.d.ts.map +1 -1
- package/dist/server/cli/headless/runner.js +52 -7
- package/dist/server/cli/headless/runner.js.map +1 -1
- package/dist/server/cli/headless/stall-assessor.d.ts +79 -1
- package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
- package/dist/server/cli/headless/stall-assessor.js +355 -20
- package/dist/server/cli/headless/stall-assessor.js.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.d.ts +70 -0
- package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -0
- package/dist/server/cli/headless/tool-watchdog.js +302 -0
- package/dist/server/cli/headless/tool-watchdog.js.map +1 -0
- package/dist/server/cli/headless/types.d.ts +98 -1
- package/dist/server/cli/headless/types.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.d.ts +136 -2
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.js +929 -132
- package/dist/server/cli/improvisation-session-manager.js.map +1 -1
- package/dist/server/index.js +5 -13
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +18 -0
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/security-audit.d.ts +2 -2
- package/dist/server/mcp/security-audit.d.ts.map +1 -1
- package/dist/server/mcp/security-audit.js +12 -8
- package/dist/server/mcp/security-audit.js.map +1 -1
- package/dist/server/mcp/security-patterns.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.js +9 -4
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/routes/improvise.js +6 -6
- package/dist/server/routes/improvise.js.map +1 -1
- package/dist/server/services/analytics.d.ts +2 -0
- package/dist/server/services/analytics.d.ts.map +1 -1
- package/dist/server/services/analytics.js +26 -4
- package/dist/server/services/analytics.js.map +1 -1
- package/dist/server/services/platform.d.ts.map +1 -1
- package/dist/server/services/platform.js +17 -10
- package/dist/server/services/platform.js.map +1 -1
- package/dist/server/services/sandbox-utils.d.ts +6 -0
- package/dist/server/services/sandbox-utils.d.ts.map +1 -0
- package/dist/server/services/sandbox-utils.js +72 -0
- package/dist/server/services/sandbox-utils.js.map +1 -0
- package/dist/server/services/settings.d.ts +6 -0
- package/dist/server/services/settings.d.ts.map +1 -1
- package/dist/server/services/settings.js +21 -0
- package/dist/server/services/settings.js.map +1 -1
- package/dist/server/services/terminal/pty-manager.d.ts +5 -51
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
- package/dist/server/services/terminal/pty-manager.js +63 -102
- package/dist/server/services/terminal/pty-manager.js.map +1 -1
- package/dist/server/services/websocket/file-explorer-handlers.d.ts +5 -0
- package/dist/server/services/websocket/file-explorer-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/file-explorer-handlers.js +518 -0
- package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -0
- package/dist/server/services/websocket/git-handlers.d.ts +36 -0
- package/dist/server/services/websocket/git-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/git-handlers.js +797 -0
- package/dist/server/services/websocket/git-handlers.js.map +1 -0
- package/dist/server/services/websocket/git-pr-handlers.d.ts +4 -0
- package/dist/server/services/websocket/git-pr-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/git-pr-handlers.js +299 -0
- package/dist/server/services/websocket/git-pr-handlers.js.map +1 -0
- package/dist/server/services/websocket/git-worktree-handlers.d.ts +4 -0
- package/dist/server/services/websocket/git-worktree-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/git-worktree-handlers.js +353 -0
- package/dist/server/services/websocket/git-worktree-handlers.js.map +1 -0
- package/dist/server/services/websocket/handler-context.d.ts +32 -0
- package/dist/server/services/websocket/handler-context.d.ts.map +1 -0
- package/dist/server/services/websocket/handler-context.js +4 -0
- package/dist/server/services/websocket/handler-context.js.map +1 -0
- package/dist/server/services/websocket/handler.d.ts +27 -338
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +74 -2106
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/index.d.ts +1 -1
- package/dist/server/services/websocket/index.d.ts.map +1 -1
- package/dist/server/services/websocket/index.js.map +1 -1
- package/dist/server/services/websocket/session-handlers.d.ts +10 -0
- package/dist/server/services/websocket/session-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/session-handlers.js +507 -0
- package/dist/server/services/websocket/session-handlers.js.map +1 -0
- package/dist/server/services/websocket/settings-handlers.d.ts +6 -0
- package/dist/server/services/websocket/settings-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/settings-handlers.js +125 -0
- package/dist/server/services/websocket/settings-handlers.js.map +1 -0
- package/dist/server/services/websocket/tab-handlers.d.ts +10 -0
- package/dist/server/services/websocket/tab-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/tab-handlers.js +131 -0
- package/dist/server/services/websocket/tab-handlers.js.map +1 -0
- package/dist/server/services/websocket/terminal-handlers.d.ts +9 -0
- package/dist/server/services/websocket/terminal-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/terminal-handlers.js +220 -0
- package/dist/server/services/websocket/terminal-handlers.js.map +1 -0
- package/dist/server/services/websocket/types.d.ts +67 -2
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/hooks/bouncer.sh +11 -4
- package/package.json +7 -2
- package/server/README.md +176 -159
- package/server/cli/headless/claude-invoker.ts +740 -133
- package/server/cli/headless/index.ts +7 -1
- package/server/cli/headless/output-utils.test.ts +225 -0
- package/server/cli/headless/prompt-utils.ts +37 -5
- package/server/cli/headless/runner.ts +55 -8
- package/server/cli/headless/stall-assessor.test.ts +165 -0
- package/server/cli/headless/stall-assessor.ts +478 -22
- package/server/cli/headless/tool-watchdog.test.ts +429 -0
- package/server/cli/headless/tool-watchdog.ts +398 -0
- package/server/cli/headless/types.ts +93 -1
- package/server/cli/improvisation-session-manager.ts +1133 -145
- package/server/index.ts +5 -14
- package/server/mcp/README.md +59 -67
- package/server/mcp/bouncer-integration.test.ts +161 -0
- package/server/mcp/bouncer-integration.ts +28 -0
- package/server/mcp/security-audit.ts +12 -8
- package/server/mcp/security-patterns.test.ts +258 -0
- package/server/mcp/security-patterns.ts +8 -2
- package/server/routes/improvise.ts +6 -6
- package/server/services/analytics.ts +26 -4
- package/server/services/platform.test.ts +0 -10
- package/server/services/platform.ts +16 -11
- package/server/services/sandbox-utils.ts +78 -0
- package/server/services/settings.ts +25 -0
- package/server/services/terminal/pty-manager.ts +68 -129
- package/server/services/websocket/autocomplete.test.ts +194 -0
- package/server/services/websocket/file-explorer-handlers.ts +587 -0
- package/server/services/websocket/git-handlers.ts +924 -0
- package/server/services/websocket/git-pr-handlers.ts +363 -0
- package/server/services/websocket/git-worktree-handlers.ts +403 -0
- package/server/services/websocket/handler-context.ts +44 -0
- package/server/services/websocket/handler.test.ts +1 -1
- package/server/services/websocket/handler.ts +90 -2421
- package/server/services/websocket/index.ts +1 -1
- package/server/services/websocket/session-handlers.ts +574 -0
- package/server/services/websocket/settings-handlers.ts +150 -0
- package/server/services/websocket/tab-handlers.ts +150 -0
- package/server/services/websocket/terminal-handlers.ts +277 -0
- package/server/services/websocket/types.ts +145 -4
- package/bin/release.sh +0 -110
- package/dist/server/services/terminal/tmux-manager.d.ts +0 -82
- package/dist/server/services/terminal/tmux-manager.d.ts.map +0 -1
- package/dist/server/services/terminal/tmux-manager.js +0 -352
- package/dist/server/services/terminal/tmux-manager.js.map +0 -1
- package/server/services/terminal/tmux-manager.ts +0 -426
package/bin/mstro.js
CHANGED
|
@@ -8,20 +8,19 @@
|
|
|
8
8
|
* Main entry point for the Mstro AI assistant.
|
|
9
9
|
*
|
|
10
10
|
* Usage:
|
|
11
|
-
* mstro # Start Mstro (
|
|
12
|
-
* mstro login #
|
|
11
|
+
* mstro # Start Mstro (logs in automatically if needed)
|
|
12
|
+
* mstro login # Re-authenticate this device
|
|
13
13
|
* mstro logout # Sign out
|
|
14
14
|
* mstro whoami # Show current user
|
|
15
15
|
* mstro status # Show connection status
|
|
16
|
-
* mstro setup-terminal # Enable web terminal
|
|
17
16
|
* mstro -p 4105 # Start on specific port (overrides auto port)
|
|
18
17
|
* mstro configure-hooks # Configure Claude Code security hooks
|
|
19
18
|
* mstro --help # Show help
|
|
20
19
|
*/
|
|
21
20
|
|
|
22
|
-
import {
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
23
22
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
24
|
-
import { homedir
|
|
23
|
+
import { homedir } from 'node:os';
|
|
25
24
|
import { dirname, join, resolve } from 'node:path';
|
|
26
25
|
import { createInterface } from 'node:readline';
|
|
27
26
|
import { fileURLToPath } from 'node:url';
|
|
@@ -36,10 +35,27 @@ const CLIENT_ROOT = resolve(__dirname, '..');
|
|
|
36
35
|
const pkg = JSON.parse(readFileSync(join(CLIENT_ROOT, 'package.json'), 'utf-8'));
|
|
37
36
|
|
|
38
37
|
// Check for updates (runs async in background, notifies on next run)
|
|
38
|
+
// update-notifier initializes lastUpdateCheck to Date.now(), which means the
|
|
39
|
+
// first check won't happen until 24h after install. We detect first-run by
|
|
40
|
+
// checking if the configstore has never stored an update result, and if so
|
|
41
|
+
// reset the timestamp to force an immediate background check.
|
|
39
42
|
const notifier = updateNotifier({
|
|
40
43
|
pkg,
|
|
41
44
|
updateCheckInterval: 1000 * 60 * 60 * 24 // Check daily
|
|
42
45
|
});
|
|
46
|
+
try {
|
|
47
|
+
if (notifier.config && !notifier.config.has('update') && !notifier.update) {
|
|
48
|
+
const lastCheck = notifier.config.get('lastUpdateCheck');
|
|
49
|
+
// If lastUpdateCheck was just set (within the last 30s), this is a fresh
|
|
50
|
+
// configstore — reset it to 0 so the library spawns a check immediately.
|
|
51
|
+
if (lastCheck && (Date.now() - lastCheck) < 30_000) {
|
|
52
|
+
notifier.config.set('lastUpdateCheck', 0);
|
|
53
|
+
notifier.check();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} catch {
|
|
57
|
+
// Non-critical — don't let update check logic crash the CLI
|
|
58
|
+
}
|
|
43
59
|
|
|
44
60
|
// Capture the user's original working directory before any cwd changes
|
|
45
61
|
const USER_CWD = process.cwd();
|
|
@@ -47,10 +63,10 @@ const USER_CWD = process.cwd();
|
|
|
47
63
|
// First-run detection paths
|
|
48
64
|
const MSTRO_CONFIG_DIR = join(homedir(), '.mstro');
|
|
49
65
|
const MSTRO_FIRST_RUN_FLAG = join(MSTRO_CONFIG_DIR, '.configured');
|
|
50
|
-
const MSTRO_TERMINAL_CHECKED_FLAG = join(MSTRO_CONFIG_DIR, '.terminal-checked');
|
|
51
66
|
const CLAUDE_SETTINGS_FILE = join(homedir(), '.claude', 'settings.json');
|
|
52
67
|
const CLAUDE_HOOKS_DIR = join(homedir(), '.claude', 'hooks');
|
|
53
68
|
const BOUNCER_HOOK_FILE = join(CLAUDE_HOOKS_DIR, 'bouncer.sh');
|
|
69
|
+
const PTY_SETUP_DISMISSED_FLAG = join(MSTRO_CONFIG_DIR, '.pty-setup-dismissed');
|
|
54
70
|
|
|
55
71
|
/**
|
|
56
72
|
* Mark Mstro as configured by writing the first-run flag file
|
|
@@ -195,19 +211,163 @@ async function promptBouncerSetup() {
|
|
|
195
211
|
}
|
|
196
212
|
}
|
|
197
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Check if node-pty native module is loadable
|
|
216
|
+
*/
|
|
217
|
+
async function isNodePtyAvailable() {
|
|
218
|
+
try {
|
|
219
|
+
await import('node-pty');
|
|
220
|
+
return true;
|
|
221
|
+
} catch {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Check if user has dismissed the pty setup prompt
|
|
228
|
+
*/
|
|
229
|
+
function hasUserDismissedPtySetup() {
|
|
230
|
+
return existsSync(PTY_SETUP_DISMISSED_FLAG);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Mark pty setup prompt as dismissed
|
|
235
|
+
*/
|
|
236
|
+
function markPtySetupDismissed() {
|
|
237
|
+
if (!existsSync(MSTRO_CONFIG_DIR)) {
|
|
238
|
+
mkdirSync(MSTRO_CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
239
|
+
}
|
|
240
|
+
writeFileSync(PTY_SETUP_DISMISSED_FLAG, new Date().toISOString());
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Show a one-line warning that node-pty is not available
|
|
245
|
+
*/
|
|
246
|
+
function showPtyWarning() {
|
|
247
|
+
log(' Terminal support not available. Run: mstro setup-terminal', colors.dim);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get platform-specific build tool instructions
|
|
252
|
+
*/
|
|
253
|
+
function getPtyBuildInstructions() {
|
|
254
|
+
const os = process.platform;
|
|
255
|
+
if (os === 'darwin') {
|
|
256
|
+
return ' Install Xcode Command Line Tools: xcode-select --install';
|
|
257
|
+
}
|
|
258
|
+
if (os === 'win32') {
|
|
259
|
+
return ' Install Windows Build Tools: npm install -g windows-build-tools';
|
|
260
|
+
}
|
|
261
|
+
return ' Debian/Ubuntu: sudo apt install build-essential python3\n' +
|
|
262
|
+
' Fedora/RHEL: sudo dnf install gcc-c++ make python3\n' +
|
|
263
|
+
' Arch: sudo pacman -S base-devel python';
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Attempt to rebuild/install node-pty from CLIENT_ROOT
|
|
268
|
+
* Returns true if npm command succeeded, false otherwise
|
|
269
|
+
*/
|
|
270
|
+
function attemptPtyRebuild() {
|
|
271
|
+
return new Promise((resolve) => {
|
|
272
|
+
const nodePtyDir = join(CLIENT_ROOT, 'node_modules', 'node-pty');
|
|
273
|
+
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
274
|
+
const command = existsSync(nodePtyDir) ? 'rebuild' : 'install';
|
|
275
|
+
const args = command === 'rebuild'
|
|
276
|
+
? ['rebuild', 'node-pty']
|
|
277
|
+
: ['install', 'node-pty', '--no-save'];
|
|
278
|
+
|
|
279
|
+
log(`\n ${command === 'rebuild' ? 'Rebuilding' : 'Installing'} node-pty...`, colors.dim);
|
|
280
|
+
|
|
281
|
+
const child = spawn(npmCmd, args, {
|
|
282
|
+
cwd: CLIENT_ROOT,
|
|
283
|
+
stdio: 'inherit',
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
child.on('error', (err) => {
|
|
287
|
+
log(` Error: ${err.message}`, colors.red);
|
|
288
|
+
resolve(false);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
child.on('exit', (code) => {
|
|
292
|
+
resolve(code === 0);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Prompt user to set up node-pty for terminal support
|
|
299
|
+
* Returns: 'configure' | 'skip' | 'never'
|
|
300
|
+
*/
|
|
301
|
+
async function promptPtySetup() {
|
|
302
|
+
log('\n Terminal Support\n', colors.bold + colors.cyan);
|
|
303
|
+
log(' Mstro includes a web terminal that lets you open a shell', colors.dim);
|
|
304
|
+
log(' directly in your browser. This requires compiling a native module (node-pty).\n', colors.dim);
|
|
305
|
+
|
|
306
|
+
const isInteractive = process.stdin.isTTY;
|
|
307
|
+
|
|
308
|
+
if (!isInteractive) {
|
|
309
|
+
log(' Non-interactive mode: skipping terminal setup.', colors.yellow);
|
|
310
|
+
log(' Run "mstro setup-terminal" to enable terminal support.\n', colors.dim);
|
|
311
|
+
return 'skip';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
log(' Set up terminal support now?', colors.bold);
|
|
315
|
+
log(' [Y] Yes, compile now (requires build tools)', colors.dim);
|
|
316
|
+
log(' [n] Not now (ask again next time)', colors.dim);
|
|
317
|
+
log(' [d] Don\'t show this again\n', colors.dim);
|
|
318
|
+
|
|
319
|
+
const answer = await prompt(' Your choice [Y/n/d]: ');
|
|
320
|
+
const choice = answer.toLowerCase();
|
|
321
|
+
|
|
322
|
+
if (choice === '' || choice === 'y' || choice === 'yes') {
|
|
323
|
+
return 'configure';
|
|
324
|
+
}
|
|
325
|
+
if (choice === 'd' || choice === 'dont' || choice === "don't") {
|
|
326
|
+
log('\n Got it! You can set up later with: mstro setup-terminal\n', colors.dim);
|
|
327
|
+
markPtySetupDismissed();
|
|
328
|
+
return 'never';
|
|
329
|
+
}
|
|
330
|
+
log('\n Skipping for now. Will ask again next time.', colors.yellow);
|
|
331
|
+
log(' You can also set up with: mstro setup-terminal\n', colors.dim);
|
|
332
|
+
return 'skip';
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Run the pty rebuild and show results
|
|
337
|
+
*/
|
|
338
|
+
async function runPtySetup() {
|
|
339
|
+
const success = await attemptPtyRebuild();
|
|
340
|
+
|
|
341
|
+
if (success) {
|
|
342
|
+
const available = await isNodePtyAvailable();
|
|
343
|
+
if (available) {
|
|
344
|
+
log('\n Terminal support enabled successfully!\n', colors.bold + colors.green);
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
log('\n node-pty installed but failed to load.', colors.red);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
log('\n Could not compile node-pty automatically.\n', colors.yellow);
|
|
351
|
+
log(' You may need to install build tools first:\n', colors.bold);
|
|
352
|
+
log(getPtyBuildInstructions(), colors.dim);
|
|
353
|
+
log('');
|
|
354
|
+
log(' After installing build tools, run: mstro setup-terminal\n', colors.dim);
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
|
|
198
358
|
function showHelp() {
|
|
199
|
-
log('\n Mstro -
|
|
200
|
-
log('
|
|
359
|
+
log('\n Mstro - Run Claude Code from any browser\n', colors.bold + colors.cyan);
|
|
360
|
+
log(' Streams live Claude Code sessions from your machine to mstro.app.\n', colors.dim);
|
|
201
361
|
log(' Usage:', colors.bold);
|
|
202
|
-
log(' mstro Start Mstro (
|
|
203
|
-
log(' mstro login
|
|
362
|
+
log(' mstro Start Mstro (logs in automatically if needed)', colors.dim);
|
|
363
|
+
log(' mstro login Re-authenticate this device with mstro.app', colors.dim);
|
|
204
364
|
log(' mstro logout Sign out of mstro.app', colors.dim);
|
|
205
365
|
log(' mstro whoami Show current user and device info', colors.dim);
|
|
206
366
|
log(' mstro status Show connection and auth status', colors.dim);
|
|
207
367
|
log(' mstro telemetry [on|off] Enable/disable anonymous telemetry', colors.dim);
|
|
208
|
-
log(' mstro setup-terminal Enable web terminal (compiles native module)', colors.dim);
|
|
209
368
|
log(' mstro -p 4105 Start on specific port (overrides auto port)', colors.dim);
|
|
210
369
|
log(' mstro configure-hooks Configure Claude Code security hooks', colors.dim);
|
|
370
|
+
log(' mstro setup-terminal Enable web terminal (compiles native module)', colors.dim);
|
|
211
371
|
log(' mstro --version Show version number', colors.dim);
|
|
212
372
|
log(' mstro --help Show this help message', colors.dim);
|
|
213
373
|
log('');
|
|
@@ -217,8 +377,8 @@ function showHelp() {
|
|
|
217
377
|
log(' --verbose, -v Enable verbose output', colors.dim);
|
|
218
378
|
log('');
|
|
219
379
|
log(' Authentication:', colors.bold);
|
|
220
|
-
log('
|
|
221
|
-
log(' Once logged in,
|
|
380
|
+
log(' Running "mstro" will prompt you to log in automatically if needed.', colors.dim);
|
|
381
|
+
log(' Once logged in, machines sync automatically with your web dashboard.', colors.dim);
|
|
222
382
|
log('');
|
|
223
383
|
log(' Security:', colors.bold);
|
|
224
384
|
log(' Mstro includes a Security Bouncer that automatically manages', colors.dim);
|
|
@@ -229,7 +389,7 @@ function showHelp() {
|
|
|
229
389
|
|
|
230
390
|
function runNpmScript(script, args = [], envOverrides = {}) {
|
|
231
391
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
232
|
-
const child = spawn(npmCmd, ['run', script, ...args], {
|
|
392
|
+
const child = spawn(npmCmd, ['run', '--silent', script, ...args], {
|
|
233
393
|
cwd: CLIENT_ROOT,
|
|
234
394
|
stdio: 'inherit',
|
|
235
395
|
env: { ...process.env, MSTRO_WORKING_DIR: USER_CWD, ...envOverrides },
|
|
@@ -291,7 +451,6 @@ function runConfigureHooks(andThenStart = false) {
|
|
|
291
451
|
markConfigured();
|
|
292
452
|
if (andThenStart) {
|
|
293
453
|
// After configuring, start the server
|
|
294
|
-
log('\nStarting Mstro client...', colors.bold + colors.cyan);
|
|
295
454
|
const requestedPort = parsePort(process.argv.slice(2));
|
|
296
455
|
const envOverrides = requestedPort ? { PORT: String(requestedPort) } : {};
|
|
297
456
|
runNpmScript('start', [], envOverrides);
|
|
@@ -325,14 +484,18 @@ function parsePort(args) {
|
|
|
325
484
|
* Show update notification if available
|
|
326
485
|
*/
|
|
327
486
|
function showUpdateNotification() {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
487
|
+
try {
|
|
488
|
+
if (notifier.update && semverGt(notifier.update.latest, notifier.update.current)) {
|
|
489
|
+
const { current, latest, type } = notifier.update;
|
|
490
|
+
const updateCmd = `npm i -g ${pkg.name}`;
|
|
491
|
+
|
|
492
|
+
log('');
|
|
493
|
+
log(` ${colors.yellow}Update available:${colors.reset} ${colors.dim}${current}${colors.reset} → ${colors.green}${latest}${colors.reset} ${colors.dim}(${type})${colors.reset}`);
|
|
494
|
+
log(` Run: ${colors.cyan}${updateCmd}${colors.reset}`);
|
|
495
|
+
log('');
|
|
496
|
+
}
|
|
497
|
+
} catch {
|
|
498
|
+
// Don't let a corrupted cache or invalid semver crash the CLI
|
|
336
499
|
}
|
|
337
500
|
}
|
|
338
501
|
|
|
@@ -353,136 +516,63 @@ function isLoggedIn() {
|
|
|
353
516
|
}
|
|
354
517
|
|
|
355
518
|
/**
|
|
356
|
-
*
|
|
519
|
+
* Auto-login if not authenticated. Exits on failure.
|
|
357
520
|
*/
|
|
358
|
-
function
|
|
359
|
-
|
|
360
|
-
log('');
|
|
361
|
-
log(' You must be logged in to use mstro.', colors.dim);
|
|
362
|
-
log(' Run "mstro login" to authenticate this device.', colors.dim);
|
|
363
|
-
log('');
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* Check if node-pty is loadable (native module compiled correctly)
|
|
368
|
-
*/
|
|
369
|
-
async function isNodePtyAvailable() {
|
|
521
|
+
async function ensureLoggedIn() {
|
|
522
|
+
if (isLoggedIn()) return;
|
|
523
|
+
log('\n Not logged in — starting authentication...\n', colors.bold + colors.cyan);
|
|
370
524
|
try {
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
return false;
|
|
525
|
+
const { login } = await import('./commands/login.js');
|
|
526
|
+
await login(args, { inline: true });
|
|
527
|
+
} catch (err) {
|
|
528
|
+
log(`\n Login failed: ${err.message}`, colors.red);
|
|
529
|
+
log(' Run "mstro login" to try again.\n', colors.dim);
|
|
530
|
+
process.exit(1);
|
|
378
531
|
}
|
|
379
532
|
}
|
|
380
533
|
|
|
381
534
|
/**
|
|
382
|
-
*
|
|
535
|
+
* Prompt for bouncer setup if not configured
|
|
536
|
+
* Returns true if runConfigureHooks was called (async exit path)
|
|
383
537
|
*/
|
|
384
|
-
function
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
} catch {
|
|
538
|
+
async function ensureBouncerSetup() {
|
|
539
|
+
if (isBouncerConfigured()) return false;
|
|
540
|
+
if (hasUserDismissedSetup()) {
|
|
541
|
+
showBouncerWarning();
|
|
389
542
|
return false;
|
|
390
543
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
*/
|
|
396
|
-
function getBuildToolInstructions() {
|
|
397
|
-
const os = osPlatform();
|
|
398
|
-
if (os === 'darwin') {
|
|
399
|
-
return ' xcode-select --install';
|
|
400
|
-
} else if (os === 'win32') {
|
|
401
|
-
return ' npm install -g windows-build-tools';
|
|
402
|
-
} else {
|
|
403
|
-
return ' sudo apt install build-essential python3 # Debian/Ubuntu\n sudo dnf install gcc-c++ make python3 # Fedora/RHEL';
|
|
544
|
+
const choice = await promptBouncerSetup();
|
|
545
|
+
if (choice === 'configure') {
|
|
546
|
+
runConfigureHooks(true);
|
|
547
|
+
return true;
|
|
404
548
|
}
|
|
549
|
+
return false;
|
|
405
550
|
}
|
|
406
551
|
|
|
407
552
|
/**
|
|
408
|
-
*
|
|
409
|
-
* Tries to rebuild node-pty automatically. If that fails, shows instructions.
|
|
553
|
+
* Prompt for node-pty setup if not available
|
|
410
554
|
*/
|
|
411
|
-
async function
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
log('\n Web Terminal', colors.bold + colors.cyan);
|
|
417
|
-
log(' mstro includes a browser-based terminal (optional).\n', colors.dim);
|
|
418
|
-
log(' Attempting to compile native module...', colors.dim);
|
|
419
|
-
|
|
420
|
-
if (tryRebuildNodePty()) {
|
|
421
|
-
log(' Terminal support enabled!\n', colors.green);
|
|
555
|
+
async function ensurePtySetup() {
|
|
556
|
+
const ptyAvailable = await isNodePtyAvailable();
|
|
557
|
+
if (ptyAvailable) return;
|
|
558
|
+
if (hasUserDismissedPtySetup()) {
|
|
559
|
+
showPtyWarning();
|
|
422
560
|
return;
|
|
423
561
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
log(' 1. Install build tools:', colors.dim);
|
|
428
|
-
log(getBuildToolInstructions(), colors.dim);
|
|
429
|
-
log(' 2. Run:', colors.dim);
|
|
430
|
-
log(' mstro setup-terminal\n', colors.dim);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
/**
|
|
434
|
-
* Explicit setup-terminal command
|
|
435
|
-
*/
|
|
436
|
-
async function setupTerminal() {
|
|
437
|
-
log('\n Setting up terminal support...\n', colors.bold + colors.cyan);
|
|
438
|
-
|
|
439
|
-
if (await isNodePtyAvailable()) {
|
|
440
|
-
log(' Terminal support is already enabled.\n', colors.green);
|
|
441
|
-
return;
|
|
562
|
+
const choice = await promptPtySetup();
|
|
563
|
+
if (choice === 'configure') {
|
|
564
|
+
await runPtySetup();
|
|
442
565
|
}
|
|
443
|
-
|
|
444
|
-
log(' Rebuilding node-pty native module...', colors.dim);
|
|
445
|
-
|
|
446
|
-
if (tryRebuildNodePty()) {
|
|
447
|
-
log('\n Terminal support enabled! Restart mstro to use it.\n', colors.green + colors.bold);
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
log('\n Failed to build node-pty.\n', colors.red);
|
|
452
|
-
log(' Install build tools first:', colors.dim);
|
|
453
|
-
log(getBuildToolInstructions(), colors.dim);
|
|
454
|
-
log('\n Then re-run: mstro setup-terminal\n', colors.dim);
|
|
455
|
-
process.exit(1);
|
|
456
566
|
}
|
|
457
567
|
|
|
458
568
|
async function startServer(envOverrides) {
|
|
459
|
-
|
|
460
|
-
showLoginRequired();
|
|
461
|
-
process.exit(1);
|
|
462
|
-
}
|
|
569
|
+
await ensureLoggedIn();
|
|
463
570
|
|
|
464
|
-
if (
|
|
465
|
-
if (hasUserDismissedSetup()) {
|
|
466
|
-
showBouncerWarning();
|
|
467
|
-
} else {
|
|
468
|
-
const choice = await promptBouncerSetup();
|
|
469
|
-
if (choice === 'configure') {
|
|
470
|
-
runConfigureHooks(true);
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
571
|
+
if (await ensureBouncerSetup()) return;
|
|
475
572
|
|
|
476
|
-
|
|
477
|
-
await checkTerminalSetup();
|
|
478
|
-
if (!existsSync(MSTRO_CONFIG_DIR)) {
|
|
479
|
-
mkdirSync(MSTRO_CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
480
|
-
}
|
|
481
|
-
writeFileSync(MSTRO_TERMINAL_CHECKED_FLAG, new Date().toISOString());
|
|
482
|
-
}
|
|
573
|
+
await ensurePtySetup();
|
|
483
574
|
|
|
484
575
|
showUpdateNotification();
|
|
485
|
-
log('\nStarting Mstro client...', colors.bold + colors.cyan);
|
|
486
576
|
runNpmScript('start', [], envOverrides);
|
|
487
577
|
}
|
|
488
578
|
|
|
@@ -504,7 +594,7 @@ async function main() {
|
|
|
504
594
|
}],
|
|
505
595
|
['logout', async () => {
|
|
506
596
|
const { logout } = await import('./commands/logout.js');
|
|
507
|
-
await logout();
|
|
597
|
+
await logout(args.slice(args.indexOf('logout') + 1));
|
|
508
598
|
}],
|
|
509
599
|
['whoami', async () => {
|
|
510
600
|
const { whoami } = await import('./commands/whoami.js');
|
|
@@ -518,8 +608,17 @@ async function main() {
|
|
|
518
608
|
const { telemetry } = await import('./commands/config.js');
|
|
519
609
|
await telemetry(args.slice(args.indexOf('telemetry') + 1));
|
|
520
610
|
}],
|
|
521
|
-
['setup-terminal', () => setupTerminal()],
|
|
522
611
|
['configure-hooks', () => runConfigureHooks(false)],
|
|
612
|
+
['setup-terminal', async () => {
|
|
613
|
+
log('\n Mstro Terminal Setup\n', colors.bold + colors.cyan);
|
|
614
|
+
const alreadyAvailable = await isNodePtyAvailable();
|
|
615
|
+
if (alreadyAvailable) {
|
|
616
|
+
log(' node-pty is already available. Terminal support is enabled!\n', colors.green);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
const success = await runPtySetup();
|
|
620
|
+
process.exit(success ? 0 : 1);
|
|
621
|
+
}],
|
|
523
622
|
]);
|
|
524
623
|
|
|
525
624
|
// Flag-based commands
|
|
@@ -544,6 +643,7 @@ async function main() {
|
|
|
544
643
|
const handler = subcommand ? commands.get(subcommand) : undefined;
|
|
545
644
|
if (handler) {
|
|
546
645
|
await handler();
|
|
646
|
+
showUpdateNotification();
|
|
547
647
|
return;
|
|
548
648
|
}
|
|
549
649
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-invoker.d.ts","sourceRoot":"","sources":["../../../../server/cli/headless/claude-invoker.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-invoker.d.ts","sourceRoot":"","sources":["../../../../server/cli/headless/claude-invoker.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;AAO9D,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC7C;AAmgCD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,eAAe,CAAC,CA0H1B"}
|