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.
Files changed (37) hide show
  1. package/.venv_status.json +1 -1
  2. package/README.md +29 -0
  3. package/bin/gitarsenal.js +220 -127
  4. package/kill_claude/requirements.txt +1 -1
  5. package/lib/dependencies.js +130 -4
  6. package/lib/e2b-sandbox.js +158 -0
  7. package/lib/execAsync.js +12 -0
  8. package/lib/sandbox.js +97 -113
  9. package/package.json +2 -1
  10. package/python/__pycache__/credentials_manager.cpython-312.pyc +0 -0
  11. package/python/__pycache__/e2b_sandbox_agent.cpython-313.pyc +0 -0
  12. package/python/__pycache__/fetch_modal_tokens.cpython-312.pyc +0 -0
  13. package/python/credentials_manager.py +2 -1
  14. package/python/e2b_sandbox_agent.py +787 -0
  15. package/python/fetch_modal_tokens.py +47 -25
  16. package/python/requirements.txt +2 -1
  17. package/python/test_enhanced_sandbox_script.py +1429 -0
  18. package/python/test_modalSandboxScript.py +41 -5
  19. package/scripts/setup_e2b.js +162 -0
  20. package/kill_claude/.claude/settings.local.json +0 -9
  21. package/kill_claude/__pycache__/bash_output_tool.cpython-313.pyc +0 -0
  22. package/kill_claude/__pycache__/bash_tool.cpython-313.pyc +0 -0
  23. package/kill_claude/__pycache__/claude_code_agent.cpython-313.pyc +0 -0
  24. package/kill_claude/__pycache__/edit_tool.cpython-313.pyc +0 -0
  25. package/kill_claude/__pycache__/exit_plan_mode_tool.cpython-313.pyc +0 -0
  26. package/kill_claude/__pycache__/glob_tool.cpython-313.pyc +0 -0
  27. package/kill_claude/__pycache__/grep_tool.cpython-313.pyc +0 -0
  28. package/kill_claude/__pycache__/kill_bash_tool.cpython-313.pyc +0 -0
  29. package/kill_claude/__pycache__/ls_tool.cpython-313.pyc +0 -0
  30. package/kill_claude/__pycache__/multiedit_tool.cpython-313.pyc +0 -0
  31. package/kill_claude/__pycache__/notebook_edit_tool.cpython-313.pyc +0 -0
  32. package/kill_claude/__pycache__/read_tool.cpython-313.pyc +0 -0
  33. package/kill_claude/__pycache__/task_tool.cpython-313.pyc +0 -0
  34. package/kill_claude/__pycache__/todo_write_tool.cpython-313.pyc +0 -0
  35. package/kill_claude/__pycache__/web_fetch_tool.cpython-313.pyc +0 -0
  36. package/kill_claude/__pycache__/web_search_tool.cpython-313.pyc +0 -0
  37. package/kill_claude/__pycache__/write_tool.cpython-313.pyc +0 -0
