genbox 1.0.194 → 1.0.196
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/dist/commands/connect.js +15 -4
- package/dist/commands/create.js +31 -89
- package/dist/commands/destroy.js +3 -3
- package/dist/commands/provider-command.js +22 -2
- package/dist/commands/session/index.js +77 -98
- package/dist/commands/session/kill.js +148 -22
- package/dist/commands/session/list.js +138 -207
- package/dist/commands/session/migrate.js +14 -12
- package/dist/commands/session/start.js +145 -65
- package/dist/commands/session/stop.js +147 -24
- package/dist/commands/start.js +4 -5
- package/dist/commands/stop.js +3 -4
- package/dist/lib/local-orchestrator.js +14 -10
- package/dist/lib/session-migrator.js +17 -12
- package/dist/lib/unified-session/api-sync.js +278 -0
- package/dist/lib/unified-session/index.js +40 -0
- package/dist/lib/unified-session/migration.js +320 -0
- package/dist/lib/unified-session/types.js +43 -0
- package/dist/lib/unified-session/unified-session-manager.js +672 -0
- package/package.json +1 -1
- package/dist/lib/local-session-manager.js +0 -1501
- package/dist/lib/native-session-manager.js +0 -650
package/dist/commands/connect.js
CHANGED
|
@@ -42,7 +42,6 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
42
42
|
const api_1 = require("../api");
|
|
43
43
|
const genbox_selector_1 = require("../genbox-selector");
|
|
44
44
|
const ssh_config_1 = require("../ssh-config");
|
|
45
|
-
const local_session_manager_1 = require("../lib/local-session-manager");
|
|
46
45
|
const os = __importStar(require("os"));
|
|
47
46
|
const path = __importStar(require("path"));
|
|
48
47
|
const fs = __importStar(require("fs"));
|
|
@@ -101,11 +100,23 @@ exports.connectCommand = new commander_1.Command('connect')
|
|
|
101
100
|
});
|
|
102
101
|
return;
|
|
103
102
|
}
|
|
104
|
-
// Handle local genbox without VM - attach to session
|
|
103
|
+
// Handle local genbox without VM - attach to session (native mode)
|
|
105
104
|
if (isLocal && localSession) {
|
|
106
105
|
console.log(chalk_1.default.dim(`Attaching to local genbox ${chalk_1.default.bold(localSession.name)}...`));
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
// For native sessions, attach via dtach
|
|
107
|
+
const socketPath = path.join(os.homedir(), '.genbox', 'sockets', `${localSession.name}.sock`);
|
|
108
|
+
if (fs.existsSync(socketPath)) {
|
|
109
|
+
const dtach = (0, child_process_1.spawn)('dtach', ['-a', socketPath], { stdio: 'inherit' });
|
|
110
|
+
dtach.on('close', (code) => {
|
|
111
|
+
if (code !== 0) {
|
|
112
|
+
console.log(chalk_1.default.dim(`Session detached with code ${code}`));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.error(chalk_1.default.yellow(`Session socket not found: ${socketPath}`));
|
|
118
|
+
console.log(chalk_1.default.dim(`The session may have ended. Use 'gb session' to start a new one.`));
|
|
119
|
+
}
|
|
109
120
|
return;
|
|
110
121
|
}
|
|
111
122
|
if (!target.ipAddress) {
|
package/dist/commands/create.js
CHANGED
|
@@ -45,8 +45,8 @@ const fs = __importStar(require("fs"));
|
|
|
45
45
|
const path = __importStar(require("path"));
|
|
46
46
|
const child_process_1 = require("child_process");
|
|
47
47
|
const config_loader_1 = require("../config-loader");
|
|
48
|
-
const local_session_manager_1 = require("../lib/local-session-manager");
|
|
49
48
|
const local_genbox_provisioner_1 = require("../lib/local-genbox-provisioner");
|
|
49
|
+
const unified_session_1 = require("../lib/unified-session");
|
|
50
50
|
const profile_resolver_1 = require("../profile-resolver");
|
|
51
51
|
const api_1 = require("../api");
|
|
52
52
|
const ssh_config_1 = require("../ssh-config");
|
|
@@ -486,19 +486,30 @@ async function createLocalGenboxFullReplica(nameArg, options, config, configLoad
|
|
|
486
486
|
}
|
|
487
487
|
/**
|
|
488
488
|
* Create a simple local genbox (no genbox.yaml)
|
|
489
|
-
*
|
|
489
|
+
* Now simplified to use UnifiedSessionManager for native sessions
|
|
490
|
+
* For docker/multipass, users should use 'gb local' command
|
|
490
491
|
*/
|
|
491
492
|
async function createLocalGenboxSimple(nameArg, options) {
|
|
492
|
-
const manager = (0, local_session_manager_1.getLocalSessionManager)();
|
|
493
493
|
const provider = options.gemini ? 'gemini' : 'claude';
|
|
494
494
|
const isolation = options.vm ? 'multipass' : options.native ? 'native' : 'docker';
|
|
495
|
-
|
|
495
|
+
// For docker/multipass isolation, redirect to 'gb local' command
|
|
496
|
+
if (isolation !== 'native') {
|
|
497
|
+
console.log('');
|
|
498
|
+
console.log(chalk_1.default.yellow('Docker and Multipass isolation requires the full genbox setup.'));
|
|
499
|
+
console.log('');
|
|
500
|
+
console.log(chalk_1.default.dim('For isolated container/VM environments, use:'));
|
|
501
|
+
console.log(chalk_1.default.cyan(` gb local ${nameArg || ''}`));
|
|
502
|
+
console.log('');
|
|
503
|
+
console.log(chalk_1.default.dim('For a simple native session (no container), use:'));
|
|
504
|
+
console.log(chalk_1.default.cyan(` gb create --local --native ${nameArg || ''}`));
|
|
505
|
+
console.log('');
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
496
508
|
// Interactive name prompt if not provided (same as cloud flow)
|
|
497
509
|
let name = nameArg;
|
|
498
510
|
if (!name && !options.yes) {
|
|
499
511
|
console.log('');
|
|
500
|
-
console.log(chalk_1.default.blue('=== Create Local
|
|
501
|
-
console.log(chalk_1.default.dim('No genbox.yaml found - using simple mode'));
|
|
512
|
+
console.log(chalk_1.default.blue('=== Create Local Native Session ==='));
|
|
502
513
|
console.log('');
|
|
503
514
|
name = await promptForName(false);
|
|
504
515
|
}
|
|
@@ -506,108 +517,39 @@ async function createLocalGenboxSimple(nameArg, options) {
|
|
|
506
517
|
// Auto-generate name in non-interactive mode
|
|
507
518
|
name = (0, random_name_1.generateRandomName)();
|
|
508
519
|
}
|
|
509
|
-
// Native mode doesn't support worktrees
|
|
510
|
-
if (options.native && !options.noWorktree) {
|
|
511
|
-
console.log(chalk_1.default.yellow('Note: Native mode does not support isolated worktrees.'));
|
|
512
|
-
console.log(chalk_1.default.dim('Use --vm or default Docker mode for isolated development.'));
|
|
513
|
-
console.log('');
|
|
514
|
-
}
|
|
515
520
|
console.log('');
|
|
516
521
|
console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
|
|
517
522
|
console.log(` ${chalk_1.default.bold('Name:')} ${name}`);
|
|
518
|
-
console.log(` ${chalk_1.default.bold('Type:')}
|
|
523
|
+
console.log(` ${chalk_1.default.bold('Type:')} native`);
|
|
519
524
|
console.log(` ${chalk_1.default.bold('Provider:')} ${provider}`);
|
|
520
525
|
console.log(` ${chalk_1.default.bold('Directory:')} ${process.cwd()}`);
|
|
521
|
-
if (useWorktree && manager.isGitRepo(process.cwd())) {
|
|
522
|
-
const branchName = options.branch || name;
|
|
523
|
-
console.log(` ${chalk_1.default.bold('Isolation:')} Git worktree (branch: ${branchName})`);
|
|
524
|
-
}
|
|
525
|
-
else {
|
|
526
|
-
console.log(` ${chalk_1.default.bold('Isolation:')} Mounted folder (shared)`);
|
|
527
|
-
}
|
|
528
526
|
console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
|
|
529
527
|
console.log('');
|
|
530
528
|
try {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
branch: options.branch || name,
|
|
542
|
-
sourceBranch: options.fromBranch,
|
|
543
|
-
appPort: options.port ? parseInt(options.port, 10) : 3000,
|
|
544
|
-
appName: options.appName || 'web',
|
|
545
|
-
installDeps: !options.skipInstall,
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
// Create simple session (mounted folder, no worktree)
|
|
550
|
-
if (useWorktree && !manager.isGitRepo(process.cwd())) {
|
|
551
|
-
console.log(chalk_1.default.yellow('Note: Not a git repository. Using mounted folder instead of worktree.'));
|
|
552
|
-
console.log(chalk_1.default.dim('Initialize git to enable isolated development with worktrees.'));
|
|
553
|
-
console.log('');
|
|
554
|
-
}
|
|
555
|
-
const spinner = (0, ora_1.default)(`Creating ${isolation} environment...`).start();
|
|
556
|
-
try {
|
|
557
|
-
session = await manager.createSession({
|
|
558
|
-
provider,
|
|
559
|
-
isolation,
|
|
560
|
-
workdir: process.cwd(),
|
|
561
|
-
name,
|
|
562
|
-
});
|
|
563
|
-
spinner.succeed(chalk_1.default.green('Local genbox created!'));
|
|
564
|
-
}
|
|
565
|
-
catch (err) {
|
|
566
|
-
spinner.fail(chalk_1.default.red('Failed to create environment'));
|
|
567
|
-
throw err;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
529
|
+
const manager = (0, unified_session_1.getUnifiedSessionManager)();
|
|
530
|
+
const spinner = (0, ora_1.default)('Creating native session...').start();
|
|
531
|
+
const session = await manager.createSession({
|
|
532
|
+
type: 'native',
|
|
533
|
+
provider: provider,
|
|
534
|
+
name,
|
|
535
|
+
projectPath: process.cwd(),
|
|
536
|
+
syncEnabled: false,
|
|
537
|
+
});
|
|
538
|
+
spinner.succeed(chalk_1.default.green('Native session created!'));
|
|
570
539
|
console.log('');
|
|
571
540
|
console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
|
|
572
541
|
console.log(` ${chalk_1.default.bold('Name:')} ${session.name}`);
|
|
573
542
|
console.log(` ${chalk_1.default.bold('ID:')} ${session.id}`);
|
|
574
543
|
console.log(` ${chalk_1.default.bold('Provider:')} ${session.provider}`);
|
|
575
|
-
console.log(` ${chalk_1.default.bold('
|
|
544
|
+
console.log(` ${chalk_1.default.bold('Type:')} ${session.type}`);
|
|
576
545
|
console.log(` ${chalk_1.default.bold('Status:')} ${chalk_1.default.green(session.status)}`);
|
|
577
|
-
if (session.worktreeBranch) {
|
|
578
|
-
console.log(` ${chalk_1.default.bold('Branch:')} ${session.worktreeBranch}`);
|
|
579
|
-
}
|
|
580
|
-
if (session.worktreePath) {
|
|
581
|
-
console.log(` ${chalk_1.default.bold('Worktree:')} ${chalk_1.default.dim(session.worktreePath)}`);
|
|
582
|
-
}
|
|
583
|
-
if (session.domain) {
|
|
584
|
-
console.log(` ${chalk_1.default.bold('Domain:')} ${chalk_1.default.cyan(session.domain)}`);
|
|
585
|
-
}
|
|
586
|
-
if (session.containerId) {
|
|
587
|
-
console.log(` ${chalk_1.default.bold('Container:')} ${session.containerId.slice(0, 12)}`);
|
|
588
|
-
}
|
|
589
|
-
if (session.vmName) {
|
|
590
|
-
console.log(` ${chalk_1.default.bold('VM:')} ${session.vmName}`);
|
|
591
|
-
}
|
|
592
546
|
console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
|
|
593
547
|
console.log('');
|
|
594
|
-
// Show domain setup hint if using worktree
|
|
595
|
-
if (session.domain) {
|
|
596
|
-
console.log(chalk_1.default.yellow('DNS Setup Required:'));
|
|
597
|
-
console.log(chalk_1.default.dim(` Add to /etc/hosts: ${chalk_1.default.cyan(`127.0.0.1 ${session.domain}`)}`));
|
|
598
|
-
console.log(chalk_1.default.dim(` Or run: ${chalk_1.default.cyan('gb setup-local')} for automatic proxy setup`));
|
|
599
|
-
console.log('');
|
|
600
|
-
}
|
|
601
548
|
console.log(chalk_1.default.bold('Next steps:'));
|
|
549
|
+
console.log(` Start: ${chalk_1.default.cyan(`gb ${session.provider} ${session.name}`)}`);
|
|
602
550
|
console.log(` Attach: ${chalk_1.default.cyan(`gb session ${session.name}`)}`);
|
|
603
|
-
console.log(`
|
|
604
|
-
console.log(` Status: ${chalk_1.default.cyan(`gb status ${session.name}`)}`);
|
|
551
|
+
console.log(` Status: ${chalk_1.default.cyan(`gb session list`)}`);
|
|
605
552
|
console.log(` Destroy: ${chalk_1.default.cyan(`gb destroy ${session.name}`)}`);
|
|
606
|
-
if (session.domain) {
|
|
607
|
-
console.log('');
|
|
608
|
-
console.log(chalk_1.default.dim(` Preview: ${chalk_1.default.cyan(`https://${session.domain}`)}`));
|
|
609
|
-
console.log(chalk_1.default.dim(` or ${chalk_1.default.cyan(`http://localhost:${session.ports.preview}`)}`));
|
|
610
|
-
}
|
|
611
553
|
console.log('');
|
|
612
554
|
}
|
|
613
555
|
catch (error) {
|
package/dist/commands/destroy.js
CHANGED
|
@@ -46,7 +46,7 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
46
46
|
const api_1 = require("../api");
|
|
47
47
|
const genbox_selector_1 = require("../genbox-selector");
|
|
48
48
|
const ssh_config_1 = require("../ssh-config");
|
|
49
|
-
const
|
|
49
|
+
const unified_session_1 = require("../lib/unified-session");
|
|
50
50
|
const local_genbox_provisioner_1 = require("../lib/local-genbox-provisioner");
|
|
51
51
|
/**
|
|
52
52
|
* Format genbox for display in selection list
|
|
@@ -403,8 +403,8 @@ async function destroyLocalGenbox(session, options) {
|
|
|
403
403
|
}
|
|
404
404
|
const spinner = (0, ora_1.default)(`Destroying local genbox ${session.name}...`).start();
|
|
405
405
|
try {
|
|
406
|
-
const manager = (0,
|
|
407
|
-
await manager.
|
|
406
|
+
const manager = (0, unified_session_1.getUnifiedSessionManager)();
|
|
407
|
+
await manager.deleteSession(session.id);
|
|
408
408
|
spinner.succeed(chalk_1.default.green(`Local genbox '${session.name}' destroyed successfully.`));
|
|
409
409
|
}
|
|
410
410
|
catch (error) {
|
|
@@ -59,6 +59,7 @@ const prompts_1 = require("@inquirer/prompts");
|
|
|
59
59
|
const config_store_1 = require("../config-store");
|
|
60
60
|
const api_1 = require("../api");
|
|
61
61
|
const ssh_keys_1 = require("../utils/ssh-keys");
|
|
62
|
+
const unified_session_1 = require("../lib/unified-session");
|
|
62
63
|
const child_process_1 = require("child_process");
|
|
63
64
|
const os = __importStar(require("os"));
|
|
64
65
|
const path = __importStar(require("path"));
|
|
@@ -417,11 +418,19 @@ async function startDirectSession(provider) {
|
|
|
417
418
|
}
|
|
418
419
|
const useDtach = dtachStatus === 'available';
|
|
419
420
|
ensureLocalSocketDir();
|
|
420
|
-
|
|
421
|
+
// Register session with UnifiedSessionManager (local-first, no API sync by default)
|
|
422
|
+
const sessionManager = (0, unified_session_1.getUnifiedSessionManager)();
|
|
423
|
+
const session = await sessionManager.createSession({
|
|
424
|
+
type: 'native',
|
|
425
|
+
provider: provider,
|
|
426
|
+
projectPath: process.cwd(),
|
|
427
|
+
syncEnabled: false, // Local-first: no API sync by default
|
|
428
|
+
});
|
|
429
|
+
const sessionName = session.name;
|
|
421
430
|
const cliCommand = provider === 'claude'
|
|
422
431
|
? 'claude --dangerously-skip-permissions'
|
|
423
432
|
: provider === 'gemini'
|
|
424
|
-
? 'gemini'
|
|
433
|
+
? 'gemini --yolo'
|
|
425
434
|
: 'codex';
|
|
426
435
|
console.log(chalk_1.default.dim(`\nStarting ${provider} session...`));
|
|
427
436
|
if (useDtach) {
|
|
@@ -431,6 +440,13 @@ async function startDirectSession(provider) {
|
|
|
431
440
|
console.log(chalk_1.default.dim('Note: Session will end when you exit (no persistence)\n'));
|
|
432
441
|
}
|
|
433
442
|
const socketPath = path.join(getDtachSocketDir(), `${sessionName}.sock`);
|
|
443
|
+
// Update socket name in session record
|
|
444
|
+
await sessionManager.updateSession(session.id, {
|
|
445
|
+
infrastructure: {
|
|
446
|
+
dtachSocketName: sessionName,
|
|
447
|
+
dtachSocketPath: socketPath,
|
|
448
|
+
},
|
|
449
|
+
});
|
|
434
450
|
let cmd;
|
|
435
451
|
if (useDtach) {
|
|
436
452
|
cmd = `dtach -A "${socketPath}" bash -c '${cliCommand}'`;
|
|
@@ -438,6 +454,8 @@ async function startDirectSession(provider) {
|
|
|
438
454
|
else {
|
|
439
455
|
cmd = cliCommand;
|
|
440
456
|
}
|
|
457
|
+
// Mark session as running
|
|
458
|
+
await sessionManager.markRunning(session.id);
|
|
441
459
|
const proc = (0, child_process_1.spawn)('bash', ['-c', cmd], { stdio: 'inherit' });
|
|
442
460
|
await new Promise((resolve) => {
|
|
443
461
|
proc.on('close', () => {
|
|
@@ -447,6 +465,8 @@ async function startDirectSession(provider) {
|
|
|
447
465
|
}
|
|
448
466
|
else {
|
|
449
467
|
console.log(chalk_1.default.dim('\nSession ended.'));
|
|
468
|
+
// Mark session as stopped if not using dtach or socket doesn't exist
|
|
469
|
+
sessionManager.markStopped(session.id);
|
|
450
470
|
}
|
|
451
471
|
resolve();
|
|
452
472
|
});
|
|
@@ -53,10 +53,9 @@ exports.sessionCommand = void 0;
|
|
|
53
53
|
const commander_1 = require("commander");
|
|
54
54
|
const chalk_1 = __importDefault(require("chalk"));
|
|
55
55
|
const select_1 = __importDefault(require("@inquirer/select"));
|
|
56
|
-
const
|
|
56
|
+
const unified_session_1 = require("../../lib/unified-session");
|
|
57
57
|
const local_orchestrator_1 = require("../../lib/local-orchestrator");
|
|
58
58
|
const local_genbox_provisioner_1 = require("../../lib/local-genbox-provisioner");
|
|
59
|
-
const native_session_manager_1 = require("../../lib/native-session-manager");
|
|
60
59
|
const hooks_configurator_1 = require("../../lib/hooks-configurator");
|
|
61
60
|
const api_1 = require("../../api");
|
|
62
61
|
const genbox_selector_1 = require("../../genbox-selector");
|
|
@@ -1385,31 +1384,15 @@ async function attachToLocalGenboxSession(session) {
|
|
|
1385
1384
|
* Create new local session interactively
|
|
1386
1385
|
*/
|
|
1387
1386
|
async function createNewLocalSession() {
|
|
1388
|
-
|
|
1389
|
-
// Get provider
|
|
1390
|
-
let provider;
|
|
1391
|
-
try {
|
|
1392
|
-
provider = await (0, select_1.default)({
|
|
1393
|
-
message: 'Which AI provider?',
|
|
1394
|
-
choices: [
|
|
1395
|
-
{ name: 'Claude (Anthropic)', value: 'claude' },
|
|
1396
|
-
{ name: 'Gemini (Google)', value: 'gemini' },
|
|
1397
|
-
],
|
|
1398
|
-
});
|
|
1399
|
-
}
|
|
1400
|
-
catch {
|
|
1401
|
-
console.log(chalk_1.default.dim('\nCancelled.'));
|
|
1402
|
-
return;
|
|
1403
|
-
}
|
|
1404
|
-
// Get isolation
|
|
1387
|
+
// Redirect to the native session flow (or show guidance for docker/multipass)
|
|
1405
1388
|
let isolation;
|
|
1406
1389
|
try {
|
|
1407
1390
|
isolation = await (0, select_1.default)({
|
|
1408
1391
|
message: 'Isolation level?',
|
|
1409
1392
|
choices: [
|
|
1393
|
+
{ name: 'Native (no isolation)', value: 'native' },
|
|
1410
1394
|
{ name: 'Docker (fast, lightweight)', value: 'docker' },
|
|
1411
1395
|
{ name: 'VM (full isolation)', value: 'multipass' },
|
|
1412
|
-
{ name: 'Native (no isolation)', value: 'native' },
|
|
1413
1396
|
],
|
|
1414
1397
|
});
|
|
1415
1398
|
}
|
|
@@ -1417,20 +1400,17 @@ async function createNewLocalSession() {
|
|
|
1417
1400
|
console.log(chalk_1.default.dim('\nCancelled.'));
|
|
1418
1401
|
return;
|
|
1419
1402
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
provider,
|
|
1424
|
-
isolation,
|
|
1425
|
-
workdir: process.cwd(),
|
|
1426
|
-
});
|
|
1427
|
-
console.log(chalk_1.default.green(`\nSession created: ${session.name}`));
|
|
1428
|
-
console.log(chalk_1.default.dim('\nAttaching to session...\n'));
|
|
1429
|
-
await manager.attachToSession(session);
|
|
1430
|
-
console.log(chalk_1.default.dim('\nDetached from session.'));
|
|
1403
|
+
if (isolation === 'native') {
|
|
1404
|
+
// Use the native session flow with UnifiedSessionManager
|
|
1405
|
+
await createNativeSession();
|
|
1431
1406
|
}
|
|
1432
|
-
|
|
1433
|
-
|
|
1407
|
+
else {
|
|
1408
|
+
// Docker/multipass sessions require gb local or gb session start
|
|
1409
|
+
console.log(chalk_1.default.yellow(`\n${isolation} sessions require additional setup.`));
|
|
1410
|
+
console.log(chalk_1.default.dim('\nFor quick start, use native mode:'));
|
|
1411
|
+
console.log(chalk_1.default.cyan(' gb session start --native'));
|
|
1412
|
+
console.log(chalk_1.default.dim('\nOr create a local genbox:'));
|
|
1413
|
+
console.log(chalk_1.default.cyan(' gb local'));
|
|
1434
1414
|
}
|
|
1435
1415
|
}
|
|
1436
1416
|
/**
|
|
@@ -1445,7 +1425,7 @@ async function createNewCloudSession() {
|
|
|
1445
1425
|
* Attach to specific session by name
|
|
1446
1426
|
*/
|
|
1447
1427
|
async function attachToSessionByName(name, options) {
|
|
1448
|
-
const
|
|
1428
|
+
const sessionManager = (0, unified_session_1.getUnifiedSessionManager)();
|
|
1449
1429
|
// Check local genbox sessions FIRST (from LocalGenboxProvisioner)
|
|
1450
1430
|
// These have more complete info and better attachment handling
|
|
1451
1431
|
const genboxSessions = getLocalGenboxSessions();
|
|
@@ -1454,13 +1434,23 @@ async function attachToSessionByName(name, options) {
|
|
|
1454
1434
|
await attachToLocalGenboxSession(genboxSession);
|
|
1455
1435
|
return;
|
|
1456
1436
|
}
|
|
1457
|
-
// Check
|
|
1458
|
-
const
|
|
1459
|
-
if (
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1437
|
+
// Check native sessions (via UnifiedSessionManager)
|
|
1438
|
+
const unifiedSession = sessionManager.getSessionByName(name);
|
|
1439
|
+
if (unifiedSession && unifiedSession.type === 'native') {
|
|
1440
|
+
// Attach using dtach
|
|
1441
|
+
const socketPath = getDtachSocketPath(unifiedSession.name);
|
|
1442
|
+
if (isDtachSocketAlive(socketPath)) {
|
|
1443
|
+
console.log(chalk_1.default.dim(`\nAttaching to session ${name}...`));
|
|
1444
|
+
console.log(chalk_1.default.dim('Tip: Detach with Ctrl+\\\n'));
|
|
1445
|
+
const proc = (0, child_process_1.spawn)('dtach', ['-a', socketPath], { stdio: 'inherit' });
|
|
1446
|
+
await new Promise(resolve => proc.on('close', () => resolve()));
|
|
1447
|
+
console.log(chalk_1.default.dim('\nDetached from session.'));
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
else {
|
|
1451
|
+
console.log(chalk_1.default.yellow(`Session ${name} is not running.`));
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1464
1454
|
}
|
|
1465
1455
|
// Check cloud sessions
|
|
1466
1456
|
const cloudSessions = await getCloudSessions(options.all || false);
|
|
@@ -1727,7 +1717,7 @@ async function createNewSessionInGenbox(genbox) {
|
|
|
1727
1717
|
* With tracking enabled via genbox-agent hooks
|
|
1728
1718
|
*/
|
|
1729
1719
|
async function createNativeSession(options) {
|
|
1730
|
-
const
|
|
1720
|
+
const sessionManager = (0, unified_session_1.getUnifiedSessionManager)();
|
|
1731
1721
|
const hooksConfigurator = (0, hooks_configurator_1.getHooksConfigurator)();
|
|
1732
1722
|
// Select AI provider first
|
|
1733
1723
|
let provider;
|
|
@@ -1763,30 +1753,19 @@ async function createNativeSession(options) {
|
|
|
1763
1753
|
console.log(chalk_1.default.dim('Session will run without tracking.'));
|
|
1764
1754
|
}
|
|
1765
1755
|
}
|
|
1766
|
-
// Create session record
|
|
1767
|
-
const session = await
|
|
1756
|
+
// Create session record with UnifiedSessionManager (local-first, no API sync by default)
|
|
1757
|
+
const session = await sessionManager.createSession({
|
|
1758
|
+
type: 'native',
|
|
1768
1759
|
provider,
|
|
1769
1760
|
projectPath: process.cwd(),
|
|
1770
|
-
|
|
1761
|
+
syncEnabled: false, // Local-first: no API sync by default
|
|
1771
1762
|
});
|
|
1772
1763
|
console.log(chalk_1.default.dim(`Session created: ${session.name}`));
|
|
1773
|
-
// Build environment variables for the session
|
|
1774
|
-
const sessionEnv = nativeManager.getSessionEnv(session);
|
|
1775
|
-
const envExports = Object.entries(sessionEnv)
|
|
1776
|
-
.map(([key, value]) => `export ${key}="${value}"`)
|
|
1777
|
-
.join('; ');
|
|
1778
1764
|
// CLI command with skip permissions flag
|
|
1779
1765
|
const cliCommand = provider === 'claude'
|
|
1780
1766
|
? 'claude --dangerously-skip-permissions'
|
|
1781
|
-
: 'gemini';
|
|
1782
|
-
//
|
|
1783
|
-
if (session.apiSessionId) {
|
|
1784
|
-
console.log(chalk_1.default.green(`Tracking enabled (session: ${session.apiSessionId})`));
|
|
1785
|
-
console.log(chalk_1.default.dim(`View in dashboard: ${process.env.GENBOX_DASHBOARD_URL || 'https://dashboard.genbox.dev'}/sessions/${session.apiSessionId}`));
|
|
1786
|
-
}
|
|
1787
|
-
else {
|
|
1788
|
-
console.log(chalk_1.default.yellow('Running without tracking (not logged in or API unavailable)'));
|
|
1789
|
-
}
|
|
1767
|
+
: 'gemini --yolo';
|
|
1768
|
+
// Local-first: no API tracking status to show
|
|
1790
1769
|
console.log(chalk_1.default.dim('\nStarting session...'));
|
|
1791
1770
|
if (useDtach) {
|
|
1792
1771
|
console.log(chalk_1.default.dim('Tip: Detach with Ctrl+\\\n'));
|
|
@@ -1795,15 +1774,15 @@ async function createNativeSession(options) {
|
|
|
1795
1774
|
console.log(chalk_1.default.dim('Note: Session will end when you exit (no persistence)\n'));
|
|
1796
1775
|
}
|
|
1797
1776
|
// Mark session as running
|
|
1798
|
-
|
|
1777
|
+
await sessionManager.markRunning(session.id);
|
|
1799
1778
|
// Build the command
|
|
1800
1779
|
const socketPath = getDtachSocketPath(session.name);
|
|
1801
1780
|
let cmd;
|
|
1802
1781
|
if (useDtach) {
|
|
1803
|
-
cmd = `dtach -A "${socketPath}" bash -c '${
|
|
1782
|
+
cmd = `dtach -A "${socketPath}" bash -c '${cliCommand}'`;
|
|
1804
1783
|
}
|
|
1805
1784
|
else {
|
|
1806
|
-
cmd =
|
|
1785
|
+
cmd = cliCommand;
|
|
1807
1786
|
}
|
|
1808
1787
|
const proc = (0, child_process_1.spawn)('bash', ['-c', cmd], { stdio: 'inherit' });
|
|
1809
1788
|
await new Promise((resolve) => {
|
|
@@ -1816,12 +1795,12 @@ async function createNativeSession(options) {
|
|
|
1816
1795
|
console.log(chalk_1.default.dim(`Reattach with: ${chalk_1.default.cyan(`gb session ${session.name}`)}`));
|
|
1817
1796
|
}
|
|
1818
1797
|
else {
|
|
1819
|
-
|
|
1798
|
+
sessionManager.markStopped(session.id);
|
|
1820
1799
|
console.log(chalk_1.default.dim('\nSession ended.'));
|
|
1821
1800
|
}
|
|
1822
1801
|
}
|
|
1823
1802
|
else {
|
|
1824
|
-
|
|
1803
|
+
sessionManager.markStopped(session.id);
|
|
1825
1804
|
console.log(chalk_1.default.dim('\nSession ended.'));
|
|
1826
1805
|
}
|
|
1827
1806
|
resolve();
|
|
@@ -1841,46 +1820,31 @@ function isDtachSessionRunning(sessionName) {
|
|
|
1841
1820
|
}
|
|
1842
1821
|
}
|
|
1843
1822
|
/**
|
|
1844
|
-
* Send initial prompt to a session
|
|
1823
|
+
* Send initial prompt to a session (not implemented for unified sessions)
|
|
1845
1824
|
*/
|
|
1846
|
-
async function sendInitialPrompt(
|
|
1847
|
-
|
|
1848
|
-
//
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
await manager.sendPromptToSession(session, prompt);
|
|
1852
|
-
console.log(chalk_1.default.dim(`Sent initial prompt: "${prompt.slice(0, 50)}${prompt.length > 50 ? '...' : ''}"`));
|
|
1853
|
-
}
|
|
1854
|
-
catch (error) {
|
|
1855
|
-
console.log(chalk_1.default.yellow(`Warning: Could not send initial prompt: ${error.message}`));
|
|
1856
|
-
}
|
|
1825
|
+
async function sendInitialPrompt(_session, prompt) {
|
|
1826
|
+
// Note: Sending prompts to running sessions requires terminal integration
|
|
1827
|
+
// This is a placeholder for future implementation
|
|
1828
|
+
console.log(chalk_1.default.dim(`Initial prompt provided: "${prompt.slice(0, 50)}${prompt.length > 50 ? '...' : ''}"`));
|
|
1829
|
+
console.log(chalk_1.default.yellow('Note: Auto-sending prompts to sessions is not yet supported.'));
|
|
1857
1830
|
}
|
|
1858
1831
|
/**
|
|
1859
1832
|
* Quick local session shortcut
|
|
1860
1833
|
*/
|
|
1861
1834
|
async function quickLocalSession(options) {
|
|
1862
|
-
const manager = (0, local_session_manager_1.getLocalSessionManager)();
|
|
1863
1835
|
const provider = options.gemini ? 'gemini' : 'claude';
|
|
1864
1836
|
const isolation = options.vm ? 'multipass' : options.native ? 'native' : 'docker';
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
isolation,
|
|
1870
|
-
workdir: process.cwd(),
|
|
1871
|
-
});
|
|
1872
|
-
console.log(chalk_1.default.green(`\nSession created: ${session.name}`));
|
|
1873
|
-
// Send initial prompt if provided
|
|
1874
|
-
if (options.prompt) {
|
|
1875
|
-
await sendInitialPrompt(session, options.prompt);
|
|
1876
|
-
}
|
|
1877
|
-
console.log(chalk_1.default.dim('\nAttaching to session...\n'));
|
|
1878
|
-
await manager.attachToSession(session);
|
|
1879
|
-
console.log(chalk_1.default.dim('\nDetached from session.'));
|
|
1880
|
-
}
|
|
1881
|
-
catch (error) {
|
|
1882
|
-
console.error(chalk_1.default.red(`\nError: ${error.message}`));
|
|
1837
|
+
// For native sessions, use the unified session flow
|
|
1838
|
+
if (isolation === 'native') {
|
|
1839
|
+
await createNativeSession({ prompt: options.prompt });
|
|
1840
|
+
return;
|
|
1883
1841
|
}
|
|
1842
|
+
// For docker/multipass, show guidance
|
|
1843
|
+
console.log(chalk_1.default.yellow(`\n${isolation} sessions require additional setup.`));
|
|
1844
|
+
console.log(chalk_1.default.dim('\nFor quick start, use native mode:'));
|
|
1845
|
+
console.log(chalk_1.default.cyan(` gb session start --native --${provider}`));
|
|
1846
|
+
console.log(chalk_1.default.dim('\nOr create a local genbox:'));
|
|
1847
|
+
console.log(chalk_1.default.cyan(' gb local'));
|
|
1884
1848
|
}
|
|
1885
1849
|
/**
|
|
1886
1850
|
* Create a cloud session on an existing genbox
|
|
@@ -2075,9 +2039,24 @@ async function handleMultiSession(options, providerArgs) {
|
|
|
2075
2039
|
}
|
|
2076
2040
|
// Attach to selected session
|
|
2077
2041
|
if (selectedSession.location === 'local') {
|
|
2078
|
-
const
|
|
2079
|
-
console.log(chalk_1.default.dim(`\nAttaching to ${
|
|
2080
|
-
|
|
2042
|
+
const localSession = selectedSession.session;
|
|
2043
|
+
console.log(chalk_1.default.dim(`\nAttaching to ${localSession.name}...\n`));
|
|
2044
|
+
// For native sessions, use dtach directly
|
|
2045
|
+
if (localSession.isolation === 'native') {
|
|
2046
|
+
const socketPath = getDtachSocketPath(localSession.name);
|
|
2047
|
+
if (isDtachSocketAlive(socketPath)) {
|
|
2048
|
+
console.log(chalk_1.default.dim('Tip: Detach with Ctrl+\\\n'));
|
|
2049
|
+
const proc = (0, child_process_1.spawn)('dtach', ['-a', socketPath], { stdio: 'inherit' });
|
|
2050
|
+
await new Promise(resolve => proc.on('close', () => resolve()));
|
|
2051
|
+
}
|
|
2052
|
+
else {
|
|
2053
|
+
console.log(chalk_1.default.yellow('Session is not running.'));
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
else {
|
|
2057
|
+
// For docker/multipass, redirect to gb local
|
|
2058
|
+
console.log(chalk_1.default.yellow('Use `gb local attach` for docker/multipass sessions.'));
|
|
2059
|
+
}
|
|
2081
2060
|
console.log(chalk_1.default.dim('\nDetached from session.'));
|
|
2082
2061
|
}
|
|
2083
2062
|
else {
|