gitarsenal-cli 1.1.20 ā 1.1.22
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
Binary file
|
@@ -9,6 +9,7 @@ import os
|
|
9
9
|
import sys
|
10
10
|
import json
|
11
11
|
import requests
|
12
|
+
import subprocess
|
12
13
|
from pathlib import Path
|
13
14
|
|
14
15
|
# Default tokens to use if we can't fetch from the server
|
@@ -29,17 +30,23 @@ def fetch_tokens_from_proxy(proxy_url=None, api_key=None):
|
|
29
30
|
# Use environment variables if not provided
|
30
31
|
if not proxy_url:
|
31
32
|
proxy_url = os.environ.get("MODAL_PROXY_URL")
|
33
|
+
if proxy_url:
|
34
|
+
print(f"š Using proxy URL from environment: {proxy_url}")
|
32
35
|
|
33
36
|
if not api_key:
|
34
37
|
api_key = os.environ.get("MODAL_PROXY_API_KEY")
|
38
|
+
if api_key:
|
39
|
+
print(f"š Using API key from environment (length: {len(api_key)})")
|
35
40
|
|
36
41
|
# Check if we have the necessary information
|
37
42
|
if not proxy_url:
|
38
43
|
print("ā No proxy URL provided or found in environment")
|
44
|
+
print("š” Set MODAL_PROXY_URL environment variable or use --proxy-url argument")
|
39
45
|
return None, None
|
40
46
|
|
41
47
|
if not api_key:
|
42
48
|
print("ā No API key provided or found in environment")
|
49
|
+
print("š” Set MODAL_PROXY_API_KEY environment variable or use --proxy-api-key argument")
|
43
50
|
return None, None
|
44
51
|
|
45
52
|
# Ensure the URL ends with a slash
|
@@ -79,6 +86,7 @@ def fetch_tokens_from_proxy(proxy_url=None, api_key=None):
|
|
79
86
|
def get_tokens():
|
80
87
|
"""
|
81
88
|
Get Modal tokens, trying to fetch from the proxy server first.
|
89
|
+
Also sets the tokens in environment variables.
|
82
90
|
|
83
91
|
Returns:
|
84
92
|
tuple: (token_id, token_secret)
|
@@ -89,15 +97,48 @@ def get_tokens():
|
|
89
97
|
# If we couldn't fetch from the server, use the default tokens
|
90
98
|
if not token_id or not token_secret:
|
91
99
|
print("ā ļø Using default tokens")
|
92
|
-
|
100
|
+
token_id = DEFAULT_TOKEN_ID
|
101
|
+
token_secret = DEFAULT_TOKEN_SECRET
|
102
|
+
|
103
|
+
# Set the tokens in environment variables
|
104
|
+
os.environ["MODAL_TOKEN_ID"] = token_id
|
105
|
+
os.environ["MODAL_TOKEN_SECRET"] = token_secret
|
106
|
+
print(f"ā
Set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables")
|
93
107
|
|
94
108
|
return token_id, token_secret
|
95
109
|
|
96
110
|
if __name__ == "__main__":
|
111
|
+
# Parse command-line arguments if run directly
|
112
|
+
import argparse
|
113
|
+
|
114
|
+
parser = argparse.ArgumentParser(description='Fetch Modal tokens from the proxy server')
|
115
|
+
parser.add_argument('--proxy-url', help='URL of the proxy server')
|
116
|
+
parser.add_argument('--proxy-api-key', help='API key for the proxy server')
|
117
|
+
args = parser.parse_args()
|
118
|
+
|
119
|
+
# Set proxy URL and API key in environment variables if provided
|
120
|
+
if args.proxy_url:
|
121
|
+
os.environ["MODAL_PROXY_URL"] = args.proxy_url
|
122
|
+
print(f"ā
Set MODAL_PROXY_URL from command line: {args.proxy_url}")
|
123
|
+
|
124
|
+
if args.proxy_api_key:
|
125
|
+
os.environ["MODAL_PROXY_API_KEY"] = args.proxy_api_key
|
126
|
+
print(f"ā
Set MODAL_PROXY_API_KEY from command line")
|
127
|
+
|
128
|
+
# Get tokens
|
97
129
|
token_id, token_secret = get_tokens()
|
98
130
|
print(f"Token ID: {token_id}")
|
99
131
|
print(f"Token Secret: {token_secret}")
|
100
132
|
|
133
|
+
# Check if tokens are set in environment variables
|
134
|
+
print(f"\nš DEBUG: Checking environment variables")
|
135
|
+
print(f"š MODAL_TOKEN_ID exists: {'Yes' if os.environ.get('MODAL_TOKEN_ID') else 'No'}")
|
136
|
+
print(f"š MODAL_TOKEN_SECRET exists: {'Yes' if os.environ.get('MODAL_TOKEN_SECRET') else 'No'}")
|
137
|
+
if os.environ.get('MODAL_TOKEN_ID'):
|
138
|
+
print(f"š MODAL_TOKEN_ID length: {len(os.environ.get('MODAL_TOKEN_ID'))}")
|
139
|
+
if os.environ.get('MODAL_TOKEN_SECRET'):
|
140
|
+
print(f"š MODAL_TOKEN_SECRET length: {len(os.environ.get('MODAL_TOKEN_SECRET'))}")
|
141
|
+
|
101
142
|
# Write the tokens to a file for use by other scripts
|
102
143
|
tokens_file = Path(__file__).parent / "modal_tokens.json"
|
103
144
|
with open(tokens_file, 'w') as f:
|
@@ -105,4 +146,38 @@ if __name__ == "__main__":
|
|
105
146
|
"token_id": token_id,
|
106
147
|
"token_secret": token_secret
|
107
148
|
}, f)
|
108
|
-
print(f"ā
Tokens written to {tokens_file}")
|
149
|
+
print(f"\nā
Tokens written to {tokens_file}")
|
150
|
+
|
151
|
+
# Create token files in standard locations
|
152
|
+
modal_dir = Path.home() / ".modal"
|
153
|
+
modal_dir.mkdir(exist_ok=True)
|
154
|
+
token_file = modal_dir / "token.json"
|
155
|
+
with open(token_file, 'w') as f:
|
156
|
+
json.dump({
|
157
|
+
"token_id": token_id,
|
158
|
+
"token_secret": token_secret
|
159
|
+
}, f)
|
160
|
+
print(f"ā
Created token file at {token_file}")
|
161
|
+
|
162
|
+
modalconfig_file = Path.home() / ".modalconfig"
|
163
|
+
with open(modalconfig_file, 'w') as f:
|
164
|
+
f.write(f"token_id = {token_id}\n")
|
165
|
+
f.write(f"token_secret = {token_secret}\n")
|
166
|
+
print(f"ā
Created .modalconfig file at {modalconfig_file}")
|
167
|
+
|
168
|
+
# Try to use the Modal CLI to set the token
|
169
|
+
try:
|
170
|
+
print(f"\nš Setting token via Modal CLI...")
|
171
|
+
result = subprocess.run(
|
172
|
+
["modal", "token", "set", "--token-id", token_id, "--token-secret", token_secret, "--profile=fr8mafia", "--no-verify"],
|
173
|
+
capture_output=True, text=True
|
174
|
+
)
|
175
|
+
|
176
|
+
if result.returncode == 0:
|
177
|
+
print(f"ā
Successfully set token via Modal CLI")
|
178
|
+
else:
|
179
|
+
print(f"ā Failed to set token via Modal CLI: {result.stderr}")
|
180
|
+
except Exception as e:
|
181
|
+
print(f"ā Error using Modal CLI: {e}")
|
182
|
+
|
183
|
+
print(f"\nā
All token setup completed successfully")
|
@@ -9,8 +9,30 @@ import getpass
|
|
9
9
|
import requests
|
10
10
|
import secrets
|
11
11
|
import string
|
12
|
+
import argparse
|
12
13
|
from pathlib import Path
|
13
14
|
|
15
|
+
# Parse command-line arguments
|
16
|
+
parser = argparse.ArgumentParser(description='Launch a Modal sandbox')
|
17
|
+
parser.add_argument('--proxy-url', help='URL of the proxy server')
|
18
|
+
parser.add_argument('--proxy-api-key', help='API key for the proxy server')
|
19
|
+
parser.add_argument('--gpu', default='A10G', help='GPU type to use')
|
20
|
+
parser.add_argument('--repo-url', help='Repository URL')
|
21
|
+
parser.add_argument('--volume-name', help='Volume name')
|
22
|
+
parser.add_argument('--use-api', action='store_true', help='Use API to fetch setup commands')
|
23
|
+
|
24
|
+
# Parse only known args to avoid conflicts with other arguments
|
25
|
+
args, unknown = parser.parse_known_args()
|
26
|
+
|
27
|
+
# Set proxy URL and API key in environment variables if provided
|
28
|
+
if args.proxy_url:
|
29
|
+
os.environ["MODAL_PROXY_URL"] = args.proxy_url
|
30
|
+
print(f"ā
Set MODAL_PROXY_URL from command line: {args.proxy_url}")
|
31
|
+
|
32
|
+
if args.proxy_api_key:
|
33
|
+
os.environ["MODAL_PROXY_API_KEY"] = args.proxy_api_key
|
34
|
+
print(f"ā
Set MODAL_PROXY_API_KEY from command line")
|
35
|
+
|
14
36
|
# First, try to fetch tokens from the proxy server
|
15
37
|
try:
|
16
38
|
# Import the fetch_modal_tokens module
|
@@ -19,6 +41,13 @@ try:
|
|
19
41
|
token_id, token_secret = get_tokens()
|
20
42
|
print(f"ā
Modal tokens fetched successfully")
|
21
43
|
|
44
|
+
# Explicitly set the environment variables again to be sure
|
45
|
+
os.environ["MODAL_TOKEN_ID"] = token_id
|
46
|
+
os.environ["MODAL_TOKEN_SECRET"] = token_secret
|
47
|
+
|
48
|
+
# Also set the old environment variable for backward compatibility
|
49
|
+
os.environ["MODAL_TOKEN"] = token_id
|
50
|
+
|
22
51
|
# Set token variables for later use
|
23
52
|
token = token_id # For backward compatibility
|
24
53
|
except Exception as e:
|
@@ -77,9 +106,12 @@ except Exception as e:
|
|
77
106
|
# Print debug info
|
78
107
|
print(f"š DEBUG: Checking environment variables")
|
79
108
|
print(f"š MODAL_TOKEN_ID exists: {'Yes' if os.environ.get('MODAL_TOKEN_ID') else 'No'}")
|
109
|
+
print(f"š MODAL_TOKEN_SECRET exists: {'Yes' if os.environ.get('MODAL_TOKEN_SECRET') else 'No'}")
|
80
110
|
print(f"š MODAL_TOKEN exists: {'Yes' if os.environ.get('MODAL_TOKEN') else 'No'}")
|
81
111
|
if os.environ.get('MODAL_TOKEN_ID'):
|
82
112
|
print(f"š MODAL_TOKEN_ID length: {len(os.environ.get('MODAL_TOKEN_ID'))}")
|
113
|
+
if os.environ.get('MODAL_TOKEN_SECRET'):
|
114
|
+
print(f"š MODAL_TOKEN_SECRET length: {len(os.environ.get('MODAL_TOKEN_SECRET'))}")
|
83
115
|
if os.environ.get('MODAL_TOKEN'):
|
84
116
|
print(f"š MODAL_TOKEN length: {len(os.environ.get('MODAL_TOKEN'))}")
|
85
117
|
print(f"ā
Modal token setup completed")
|
@@ -2462,7 +2494,7 @@ def fetch_setup_commands_from_api(repo_url):
|
|
2462
2494
|
import shutil
|
2463
2495
|
import json
|
2464
2496
|
|
2465
|
-
api_url = "
|
2497
|
+
api_url = "https://git-arsenal.vercel.app/api/analyze-with-gitingest"
|
2466
2498
|
|
2467
2499
|
print(f"š Fetching setup commands from API for repository: {repo_url}")
|
2468
2500
|
|
@@ -2573,11 +2605,32 @@ def fetch_setup_commands_from_api(repo_url):
|
|
2573
2605
|
commands = data["setupInstructions"]["commands"]
|
2574
2606
|
print(f"ā
Successfully fetched {len(commands)} setup commands from API")
|
2575
2607
|
|
2576
|
-
# Print the commands for reference
|
2608
|
+
# Print the original commands for reference
|
2609
|
+
print("š Original commands from API:")
|
2577
2610
|
for i, cmd in enumerate(commands, 1):
|
2578
2611
|
print(f" {i}. {cmd}")
|
2579
2612
|
|
2580
|
-
|
2613
|
+
# Fix the commands by removing placeholders and comments
|
2614
|
+
fixed_commands = fix_setup_commands(commands)
|
2615
|
+
|
2616
|
+
# If we have a temp_dir with the cloned repo, try to find the entry point
|
2617
|
+
# and replace any placeholder entry points
|
2618
|
+
for i, cmd in enumerate(fixed_commands):
|
2619
|
+
if "python main.py" in cmd or "python3 main.py" in cmd:
|
2620
|
+
try:
|
2621
|
+
entry_point = find_entry_point(temp_dir)
|
2622
|
+
if entry_point and entry_point != "main.py":
|
2623
|
+
fixed_commands[i] = cmd.replace("main.py", entry_point)
|
2624
|
+
print(f"š Replaced main.py with detected entry point: {entry_point}")
|
2625
|
+
except Exception as e:
|
2626
|
+
print(f"ā ļø Error finding entry point: {e}")
|
2627
|
+
|
2628
|
+
# Print the fixed commands
|
2629
|
+
print("\nš Fixed commands:")
|
2630
|
+
for i, cmd in enumerate(fixed_commands, 1):
|
2631
|
+
print(f" {i}. {cmd}")
|
2632
|
+
|
2633
|
+
return fixed_commands
|
2581
2634
|
else:
|
2582
2635
|
print("ā ļø API response did not contain setupInstructions.commands field")
|
2583
2636
|
print("š Available fields in response:")
|
@@ -2723,11 +2776,14 @@ def generate_fallback_commands(gitingest_data):
|
|
2723
2776
|
# Combine all commands
|
2724
2777
|
all_commands = default_commands + language_commands
|
2725
2778
|
|
2779
|
+
# Fix the commands
|
2780
|
+
fixed_commands = fix_setup_commands(all_commands)
|
2781
|
+
|
2726
2782
|
print("\nš Generated fallback setup commands:")
|
2727
|
-
for i, cmd in enumerate(
|
2783
|
+
for i, cmd in enumerate(fixed_commands, 1):
|
2728
2784
|
print(f" {i}. {cmd}")
|
2729
2785
|
|
2730
|
-
return
|
2786
|
+
return fixed_commands
|
2731
2787
|
|
2732
2788
|
def generate_basic_repo_analysis_from_url(repo_url):
|
2733
2789
|
"""Generate basic repository analysis data from a repository URL."""
|
@@ -2915,9 +2971,21 @@ def get_setup_commands_from_local_api(repo_url, gitingest_data):
|
|
2915
2971
|
if "setupInstructions" in data and "commands" in data["setupInstructions"]:
|
2916
2972
|
commands = data["setupInstructions"]["commands"]
|
2917
2973
|
print(f"ā
Successfully fetched {len(commands)} setup commands from local API")
|
2974
|
+
|
2975
|
+
# Print the original commands
|
2976
|
+
print("š Original commands from local API:")
|
2918
2977
|
for i, cmd in enumerate(commands, 1):
|
2919
2978
|
print(f" {i}. {cmd}")
|
2920
|
-
|
2979
|
+
|
2980
|
+
# Fix the commands
|
2981
|
+
fixed_commands = fix_setup_commands(commands)
|
2982
|
+
|
2983
|
+
# Print the fixed commands
|
2984
|
+
print("\nš Fixed commands:")
|
2985
|
+
for i, cmd in enumerate(fixed_commands, 1):
|
2986
|
+
print(f" {i}. {cmd}")
|
2987
|
+
|
2988
|
+
return fixed_commands
|
2921
2989
|
except Exception as e:
|
2922
2990
|
print(f"ā Error connecting to local API: {e}")
|
2923
2991
|
|
@@ -3041,6 +3109,58 @@ def create_ssh_container_function(gpu_type="a10g", timeout_minutes=60, volume=No
|
|
3041
3109
|
# Return the configured function
|
3042
3110
|
return ssh_container, app_name
|
3043
3111
|
|
3112
|
+
def fix_setup_commands(commands):
|
3113
|
+
"""Fix setup commands by removing placeholders and comments."""
|
3114
|
+
fixed_commands = []
|
3115
|
+
|
3116
|
+
for cmd in commands:
|
3117
|
+
# Remove placeholders like "(or the appropriate entry point...)"
|
3118
|
+
cmd = re.sub(r'\([^)]*\)', '', cmd).strip()
|
3119
|
+
|
3120
|
+
# Skip empty commands or pure comments
|
3121
|
+
if not cmd or cmd.startswith('#'):
|
3122
|
+
continue
|
3123
|
+
|
3124
|
+
# Remove trailing comments
|
3125
|
+
cmd = re.sub(r'#.*$', '', cmd).strip()
|
3126
|
+
|
3127
|
+
if cmd:
|
3128
|
+
fixed_commands.append(cmd)
|
3129
|
+
|
3130
|
+
return fixed_commands
|
3131
|
+
|
3132
|
+
def find_entry_point(repo_dir):
|
3133
|
+
"""Find the entry point script for a repository."""
|
3134
|
+
# Common entry point files to check
|
3135
|
+
common_entry_points = [
|
3136
|
+
"main.py", "app.py", "run.py", "train.py", "start.py",
|
3137
|
+
"server.py", "cli.py", "demo.py", "example.py"
|
3138
|
+
]
|
3139
|
+
|
3140
|
+
# Check if any of the common entry points exist
|
3141
|
+
for entry_point in common_entry_points:
|
3142
|
+
if os.path.exists(os.path.join(repo_dir, entry_point)):
|
3143
|
+
return entry_point
|
3144
|
+
|
3145
|
+
# Look for Python files in the root directory
|
3146
|
+
python_files = [f for f in os.listdir(repo_dir) if f.endswith('.py')]
|
3147
|
+
if python_files:
|
3148
|
+
# Prioritize files with main function or if_name_main pattern
|
3149
|
+
for py_file in python_files:
|
3150
|
+
file_path = os.path.join(repo_dir, py_file)
|
3151
|
+
try:
|
3152
|
+
with open(file_path, 'r') as f:
|
3153
|
+
content = f.read()
|
3154
|
+
if "def main" in content or "if __name__ == '__main__'" in content or 'if __name__ == "__main__"' in content:
|
3155
|
+
return py_file
|
3156
|
+
except:
|
3157
|
+
pass
|
3158
|
+
|
3159
|
+
# If no main function found, return the first Python file
|
3160
|
+
return python_files[0]
|
3161
|
+
|
3162
|
+
return None
|
3163
|
+
|
3044
3164
|
if __name__ == "__main__":
|
3045
3165
|
# Parse command line arguments when script is run directly
|
3046
3166
|
import argparse
|