@@ -0,0 +1,787 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ E2B Sandbox Runner with Agent for GitArsenal
4
+ -------------------------------------------
5
+ This script creates an E2B sandbox, uploads the kill_claude agent files,
6
+ and runs the agent to set up a repository.
7
+ """
8
+
9
+ import argparse
10
+ import json
11
+ import os
12
+ import sys
13
+ import time
14
+ from pathlib import Path
15
+
16
+ from e2b_code_interpreter import Sandbox
17
+
18
+ def install_dependencies_in_sandbox(sandbox):
19
+ """
20
+ Install required packages in the sandbox
21
+ """
22
+ print("šŸ“¦ Installing required packages in sandbox...")
23
+
24
+ # Install Python packages
25
+ packages = [
26
+ "openai",
27
+ "anthropic",
28
+ "python-dotenv",
29
+ "requests",
30
+ "tiktoken",
31
+ "typer",
32
+ "rich"
33
+ ]
34
+
35
+ for package in packages:
36
+ print(f" šŸ“¦ Installing {package}...")
37
+ result = sandbox.commands.run(f"pip install {package}")
38
+ if result.exit_code == 0:
39
+ print(f" āœ“ Installed {package}")
40
+ else:
41
+ print(f" āŒ Failed to install {package}")
42
+ print(result.stderr)
43
+
44
+ # Check if git is available
45
+ result = sandbox.commands.run("which git")
46
+ if result.exit_code == 0:
47
+ print(" āœ“ Git is already installed")
48
+ else:
49
+ print(" āŒ Git is not available")
50
+ return False
51
+
52
+ print("āœ… Dependencies installation completed")
53
+ return True
54
+
55
+ def upload_claude_agent_to_sandbox(sandbox):
56
+ """
57
+ Upload the claude_code_agent.py and related files to the sandbox
58
+ """
59
+ print("šŸ“¤ Uploading claude_code_agent.py and related files...")
60
+
61
+ # Create necessary directories
62
+ sandbox.commands.run("mkdir -p /home/user/kill_claude/tools")
63
+ sandbox.commands.run("mkdir -p /home/user/kill_claude/prompts")
64
+
65
+ # Find the kill_claude directory path
66
+ script_dir = os.path.dirname(os.path.abspath(__file__))
67
+ gitarsenal_root = os.path.dirname(script_dir)
68
+ kill_claude_dir = os.path.join(gitarsenal_root, "kill_claude")
69
+
70
+ if not os.path.exists(kill_claude_dir):
71
+ print(f"āŒ Could not find kill_claude directory at {kill_claude_dir}")
72
+ return False
73
+
74
+ # Upload claude_code_agent.py
75
+ agent_path = os.path.join(kill_claude_dir, "claude_code_agent.py")
76
+ if os.path.exists(agent_path):
77
+ with open(agent_path, "r") as f:
78
+ agent_content = f.read()
79
+
80
+ # Check for common issues and fix them
81
+ print("Checking for common issues in claude_code_agent.py...")
82
+
83
+ # Ensure it has the proper shebang
84
+ if not agent_content.startswith("#!/usr/bin/env python"):
85
+ agent_content = "#!/usr/bin/env python3\n" + agent_content
86
+ print(" āœ“ Added shebang to claude_code_agent.py")
87
+
88
+ # Check for API key environment variable access
89
+ if "os.environ['ANTHROPIC_API_KEY']" in agent_content and "os.environ.get('ANTHROPIC_API_KEY')" not in agent_content:
90
+ agent_content = agent_content.replace(
91
+ "os.environ['ANTHROPIC_API_KEY']",
92
+ "os.environ.get('ANTHROPIC_API_KEY')"
93
+ )
94
+ print(" āœ“ Fixed API key access to use os.environ.get()")
95
+
96
+ # Check for the correct model name
97
+ if "claude-3-5-sonnet" in agent_content and "claude-3-5-sonnet-20241022" not in agent_content:
98
+ agent_content = agent_content.replace(
99
+ "claude-3-5-sonnet",
100
+ "claude-3-5-sonnet-20241022"
101
+ )
102
+ print(" āœ“ Updated model name to claude-3-5-sonnet-20241022")
103
+
104
+ # Check if it's using Typer correctly
105
+ if "app = typer.Typer()" in agent_content and "if __name__ == \"__main__\":" in agent_content:
106
+ # Make sure the main function is called correctly
107
+ if "if __name__ == \"__main__\":\n app()" not in agent_content and "if __name__ == \"__main__\":\n main()" in agent_content:
108
+ agent_content = agent_content.replace(
109
+ "if __name__ == \"__main__\":\n main()",
110
+ "if __name__ == \"__main__\":\n app()"
111
+ )
112
+ print(" āœ“ Fixed Typer app execution")
113
+
114
+ sandbox.run_code(f"""
115
+ with open('/home/user/kill_claude/claude_code_agent.py', 'w') as f:
116
+ f.write({repr(agent_content)})
117
+ """)
118
+ print(" āœ“ Uploaded claude_code_agent.py with fixes")
119
+
120
+ # Ensure the first line has the shebang
121
+ sandbox.run_code("""
122
+ content = ''
123
+ with open('/home/user/kill_claude/claude_code_agent.py', 'r') as f:
124
+ content = f.read()
125
+ if not content.startswith('#!/usr/bin/env python'):
126
+ with open('/home/user/kill_claude/claude_code_agent.py', 'w') as f:
127
+ f.write('#!/usr/bin/env python3\\n' + content)
128
+ print(" āœ“ Added shebang to claude_code_agent.py")
129
+ """)
130
+ else:
131
+ print(f"āŒ Could not find claude_code_agent.py at {agent_path}")
132
+ return False
133
+
134
+ # Upload requirements.txt
135
+ req_path = os.path.join(kill_claude_dir, "requirements.txt")
136
+ if os.path.exists(req_path):
137
+ with open(req_path, "r") as f:
138
+ req_content = f.read()
139
+ sandbox.run_code(f"""
140
+ with open('/home/user/kill_claude/requirements.txt', 'w') as f:
141
+ f.write({repr(req_content)})
142
+ """)
143
+ print(" āœ“ Uploaded requirements.txt")
144
+
145
+ # Upload prompts
146
+ prompts_dir = os.path.join(kill_claude_dir, "prompts")
147
+ if os.path.exists(prompts_dir):
148
+ for prompt_file in os.listdir(prompts_dir):
149
+ if prompt_file.endswith(".md"):
150
+ prompt_path = os.path.join(prompts_dir, prompt_file)
151
+ with open(prompt_path, "r") as f:
152
+ prompt_content = f.read()
153
+ sandbox.run_code(f"""
154
+ with open('/home/user/kill_claude/prompts/{prompt_file}', 'w') as f:
155
+ f.write({repr(prompt_content)})
156
+ """)
157
+ print(f"Preparing Agents...")
158
+
159
+ # Upload tools
160
+ tools_dir = os.path.join(kill_claude_dir, "tools")
161
+ if os.path.exists(tools_dir):
162
+ for tool_file in os.listdir(tools_dir):
163
+ if tool_file.endswith(".py"):
164
+ tool_path = os.path.join(tools_dir, tool_file)
165
+ with open(tool_path, "r") as f:
166
+ tool_content = f.read()
167
+ sandbox.run_code(f"""
168
+ with open('/home/user/kill_claude/tools/{tool_file}', 'w') as f:
169
+ f.write({repr(tool_content)})
170
+ """)
171
+ print(f"Preparing Tools...")
172
+
173
+ # Create __init__.py in tools directory
174
+ sandbox.run_code("""
175
+ with open('/home/user/kill_claude/tools/__init__.py', 'w') as f:
176
+ f.write('')
177
+ """)
178
+
179
+ print("āœ… Agents are ready to go!")
180
+ return True
181
+
182
+ def create_simple_agent_script(sandbox):
183
+ """
184
+ Create a simpler agent script that emulates the TodoWrite functionality
185
+ """
186
+ print("šŸ“ Creating simple agent script...")
187
+
188
+ script_content = """
189
+ import os
190
+ import sys
191
+ import subprocess
192
+ import time
193
+ import json
194
+
195
+ def run_command(cmd, cwd=None):
196
+ print(f"Running: {cmd}")
197
+ result = subprocess.run(cmd, shell=True, capture_output=True, text=True, cwd=cwd)
198
+ if result.stdout:
199
+ print("Output:")
200
+ print(result.stdout.strip())
201
+ if result.stderr:
202
+ print("Error:")
203
+ print(result.stderr.strip())
204
+ return result.returncode == 0, result.stdout
205
+
206
+ def print_todo_list(todos):
207
+ print("╭────────────────────────── šŸ› ļø Using Tool: TodoWrite ───────────────────────────╮")
208
+ print("│ ╭────────────────────────── Todo List ({} items) ───────────────────────────╮ │".format(len(todos)))
209
+ print("│ │ ā”ā”ā”ā”ā”ā”ā”³ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”³ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”ā”“ │ │")
210
+ print("│ │ ā”ƒ # ā”ƒ Status ā”ƒ Task ā”ƒ │ │")
211
+ print("│ │ └━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │ │")
212
+
213
+ for i, todo in enumerate(todos, 1):
214
+ status = "ā³ Pending"
215
+ if todo.get("status") == "in_progress":
216
+ status = "šŸ”„ In Progress"
217
+ elif todo.get("status") == "completed":
218
+ status = "āœ“ Completed"
219
+
220
+ content = todo.get("content", "")
221
+ print("│ │ │ {:<3} │ {:<10} │ {:<50} │ │ │".format(i, status, content[:50]))
222
+
223
+ print("│ │ ā””ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ │ │")
224
+ print("│ ╰────────────────────────────────────────────────────────────────────────────╯ │")
225
+ print("╰──────────────────────────────────────────────────────────────────────────────────╯")
226
+
227
+ def update_todo(todos, index, status):
228
+ if 0 <= index < len(todos):
229
+ todos[index]["status"] = status
230
+ return todos
231
+
232
+ def setup_repository(repo_url):
233
+ print("Setting up repository: " + repo_url)
234
+
235
+ # Initialize todo list
236
+ todos = [
237
+ {"id": "1", "content": "Clone the repository from GitHub", "status": "pending"},
238
+ {"id": "2", "content": "Examine repository structure and setup requirements", "status": "pending"},
239
+ {"id": "3", "content": "Install dependencies and setup the project", "status": "pending"},
240
+ {"id": "4", "content": "Run the application/tests", "status": "pending"},
241
+ {"id": "5", "content": "Print ordered list of successful commands", "status": "pending"}
242
+ ]
243
+
244
+ print_todo_list(todos)
245
+
246
+ # Step 1: Clone repository
247
+ print("\\n============================================================")
248
+ print("šŸŽ‰ AGENT OUTPUT (LIVE)")
249
+ print("============================================================")
250
+
251
+ todos = update_todo(todos, 0, "in_progress")
252
+ print_todo_list(todos)
253
+
254
+ # Create directory
255
+ repo_dir = os.path.join(os.getcwd(), 'repo')
256
+ os.makedirs(repo_dir, exist_ok=True)
257
+
258
+ # Clone repository
259
+ print("Cloning repository...")
260
+ success, _ = run_command(f"git clone {repo_url} .", cwd=repo_dir)
261
+ if not success:
262
+ print("Failed to clone repository")
263
+ print("Trying again with --depth 1...")
264
+ success, _ = run_command(f"git clone --depth 1 {repo_url} .", cwd=repo_dir)
265
+ if not success:
266
+ print("Failed to clone repository even with --depth 1")
267
+ return False
268
+
269
+ todos = update_todo(todos, 0, "completed")
270
+ todos = update_todo(todos, 1, "in_progress")
271
+ print_todo_list(todos)
272
+
273
+ # Step 2: Examine repository structure
274
+ print("Analyzing repository structure...")
275
+
276
+ # Python project checks
277
+ has_requirements = os.path.exists(os.path.join(repo_dir, 'requirements.txt'))
278
+ has_setup_py = os.path.exists(os.path.join(repo_dir, 'setup.py'))
279
+ has_pyproject = os.path.exists(os.path.join(repo_dir, 'pyproject.toml'))
280
+
281
+ # JavaScript project checks
282
+ has_package_json = os.path.exists(os.path.join(repo_dir, 'package.json'))
283
+
284
+ # Print repository info
285
+ print("Repository information:")
286
+ print(f" Python project: {has_requirements or has_setup_py or has_pyproject}")
287
+ print(f" JavaScript project: {has_package_json}")
288
+
289
+ todos = update_todo(todos, 1, "completed")
290
+ todos = update_todo(todos, 2, "in_progress")
291
+ print_todo_list(todos)
292
+
293
+ # Step 3: Setup Python environment if needed
294
+ if has_requirements or has_setup_py or has_pyproject:
295
+ print("Setting up Python environment...")
296
+
297
+ # Create and activate virtual environment
298
+ run_command('python -m venv .venv', cwd=repo_dir)
299
+
300
+ # Install dependencies
301
+ if has_requirements:
302
+ print("Installing requirements.txt dependencies...")
303
+ run_command('.venv/bin/pip install -r requirements.txt', cwd=repo_dir)
304
+
305
+ if has_setup_py:
306
+ print("Installing package in development mode...")
307
+ run_command('.venv/bin/pip install -e .', cwd=repo_dir)
308
+
309
+ # Setup JavaScript environment if needed
310
+ if has_package_json:
311
+ print("Setting up JavaScript environment...")
312
+ run_command('npm install', cwd=repo_dir)
313
+
314
+ todos = update_todo(todos, 2, "completed")
315
+ todos = update_todo(todos, 3, "in_progress")
316
+ print_todo_list(todos)
317
+
318
+ # Step 4: Run tests if available
319
+ if has_requirements or has_setup_py or has_pyproject:
320
+ if os.path.exists(os.path.join(repo_dir, 'tests')):
321
+ print("Running tests...")
322
+ run_command('.venv/bin/pytest', cwd=repo_dir)
323
+
324
+ todos = update_todo(todos, 3, "completed")
325
+ todos = update_todo(todos, 4, "in_progress")
326
+ print_todo_list(todos)
327
+
328
+ # Step 5: Print successful commands
329
+ print("\\n============================================================")
330
+ print("āœ… Successful commands:")
331
+ print("git clone " + repo_url)
332
+ if has_requirements:
333
+ print("python -m venv .venv")
334
+ print(".venv/bin/pip install -r requirements.txt")
335
+ if has_setup_py:
336
+ print(".venv/bin/pip install -e .")
337
+ if has_package_json:
338
+ print("npm install")
339
+ print("============================================================")
340
+
341
+ todos = update_todo(todos, 4, "completed")
342
+ print_todo_list(todos)
343
+
344
+ print("Repository setup complete!")
345
+ return True
346
+
347
+ if __name__ == '__main__':
348
+ if len(sys.argv) < 2:
349
+ print('Usage: python simple_agent.py <repository_url>')
350
+ sys.exit(1)
351
+
352
+ repo_url = sys.argv[1]
353
+ print('GitArsenal Simple Agent')
354
+ print('Repository URL: ' + repo_url)
355
+ print('Working Directory: ' + os.getcwd())
356
+
357
+ start_time = time.time()
358
+ success = setup_repository(repo_url)
359
+ end_time = time.time()
360
+
361
+ print('Setup completed in ' + str(round(end_time - start_time, 2)) + ' seconds')
362
+
363
+ if success:
364
+ print('Repository setup successful!')
365
+ print('You can now work with the repository in the repo directory')
366
+ else:
367
+ print('Repository setup failed')
368
+ sys.exit(1)
369
+ """
370
+
371
+ # Debugging: Check if we can write to the directory
372
+ try:
373
+ # First check if we can list the directory
374
+ result = sandbox.commands.run("ls -la /home/user")
375
+ print(f"Directory contents of /home/user: {result.stdout}")
376
+
377
+ # Check if we can create a simple file
378
+ result = sandbox.commands.run("echo 'test' > /home/user/test.txt")
379
+ print(f"Create test file result: {result.exit_code}")
380
+
381
+ # Check if the file was created
382
+ result = sandbox.commands.run("cat /home/user/test.txt")
383
+ print(f"Test file contents: {result.stdout}")
384
+ except Exception as e:
385
+ print(f"āš ļø Directory check failed: {e}")
386
+
387
+ # Method 1: Use Python to write the file
388
+ try:
389
+ # Use Python to create the file
390
+ python_code = f'''
391
+ import os
392
+
393
+ script_content = """{script_content}"""
394
+
395
+ with open("/home/user/simple_agent.py", "w") as f:
396
+ f.write(script_content)
397
+
398
+ print("File written successfully")
399
+ '''
400
+
401
+ result = sandbox.run_code(python_code)
402
+ print(f"Python file creation result: {result}")
403
+
404
+ # Verify the file exists
405
+ result = sandbox.commands.run("ls -la /home/user/simple_agent.py")
406
+ if result.exit_code == 0:
407
+ print("āœ… Simple agent script created successfully")
408
+ return True
409
+ else:
410
+ print(f"āš ļø File creation verification failed: {result.stderr}")
411
+ except Exception as e:
412
+ print(f"āš ļø Error creating file with Python: {e}")
413
+
414
+ # Method 2: Use a temporary file
415
+ try:
416
+ print("Trying with temporary file...")
417
+ # Create a temporary file
418
+ result = sandbox.commands.run("touch /home/user/temp_script.py")
419
+
420
+ # Write the script content to the temporary file in chunks
421
+ chunk_size = 1000 # Write in chunks to avoid command line limits
422
+ for i in range(0, len(script_content), chunk_size):
423
+ chunk = script_content[i:i+chunk_size]
424
+ # Escape special characters
425
+ chunk = chunk.replace('"', '\\"').replace("'", "\\'").replace("`", "\\`").replace("$", "\\$")
426
+ result = sandbox.commands.run(f'echo "{chunk}" >> /home/user/temp_script.py')
427
+ print(f" Writing chunk {i//chunk_size + 1}...")
428
+
429
+ # Move the temporary file to the final location
430
+ result = sandbox.commands.run("mv /home/user/temp_script.py /home/user/simple_agent.py")
431
+
432
+ # Make it executable
433
+ result = sandbox.commands.run("chmod +x /home/user/simple_agent.py")
434
+
435
+ # Verify the file exists
436
+ result = sandbox.commands.run("ls -la /home/user/simple_agent.py")
437
+ if result.exit_code == 0:
438
+ print("āœ… Simple agent script created (chunked method)")
439
+ return True
440
+ else:
441
+ print(f"āš ļø File creation verification failed: {result.stderr}")
442
+ except Exception as e:
443
+ print(f"āŒ Failed to create simple_agent.py with chunked method: {e}")
444
+
445
+ # Method 3: Use a heredoc approach
446
+ try:
447
+ print("Trying with heredoc approach...")
448
+
449
+ # Create a small script that uses heredoc to create the file
450
+ heredoc_script = """
451
+ cat > /home/user/simple_agent.py << 'EOL'
452
+ """ + script_content + """
453
+ EOL
454
+ """
455
+
456
+ # Write the heredoc script to a temporary file
457
+ result = sandbox.commands.run("touch /home/user/create_script.sh")
458
+ result = sandbox.commands.run(f'echo "{heredoc_script}" > /home/user/create_script.sh')
459
+
460
+ # Make it executable
461
+ result = sandbox.commands.run("chmod +x /home/user/create_script.sh")
462
+
463
+ # Run the script
464
+ result = sandbox.commands.run("bash /home/user/create_script.sh")
465
+
466
+ # Verify the file exists
467
+ result = sandbox.commands.run("ls -la /home/user/simple_agent.py")
468
+ if result.exit_code == 0:
469
+ print("āœ… Simple agent script created (heredoc method)")
470
+ return True
471
+ else:
472
+ print(f"āš ļø File creation verification failed: {result.stderr}")
473
+ except Exception as e:
474
+ print(f"āŒ Failed to create simple_agent.py with heredoc method: {e}")
475
+
476
+ print("āŒ All methods to create simple_agent.py failed")
477
+ return False
478
+
479
+ def run_e2b_sandbox(repo_url, setup_commands=None, api_keys=None):
480
+ """
481
+ Run the E2B sandbox with the given repository URL
482
+ """
483
+ print("šŸ”„ Creating E2B sandbox...")
484
+ try:
485
+ # Create a new E2B sandbox with a longer timeout (30 minutes)
486
+ sandbox = Sandbox.create(timeout=1800)
487
+ print("āœ… E2B sandbox created successfully (30 minute timeout)")
488
+
489
+ # Install required packages
490
+ print("šŸ“¦ Installing required packages in sandbox...")
491
+ install_dependencies_in_sandbox(sandbox)
492
+
493
+ # Upload claude_code_agent.py and related files
494
+ upload_claude_agent_to_sandbox(sandbox)
495
+ print("šŸ“¦ Installing required packages for claude_code_agent...")
496
+ result = sandbox.commands.run("cd /home/user/kill_claude && pip install -r requirements.txt")
497
+ if result.exit_code != 0:
498
+ print(f"āš ļø Failed to install requirements for claude_code_agent: {result.stderr}")
499
+ else:
500
+ print("āœ… Successfully installed requirements for claude_code_agent")
501
+
502
+ # Verify package installation
503
+ result = sandbox.commands.run("pip list | grep -E 'anthropic|typer|rich'")
504
+ print(f"Installed packages verification: {result.stdout}")
505
+
506
+ # Create a wrapper script to run claude_code_agent.py
507
+ wrapper_script = """#!/usr/bin/env python3
508
+ import sys
509
+ import os
510
+ import subprocess
511
+
512
+ if __name__ == "__main__":
513
+ if len(sys.argv) < 2:
514
+ print("Usage: python run_claude_agent.py <prompt>")
515
+ sys.exit(1)
516
+
517
+ prompt = sys.argv[1]
518
+
519
+ # Set up the environment
520
+ os.environ['ANTHROPIC_API_KEY'] = os.environ.get('ANTHROPIC_API_KEY', '')
521
+
522
+ try:
523
+ # Import the module
524
+ sys.path.append('/home/user')
525
+ from kill_claude import claude_code_agent
526
+
527
+ # Set sys.argv to use the query subcommand
528
+ sys.argv = ['/home/user/kill_claude/claude_code_agent.py', 'query', prompt]
529
+
530
+ # Call the main function
531
+ claude_code_agent.main()
532
+ except Exception as e:
533
+ print(f"Error executing claude_code_agent.py: {e}")
534
+ import traceback
535
+ traceback.print_exc()
536
+ sys.exit(1)
537
+ """
538
+
539
+ sandbox.run_code(f"""
540
+ with open('/home/user/run_claude_agent.py', 'w') as f:
541
+ f.write({repr(wrapper_script)})
542
+ print("āœ… Created wrapper script for claude_code_agent.py")
543
+ """)
544
+
545
+ # List the contents of the kill_claude directory
546
+ print("šŸ“‚ Listing contents of kill_claude directory:")
547
+ result = sandbox.commands.run("ls -la /home/user/kill_claude")
548
+ print(result.stdout)
549
+
550
+ # List the contents of the tools directory
551
+ print("šŸ“‚ Listing contents of kill_claude/tools directory:")
552
+ result = sandbox.commands.run("ls -la /home/user/kill_claude/tools")
553
+ print(result.stdout)
554
+
555
+ # List the contents of the prompts directory
556
+ print("šŸ“‚ Listing contents of kill_claude/prompts directory:")
557
+ result = sandbox.commands.run("ls -la /home/user/kill_claude/prompts")
558
+ print(result.stdout)
559
+
560
+ # Find the Python executable path
561
+ result = sandbox.commands.run("which python")
562
+ python_path = result.stdout.strip()
563
+ print(f"Python executable path: {python_path}")
564
+
565
+ # Test Python interpreter
566
+ result = sandbox.commands.run("python -c \"print('Python interpreter test')\"")
567
+ if result.exit_code == 0:
568
+ print("āœ… Python interpreter is working correctly")
569
+ else:
570
+ print("āŒ Python interpreter test failed")
571
+ print(f"Error: {result.stderr}")
572
+
573
+ # Set up API keys in the sandbox environment
574
+ if api_keys:
575
+ for key_name, key_value in api_keys.items():
576
+ if key_value:
577
+ # Set environment variable in the sandbox
578
+ sandbox.run_code(f"""
579
+ import os
580
+ os.environ['{key_name}'] = '{key_value}'
581
+ print(f"āœ… Set {key_name} in sandbox environment")
582
+ """)
583
+
584
+ print("\n" + "="*80)
585
+ print("šŸ¤– CLAUDE AGENT REPOSITORY SETUP")
586
+ print("="*80)
587
+ print(f"Repository: {repo_url}")
588
+ print(f"Working Directory: /home/user")
589
+ print(f"Available Credentials: {len(api_keys) if api_keys else 0} items")
590
+ print("="*80 + "\n")
591
+
592
+ print("\n" + "="*60)
593
+ print("šŸŽ‰ AGENT OUTPUT (LIVE)")
594
+ print("="*60)
595
+
596
+ # Create a prompt for the agent
597
+ claude_prompt = f"clone, setup and run {repo_url}. At the end of the setup process, print the ordered list of every shell command that actually ran successfully (exclude any commands that returned non-zero exit codes). Show each command exactly as executed, one per line."
598
+
599
+ # Set environment variables directly in the command
600
+ print("šŸš€ Running claude_code_agent.py...")
601
+ if api_keys and 'ANTHROPIC_API_KEY' in api_keys:
602
+ anthropic_key = api_keys['ANTHROPIC_API_KEY']
603
+ # Print the first few characters of the API key to verify it's being passed correctly
604
+ print(f"āœ… Using Anthropic API key: {anthropic_key[:8]}...")
605
+
606
+ # Run the claude_code_agent.py directly with the environment variable
607
+ print("šŸ“ Running claude_code_agent.py directly...")
608
+
609
+ # Debug: Check if the file exists and is executable
610
+ result = sandbox.commands.run("ls -la /home/user/kill_claude/claude_code_agent.py")
611
+ print(f"File check: {result.stdout}")
612
+
613
+ # Test importing the module
614
+ import_test = sandbox.run_code("""
615
+ try:
616
+ import sys
617
+ sys.path.append('/home/user')
618
+ from kill_claude import claude_code_agent
619
+ print("āœ… Successfully imported claude_code_agent module")
620
+
621
+ # Check if the main function exists and is callable
622
+ if hasattr(claude_code_agent, 'main'):
623
+ print("āœ… main function exists in claude_code_agent module")
624
+ if callable(getattr(claude_code_agent, 'main')):
625
+ print("āœ… main function is callable")
626
+ else:
627
+ print("āŒ main function is not callable")
628
+ else:
629
+ print("āŒ main function does not exist in claude_code_agent module")
630
+
631
+ # Check if it's a Typer app
632
+ if hasattr(claude_code_agent, 'app') and hasattr(claude_code_agent.app, 'command'):
633
+ print("āœ… This is a Typer app")
634
+ print("Available commands:", [cmd.name for cmd in claude_code_agent.app.registered_commands])
635
+ else:
636
+ print("āŒ This is not a Typer app or app structure is different")
637
+
638
+ # Print the module's attributes to see what's available
639
+ print("Module attributes:", dir(claude_code_agent))
640
+ except Exception as e:
641
+ print(f"āŒ Failed to import claude_code_agent module: {e}")
642
+ """)
643
+
644
+ # Now run the actual command with more debugging
645
+ print("šŸ“ Running claude_code_agent.py with debugging...")
646
+
647
+ # Try with a simpler approach - just the query subcommand
648
+ debug_cmd = f"cd /home/user && ANTHROPIC_API_KEY=\"{anthropic_key}\" python /home/user/kill_claude/claude_code_agent.py query \"{claude_prompt}\""
649
+ print("Command to execute:", debug_cmd)
650
+
651
+ # Define stdout and stderr handlers to stream output in real-time
652
+ def on_stdout(data):
653
+ print(data.strip())
654
+
655
+ def on_stderr(data):
656
+ print(f"STDERR: {data.strip()}")
657
+
658
+ # Run the command with streaming output
659
+ print("Starting command execution with streaming output...")
660
+ try:
661
+ result = sandbox.commands.run(debug_cmd, timeout=1800, on_stdout=on_stdout, on_stderr=on_stderr)
662
+
663
+ print(f"Claude agent exit code: {result.exit_code}")
664
+
665
+ if result.exit_code != 0:
666
+ print(f"āš ļø Claude agent failed with exit code {result.exit_code}")
667
+
668
+ # Try to diagnose the issue
669
+ print("šŸ” Diagnosing the issue...")
670
+
671
+ # Check if the file exists
672
+ file_check = sandbox.commands.run("ls -la /home/user/kill_claude/claude_code_agent.py")
673
+ print(f"File exists: {file_check.exit_code == 0}")
674
+
675
+ # Check Python version
676
+ python_version = sandbox.commands.run("python --version")
677
+ print(f"Python version: {python_version.stdout}")
678
+ else:
679
+ print("āœ… Claude agent completed successfully")
680
+ return True
681
+
682
+ # Use the simple agent as a fallback
683
+ print("Will use simple agent as a fallback if needed...")
684
+
685
+ # Try using the wrapper script
686
+ print("Trying wrapper script execution method...")
687
+ wrapper_cmd = f"cd /home/user && ANTHROPIC_API_KEY=\"{anthropic_key}\" python run_claude_agent.py \"{claude_prompt}\""
688
+ wrapper_result = sandbox.commands.run(wrapper_cmd, timeout=1800, on_stdout=on_stdout, on_stderr=on_stderr)
689
+ print(f"Wrapper script execution result: {wrapper_result.exit_code}")
690
+
691
+ if wrapper_result.exit_code == 0:
692
+ print("āœ… Claude agent completed successfully using wrapper script")
693
+ return True
694
+
695
+ # Try direct command with query
696
+ print("Trying direct command with query subcommand...")
697
+ direct_cmd = f"cd /home/user && ANTHROPIC_API_KEY=\"{anthropic_key}\" python /home/user/kill_claude/claude_code_agent.py query \"{claude_prompt}\""
698
+ direct_result = sandbox.commands.run(direct_cmd, timeout=1800, on_stdout=on_stdout, on_stderr=on_stderr)
699
+ print(f"Direct command result: {direct_result.exit_code}")
700
+
701
+ if direct_result.exit_code == 0:
702
+ print("āœ… Claude agent completed successfully using direct command")
703
+ return True
704
+
705
+ # Final fallback: Create and use a simple agent
706
+ print("šŸ”„ Falling back to simple agent...")
707
+ if create_simple_agent_script(sandbox):
708
+ simple_cmd = f"cd /home/user && python simple_agent.py \"{repo_url}\""
709
+ simple_result = sandbox.commands.run(simple_cmd, timeout=1800, on_stdout=on_stdout, on_stderr=on_stderr)
710
+ print(f"Simple agent result: {simple_result.exit_code}")
711
+
712
+ if simple_result.exit_code == 0:
713
+ print("āœ… Simplified claude agent completed successfully")
714
+ return True
715
+ return False
716
+
717
+ except KeyboardInterrupt:
718
+ print("\nšŸ›‘ Execution interrupted by user")
719
+ # Try to gracefully terminate the process
720
+ try:
721
+ sandbox.commands.run("pkill -f 'python.*claude_code_agent.py'", timeout=10)
722
+ except:
723
+ pass
724
+ return False
725
+ else:
726
+ print("āš ļø No Anthropic API key found")
727
+ return False
728
+ except KeyboardInterrupt:
729
+ print("\nšŸ›‘ Execution interrupted by user")
730
+ return False
731
+ except Exception as e:
732
+ print(f"āŒ E2B sandbox setup failed: {e}")
733
+ return False
734
+
735
+ def main():
736
+ """
737
+ Main function to run the E2B sandbox
738
+ """
739
+ parser = argparse.ArgumentParser(description="Run an E2B sandbox with a repository")
740
+ parser.add_argument("--repo", required=True, help="Repository URL to clone")
741
+ parser.add_argument("--setup-commands", help="JSON file with setup commands")
742
+ parser.add_argument("--openai-api-key", help="OpenAI API key")
743
+ parser.add_argument("--anthropic-api-key", help="Anthropic API key")
744
+ args = parser.parse_args()
745
+
746
+ # Prepare API keys
747
+ api_keys = {}
748
+
749
+ # Check for OpenAI API key
750
+ openai_api_key = args.openai_api_key or os.environ.get("OPENAI_API_KEY")
751
+ if openai_api_key:
752
+ api_keys["OPENAI_API_KEY"] = openai_api_key
753
+
754
+ # Check for Anthropic API key
755
+ anthropic_api_key = args.anthropic_api_key or os.environ.get("ANTHROPIC_API_KEY")
756
+ if anthropic_api_key:
757
+ api_keys["ANTHROPIC_API_KEY"] = anthropic_api_key
758
+ else:
759
+ # Try to get Anthropic API key from modal_tokens.json
760
+ modal_tokens_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "modal_tokens.json")
761
+ if os.path.exists(modal_tokens_path):
762
+ try:
763
+ with open(modal_tokens_path, "r") as f:
764
+ modal_tokens = json.load(f)
765
+ if "anthropic_api_key" in modal_tokens:
766
+ api_keys["ANTHROPIC_API_KEY"] = modal_tokens["anthropic_api_key"]
767
+ print("āœ… Found Anthropic API key in modal_tokens.json")
768
+ except Exception as e:
769
+ print(f"Error loading modal_tokens.json: {e}")
770
+
771
+ # Parse setup commands if provided
772
+ setup_commands = None
773
+ if args.setup_commands:
774
+ try:
775
+ with open(args.setup_commands, "r") as f:
776
+ setup_commands = json.load(f)
777
+ except Exception as e:
778
+ print(f"Error loading setup commands: {e}")
779
+
780
+ # Run the sandbox
781
+ success = run_e2b_sandbox(args.repo, setup_commands, api_keys)
782
+
783
+ # Exit with appropriate code
784
+ sys.exit(0 if success else 1)
785
+
786
+ if __name__ == "__main__":
787
+ main()