gitarsenal-cli 1.9.96 → 1.9.97
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/.venv_status.json +1 -1
- package/README.md +29 -0
- package/bin/gitarsenal.js +220 -127
- package/kill_claude/requirements.txt +1 -1
- package/lib/dependencies.js +130 -4
- package/lib/e2b-sandbox.js +158 -0
- package/lib/execAsync.js +12 -0
- package/lib/sandbox.js +97 -113
- package/package.json +2 -1
- package/python/__pycache__/credentials_manager.cpython-312.pyc +0 -0
- package/python/__pycache__/e2b_sandbox_agent.cpython-313.pyc +0 -0
- package/python/__pycache__/fetch_modal_tokens.cpython-312.pyc +0 -0
- package/python/credentials_manager.py +2 -1
- package/python/e2b_sandbox_agent.py +787 -0
- package/python/fetch_modal_tokens.py +47 -25
- package/python/requirements.txt +2 -1
- package/python/test_enhanced_sandbox_script.py +1429 -0
- package/python/test_modalSandboxScript.py +41 -5
- package/scripts/setup_e2b.js +162 -0
- package/kill_claude/.claude/settings.local.json +0 -9
- package/kill_claude/__pycache__/bash_output_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/bash_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/claude_code_agent.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/edit_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/exit_plan_mode_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/glob_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/grep_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/kill_bash_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/ls_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/multiedit_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/notebook_edit_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/read_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/task_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/todo_write_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/web_fetch_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/web_search_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/write_tool.cpython-313.pyc +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const ora = require('ora');
|
|
6
|
+
const { promisify } = require('util');
|
|
7
|
+
const { exec } = require('child_process');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
|
|
10
|
+
const execAsync = promisify(exec);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the Python executable path from the virtual environment
|
|
14
|
+
* @returns {string} - Path to Python executable or 'python3'
|
|
15
|
+
*/
|
|
16
|
+
function getPythonExecutable() {
|
|
17
|
+
// Check if PYTHON_EXECUTABLE is set by the virtual environment activation
|
|
18
|
+
if (process.env.PYTHON_EXECUTABLE && fs.existsSync(process.env.PYTHON_EXECUTABLE)) {
|
|
19
|
+
return process.env.PYTHON_EXECUTABLE;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Try to find the virtual environment Python
|
|
23
|
+
const venvPath = path.join(__dirname, '..', '.venv');
|
|
24
|
+
const isWindows = process.platform === 'win32';
|
|
25
|
+
|
|
26
|
+
// Check for uv-style virtual environment first
|
|
27
|
+
const uvPythonPath = path.join(venvPath, 'bin', 'python');
|
|
28
|
+
|
|
29
|
+
// Check for traditional venv structure
|
|
30
|
+
const traditionalPythonPath = isWindows ?
|
|
31
|
+
path.join(venvPath, 'Scripts', 'python.exe') :
|
|
32
|
+
path.join(venvPath, 'bin', 'python');
|
|
33
|
+
|
|
34
|
+
if (fs.existsSync(uvPythonPath)) {
|
|
35
|
+
return uvPythonPath;
|
|
36
|
+
} else if (fs.existsSync(traditionalPythonPath)) {
|
|
37
|
+
return traditionalPythonPath;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Fall back to system Python
|
|
41
|
+
return isWindows ? 'python' : 'python3';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Run an E2B sandbox with the given options
|
|
46
|
+
* @param {Object} options - Sandbox options
|
|
47
|
+
* @param {string} options.repoUrl - GitHub repository URL
|
|
48
|
+
* @param {Array<string>} options.setupCommands - Setup commands
|
|
49
|
+
* @returns {Promise<void>}
|
|
50
|
+
*/
|
|
51
|
+
async function runE2BSandbox(options) {
|
|
52
|
+
const {
|
|
53
|
+
repoUrl,
|
|
54
|
+
setupCommands = [],
|
|
55
|
+
userId,
|
|
56
|
+
userName,
|
|
57
|
+
userEmail,
|
|
58
|
+
apiKeys = {}
|
|
59
|
+
} = options;
|
|
60
|
+
|
|
61
|
+
console.log(chalk.blue('🚀 Starting E2B sandbox...'));
|
|
62
|
+
|
|
63
|
+
// Check if E2B_API_KEY is already set in environment variables
|
|
64
|
+
let e2bApiKey = process.env.E2B_API_KEY;
|
|
65
|
+
|
|
66
|
+
// If not, try to get it from apiKeys
|
|
67
|
+
if (!e2bApiKey && apiKeys.E2B_API_KEY) {
|
|
68
|
+
e2bApiKey = apiKeys.E2B_API_KEY;
|
|
69
|
+
console.log(chalk.green('✅ Using E2B API key from apiKeys'));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// If still not found, try to get it from modal_tokens.json
|
|
73
|
+
if (!e2bApiKey) {
|
|
74
|
+
try {
|
|
75
|
+
const modalTokensPath = path.join(__dirname, '..', 'python', 'modal_tokens.json');
|
|
76
|
+
if (fs.existsSync(modalTokensPath)) {
|
|
77
|
+
const modalTokens = JSON.parse(fs.readFileSync(modalTokensPath, 'utf8'));
|
|
78
|
+
if (modalTokens.e2b_api_key) {
|
|
79
|
+
e2bApiKey = modalTokens.e2b_api_key;
|
|
80
|
+
console.log(chalk.green('✅ Using E2B API key from modal_tokens.json'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error(chalk.yellow(`⚠️ Error reading modal_tokens.json: ${error.message}`));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Check if we have a valid E2B API key
|
|
89
|
+
if (!e2bApiKey) {
|
|
90
|
+
console.error(chalk.red('❌ E2B API key not found'));
|
|
91
|
+
console.error(chalk.yellow('Please set the E2B_API_KEY environment variable or add it to your API keys'));
|
|
92
|
+
return { success: false, error: 'E2B API key not found' };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Log a masked version of the API key for debugging
|
|
96
|
+
console.log(chalk.green(`✅ E2B API key found (${e2bApiKey.substring(0, 5)}...)`));
|
|
97
|
+
|
|
98
|
+
// Set up the environment for the Python process
|
|
99
|
+
const pythonExecutable = getPythonExecutable();
|
|
100
|
+
if (!pythonExecutable) {
|
|
101
|
+
console.error(chalk.red('❌ Python executable not found'));
|
|
102
|
+
return { success: false, error: 'Python executable not found' };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Get OpenAI and Anthropic API keys from environment or apiKeys
|
|
106
|
+
const openaiApiKey = apiKeys.OPENAI_API_KEY || process.env.OPENAI_API_KEY;
|
|
107
|
+
const anthropicApiKey = apiKeys.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY;
|
|
108
|
+
|
|
109
|
+
// Run the e2b_sandbox_agent.py script with the repository URL
|
|
110
|
+
const scriptPath = path.join(__dirname, '..', 'python', 'e2b_sandbox_agent.py');
|
|
111
|
+
|
|
112
|
+
// Prepare command line arguments
|
|
113
|
+
const args = [
|
|
114
|
+
scriptPath,
|
|
115
|
+
'--repo', repoUrl
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
// Add API keys if available
|
|
119
|
+
if (openaiApiKey) {
|
|
120
|
+
args.push('--openai-api-key', openaiApiKey);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (anthropicApiKey) {
|
|
124
|
+
args.push('--anthropic-api-key', anthropicApiKey);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Run the Python script
|
|
128
|
+
const pythonProcess = spawn(pythonExecutable, args, {
|
|
129
|
+
stdio: 'inherit',
|
|
130
|
+
env: {
|
|
131
|
+
...process.env,
|
|
132
|
+
E2B_API_KEY: e2bApiKey
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
pythonProcess.on('close', (code) => {
|
|
138
|
+
if (code === 0 || code === 130) { // 130 is the exit code for SIGINT (Ctrl+C)
|
|
139
|
+
console.log(chalk.green('✅ E2B sandbox session completed'));
|
|
140
|
+
resolve({ success: true });
|
|
141
|
+
} else {
|
|
142
|
+
console.error(chalk.red(`✗ E2B sandbox session failed`));
|
|
143
|
+
console.error(chalk.red(` Exit code: ${code}`));
|
|
144
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
pythonProcess.on('error', (error) => {
|
|
149
|
+
console.error(chalk.red(`✗ E2B sandbox session failed`));
|
|
150
|
+
console.error(chalk.red(` Error: ${error.message}`));
|
|
151
|
+
reject(error);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
runE2BSandbox
|
|
158
|
+
};
|
package/lib/execAsync.js
ADDED
package/lib/sandbox.js
CHANGED
|
@@ -6,6 +6,7 @@ const ora = require('ora');
|
|
|
6
6
|
const { promisify } = require('util');
|
|
7
7
|
const { exec } = require('child_process');
|
|
8
8
|
const os = require('os');
|
|
9
|
+
const { runE2BSandbox } = require('./e2b-sandbox');
|
|
9
10
|
|
|
10
11
|
const execAsync = promisify(exec);
|
|
11
12
|
|
|
@@ -22,62 +23,38 @@ function getPythonScriptPath() {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
// If not found, return the path where it will be copied during installation
|
|
25
|
-
return
|
|
26
|
+
return path.join(os.homedir(), '.gitarsenal', 'python', 'test_modalSandboxScript.py');
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
|
-
* Run
|
|
30
|
+
* Run a container with the given options
|
|
30
31
|
* @param {Object} options - Container options
|
|
31
|
-
* @param {string} options.repoUrl - GitHub repository URL
|
|
32
|
-
* @param {string} options.gpuType - GPU type
|
|
33
|
-
* @param {number} options.gpuCount - Number of GPUs (default: 1)
|
|
34
|
-
* @param {string} options.volumeName - Volume name
|
|
35
|
-
* @param {Array<string>} options.setupCommands - Setup commands
|
|
36
|
-
* @param {boolean} options.showExamples - Whether to show usage examples
|
|
37
|
-
* @param {Object} options.analysisData - Repository analysis data from best_gpu endpoint
|
|
38
32
|
* @returns {Promise<void>}
|
|
39
33
|
*/
|
|
40
|
-
async function runContainer(options) {
|
|
41
|
-
const {
|
|
42
|
-
repoUrl,
|
|
43
|
-
gpuType,
|
|
44
|
-
gpuCount = 1,
|
|
45
|
-
volumeName,
|
|
46
|
-
setupCommands = [],
|
|
34
|
+
async function runContainer(options = {}) {
|
|
35
|
+
const {
|
|
47
36
|
showExamples = false,
|
|
37
|
+
repoUrl = '',
|
|
38
|
+
gpuType = 'A10G',
|
|
39
|
+
gpuCount = 1,
|
|
40
|
+
volumeName = '',
|
|
41
|
+
setupCommands = [],
|
|
48
42
|
yes = false,
|
|
49
|
-
userId,
|
|
50
|
-
userName,
|
|
51
|
-
userEmail,
|
|
52
|
-
|
|
43
|
+
userId = '',
|
|
44
|
+
userName = '',
|
|
45
|
+
userEmail = '',
|
|
46
|
+
apiKeys = {},
|
|
47
|
+
analysisData = null,
|
|
48
|
+
sandboxProvider = 'modal'
|
|
53
49
|
} = options;
|
|
54
|
-
|
|
55
|
-
// Get the path to the Python script
|
|
56
|
-
const scriptPath = getPythonScriptPath();
|
|
57
|
-
|
|
58
|
-
// Check if the script exists
|
|
59
|
-
if (!fs.existsSync(scriptPath)) {
|
|
60
|
-
throw new Error(`Python script not found at ${scriptPath}. Please reinstall the package.`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Prepare command arguments
|
|
64
|
-
const args = [
|
|
65
|
-
scriptPath
|
|
66
|
-
];
|
|
67
50
|
|
|
68
|
-
//
|
|
51
|
+
// Check if this is just a request to show examples
|
|
69
52
|
if (showExamples) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
// Run the Python script with show examples flag
|
|
76
|
-
const pythonExecutable = process.env.PYTHON_EXECUTABLE || 'python';
|
|
77
|
-
const pythonProcess = spawn(pythonExecutable, ['-u', ...args], {
|
|
78
|
-
stdio: 'inherit', // Inherit stdio to show real-time output
|
|
79
|
-
env: { ...process.env, PYTHONUNBUFFERED: '1' } // Force unbuffered output
|
|
80
|
-
});
|
|
53
|
+
const scriptPath = getPythonScriptPath();
|
|
54
|
+
const pythonProcess = spawn('python', [
|
|
55
|
+
scriptPath,
|
|
56
|
+
'--show-examples'
|
|
57
|
+
], { stdio: 'inherit' });
|
|
81
58
|
|
|
82
59
|
return new Promise((resolve, reject) => {
|
|
83
60
|
pythonProcess.on('close', (code) => {
|
|
@@ -87,94 +64,101 @@ async function runContainer(options) {
|
|
|
87
64
|
reject(new Error(`Process exited with code ${code}`));
|
|
88
65
|
}
|
|
89
66
|
});
|
|
90
|
-
|
|
91
|
-
pythonProcess.on('error', (error) => {
|
|
92
|
-
reject(error);
|
|
93
|
-
});
|
|
94
67
|
});
|
|
95
68
|
}
|
|
69
|
+
|
|
70
|
+
// Choose sandbox provider
|
|
71
|
+
if (sandboxProvider === 'e2b') {
|
|
72
|
+
console.log(chalk.blue('🚀 Using E2B sandbox provider'));
|
|
73
|
+
return runE2BSandbox({
|
|
74
|
+
repoUrl,
|
|
75
|
+
setupCommands,
|
|
76
|
+
userId,
|
|
77
|
+
userName,
|
|
78
|
+
userEmail,
|
|
79
|
+
apiKeys
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
console.log(chalk.blue('🚀 Using Modal sandbox provider'));
|
|
84
|
+
|
|
85
|
+
// Get the path to the Python script
|
|
86
|
+
const scriptPath = getPythonScriptPath();
|
|
87
|
+
|
|
88
|
+
if (!fs.existsSync(scriptPath)) {
|
|
89
|
+
throw new Error(`Python script not found at ${scriptPath}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log('Launching container...');
|
|
93
|
+
|
|
94
|
+
// Convert setup commands to JSON for passing to Python
|
|
95
|
+
const setupCommandsJson = JSON.stringify(setupCommands);
|
|
96
|
+
|
|
97
|
+
// Convert analysis data to JSON for passing to Python
|
|
98
|
+
const analysisDataJson = analysisData ? JSON.stringify(analysisData) : '';
|
|
99
|
+
|
|
100
|
+
// Convert API keys to JSON for passing to Python
|
|
101
|
+
const apiKeysJson = JSON.stringify(apiKeys);
|
|
102
|
+
|
|
103
|
+
// Build the command arguments
|
|
104
|
+
const args = [
|
|
105
|
+
scriptPath,
|
|
106
|
+
'--gpu', gpuType,
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
if (gpuCount && gpuCount > 1) {
|
|
110
|
+
args.push('--gpu-count', gpuCount.toString());
|
|
111
|
+
}
|
|
96
112
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (repoUrl) args.push('--repo-url', repoUrl);
|
|
113
|
+
if (repoUrl) {
|
|
114
|
+
args.push('--repo-url', repoUrl);
|
|
115
|
+
}
|
|
101
116
|
|
|
102
117
|
if (volumeName) {
|
|
103
118
|
args.push('--volume-name', volumeName);
|
|
104
119
|
}
|
|
105
120
|
|
|
106
|
-
|
|
121
|
+
if (setupCommands && setupCommands.length > 0) {
|
|
122
|
+
args.push('--setup-commands-json', setupCommandsJson);
|
|
123
|
+
}
|
|
107
124
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
args.push('--yes');
|
|
111
|
-
console.log(chalk.gray(`🔍 Debug: Adding --yes flag to Python script`));
|
|
125
|
+
if (userId) {
|
|
126
|
+
args.push('--user-id', userId);
|
|
112
127
|
}
|
|
113
128
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
args.push('--user-id', userEmail);
|
|
117
|
-
args.push('--user-name', userId);
|
|
118
|
-
args.push('--display-name', userName);
|
|
129
|
+
if (userName) {
|
|
130
|
+
args.push('--user-name', userName);
|
|
119
131
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
132
|
+
|
|
133
|
+
if (userEmail) {
|
|
134
|
+
args.push('--display-name', userEmail);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (analysisDataJson) {
|
|
138
|
+
args.push('--analysis-data', analysisDataJson);
|
|
124
139
|
}
|
|
125
140
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
// Create a temporary file to store setup commands
|
|
129
|
-
const tempCommandsFile = path.join(os.tmpdir(), `gitarsenal-commands-${Date.now()}.txt`);
|
|
130
|
-
fs.writeFileSync(tempCommandsFile, setupCommands.join('\n'));
|
|
131
|
-
args.push('--commands-file', tempCommandsFile);
|
|
141
|
+
if (yes) {
|
|
142
|
+
args.push('--yes');
|
|
132
143
|
}
|
|
133
144
|
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
// console.log(chalk.gray(`🔍 Debug: yes parameter = ${yes}`));
|
|
145
|
+
// Use system Python instead of virtual env Python
|
|
146
|
+
const pythonCmd = process.platform === 'win32' ? 'python' : 'python3';
|
|
137
147
|
|
|
138
|
-
// Run the Python script
|
|
139
|
-
|
|
148
|
+
// Run the Python script
|
|
149
|
+
const pythonProcess = spawn(pythonCmd, args, { stdio: 'inherit' });
|
|
140
150
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// Handle process completion
|
|
150
|
-
return new Promise((resolve, reject) => {
|
|
151
|
-
pythonProcess.on('close', (code) => {
|
|
152
|
-
if (code === 0) {
|
|
153
|
-
console.log(chalk.green('✓ Environment ready'));
|
|
154
|
-
console.log(chalk.dim(' Your secure development environment is now active'));
|
|
155
|
-
resolve();
|
|
156
|
-
} else {
|
|
157
|
-
console.log(chalk.red('✗ Launch failed'));
|
|
158
|
-
console.log(chalk.dim(` Exit code: ${code}`));
|
|
159
|
-
reject(new Error(`Process exited with code ${code}`));
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// Handle process errors
|
|
164
|
-
pythonProcess.on('error', (error) => {
|
|
165
|
-
console.log(chalk.red('✗ Process error'));
|
|
166
|
-
console.log(chalk.dim(` ${error.message}`));
|
|
167
|
-
reject(error);
|
|
168
|
-
});
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
pythonProcess.on('close', (code) => {
|
|
153
|
+
if (code === 0) {
|
|
154
|
+
resolve();
|
|
155
|
+
} else {
|
|
156
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
157
|
+
}
|
|
169
158
|
});
|
|
170
|
-
}
|
|
171
|
-
console.log(chalk.red('✗ Launch error'));
|
|
172
|
-
console.log(chalk.dim(` ${error.message}`));
|
|
173
|
-
throw error;
|
|
174
|
-
}
|
|
159
|
+
});
|
|
175
160
|
}
|
|
176
161
|
|
|
177
162
|
module.exports = {
|
|
178
|
-
runContainer
|
|
179
|
-
getPythonScriptPath
|
|
163
|
+
runContainer
|
|
180
164
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gitarsenal-cli",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.97",
|
|
4
4
|
"description": "CLI tool for creating Modal sandboxes with GitHub repositories",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"author": "",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"@e2b/code-interpreter": "^2.0.0",
|
|
24
25
|
"@supabase/supabase-js": "^2.53.0",
|
|
25
26
|
"boxen": "^5.1.2",
|
|
26
27
|
"chalk": "^4.1.2",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|