gitarsenal-cli 1.5.4 → 1.5.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": "gitarsenal-cli",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "CLI tool for creating Modal sandboxes with GitHub repositories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -343,10 +343,6 @@ def call_openai_for_debug(command, error_output, api_key=None, current_dir=None,
343
343
  print(f"šŸ” DEBUG: Current directory: {current_dir}")
344
344
  print(f"šŸ” DEBUG: Sandbox available: {sandbox is not None}")
345
345
  print(f"šŸ” DEBUG: API key provided: {'Yes' if api_key else 'No'}")
346
- if api_key:
347
- print(f"šŸ” DEBUG: API key value: {api_key}")
348
- else:
349
- print(f"šŸ” DEBUG: API key from environment: {os.environ.get('OPENAI_API_KEY')}")
350
346
 
351
347
  # Define _to_str function locally to avoid NameError
352
348
  def _to_str(maybe_bytes):
@@ -692,9 +688,9 @@ Do not provide any explanations, just the exact command to run.
692
688
  def try_api_call(model_name, retries=2, backoff_factor=1.5):
693
689
  print(f"šŸ” DEBUG: Attempting API call with model: {model_name}")
694
690
  print(f"šŸ” DEBUG: API key available: {'Yes' if api_key else 'No'}")
695
- if api_key:
696
- print(f"šŸ” DEBUG: API key length: {len(api_key)}")
697
- print(f"šŸ” DEBUG: API key starts with: {api_key[:10]}...")
691
+ # if api_key:
692
+ # print(f"šŸ” DEBUG: API key length: {len(api_key)}")
693
+ # print(f"šŸ” DEBUG: API key starts with: {api_key[:10]}...")
698
694
 
699
695
  payload = {
700
696
  "model": model_name,
package/install.sh DELETED
@@ -1,30 +0,0 @@
1
- #!/bin/bash
2
-
3
- # GitArsenal CLI Installation Script
4
-
5
- echo "šŸš€ Installing GitArsenal CLI..."
6
-
7
- # Check if npm is installed
8
- if ! command -v npm &> /dev/null; then
9
- echo "āŒ npm is not installed. Please install Node.js and npm first."
10
- exit 1
11
- fi
12
-
13
- # Check if Python is installed
14
- if ! command -v python &> /dev/null && ! command -v python3 &> /dev/null; then
15
- echo "āŒ Python is not installed. Please install Python 3.8 or higher."
16
- exit 1
17
- fi
18
-
19
- # Check if Modal is installed
20
- if ! command -v modal &> /dev/null; then
21
- echo "āš ļø Modal CLI not found. Installing modal-client..."
22
- pip install modal || python3 -m pip install modal
23
- fi
24
-
25
- # Install the package globally
26
- echo "šŸ“¦ Installing GitArsenal CLI globally..."
27
- npm install -g .
28
-
29
- echo "āœ… Installation complete!"
30
- echo "You can now run the CLI tool with: gitarsenal"
@@ -1,145 +0,0 @@
1
- # Modal Proxy Service for GitArsenal CLI
2
-
3
- This document explains how to set up and use the Modal proxy service with GitArsenal CLI.
4
-
5
- ## What is the Modal Proxy Service?
6
-
7
- The Modal proxy service allows users to access Modal services (like GPU-accelerated containers) without exposing the owner's Modal token. The service runs on a server and provides API endpoints for creating sandboxes and SSH containers, using API key authentication.
8
-
9
- ## Server-Side Setup
10
-
11
- 1. **Install Requirements**:
12
- ```bash
13
- pip install flask flask-cors modal python-dotenv
14
- ```
15
-
16
- 2. **Set Environment Variables**:
17
- Create a `.env` file in the same directory as `modal_proxy_service.py`:
18
- ```
19
- MODAL_TOKEN=your_modal_token_here
20
- ADMIN_KEY=your_admin_key_here
21
- API_KEYS=optional_comma_separated_list_of_api_keys
22
- ```
23
-
24
- 3. **Start the Service**:
25
- ```bash
26
- python modal_proxy_service.py
27
- ```
28
-
29
- The service will start on port 5001 by default.
30
-
31
- 4. **Create an API Key** (if not pre-configured in `.env`):
32
- ```bash
33
- curl -X POST http://localhost:5001/api/create-api-key \
34
- -H "X-Admin-Key: your_admin_key_here"
35
- ```
36
-
37
- This will return a JSON response with a new API key:
38
- ```json
39
- {"api_key": "generated_api_key_here"}
40
- ```
41
-
42
- 5. **Optional: Use ngrok to expose the service publicly**:
43
- ```bash
44
- ngrok http 5001
45
- ```
46
-
47
- This will provide you with a public URL that you can share with users.
48
-
49
- Current ngrok URL: `https://932ffd63ad3d.ngrok-free.app`
50
-
51
- ## Client-Side Setup
52
-
53
- 1. **Configure the proxy client**:
54
- ```bash
55
- ./gitarsenal.py proxy configure
56
- ```
57
-
58
- You'll be prompted to enter:
59
- - The proxy URL (the default is now set to `https://932ffd63ad3d.ngrok-free.app`)
60
- - Your API key
61
-
62
- 2. **Check proxy service status**:
63
- ```bash
64
- ./gitarsenal.py proxy status
65
- ```
66
-
67
- ## Using the Proxy Service
68
-
69
- ### Create an SSH Container
70
-
71
- ```bash
72
- # Using the proxy command
73
- ./gitarsenal.py proxy ssh --gpu A10G --repo-url https://github.com/username/repo.git --wait
74
-
75
- # Or using the standard ssh command with --use-proxy flag
76
- ./gitarsenal.py ssh --use-proxy --gpu A10G --repo-url https://github.com/username/repo.git
77
- ```
78
-
79
- ### Create a Sandbox
80
-
81
- ```bash
82
- # Using the proxy command
83
- ./gitarsenal.py proxy sandbox --gpu A10G --repo-url https://github.com/username/repo.git --wait
84
-
85
- # Or using the standard sandbox command with --use-proxy flag
86
- ./gitarsenal.py sandbox --use-proxy --gpu A10G --repo-url https://github.com/username/repo.git
87
- ```
88
-
89
- ## Troubleshooting
90
-
91
- ### "Token missing" Error
92
-
93
- If you see a "Token missing" error when creating containers through the proxy service:
94
-
95
- 1. **Check that the MODAL_TOKEN is set on the server**:
96
- - Verify the `.env` file has a valid MODAL_TOKEN
97
- - Ensure the token is correctly formatted and not expired
98
- - Restart the proxy service after updating the token
99
-
100
- 2. **Manually set the token on the server**:
101
- ```bash
102
- # On the server running the proxy service
103
- export MODAL_TOKEN_ID=your_modal_token_here
104
- modal token set your_modal_token_here
105
- ```
106
-
107
- 3. **Verify the token works directly on the server**:
108
- ```bash
109
- # Test if the token works by listing Modal volumes
110
- modal volume list
111
- ```
112
-
113
- 4. **Check the proxy service logs**:
114
- - Look at `modal_proxy.log` on the server for detailed error messages
115
- - Check for messages like "Modal token verification failed"
116
- - Ensure the token is being properly passed to the Modal API
117
-
118
- 5. **Restart the proxy service**:
119
- ```bash
120
- # Kill the existing process and restart
121
- pkill -f modal_proxy_service.py
122
- python modal_proxy_service.py
123
- ```
124
-
125
- 6. **Check ngrok connection**:
126
- - Verify the ngrok tunnel is active and the URL is correct
127
- - Ensure requests are being properly forwarded to the proxy service
128
-
129
- ### "Unauthorized" Error
130
-
131
- If you see an "Unauthorized" error:
132
-
133
- 1. **When creating an API key**:
134
- - Make sure you're including the correct admin key in the request header
135
- - Example: `-H "X-Admin-Key: your_admin_key_here"`
136
-
137
- 2. **When using the API**:
138
- - Make sure your client is configured with a valid API key
139
- - Reconfigure with `./gitarsenal.py proxy configure`
140
-
141
- ## Security Considerations
142
-
143
- - Keep your admin key and API keys secure
144
- - Use HTTPS if exposing the service publicly (ngrok provides this automatically)
145
- - Consider implementing additional authentication mechanisms for production use
package/python/README.md DELETED
@@ -1,68 +0,0 @@
1
- # GitArsenal CLI Python Modules
2
-
3
- This directory contains Python modules for the GitArsenal CLI.
4
-
5
- ## Modal Integration
6
-
7
- The GitArsenal CLI integrates with Modal for creating sandboxes and SSH containers. The following modules are available:
8
-
9
- - `modal_proxy_service.py`: A proxy service for Modal operations
10
- - `test_modalSandboxScript.py`: Creates Modal sandboxes and SSH containers
11
- - `setup_modal_token.py`: Sets up the Modal token in the environment
12
- - `fetch_modal_tokens.py`: Fetches Modal tokens from the proxy server
13
-
14
- ## Security Features
15
-
16
- ### Modal Token Cleanup
17
-
18
- For enhanced security, GitArsenal CLI now automatically cleans up Modal tokens after SSH containers are created. This ensures that your Modal token is not left in the environment or on disk after the container is started.
19
-
20
- The cleanup process:
21
- 1. Removes Modal token environment variables (MODAL_TOKEN_ID, MODAL_TOKEN, MODAL_TOKEN_SECRET)
22
- 2. Deletes the ~/.modal.toml file which contains the authentication token
23
- 3. Runs automatically after SSH container creation
24
- 4. Runs on service shutdown via signal handlers
25
-
26
- This simple but effective approach prevents potential token leakage when containers are shared or when the service is stopped, and ensures that users cannot continue to use Modal CLI commands like `modal shell` after the container is created.
27
-
28
- ## Usage
29
-
30
- To use the GitArsenal CLI Python modules, you can import them directly or use the provided scripts.
31
-
32
- ### Creating a Modal SSH Container
33
-
34
- ```python
35
- from test_modalSandboxScript import create_modal_ssh_container
36
-
37
- result = create_modal_ssh_container(
38
- gpu_type="A10G",
39
- repo_url="https://github.com/user/repo",
40
- repo_name="repo",
41
- setup_commands=["pip install -r requirements.txt"],
42
- timeout_minutes=60
43
- )
44
-
45
- # The Modal token is automatically cleaned up after the container is created
46
- ```
47
-
48
- ### Running the Modal Proxy Service
49
-
50
- ```bash
51
- python modal_proxy_service.py
52
- ```
53
-
54
- The service will automatically clean up Modal tokens on shutdown.
55
-
56
- ## Testing
57
-
58
- To test the Modal token cleanup functionality:
59
-
60
- ```bash
61
- python test_token_cleanup.py
62
- ```
63
-
64
- This script verifies that the token cleanup process works correctly by:
65
- 1. Setting up a test Modal token
66
- 2. Verifying the token exists in environment and files
67
- 3. Cleaning up the token
68
- 4. Verifying the token has been removed
@@ -1,71 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Fix commands for Modal SSH container
4
- This script fixes common issues with commands in the Modal SSH container
5
- """
6
-
7
- import os
8
- import sys
9
- import subprocess
10
-
11
- def fix_command(cmd):
12
- """Fix common issues with commands"""
13
- # Replace 'source' with '.' for sh shell
14
- if 'source' in cmd:
15
- cmd = cmd.replace('source', '.')
16
- print(f"āœ… Fixed: Replaced 'source' with '.' for sh shell")
17
-
18
- # Fix uv venv and activation in one command
19
- if 'uv venv' in cmd and '&&' in cmd:
20
- # The command is already trying to create and activate a venv
21
- # Just need to make sure 'source' is replaced with '.'
22
- pass
23
-
24
- # Fix uv pip install without active venv
25
- if 'uv pip install' in cmd and 'venv' not in cmd:
26
- # Create and activate a venv first
27
- cmd = f"uv venv .venv && . .venv/bin/activate && {cmd}"
28
- print(f"āœ… Fixed: Added venv creation and activation before pip install")
29
-
30
- return cmd
31
-
32
- def run_fixed_command(cmd):
33
- """Run the fixed command"""
34
- fixed_cmd = fix_command(cmd)
35
- print(f"\nšŸ”§ Running fixed command: {fixed_cmd}")
36
-
37
- # Run the command
38
- result = subprocess.run(fixed_cmd, shell=True, text=True, capture_output=True)
39
-
40
- # Print the output
41
- if result.stdout:
42
- print(f"\n--- Output ---\n{result.stdout}")
43
- if result.stderr:
44
- print(f"\n--- Error ---\n{result.stderr}")
45
-
46
- # Return the result
47
- return result.returncode == 0
48
-
49
- def main():
50
- """Main function"""
51
- if len(sys.argv) < 2:
52
- print("Usage: python fix_commands.py 'command to fix'")
53
- return 1
54
-
55
- # Get the command from command line
56
- cmd = ' '.join(sys.argv[1:])
57
- print(f"šŸ” Original command: {cmd}")
58
-
59
- # Run the fixed command
60
- success = run_fixed_command(cmd)
61
-
62
- # Print the result
63
- if success:
64
- print("\nāœ… Command executed successfully")
65
- else:
66
- print("\nāŒ Command failed")
67
-
68
- return 0 if success else 1
69
-
70
- if __name__ == "__main__":
71
- sys.exit(main())
@@ -1,58 +0,0 @@
1
- def get_setup_commands_from_local_api(repo_url, gitingest_data):
2
- """Try to get setup commands from the API."""
3
- # Use only online endpoints
4
- api_endpoints = [
5
- "https://www.gitarsenal.dev/api/analyze-with-gitingest" # Working endpoint with www prefix
6
- ]
7
-
8
- # Prepare the request payload
9
- payload = {
10
- "repoUrl": repo_url,
11
- "gitingestData": gitingest_data,
12
- "userRequest": "Setup and run the repository"
13
- }
14
-
15
- # Try each API endpoint
16
- for api_url in api_endpoints:
17
- # Use the retry mechanism for more reliable requests
18
- response = make_api_request_with_retry(
19
- url=api_url,
20
- payload=payload,
21
- max_retries=2,
22
- timeout=180 # 3 minute timeout
23
- )
24
-
25
- if response and response.status_code == 200:
26
- try:
27
- data = response.json()
28
- print(f"šŸ“„ Response size: {len(response.text)} bytes")
29
- print(f"šŸ“„ Response URL: {response.url}")
30
- if "setupInstructions" in data and "commands" in data["setupInstructions"]:
31
- commands = data["setupInstructions"]["commands"]
32
- print(f"āœ… Successfully fetched {len(commands)} setup commands from API at {api_url}")
33
-
34
- # Print the original commands
35
- print("šŸ“‹ Original commands from API:")
36
- for i, cmd in enumerate(commands, 1):
37
- print(f" {i}. {cmd}")
38
-
39
- # Fix the commands
40
- fixed_commands = fix_setup_commands(commands)
41
-
42
- # Print the fixed commands
43
- print("\nšŸ“‹ Fixed commands:")
44
- for i, cmd in enumerate(fixed_commands, 1):
45
- print(f" {i}. {cmd}")
46
-
47
- return fixed_commands
48
- else:
49
- print("āš ļø API response did not contain setupInstructions.commands field")
50
- except json.JSONDecodeError:
51
- print(f"āŒ Failed to parse API response as JSON")
52
- elif response:
53
- print(f"āŒ API request failed with status code: {response.status_code}")
54
- else:
55
- print(f"āŒ Failed to connect to {api_url}")
56
-
57
- print("āŒ All API endpoints failed")
58
- return None
@@ -1,119 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- GitArsenal Credentials Manager CLI
4
-
5
- This script allows users to manage their API keys and tokens for GitArsenal CLI.
6
- """
7
-
8
- import argparse
9
- import sys
10
- from credentials_manager import CredentialsManager
11
-
12
- def main():
13
- parser = argparse.ArgumentParser(description="Manage credentials for GitArsenal CLI")
14
- subparsers = parser.add_subparsers(dest="command", help="Command to run")
15
-
16
- # Setup command
17
- setup_parser = subparsers.add_parser("setup", help="Set up all credentials")
18
-
19
- # Set command
20
- set_parser = subparsers.add_parser("set", help="Set a specific credential")
21
- set_parser.add_argument("key", choices=["openai_api_key", "modal_token", "huggingface_token", "wandb_api_key"],
22
- help="The credential to set")
23
-
24
- # Get command
25
- get_parser = subparsers.add_parser("get", help="Get a specific credential")
26
- get_parser.add_argument("key", choices=["openai_api_key", "modal_token", "huggingface_token", "wandb_api_key"],
27
- help="The credential to get")
28
-
29
- # Clear command
30
- clear_parser = subparsers.add_parser("clear", help="Clear credentials")
31
- clear_parser.add_argument("key", nargs="?", choices=["openai_api_key", "modal_token", "huggingface_token", "wandb_api_key", "all"],
32
- default="all", help="The credential to clear (default: all)")
33
-
34
- # List command
35
- list_parser = subparsers.add_parser("list", help="List all saved credentials (shows only existence, not values)")
36
-
37
- args = parser.parse_args()
38
-
39
- # Create credentials manager
40
- credentials_manager = CredentialsManager()
41
-
42
- if args.command == "setup":
43
- print("šŸ“‹ Setting up all credentials for GitArsenal CLI")
44
- print("You'll be prompted for each credential. Press Ctrl+C to skip any credential.")
45
-
46
- try:
47
- # OpenAI API key
48
- print("\nšŸ”‘ Setting up OpenAI API key")
49
- credentials_manager.get_openai_api_key()
50
-
51
- # Modal token
52
- print("\nšŸ”‘ Setting up Modal token")
53
- credentials_manager.get_modal_token()
54
-
55
- # Hugging Face token
56
- print("\nšŸ”‘ Setting up Hugging Face token")
57
- credentials_manager.get_huggingface_token()
58
-
59
- # Weights & Biases API key
60
- print("\nšŸ”‘ Setting up Weights & Biases API key")
61
- credentials_manager.get_wandb_api_key()
62
-
63
- print("\nāœ… Credentials setup complete!")
64
-
65
- except KeyboardInterrupt:
66
- print("\n\nāš ļø Setup interrupted. Some credentials may not have been set.")
67
- return 1
68
-
69
- elif args.command == "set":
70
- print(f"šŸ”‘ Setting {args.key}")
71
- if args.key == "openai_api_key":
72
- credentials_manager.get_openai_api_key()
73
- elif args.key == "modal_token":
74
- credentials_manager.get_modal_token()
75
- elif args.key == "huggingface_token":
76
- credentials_manager.get_huggingface_token()
77
- elif args.key == "wandb_api_key":
78
- credentials_manager.get_wandb_api_key()
79
-
80
- elif args.command == "get":
81
- credentials = credentials_manager.load_credentials()
82
- if args.key in credentials:
83
- # Show only first and last few characters for security
84
- value = credentials[args.key]
85
- masked_value = value[:4] + "*" * (len(value) - 8) + value[-4:] if len(value) > 8 else "****"
86
- print(f"{args.key}: {masked_value}")
87
- else:
88
- print(f"āŒ {args.key} not found in saved credentials")
89
- return 1
90
-
91
- elif args.command == "clear":
92
- if args.key == "all":
93
- credentials_manager.clear_all_credentials()
94
- print("āœ… All credentials cleared")
95
- else:
96
- if credentials_manager.clear_credential(args.key):
97
- print(f"āœ… {args.key} cleared")
98
- else:
99
- print(f"āŒ {args.key} not found in saved credentials")
100
- return 1
101
-
102
- elif args.command == "list":
103
- credentials = credentials_manager.load_credentials()
104
- if not credentials:
105
- print("No credentials saved")
106
- return 0
107
-
108
- print("šŸ“‹ Saved credentials:")
109
- for key in credentials:
110
- print(f"- {key}: {'*' * 8}")
111
-
112
- else:
113
- parser.print_help()
114
- return 1
115
-
116
- return 0
117
-
118
- if __name__ == "__main__":
119
- sys.exit(main())
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- This script patches the test_modalSandboxScript.py file to replace "modal" with "container" in the logs.
4
- """
5
-
6
- import os
7
- import re
8
- import sys
9
- import shutil
10
- from pathlib import Path
11
-
12
- def patch_modal_logs(script_path):
13
- """
14
- Patch the Python script to replace "modal" with "container" in the logs.
15
- """
16
- print(f"Patching {script_path} to replace 'modal' with 'container' in logs...")
17
-
18
- # Make a backup of the original file
19
- backup_path = f"{script_path}.bak"
20
- shutil.copy2(script_path, backup_path)
21
-
22
- # Read the file
23
- with open(script_path, 'r', encoding='utf-8') as f:
24
- content = f.read()
25
-
26
- # Define replacements
27
- replacements = [
28
- # Function names
29
- (r'def create_modal_sandbox', r'def create_container'),
30
- (r'def create_modal_ssh_container', r'def create_ssh_container'),
31
-
32
- # Log messages - case sensitive replacements
33
- (r'Modal sandbox', r'Container'),
34
- (r'Modal authentication', r'Container authentication'),
35
- (r'Modal token', r'Container token'),
36
- (r'Modal package', r'Container package'),
37
- (r'Modal operations', r'Container operations'),
38
-
39
- # Log messages - case insensitive replacements (lowercase)
40
- (r'modal sandbox', r'container'),
41
- (r'modal authentication', r'container authentication'),
42
- (r'modal token', r'container token'),
43
- (r'modal package', r'container package'),
44
- (r'modal operations', r'container operations'),
45
-
46
- # Keep function calls to modal library intact but change logs
47
- (r'print\([\'"](.*)modal(.*)[\'"]', r'print(\1container\2'),
48
- (r'log\([\'"](.*)modal(.*)[\'"]', r'log(\1container\2'),
49
- (r'logger\.info\([\'"](.*)modal(.*)[\'"]', r'logger.info(\1container\2'),
50
- (r'logger\.error\([\'"](.*)modal(.*)[\'"]', r'logger.error(\1container\2'),
51
- (r'logger\.warning\([\'"](.*)modal(.*)[\'"]', r'logger.warning(\1container\2'),
52
- (r'logger\.debug\([\'"](.*)modal(.*)[\'"]', r'logger.debug(\1container\2'),
53
- ]
54
-
55
- # Apply replacements
56
- for pattern, replacement in replacements:
57
- content = re.sub(pattern, replacement, content, flags=re.IGNORECASE)
58
-
59
- # Write the modified content back to the file
60
- with open(script_path, 'w', encoding='utf-8') as f:
61
- f.write(content)
62
-
63
- print(f"Patching complete. Original file backed up to {backup_path}")
64
- return True
65
-
66
- def main():
67
- """
68
- Main entry point for the script.
69
- """
70
- # Get the path to the script
71
- script_dir = Path(__file__).parent
72
- script_path = script_dir / "test_modalSandboxScript.py"
73
-
74
- if not script_path.exists():
75
- print(f"Error: Script not found at {script_path}")
76
- return 1
77
-
78
- try:
79
- patch_modal_logs(script_path)
80
- return 0
81
- except Exception as e:
82
- print(f"Error patching file: {e}")
83
- return 1
84
-
85
- if __name__ == "__main__":
86
- sys.exit(main())
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Patch the test_modalSandboxScript.py file to fix issues with LLM debugging
4
- """
5
-
6
- import os
7
- import sys
8
- import re
9
-
10
- def read_file(filename):
11
- """Read a file and return its contents"""
12
- with open(filename, 'r') as f:
13
- return f.read()
14
-
15
- def write_file(filename, content):
16
- """Write content to a file"""
17
- with open(filename, 'w') as f:
18
- f.write(content)
19
-
20
- def patch_file(filename):
21
- """Patch the file to fix issues with LLM debugging"""
22
- print(f"šŸ”§ Patching {filename}...")
23
-
24
- # Read the file
25
- content = read_file(filename)
26
-
27
- # Make a backup
28
- backup_filename = f"{filename}.bak"
29
- write_file(backup_filename, content)
30
- print(f"āœ… Created backup: {backup_filename}")
31
-
32
- # Fix 1: Replace 'source' with '.' in commands
33
- pattern1 = r'(uv venv.*?)source(.*?activate)'
34
- replacement1 = r'\1.\2'
35
- content = re.sub(pattern1, replacement1, content)
36
- print("āœ… Fixed 'source' commands")
37
-
38
- # Fix 2: Add environment activation before uv pip commands
39
- pattern2 = r'(uv pip install.*?)(?!\. .*?activate)'
40
- replacement2 = r'. openr1/bin/activate && \1'
41
- content = re.sub(pattern2, replacement2, content)
42
- print("āœ… Added environment activation before pip commands")
43
-
44
- # Write the patched file
45
- write_file(filename, content)
46
- print(f"āœ… Patched file written: {filename}")
47
-
48
- return True
49
-
50
- def main():
51
- """Main function"""
52
- # Get the file to patch
53
- if len(sys.argv) > 1:
54
- filename = sys.argv[1]
55
- else:
56
- # Default to the test_modalSandboxScript.py in the current directory
57
- filename = "test_modalSandboxScript.py"
58
-
59
- # Check if the file exists
60
- if not os.path.exists(filename):
61
- print(f"āŒ File not found: {filename}")
62
- return 1
63
-
64
- # Patch the file
65
- success = patch_file(filename)
66
-
67
- if success:
68
- print("\nāœ… Patching completed successfully")
69
- return 0
70
- else:
71
- print("\nāŒ Patching failed")
72
- return 1
73
-
74
- if __name__ == "__main__":
75
- sys.exit(main())