genbox 1.0.164 → 1.0.165

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.
@@ -153,18 +153,48 @@ function extractLocalImagePath(text) {
153
153
  }
154
154
  return { path: null };
155
155
  }
156
+ // SSH ControlMaster for faster subsequent connections
157
+ function getControlPath(ipAddress) {
158
+ return `/tmp/genbox-ssh-${ipAddress}`;
159
+ }
160
+ function setupSshMultiplexing(ipAddress, keyPath) {
161
+ const controlPath = getControlPath(ipAddress);
162
+ // Check if master connection already exists
163
+ const checkResult = (0, child_process_1.spawnSync)('ssh', [
164
+ '-O', 'check',
165
+ '-o', `ControlPath=${controlPath}`,
166
+ `dev@${ipAddress}`
167
+ ], { stdio: 'ignore' });
168
+ if (checkResult.status === 0) {
169
+ return; // Already connected
170
+ }
171
+ // Start master connection in background
172
+ (0, child_process_1.spawn)('ssh', [
173
+ '-i', keyPath,
174
+ '-o', 'StrictHostKeyChecking=no',
175
+ '-o', 'UserKnownHostsFile=/dev/null',
176
+ '-o', 'ControlMaster=yes',
177
+ '-o', `ControlPath=${controlPath}`,
178
+ '-o', 'ControlPersist=10m',
179
+ '-fN', // Background, no command
180
+ `dev@${ipAddress}`
181
+ ], { stdio: 'ignore', detached: true });
182
+ }
156
183
  function uploadFileSync(localPath, ipAddress, keyPath) {
157
184
  const fileName = path.basename(localPath);
158
185
  const timestamp = Date.now();
159
186
  const remotePath = `/home/dev/uploads/${timestamp}-${fileName}`;
187
+ const controlPath = getControlPath(ipAddress);
160
188
  try {
161
- // Ensure uploads directory exists
162
- (0, child_process_1.execSync)(`ssh -i "${keyPath}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null dev@${ipAddress} "mkdir -p /home/dev/uploads" 2>/dev/null`, { encoding: 'utf-8', timeout: 10000 });
163
- // Upload file
189
+ // Ensure uploads directory exists (uses multiplexed connection if available)
190
+ (0, child_process_1.execSync)(`ssh -i "${keyPath}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlPath=${controlPath} dev@${ipAddress} "mkdir -p /home/dev/uploads" 2>/dev/null`, { encoding: 'utf-8', timeout: 10000 });
191
+ // Upload file with compression and multiplexing
164
192
  const result = (0, child_process_1.spawnSync)('scp', [
165
193
  '-i', keyPath,
166
194
  '-o', 'StrictHostKeyChecking=no',
167
195
  '-o', 'UserKnownHostsFile=/dev/null',
196
+ '-o', `ControlPath=${controlPath}`,
197
+ '-C', // Enable compression
168
198
  localPath,
169
199
  `dev@${ipAddress}:${remotePath}`
170
200
  ], { timeout: 60000 });
@@ -177,6 +207,17 @@ function uploadFileSync(localPath, ipAddress, keyPath) {
177
207
  return { success: false, remotePath: '', error: error.message };
178
208
  }
179
209
  }
210
+ // Show message in tmux status bar
211
+ function showTmuxMessage(ipAddress, keyPath, sessionName, message) {
212
+ const controlPath = getControlPath(ipAddress);
213
+ try {
214
+ // Send message to tmux session's status bar
215
+ (0, child_process_1.execSync)(`ssh -i "${keyPath}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ControlPath=${controlPath} dev@${ipAddress} "tmux display-message -t ${sessionName} -d 3000 '${message.replace(/'/g, "\\'")}'" 2>/dev/null`, { encoding: 'utf-8', timeout: 5000 });
216
+ }
217
+ catch {
218
+ // Fallback to macOS notification if tmux message fails
219
+ }
220
+ }
180
221
  function getPrivateSshKey() {
181
222
  const home = os.homedir();
182
223
  const potentialKeys = [
@@ -450,8 +491,10 @@ async function attachToSession(ipAddress, keyPath, sessionName, genboxName) {
450
491
  console.log(chalk_1.default.dim(`\nAttaching to ${chalk_1.default.bold(sessionName)} on ${chalk_1.default.bold(genboxName)}...`));
451
492
  console.log(chalk_1.default.dim('Detach: Ctrl+b d'));
452
493
  console.log('');
453
- console.log(chalk_1.default.yellow('📋 Image Upload Active') + chalk_1.default.dim(' - Drag image select path Cmd+C → wait for → Cmd+V'));
454
- console.log(chalk_1.default.dim(' Watching clipboard for local image paths...\n'));
494
+ console.log(chalk_1.default.yellow('📋 Image Upload Active') + chalk_1.default.dim(' - Cmd+C image file → wait for tmux message → Cmd+V'));
495
+ console.log(chalk_1.default.dim(' Setting up fast upload connection...\n'));
496
+ // Set up SSH multiplexing for faster uploads
497
+ setupSshMultiplexing(ipAddress, keyPath);
455
498
  const sshArgs = [
456
499
  '-t',
457
500
  '-i', keyPath,
@@ -480,13 +523,7 @@ async function attachToSession(ipAddress, keyPath, sessionName, genboxName) {
480
523
  // If file path was detected but file doesn't exist (e.g., macOS temp file was cleaned up)
481
524
  if (extractResult.notFound) {
482
525
  const fileName = path.basename(extractResult.notFound);
483
- // Use macOS notification since tmux obscures stderr
484
- if (os.platform() === 'darwin') {
485
- try {
486
- (0, child_process_1.execSync)(`osascript -e 'display notification "File not found: ${fileName.replace(/'/g, "\\'")}" with title "Genbox" sound name "Basso"'`, { stdio: 'ignore' });
487
- }
488
- catch { }
489
- }
526
+ showTmuxMessage(ipAddress, keyPath, sessionName, '⚠ File not found: ' + fileName.substring(0, 30));
490
527
  return;
491
528
  }
492
529
  if (!extractResult.path) {
@@ -497,13 +534,8 @@ async function attachToSession(ipAddress, keyPath, sessionName, genboxName) {
497
534
  if (uploadedPaths.has(localPath)) {
498
535
  return;
499
536
  }
500
- // Show uploading notification
501
- if (os.platform() === 'darwin') {
502
- try {
503
- (0, child_process_1.execSync)(`osascript -e 'display notification "Uploading to genbox..." with title "📤 Image Detected"'`, { stdio: 'ignore' });
504
- }
505
- catch { }
506
- }
537
+ // Show uploading message in tmux
538
+ showTmuxMessage(ipAddress, keyPath, sessionName, '📤 Uploading image... please wait');
507
539
  // Upload the file (this happens in background, might cause brief pause)
508
540
  const result = uploadFileSync(localPath, ipAddress, keyPath);
509
541
  if (result.success) {
@@ -511,22 +543,12 @@ async function attachToSession(ipAddress, keyPath, sessionName, genboxName) {
511
543
  uploadedPaths.add(result.remotePath); // Also track remote path to avoid re-detection
512
544
  // Replace clipboard with remote path
513
545
  setClipboard(result.remotePath);
514
- // Use macOS notification since tmux obscures stderr
515
- if (os.platform() === 'darwin') {
516
- try {
517
- (0, child_process_1.execSync)(`osascript -e 'display notification "Copied to clipboard! Cmd+V to paste." with title "✓ Uploaded" sound name "Glass"'`, { stdio: 'ignore' });
518
- }
519
- catch { }
520
- }
546
+ // Show success in tmux
547
+ showTmuxMessage(ipAddress, keyPath, sessionName, '✓ Image ready! Press Cmd+V to paste');
521
548
  }
522
549
  else {
523
- // Notification for failure
524
- if (os.platform() === 'darwin') {
525
- try {
526
- (0, child_process_1.execSync)(`osascript -e 'display notification "Upload failed: ${(result.error || 'unknown').replace(/'/g, "\\'")}" with title "Genbox" sound name "Basso"'`, { stdio: 'ignore' });
527
- }
528
- catch { }
529
- }
550
+ // Show failure in tmux
551
+ showTmuxMessage(ipAddress, keyPath, sessionName, '✗ Upload failed: ' + (result.error || 'unknown'));
530
552
  }
531
553
  }
532
554
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.164",
3
+ "version": "1.0.165",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {