sandboxbox 3.0.4 → 3.0.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": "3.0.4",
3
+ "version": "3.0.6",
4
4
  "description": "Lightweight process containment sandbox for CLI tools - Playwright, Claude Code, and more. Pure Node.js, no dependencies.",
5
5
  "type": "module",
6
6
  "main": "cli.js",
@@ -65,11 +65,10 @@ export async function claudeCommand(projectDir, prompt) {
65
65
  const claudeStartTime = Date.now();
66
66
  console.log(color('cyan', '⏱️ Stage 3: Starting Claude Code...'));
67
67
 
68
- const proc = spawn('claude', claudeArgs, {
69
- cwd: join(sandboxDir, 'workspace'),
68
+ const proc = spawn('sh', ['-c', `cd "${join(sandboxDir, 'workspace')}" && claude ${claudeArgs.join(' ')}`], {
70
69
  env: env, // Use the environment directly without modification
71
70
  stdio: ['pipe', 'pipe', 'pipe'],
72
- shell: true, // Use shell to ensure environment variables are properly expanded
71
+ shell: true, // Use shell for proper directory handling
73
72
  detached: false
74
73
  });
75
74
 
@@ -79,36 +78,41 @@ export async function claudeCommand(projectDir, prompt) {
79
78
  const lines = data.toString().split('\n').filter(line => line.trim());
80
79
 
81
80
  for (const line of lines) {
82
- const event = JSON.parse(line);
81
+ try {
82
+ const event = JSON.parse(line);
83
83
 
84
- if (event.type === 'system' && event.subtype === 'init') {
85
- if (!claudeStarted) {
86
- const claudeCreateTime = Date.now() - claudeStartTime;
87
- console.log(color('green', `✅ Claude Code started in ${claudeCreateTime}ms`));
88
- claudeStarted = true;
89
- }
90
- console.log(color('green', `✅ Session started (${event.session_id.substring(0, 8)}...)`));
91
- console.log(color('cyan', `📦 Model: ${event.model}`));
92
- console.log(color('cyan', `🔧 Tools: ${event.tools.length} available\n`));
93
- } else if (event.type === 'assistant' && event.message) {
94
- const content = event.message.content;
95
- if (Array.isArray(content)) {
96
- for (const block of content) {
97
- if (block.type === 'text') {
98
- process.stdout.write(block.text);
99
- } else if (block.type === 'tool_use') {
100
- console.log(color('cyan', `\n🔧 Using tool: ${block.name}`));
84
+ if (event.type === 'system' && event.subtype === 'init') {
85
+ if (!claudeStarted) {
86
+ const claudeCreateTime = Date.now() - claudeStartTime;
87
+ console.log(color('green', `✅ Claude Code started in ${claudeCreateTime}ms`));
88
+ claudeStarted = true;
89
+ }
90
+ console.log(color('green', `✅ Session started (${event.session_id.substring(0, 8)}...)`));
91
+ console.log(color('cyan', `📦 Model: ${event.model}`));
92
+ console.log(color('cyan', `🔧 Tools: ${event.tools.length} available\n`));
93
+ } else if (event.type === 'assistant' && event.message) {
94
+ const content = event.message.content;
95
+ if (Array.isArray(content)) {
96
+ for (const block of content) {
97
+ if (block.type === 'text') {
98
+ process.stdout.write(block.text);
99
+ } else if (block.type === 'tool_use') {
100
+ console.log(color('cyan', `\n🔧 Using tool: ${block.name}`));
101
+ }
101
102
  }
102
103
  }
104
+ } else if (event.type === 'result') {
105
+ const usage = event.usage || {};
106
+ const cost = event.total_cost_usd || 0;
107
+ console.log(color('green', `\n\n✅ Completed in ${event.duration_ms}ms`));
108
+ console.log(color('yellow', `💰 Cost: $${cost.toFixed(4)}`));
109
+ if (usage.input_tokens) {
110
+ console.log(color('cyan', `📊 Tokens: ${usage.input_tokens} in, ${usage.output_tokens} out`));
111
+ }
103
112
  }
104
- } else if (event.type === 'result') {
105
- const usage = event.usage || {};
106
- const cost = event.total_cost_usd || 0;
107
- console.log(color('green', `\n\n✅ Completed in ${event.duration_ms}ms`));
108
- console.log(color('yellow', `💰 Cost: $${cost.toFixed(4)}`));
109
- if (usage.input_tokens) {
110
- console.log(color('cyan', `📊 Tokens: ${usage.input_tokens} in, ${usage.output_tokens} out`));
111
- }
113
+ } catch (jsonError) {
114
+ // Skip malformed JSON lines - might be incomplete chunks
115
+ // Silently continue to avoid breaking the stream
112
116
  }
113
117
  }
114
118
  }
@@ -130,12 +134,17 @@ export async function claudeCommand(projectDir, prompt) {
130
134
  proc.stdout.on('data', (data) => {
131
135
  stdoutOutput += data.toString();
132
136
 
133
- // Check for errors in JSON output
137
+ // Check for errors in JSON output with error handling
134
138
  const lines = data.toString().split('\n').filter(l => l.trim());
135
139
  for (const line of lines) {
136
- const event = JSON.parse(line);
137
- if (event.type === 'result' && event.is_error) {
138
- lastError = event.result;
140
+ try {
141
+ const event = JSON.parse(line);
142
+ if (event.type === 'result' && event.is_error) {
143
+ lastError = event.result;
144
+ }
145
+ } catch (jsonError) {
146
+ // Ignore JSON parsing errors - might be incomplete chunks
147
+ console.error('JSON parse error:', jsonError.message);
139
148
  }
140
149
  }
141
150