gitarsenal-cli 1.9.66 ā 1.9.68
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/package.json +1 -1
- package/python/test_modalSandboxScript.py +65 -67
package/.venv_status.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"created":"2025-08-
|
|
1
|
+
{"created":"2025-08-15T04:06:48.506Z","packages":["modal","gitingest","requests","anthropic"],"uv_version":"uv 0.8.4 (Homebrew 2025-07-30)"}
|
package/package.json
CHANGED
|
@@ -203,8 +203,8 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
|
203
203
|
volume_name=None, timeout_minutes=60, ssh_password=None, interactive=False, gpu_count=1):
|
|
204
204
|
"""Create a Modal SSH container with GPU support and intelligent repository setup.
|
|
205
205
|
|
|
206
|
-
When repo_url is provided, uses
|
|
207
|
-
The setup_commands parameter is maintained for backwards compatibility but ignored when using
|
|
206
|
+
When repo_url is provided, uses Agent for intelligent repository setup.
|
|
207
|
+
The setup_commands parameter is maintained for backwards compatibility but ignored when using Agent.
|
|
208
208
|
"""
|
|
209
209
|
|
|
210
210
|
# Use interactive mode if specified
|
|
@@ -388,29 +388,12 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
|
388
388
|
# Set up a nice bash prompt
|
|
389
389
|
"echo 'export PS1=\"\\[\\e[1;32m\\]modal:\\[\\e[1;34m\\]\\w\\[\\e[0m\\]$ \"' >> /root/.bashrc",
|
|
390
390
|
|
|
391
|
-
# Create directories
|
|
392
|
-
"mkdir -p /python
|
|
391
|
+
# Create base directories (subdirectories will be created automatically when mounting)
|
|
392
|
+
"mkdir -p /python",
|
|
393
393
|
)
|
|
394
|
-
# Mount
|
|
395
|
-
.
|
|
396
|
-
.
|
|
397
|
-
.add_local_file(os.path.join(current_dir, "fetch_modal_tokens.py"), "/python/fetch_modal_tokens.py") # Mount fetch_modal_token.py
|
|
398
|
-
.add_local_file(os.path.join(current_dir, "llm_debugging.py"), "/python/llm_debugging.py") # Mount llm_debugging.py
|
|
399
|
-
.add_local_file(os.path.join(current_dir, "credentials_manager.py"), "/python/credentials_manager.py") # Mount credentials_manager.py
|
|
400
|
-
# Mount Claude Code Agent and its dependencies
|
|
401
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "claude_code_agent.py"), "/python/kill_claude/claude_code_agent.py")
|
|
402
|
-
# Mount the tools and prompts directories manually with key files
|
|
403
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "__init__.py"), "/python/kill_claude/tools/__init__.py")
|
|
404
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "bash_tool.py"), "/python/kill_claude/tools/bash_tool.py")
|
|
405
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "read_tool.py"), "/python/kill_claude/tools/read_tool.py")
|
|
406
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "write_tool.py"), "/python/kill_claude/tools/write_tool.py")
|
|
407
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "ls_tool.py"), "/python/kill_claude/tools/ls_tool.py")
|
|
408
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "edit_tool.py"), "/python/kill_claude/tools/edit_tool.py")
|
|
409
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "grep_tool.py"), "/python/kill_claude/tools/grep_tool.py")
|
|
410
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "glob_tool.py"), "/python/kill_claude/tools/glob_tool.py")
|
|
411
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "tools", "todo_write_tool.py"), "/python/kill_claude/tools/todo_write_tool.py")
|
|
412
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "prompts", "claude-code-system-prompt.md"), "/python/kill_claude/prompts/claude-code-system-prompt.md")
|
|
413
|
-
.add_local_file(os.path.join(gitarsenal_root, "kill_claude", "prompts", "claude-code-agent-prompts.md"), "/python/kill_claude/prompts/claude-code-agent-prompts.md")
|
|
394
|
+
# Mount entire directories instead of individual files
|
|
395
|
+
.add_local_dir(current_dir, "/python", ignore=lambda p: not p.name.endswith('.py')) # Mount all Python files from current directory
|
|
396
|
+
.add_local_dir(os.path.join(gitarsenal_root, "kill_claude"), "/python/kill_claude") # Mount entire kill_claude directory with all subdirectories
|
|
414
397
|
|
|
415
398
|
)
|
|
416
399
|
print("ā
SSH image built successfully")
|
|
@@ -437,7 +420,7 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
|
437
420
|
volumes=volumes_config if volumes_config else None,
|
|
438
421
|
)
|
|
439
422
|
def ssh_container_function(ssh_password=None, repo_url=None, repo_name=None, setup_commands=None, openai_api_key=None, anthropic_api_key=None, stored_credentials=None):
|
|
440
|
-
"""Start SSH container with password authentication and intelligent repository setup using
|
|
423
|
+
"""Start SSH container with password authentication and intelligent repository setup using Agent."""
|
|
441
424
|
import subprocess
|
|
442
425
|
import time
|
|
443
426
|
import os
|
|
@@ -514,11 +497,11 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
|
514
497
|
# Start SSH service
|
|
515
498
|
subprocess.run(["service", "ssh", "start"], check=True)
|
|
516
499
|
|
|
517
|
-
# Use
|
|
500
|
+
# Use Agent for intelligent repository setup
|
|
518
501
|
if repo_url:
|
|
519
|
-
print("š¤ Using
|
|
502
|
+
print("š¤ Using Agent for intelligent repository setup...")
|
|
520
503
|
|
|
521
|
-
# Set up environment variables for the
|
|
504
|
+
# Set up environment variables for the Agent
|
|
522
505
|
if openai_api_key:
|
|
523
506
|
os.environ['OPENAI_API_KEY'] = openai_api_key
|
|
524
507
|
if anthropic_api_key:
|
|
@@ -537,13 +520,13 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
|
537
520
|
|
|
538
521
|
if not anthropic_api_key:
|
|
539
522
|
print("ā ļø No Anthropic API key found in stored credentials")
|
|
540
|
-
print("š”
|
|
523
|
+
print("š” Agent will require an Anthropic API key for operation")
|
|
541
524
|
|
|
542
525
|
try:
|
|
543
|
-
print("š§ Running
|
|
526
|
+
print("š§ Running Agent for repository setup...")
|
|
544
527
|
|
|
545
528
|
print("\n" + "="*80)
|
|
546
|
-
print("š¤
|
|
529
|
+
print("š¤ AGENT REPOSITORY SETUP")
|
|
547
530
|
print("="*80)
|
|
548
531
|
print(f"Repository: {repo_url}")
|
|
549
532
|
print(f"Working Directory: /root")
|
|
@@ -551,36 +534,51 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
|
551
534
|
print(f"Available Credentials: {len(stored_credentials)} items")
|
|
552
535
|
print("="*80 + "\n")
|
|
553
536
|
|
|
554
|
-
# Call
|
|
555
|
-
claude_prompt = f"clone and
|
|
556
|
-
print(f"š Executing
|
|
537
|
+
# Call Agent directly as subprocess with real-time output
|
|
538
|
+
claude_prompt = f"clone, setup and run {repo_url}"
|
|
539
|
+
print(f"š Executing the task: \"{claude_prompt}\"")
|
|
540
|
+
print("\n" + "="*60)
|
|
541
|
+
print("š AGENT OUTPUT (LIVE)")
|
|
542
|
+
print("="*60)
|
|
557
543
|
|
|
558
|
-
|
|
544
|
+
# Use Popen for real-time output streaming
|
|
545
|
+
process = subprocess.Popen(
|
|
559
546
|
["python", "/python/kill_claude/claude_code_agent.py", claude_prompt],
|
|
560
547
|
cwd="/root",
|
|
561
|
-
|
|
548
|
+
stdout=subprocess.PIPE,
|
|
549
|
+
stderr=subprocess.STDOUT, # Merge stderr into stdout
|
|
562
550
|
text=True,
|
|
563
|
-
|
|
551
|
+
bufsize=1, # Line buffered
|
|
552
|
+
universal_newlines=True
|
|
564
553
|
)
|
|
565
554
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
555
|
+
# Stream output in real-time
|
|
556
|
+
try:
|
|
557
|
+
while True:
|
|
558
|
+
output = process.stdout.readline()
|
|
559
|
+
if output == '' and process.poll() is not None:
|
|
560
|
+
break
|
|
561
|
+
if output:
|
|
562
|
+
print(output.rstrip())
|
|
573
563
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
print(result.stderr)
|
|
564
|
+
# Wait for process to complete and get return code
|
|
565
|
+
return_code = process.wait(timeout=600) # 10 minute timeout
|
|
577
566
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
567
|
+
print("\n" + "="*60)
|
|
568
|
+
if return_code == 0:
|
|
569
|
+
print("ā
Agent completed successfully!")
|
|
570
|
+
else:
|
|
571
|
+
print(f"ā ļø Agent exited with code: {return_code}")
|
|
572
|
+
print("="*60)
|
|
573
|
+
|
|
574
|
+
except subprocess.TimeoutExpired:
|
|
575
|
+
print("\nā ļø Agent timed out after 10 minutes")
|
|
576
|
+
process.kill()
|
|
577
|
+
process.wait()
|
|
578
|
+
except Exception as stream_error:
|
|
579
|
+
print(f"\nā ļø Error streaming output: {stream_error}")
|
|
580
|
+
process.kill()
|
|
581
|
+
process.wait()
|
|
584
582
|
|
|
585
583
|
except Exception as e:
|
|
586
584
|
print(f"ā Error during repository setup: {e}")
|
|
@@ -626,11 +624,11 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
|
|
|
626
624
|
with app.run():
|
|
627
625
|
# Get the API key from environment
|
|
628
626
|
api_key = os.environ.get("OPENAI_API_KEY")
|
|
629
|
-
print(f"š API key: {api_key}")
|
|
627
|
+
# print(f"š API key: {api_key}")
|
|
630
628
|
|
|
631
629
|
# Get stored credentials from local file
|
|
632
630
|
stored_credentials = get_stored_credentials()
|
|
633
|
-
print(f"š Stored credentials: {stored_credentials}")
|
|
631
|
+
# print(f"š Stored credentials: {stored_credentials}")
|
|
634
632
|
if stored_credentials:
|
|
635
633
|
print(f"š Found {len(stored_credentials)} stored credentials to send to container")
|
|
636
634
|
else:
|
|
@@ -1093,10 +1091,10 @@ def show_usage_examples():
|
|
|
1093
1091
|
print("ā gitarsenal --auth # Interactive auth management ā")
|
|
1094
1092
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
|
1095
1093
|
|
|
1096
|
-
print("Basic Container Creation with
|
|
1094
|
+
print("Basic Container Creation with Agent")
|
|
1097
1095
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā")
|
|
1098
1096
|
print("ā gitarsenal --gpu A10G --repo-url https://github.com/username/repo.git ā")
|
|
1099
|
-
print("ā #
|
|
1097
|
+
print("ā # Agent will intelligently clone and setup the repository ā")
|
|
1100
1098
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
|
1101
1099
|
|
|
1102
1100
|
print("With Persistent Storage")
|
|
@@ -1114,13 +1112,13 @@ def show_usage_examples():
|
|
|
1114
1112
|
print("Intelligent Repository Setup (default)")
|
|
1115
1113
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā")
|
|
1116
1114
|
print("ā gitarsenal --gpu A10G --repo-url https://github.com/username/repo.git ā")
|
|
1117
|
-
print("ā #
|
|
1115
|
+
print("ā # Agent analyzes repo and sets up environment automatically ā")
|
|
1118
1116
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
|
1119
1117
|
|
|
1120
1118
|
print("With Manual Setup Commands (Advanced)")
|
|
1121
1119
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā")
|
|
1122
1120
|
print("ā gitarsenal --gpu A10G --setup-commands \"pip install torch\" \"python train.py\" ā")
|
|
1123
|
-
print("ā # Only use when not providing --repo-url (bypasses
|
|
1121
|
+
print("ā # Only use when not providing --repo-url (bypasses Agent) ā")
|
|
1124
1122
|
print("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n")
|
|
1125
1123
|
|
|
1126
1124
|
print("Development Mode (Skip Authentication)")
|
|
@@ -1142,7 +1140,7 @@ def show_usage_examples():
|
|
|
1142
1140
|
print(" ⢠Without --gpu: Shows interactive GPU selection menu")
|
|
1143
1141
|
print()
|
|
1144
1142
|
print("Repository Setup Behavior:")
|
|
1145
|
-
print(" ⢠With --repo-url
|
|
1143
|
+
print(" ⢠With --repo-url Agent intelligently clones and sets up repository")
|
|
1146
1144
|
print(" ⢠Without --repo-url: Manual container setup (no automatic repository setup)")
|
|
1147
1145
|
print(" ⢠Legacy --setup-commands: Only used when --repo-url not provided")
|
|
1148
1146
|
print()
|
|
@@ -1816,9 +1814,9 @@ if __name__ == "__main__":
|
|
|
1816
1814
|
parser.add_argument('--volume-name', type=str, help='Name of the Modal volume for persistent storage')
|
|
1817
1815
|
parser.add_argument('--timeout', type=int, default=60, help='Container timeout in minutes (default: 60)')
|
|
1818
1816
|
parser.add_argument('--ssh-password', type=str, help='SSH password (random if not provided)')
|
|
1819
|
-
parser.add_argument('--use-api', action='store_true', help='[DEPRECATED] Fetch setup commands from original API (use --repo-url for
|
|
1820
|
-
parser.add_argument('--use-gitingest', action='store_true', default=True, help='[DEPRECATED] Use gitingest approach (
|
|
1821
|
-
parser.add_argument('--no-gitingest', action='store_true', help='[DEPRECATED] Disable gitingest approach (no longer needed with
|
|
1817
|
+
parser.add_argument('--use-api', action='store_true', help='[DEPRECATED] Fetch setup commands from original API (use --repo-url for Agent instead)')
|
|
1818
|
+
parser.add_argument('--use-gitingest', action='store_true', default=True, help='[DEPRECATED] Use gitingest approach (Agent is now used when --repo-url is provided)')
|
|
1819
|
+
parser.add_argument('--no-gitingest', action='store_true', help='[DEPRECATED] Disable gitingest approach (no longer needed with Agent)')
|
|
1822
1820
|
parser.add_argument('--show-examples', action='store_true', help='Show usage examples')
|
|
1823
1821
|
parser.add_argument('--list-gpus', action='store_true', help='List available GPU types with their specifications')
|
|
1824
1822
|
parser.add_argument('--interactive', action='store_true', help='Run in interactive mode with prompts')
|
|
@@ -1951,7 +1949,7 @@ if __name__ == "__main__":
|
|
|
1951
1949
|
print(f"GPU Type: {gpu_type}")
|
|
1952
1950
|
print(f"Volume: {args.volume_name or 'None'}")
|
|
1953
1951
|
if args.repo_url:
|
|
1954
|
-
print("Repository Setup:
|
|
1952
|
+
print("Repository Setup: Agent (intelligent)")
|
|
1955
1953
|
elif args.use_api:
|
|
1956
1954
|
print("Setup Commands: Auto-detect from repository")
|
|
1957
1955
|
elif args.setup_commands:
|
|
@@ -2037,13 +2035,13 @@ if __name__ == "__main__":
|
|
|
2037
2035
|
args.use_gitingest = use_gitingest
|
|
2038
2036
|
|
|
2039
2037
|
try:
|
|
2040
|
-
# Setup commands are no longer used when repo_url is provided (
|
|
2038
|
+
# Setup commands are no longer used when repo_url is provided ( Agent handles setup)
|
|
2041
2039
|
setup_commands = args.setup_commands or []
|
|
2042
2040
|
|
|
2043
2041
|
# Repository setup approach
|
|
2044
2042
|
if args.repo_url:
|
|
2045
|
-
print("š¤ Repository setup will be handled by
|
|
2046
|
-
setup_commands = [] #
|
|
2043
|
+
print("š¤ Repository setup will be handled by Agent in container")
|
|
2044
|
+
setup_commands = [] # Agent will handle setup intelligently
|
|
2047
2045
|
else:
|
|
2048
2046
|
print("ā ļø No repository URL provided - setup commands may be needed manually")
|
|
2049
2047
|
|