gitarsenal-cli 1.1.10 → 1.1.12
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 +1 -1
- package/python/MODAL_PROXY_README.md +2 -2
- package/python/MODAL_TOKEN_SETUP.md +82 -0
- package/python/README.md +11 -1
- package/python/__pycache__/credentials_manager.cpython-313.pyc +0 -0
- package/python/__pycache__/setup_modal_token.cpython-313.pyc +0 -0
- package/python/gitarsenal.py +11 -1
- package/python/gitarsenal_proxy_client.py +1 -1
- package/python/modal_proxy_service.py +33 -5
- package/python/run_with_modal_token.py +50 -0
- package/python/setup_modal_token.py +106 -0
- package/python/test_modalSandboxScript.py +12 -1
package/package.json
CHANGED
@@ -46,7 +46,7 @@ The Modal proxy service allows users to access Modal services (like GPU-accelera
|
|
46
46
|
|
47
47
|
This will provide you with a public URL that you can share with users.
|
48
48
|
|
49
|
-
Current ngrok URL: `https://
|
49
|
+
Current ngrok URL: `https://932ffd63ad3d.ngrok-free.app`
|
50
50
|
|
51
51
|
## Client-Side Setup
|
52
52
|
|
@@ -56,7 +56,7 @@ The Modal proxy service allows users to access Modal services (like GPU-accelera
|
|
56
56
|
```
|
57
57
|
|
58
58
|
You'll be prompted to enter:
|
59
|
-
- The proxy URL (the default is now set to `https://
|
59
|
+
- The proxy URL (the default is now set to `https://932ffd63ad3d.ngrok-free.app`)
|
60
60
|
- Your API key
|
61
61
|
|
62
62
|
2. **Check proxy service status**:
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Modal Token Setup Solution
|
2
|
+
|
3
|
+
This document explains how the Modal token setup solution works in GitArsenal CLI.
|
4
|
+
|
5
|
+
## Problem
|
6
|
+
|
7
|
+
The GitArsenal CLI was failing with errors like:
|
8
|
+
|
9
|
+
```
|
10
|
+
🔍 MODAL_TOKEN_ID not found in environment.
|
11
|
+
❌ No Modal token found in environment variables
|
12
|
+
❌ Modal token file not found
|
13
|
+
❌ Could not find Modal token in any location
|
14
|
+
```
|
15
|
+
|
16
|
+
This happened because the Modal token was not being properly set in the environment variables.
|
17
|
+
|
18
|
+
## Solution
|
19
|
+
|
20
|
+
We implemented a comprehensive solution to automatically find and set up the Modal token from various sources:
|
21
|
+
|
22
|
+
1. Created a `setup_modal_token.py` module that:
|
23
|
+
- Checks for the token in environment variables (MODAL_TOKEN_ID and MODAL_TOKEN)
|
24
|
+
- Checks for the token in GitArsenal credentials file (~/.gitarsenal/credentials.json)
|
25
|
+
- Checks for the token in Modal token file (~/.modal/token.json)
|
26
|
+
- Sets the token in both MODAL_TOKEN_ID and MODAL_TOKEN environment variables
|
27
|
+
|
28
|
+
2. Modified key files to use this module:
|
29
|
+
- `gitarsenal.py` - Main CLI entry point
|
30
|
+
- `modal_proxy_service.py` - Modal proxy service
|
31
|
+
- `test_modalSandboxScript.py` - Modal sandbox script
|
32
|
+
|
33
|
+
3. Created a wrapper script `run_with_modal_token.py` that:
|
34
|
+
- Sets up the Modal token using the setup_modal_token module
|
35
|
+
- Runs a specified command with the token properly set in the environment
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
### Running Commands with Modal Token
|
40
|
+
|
41
|
+
Use the wrapper script to run any command that requires Modal authentication:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
python run_with_modal_token.py <command> [args...]
|
45
|
+
```
|
46
|
+
|
47
|
+
Example:
|
48
|
+
|
49
|
+
```bash
|
50
|
+
python run_with_modal_token.py python modal_proxy_service.py
|
51
|
+
```
|
52
|
+
|
53
|
+
### Setting Up Modal Token
|
54
|
+
|
55
|
+
If you need to set up the Modal token manually:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
python setup_modal_token.py
|
59
|
+
```
|
60
|
+
|
61
|
+
This will prompt you for the token if it's not found in any of the sources.
|
62
|
+
|
63
|
+
### Adding Modal Token to GitArsenal Credentials
|
64
|
+
|
65
|
+
You can also add the Modal token to GitArsenal credentials:
|
66
|
+
|
67
|
+
```bash
|
68
|
+
./gitarsenal.py credentials set modal_token
|
69
|
+
```
|
70
|
+
|
71
|
+
## How It Works
|
72
|
+
|
73
|
+
1. The `setup_modal_token.py` module checks multiple sources for the Modal token:
|
74
|
+
- Environment variables (MODAL_TOKEN_ID and MODAL_TOKEN)
|
75
|
+
- GitArsenal credentials file (~/.gitarsenal/credentials.json)
|
76
|
+
- Modal token file (~/.modal/token.json)
|
77
|
+
|
78
|
+
2. When it finds a token, it sets both MODAL_TOKEN_ID and MODAL_TOKEN environment variables.
|
79
|
+
|
80
|
+
3. The modified files import and use this module to ensure the token is set before any Modal operations.
|
81
|
+
|
82
|
+
4. The wrapper script makes it easy to run any command with the token properly set up.
|
package/python/README.md
CHANGED
@@ -198,7 +198,7 @@ Proxy configuration is stored in `~/.gitarsenal/proxy_config.json` with similar
|
|
198
198
|
|
199
199
|
### Modal Authentication Issues
|
200
200
|
|
201
|
-
If you see errors like "Token missing"
|
201
|
+
If you see errors like "Token missing", "Could not authenticate client", or "MODAL_TOKEN_ID not found in environment":
|
202
202
|
|
203
203
|
1. Ensure Modal is installed:
|
204
204
|
```bash
|
@@ -215,6 +215,16 @@ If you see errors like "Token missing" or "Could not authenticate client":
|
|
215
215
|
./gitarsenal.py credentials set modal_token
|
216
216
|
```
|
217
217
|
|
218
|
+
4. Use the wrapper script to run commands with the Modal token properly set up:
|
219
|
+
```bash
|
220
|
+
python run_with_modal_token.py python modal_proxy_service.py
|
221
|
+
```
|
222
|
+
|
223
|
+
The wrapper script automatically sets up the Modal token from one of these sources:
|
224
|
+
- Environment variables (MODAL_TOKEN_ID or MODAL_TOKEN)
|
225
|
+
- GitArsenal credentials file (~/.gitarsenal/credentials.json)
|
226
|
+
- Modal token file (~/.modal/token.json)
|
227
|
+
|
218
228
|
### Proxy Service Issues
|
219
229
|
|
220
230
|
If you're having issues with the proxy service:
|
Binary file
|
Binary file
|
package/python/gitarsenal.py
CHANGED
@@ -12,6 +12,16 @@ import subprocess
|
|
12
12
|
import json
|
13
13
|
from pathlib import Path
|
14
14
|
|
15
|
+
# Import the Modal token setup module
|
16
|
+
try:
|
17
|
+
from setup_modal_token import setup_modal_token
|
18
|
+
# Set up Modal token at import time
|
19
|
+
setup_modal_token()
|
20
|
+
except ImportError:
|
21
|
+
print("⚠️ Warning: setup_modal_token module not found. Modal authentication may fail.")
|
22
|
+
except Exception as e:
|
23
|
+
print(f"⚠️ Warning: Error setting up Modal token: {e}")
|
24
|
+
|
15
25
|
def check_modal_auth():
|
16
26
|
"""Check if Modal is authenticated and guide user if not"""
|
17
27
|
try:
|
@@ -74,7 +84,7 @@ def check_proxy_config():
|
|
74
84
|
print("⚠️ Modal proxy not configured. Setting up with default values...")
|
75
85
|
|
76
86
|
# Set default proxy URL to the ngrok URL
|
77
|
-
default_url = "https://
|
87
|
+
default_url = "https://932ffd63ad3d.ngrok-free.app"
|
78
88
|
|
79
89
|
# Update configuration with default URL
|
80
90
|
config["proxy_url"] = default_url
|
@@ -32,7 +32,7 @@ class GitArsenalProxyClient:
|
|
32
32
|
|
33
33
|
# If still no URL, use default
|
34
34
|
if not self.base_url:
|
35
|
-
self.base_url = "https://
|
35
|
+
self.base_url = "https://932ffd63ad3d.ngrok-free.app" # Default to new ngrok URL
|
36
36
|
|
37
37
|
# Warn if no API key
|
38
38
|
if not self.api_key:
|
@@ -42,8 +42,21 @@ logger = logging.getLogger("modal-proxy")
|
|
42
42
|
app = Flask(__name__)
|
43
43
|
CORS(app) # Enable CORS for all routes
|
44
44
|
|
45
|
+
# Try to set up Modal token using our setup module
|
46
|
+
try:
|
47
|
+
from setup_modal_token import setup_modal_token
|
48
|
+
token_setup_success = setup_modal_token()
|
49
|
+
if token_setup_success:
|
50
|
+
logger.info("Modal token set up successfully using setup_modal_token module")
|
51
|
+
else:
|
52
|
+
logger.warning("setup_modal_token module failed to set up Modal token")
|
53
|
+
except ImportError:
|
54
|
+
logger.warning("setup_modal_token module not found")
|
55
|
+
except Exception as e:
|
56
|
+
logger.error(f"Error using setup_modal_token module: {e}")
|
57
|
+
|
45
58
|
# Get Modal token from environment variable
|
46
|
-
MODAL_TOKEN = os.environ.get("MODAL_TOKEN")
|
59
|
+
MODAL_TOKEN = os.environ.get("MODAL_TOKEN") or os.environ.get("MODAL_TOKEN_ID")
|
47
60
|
if not MODAL_TOKEN:
|
48
61
|
logger.error("MODAL_TOKEN environment variable is not set!")
|
49
62
|
|
@@ -75,19 +88,34 @@ def generate_random_password(length=16):
|
|
75
88
|
|
76
89
|
def setup_modal_auth():
|
77
90
|
"""Set up Modal authentication using the server's token"""
|
78
|
-
|
91
|
+
# Try to use our setup_modal_token module first
|
92
|
+
try:
|
93
|
+
from setup_modal_token import setup_modal_token
|
94
|
+
if setup_modal_token():
|
95
|
+
logger.info("Modal token set up successfully using setup_modal_token module")
|
96
|
+
return True
|
97
|
+
except ImportError:
|
98
|
+
logger.info("setup_modal_token module not found, falling back to direct setup")
|
99
|
+
except Exception as e:
|
100
|
+
logger.warning(f"Error using setup_modal_token module: {e}, falling back to direct setup")
|
101
|
+
|
102
|
+
# Fall back to direct token setup if the module approach failed
|
103
|
+
token = MODAL_TOKEN or os.environ.get("MODAL_TOKEN") or os.environ.get("MODAL_TOKEN_ID")
|
104
|
+
|
105
|
+
if not token:
|
79
106
|
logger.error("Cannot set up Modal authentication: No token provided")
|
80
107
|
return False
|
81
108
|
|
82
109
|
try:
|
83
|
-
# Set the token in the environment
|
84
|
-
os.environ["MODAL_TOKEN_ID"] =
|
110
|
+
# Set the token in the environment (both variables to be safe)
|
111
|
+
os.environ["MODAL_TOKEN_ID"] = token
|
112
|
+
os.environ["MODAL_TOKEN"] = token
|
85
113
|
|
86
114
|
# Try to set the token using Modal CLI
|
87
115
|
try:
|
88
116
|
import subprocess
|
89
117
|
result = subprocess.run(
|
90
|
-
["modal", "token", "set",
|
118
|
+
["modal", "token", "set", token],
|
91
119
|
capture_output=True, text=True, check=False
|
92
120
|
)
|
93
121
|
if result.returncode == 0:
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Run With Modal Token - Wrapper Script
|
4
|
+
|
5
|
+
This script sets up the Modal token in the environment and then runs a specified command.
|
6
|
+
It's useful for running commands that need Modal authentication without modifying them.
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
python run_with_modal_token.py <command> [args...]
|
10
|
+
|
11
|
+
Example:
|
12
|
+
python run_with_modal_token.py python modal_proxy_service.py
|
13
|
+
"""
|
14
|
+
|
15
|
+
import os
|
16
|
+
import sys
|
17
|
+
import subprocess
|
18
|
+
from setup_modal_token import setup_modal_token
|
19
|
+
|
20
|
+
def main():
|
21
|
+
# Set up Modal token
|
22
|
+
if not setup_modal_token():
|
23
|
+
print("❌ Failed to set up Modal token")
|
24
|
+
print("Please set up your credentials with:")
|
25
|
+
print(" ./gitarsenal.py credentials set modal_token")
|
26
|
+
sys.exit(1)
|
27
|
+
|
28
|
+
# Check if a command was provided
|
29
|
+
if len(sys.argv) < 2:
|
30
|
+
print("❌ No command provided")
|
31
|
+
print(f"Usage: {sys.argv[0]} <command> [args...]")
|
32
|
+
sys.exit(1)
|
33
|
+
|
34
|
+
# Get the command and arguments
|
35
|
+
cmd = sys.argv[1]
|
36
|
+
args = sys.argv[2:]
|
37
|
+
|
38
|
+
# Print what we're about to run
|
39
|
+
print(f"🚀 Running command with Modal token: {cmd} {' '.join(args)}")
|
40
|
+
|
41
|
+
# Run the command
|
42
|
+
try:
|
43
|
+
result = subprocess.run([cmd] + args)
|
44
|
+
sys.exit(result.returncode)
|
45
|
+
except Exception as e:
|
46
|
+
print(f"❌ Error running command: {e}")
|
47
|
+
sys.exit(1)
|
48
|
+
|
49
|
+
if __name__ == "__main__":
|
50
|
+
main()
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Modal Token Setup Script for GitArsenal CLI
|
4
|
+
|
5
|
+
This script ensures that the Modal token is properly set up in the environment
|
6
|
+
before running any Modal operations. It checks for the token in various locations
|
7
|
+
and sets the required environment variables.
|
8
|
+
"""
|
9
|
+
|
10
|
+
import os
|
11
|
+
import sys
|
12
|
+
from pathlib import Path
|
13
|
+
import logging
|
14
|
+
|
15
|
+
# Configure logging
|
16
|
+
logging.basicConfig(
|
17
|
+
level=logging.INFO,
|
18
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
19
|
+
)
|
20
|
+
logger = logging.getLogger("modal-setup")
|
21
|
+
|
22
|
+
def setup_modal_token():
|
23
|
+
"""
|
24
|
+
Set up Modal token in the environment.
|
25
|
+
|
26
|
+
Checks for the token in:
|
27
|
+
1. Environment variables (MODAL_TOKEN_ID and MODAL_TOKEN)
|
28
|
+
2. GitArsenal credentials file
|
29
|
+
3. Modal token file (~/.modal/token.json)
|
30
|
+
|
31
|
+
Returns:
|
32
|
+
bool: True if token was set up successfully, False otherwise
|
33
|
+
"""
|
34
|
+
# Check if token is already in environment
|
35
|
+
if os.environ.get("MODAL_TOKEN_ID") and os.environ.get("MODAL_TOKEN"):
|
36
|
+
logger.info("Modal token already set in environment")
|
37
|
+
return True
|
38
|
+
|
39
|
+
# Try to get token from GitArsenal credentials
|
40
|
+
token = get_token_from_gitarsenal()
|
41
|
+
if token:
|
42
|
+
os.environ["MODAL_TOKEN_ID"] = token
|
43
|
+
os.environ["MODAL_TOKEN"] = token
|
44
|
+
logger.info("Modal token set from GitArsenal credentials")
|
45
|
+
return True
|
46
|
+
|
47
|
+
# Try to get token from Modal token file
|
48
|
+
token = get_token_from_modal_file()
|
49
|
+
if token:
|
50
|
+
os.environ["MODAL_TOKEN_ID"] = token
|
51
|
+
os.environ["MODAL_TOKEN"] = token
|
52
|
+
logger.info("Modal token set from Modal token file")
|
53
|
+
return True
|
54
|
+
|
55
|
+
# If we got here, no token was found
|
56
|
+
logger.error("No Modal token found in any location")
|
57
|
+
return False
|
58
|
+
|
59
|
+
def get_token_from_gitarsenal():
|
60
|
+
"""Get Modal token from GitArsenal credentials file"""
|
61
|
+
try:
|
62
|
+
from credentials_manager import CredentialsManager
|
63
|
+
credentials_manager = CredentialsManager()
|
64
|
+
token = credentials_manager.get_modal_token()
|
65
|
+
if token:
|
66
|
+
logger.info("Found Modal token in GitArsenal credentials")
|
67
|
+
return token
|
68
|
+
except ImportError:
|
69
|
+
logger.warning("Could not import CredentialsManager")
|
70
|
+
except Exception as e:
|
71
|
+
logger.warning(f"Error getting token from GitArsenal credentials: {e}")
|
72
|
+
|
73
|
+
return None
|
74
|
+
|
75
|
+
def get_token_from_modal_file():
|
76
|
+
"""Get Modal token from Modal token file"""
|
77
|
+
try:
|
78
|
+
import json
|
79
|
+
token_file = Path.home() / ".modal" / "token.json"
|
80
|
+
|
81
|
+
if not token_file.exists():
|
82
|
+
logger.warning(f"Modal token file not found at {token_file}")
|
83
|
+
return None
|
84
|
+
|
85
|
+
with open(token_file, 'r') as f:
|
86
|
+
token_data = json.load(f)
|
87
|
+
|
88
|
+
# The token file contains both token_id and token
|
89
|
+
token_id = token_data.get("token_id")
|
90
|
+
if token_id:
|
91
|
+
logger.info("Found token_id in Modal token file")
|
92
|
+
return token_id
|
93
|
+
except Exception as e:
|
94
|
+
logger.warning(f"Error reading Modal token file: {e}")
|
95
|
+
|
96
|
+
return None
|
97
|
+
|
98
|
+
if __name__ == "__main__":
|
99
|
+
if setup_modal_token():
|
100
|
+
print("✅ Modal token set up successfully")
|
101
|
+
sys.exit(0)
|
102
|
+
else:
|
103
|
+
print("❌ Failed to set up Modal token")
|
104
|
+
print("Please set up your credentials with:")
|
105
|
+
print(" ./gitarsenal.py credentials set modal_token")
|
106
|
+
sys.exit(1)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import os
|
2
2
|
import sys
|
3
|
-
import modal
|
4
3
|
import time
|
5
4
|
import subprocess
|
6
5
|
import json
|
@@ -11,6 +10,18 @@ import requests
|
|
11
10
|
import secrets
|
12
11
|
import string
|
13
12
|
|
13
|
+
# Try to set up Modal token before importing modal
|
14
|
+
try:
|
15
|
+
from setup_modal_token import setup_modal_token
|
16
|
+
setup_modal_token()
|
17
|
+
except ImportError:
|
18
|
+
print("⚠️ Warning: setup_modal_token module not found. Modal authentication may fail.")
|
19
|
+
except Exception as e:
|
20
|
+
print(f"⚠️ Warning: Error setting up Modal token: {e}")
|
21
|
+
|
22
|
+
# Import modal after token setup
|
23
|
+
import modal
|
24
|
+
|
14
25
|
def handle_interactive_input(prompt, is_password=False):
|
15
26
|
"""Handle interactive input from the user with optional password masking"""
|
16
27
|
print("\n" + "="*60)
|