sandboxbox 2.3.5 → 2.3.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sandboxbox",
3
- "version": "2.3.5",
3
+ "version": "2.3.6",
4
4
  "description": "Portable container runner with Podman - Claude Code & Playwright support. Works on Windows, macOS, and Linux.",
5
5
  "type": "module",
6
6
  "main": "cli.js",
@@ -16,19 +16,40 @@ export function buildCommand(dockerfilePath) {
16
16
 
17
17
  const podmanPath = checkPodman();
18
18
  if (!podmanPath) return false;
19
- if (!setupBackendNonBlocking(podmanPath)) return false;
20
19
 
21
- try {
22
- execSync(`"${podmanPath}" build -f "${dockerfilePath}" -t sandboxbox:latest .`, {
23
- stdio: 'inherit',
24
- cwd: dirname(dockerfilePath),
25
- shell: process.platform === 'win32'
26
- });
27
- console.log(color('green', '\n✅ Container built successfully!'));
28
- return true;
29
- } catch (error) {
30
- console.log(color('red', `\n❌ Build failed: ${error.message}`));
31
- return false;
20
+ // Start backend setup but don't block on Windows/macOS
21
+ const backendReady = setupBackendNonBlocking(podmanPath);
22
+ if (process.platform === 'linux' && !backendReady) {
23
+ return false; // Only block on Linux for rootless service
24
+ }
25
+
26
+ // Retry container operation with backend readiness check
27
+ let retries = 0;
28
+ const maxRetries = process.platform === 'linux' ? 3 : 12; // More retries for Windows/macOS
29
+
30
+ while (retries < maxRetries) {
31
+ try {
32
+ execSync(`"${podmanPath}" build -f "${dockerfilePath}" -t sandboxbox:latest .`, {
33
+ stdio: 'inherit',
34
+ cwd: dirname(dockerfilePath),
35
+ shell: process.platform === 'win32',
36
+ timeout: 30000 // 30 second timeout
37
+ });
38
+ console.log(color('green', '\n✅ Container built successfully!'));
39
+ return true;
40
+ } catch (error) {
41
+ retries++;
42
+ if (retries < maxRetries && error.message.includes('Cannot connect to Podman')) {
43
+ console.log(color('yellow', ` Backend not ready yet (${retries}/${maxRetries}), waiting 15 seconds...`));
44
+ const start = Date.now();
45
+ while (Date.now() - start < 15000) {
46
+ // Wait 15 seconds
47
+ }
48
+ continue;
49
+ }
50
+ console.log(color('red', `\n❌ Build failed: ${error.message}`));
51
+ return false;
52
+ }
32
53
  }
33
54
  }
34
55
 
@@ -45,7 +66,12 @@ export function runCommand(projectDir, cmd = 'bash') {
45
66
 
46
67
  const podmanPath = checkPodman();
47
68
  if (!podmanPath) return false;
48
- if (!setupBackendNonBlocking(podmanPath)) return false;
69
+
70
+ // Start backend setup but don't block on Windows/macOS
71
+ const backendReady = setupBackendNonBlocking(podmanPath);
72
+ if (process.platform === 'linux' && !backendReady) {
73
+ return false; // Only block on Linux for rootless service
74
+ }
49
75
 
50
76
  try {
51
77
  const { tempProjectDir, cleanup } = createIsolatedEnvironment(projectDir);
@@ -78,7 +104,12 @@ export function shellCommand(projectDir) {
78
104
 
79
105
  const podmanPath = checkPodman();
80
106
  if (!podmanPath) return false;
81
- if (!setupBackendNonBlocking(podmanPath)) return false;
107
+
108
+ // Start backend setup but don't block on Windows/macOS
109
+ const backendReady = setupBackendNonBlocking(podmanPath);
110
+ if (process.platform === 'linux' && !backendReady) {
111
+ return false; // Only block on Linux for rootless service
112
+ }
82
113
 
83
114
  try {
84
115
  const { tempProjectDir, cleanup } = createIsolatedEnvironment(projectDir);
package/utils/podman.js CHANGED
@@ -35,37 +35,85 @@ export function setupBackendNonBlocking(podmanPath) {
35
35
  return true;
36
36
  } catch (infoError) {
37
37
  console.log(color('yellow', '\n🔧 Starting Podman rootless service...'));
38
- console.log(color('cyan', ' Run: podman system service --time=0 &'));
39
- console.log(color('yellow', ' Or use systemd: sudo systemctl enable --now podman'));
40
- return false;
38
+ // Try to start service automatically
39
+ try {
40
+ execSync('podman system service --time=0 &', { stdio: 'ignore', shell: true });
41
+ return true;
42
+ } catch (serviceError) {
43
+ console.log(color('cyan', ' Run: podman system service --time=0 &'));
44
+ return false;
45
+ }
41
46
  }
42
47
  }
43
48
 
44
- // Windows/macOS: Show setup instructions (VM required, no way around it)
45
- const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
49
+ // Windows: Implement completely silent automated setup
50
+ if (process.platform === 'win32') {
51
+ const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
46
52
 
47
- try {
48
- execSync(`"${podmanPath}" info`, execOptions);
49
- return true;
50
- } catch (infoError) {
51
- if (!infoError.message.includes('Cannot connect to Podman')) {
52
- return false;
53
+ try {
54
+ execSync(`"${podmanPath}" info`, execOptions);
55
+ return true;
56
+ } catch (infoError) {
57
+ if (!infoError.message.includes('Cannot connect to Podman')) {
58
+ return false;
59
+ }
60
+
61
+ console.log(color('yellow', '\n🔧 Setting up Podman automatically (silent mode)...'));
62
+
63
+ // Start machine setup in background without blocking
64
+ setupMachineBackground(podmanPath);
65
+ return true; // Continue even if setup is in progress
53
66
  }
67
+ }
54
68
 
55
- console.log(color('yellow', '\n🔧 Podman machine setup required (Windows/macOS limitation)'));
56
- console.log(color('cyan', process.platform === 'win32'
57
- ? ' Windows requires a VM backend for Podman containers'
58
- : ' macOS requires a VM backend for Podman containers'));
69
+ // macOS: Similar automated approach
70
+ if (process.platform === 'darwin') {
71
+ const execOptions = { encoding: 'utf-8', stdio: 'pipe', shell: true };
59
72
 
60
- console.log(color('yellow', '\n📋 One-time setup (takes 2-3 minutes):'));
61
- const setupCmd = process.platform === 'win32'
62
- ? `podman machine init --rootful=false && podman machine start`
63
- : `podman machine init && podman machine start`;
73
+ try {
74
+ execSync(`"${podmanPath}" info`, execOptions);
75
+ return true;
76
+ } catch (infoError) {
77
+ if (!infoError.message.includes('Cannot connect to Podman')) {
78
+ return false;
79
+ }
64
80
 
65
- console.log(color('cyan', ` ${setupCmd}`));
66
- console.log(color('yellow', '\n💡 After setup, sandboxbox will work instantly forever\n'));
67
- return false;
81
+ console.log(color('yellow', '\n🔧 Setting up Podman automatically...'));
82
+ setupMachineBackground(podmanPath);
83
+ return true;
84
+ }
68
85
  }
86
+
87
+ return false;
88
+ }
89
+
90
+ function setupMachineBackground(podmanPath) {
91
+ console.log(color('cyan', ' Starting machine setup in background...'));
92
+
93
+ const initCmd = process.platform === 'win32'
94
+ ? `"${podmanPath}" machine init --rootful=false`
95
+ : `"${podmanPath}" machine init`;
96
+
97
+ const initProcess = spawn(initCmd, {
98
+ stdio: ['pipe', 'pipe', 'pipe'],
99
+ shell: true,
100
+ detached: true
101
+ });
102
+
103
+ initProcess.unref();
104
+
105
+ // Start machine after init completes (with delay)
106
+ setTimeout(() => {
107
+ const startProcess = spawn(`"${podmanPath}" machine start`, {
108
+ stdio: ['pipe', 'pipe', 'pipe'],
109
+ shell: true,
110
+ detached: true
111
+ });
112
+ startProcess.unref();
113
+ }, 30000); // Wait 30 seconds for init to complete
114
+
115
+ console.log(color('yellow', ' Setup initiated in background (may take 2-3 minutes)'));
116
+ console.log(color('cyan', ' Container operations will work when setup completes\n'));
69
117
  }
70
118
 
71
119
  export function checkBackend(podmanPath) {