gitarsenal-cli 1.1.4 → 1.1.5

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.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "CLI tool for creating Modal sandboxes with GitHub repositories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -94,18 +94,37 @@ If you see a "Token missing" error when creating containers through the proxy se
94
94
 
95
95
  1. **Check that the MODAL_TOKEN is set on the server**:
96
96
  - Verify the `.env` file has a valid MODAL_TOKEN
97
+ - Ensure the token is correctly formatted and not expired
97
98
  - Restart the proxy service after updating the token
98
99
 
99
- 2. **Check that the proxy service is running**:
100
- - Use `./gitarsenal.py proxy status` to check connectivity
101
- - Verify the ngrok tunnel is active and the URL is correct
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
+ ```
102
106
 
103
- 3. **Check API key authentication**:
104
- - Make sure your client is configured with a valid API key
105
- - If needed, reconfigure with `./gitarsenal.py proxy configure`
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
+ ```
106
112
 
107
- 4. **Check server logs**:
113
+ 4. **Check the proxy service logs**:
108
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
109
128
 
110
129
  ### "Unauthorized" Error
111
130
 
@@ -84,6 +84,27 @@ def setup_modal_auth():
84
84
  os.environ["MODAL_TOKEN_ID"] = MODAL_TOKEN
85
85
  # Also set the token directly in modal.config
86
86
  modal.config._auth_config.token_id = MODAL_TOKEN
87
+
88
+ # Verify token is working by attempting a simple operation
89
+ try:
90
+ # Try to list volumes as a simple API test
91
+ test_vol = modal.Volume.list()
92
+ logger.info("Modal token verified successfully - able to list volumes")
93
+ except Exception as vol_err:
94
+ logger.error(f"Modal token verification failed: {vol_err}")
95
+ # Try setting token again with different approach
96
+ try:
97
+ import subprocess
98
+ result = subprocess.run(
99
+ ["modal", "token", "set", MODAL_TOKEN],
100
+ capture_output=True, text=True, check=True
101
+ )
102
+ logger.info("Modal token set via CLI command")
103
+ return True
104
+ except Exception as cli_err:
105
+ logger.error(f"Failed to set token via CLI: {cli_err}")
106
+ return False
107
+
87
108
  logger.info("Modal token set in environment and config")
88
109
  return True
89
110
  except Exception as e:
@@ -203,6 +224,18 @@ def create_ssh_container():
203
224
  # Create a unique ID for this container
204
225
  container_id = str(uuid.uuid4())
205
226
 
227
+ # Log token status for debugging
228
+ token_status = "Token is set" if MODAL_TOKEN else "Token is missing"
229
+ logger.info(f"Modal token status before thread: {token_status}")
230
+ logger.info(f"Modal token length: {len(MODAL_TOKEN) if MODAL_TOKEN else 'N/A'}")
231
+
232
+ # Ensure Modal token is set in environment
233
+ if MODAL_TOKEN:
234
+ os.environ["MODAL_TOKEN_ID"] = MODAL_TOKEN
235
+ # Also set directly in modal.config
236
+ modal.config._auth_config.token_id = MODAL_TOKEN
237
+ logger.info("Modal token explicitly set in environment and config")
238
+
206
239
  # Start container creation in a separate thread
207
240
  def create_container_thread():
208
241
  try:
@@ -214,9 +247,21 @@ def create_ssh_container():
214
247
  # Explicitly set the Modal token in the environment again for this thread
215
248
  os.environ["MODAL_TOKEN_ID"] = MODAL_TOKEN
216
249
 
250
+ # Directly set the token in Modal config
251
+ modal.config._auth_config.token_id = MODAL_TOKEN
252
+
217
253
  # Log token status for debugging
218
254
  token_status = "Token is set" if MODAL_TOKEN else "Token is missing"
219
- logger.info(f"Modal token status: {token_status}")
255
+ logger.info(f"Modal token status in thread: {token_status}")
256
+ logger.info(f"Modal token length in thread: {len(MODAL_TOKEN) if MODAL_TOKEN else 'N/A'}")
257
+
258
+ # Verify token is actually working
259
+ try:
260
+ # Try a simple Modal operation to verify authentication
261
+ import modal.cli.app_create
262
+ logger.info("Modal module imported successfully in thread")
263
+ except Exception as auth_err:
264
+ logger.error(f"Modal authentication verification error: {auth_err}")
220
265
 
221
266
  result = create_modal_ssh_container(
222
267
  gpu_type,
@@ -2071,9 +2071,30 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
2071
2071
  try:
2072
2072
  # Try to access Modal token to check authentication
2073
2073
  try:
2074
- # This will raise an exception if not authenticated
2075
- modal.config.get_current_workspace_name()
2076
- print("✅ Modal authentication verified")
2074
+ # Check if token is set in environment
2075
+ modal_token = os.environ.get("MODAL_TOKEN_ID")
2076
+ if not modal_token:
2077
+ print("⚠️ MODAL_TOKEN_ID not found in environment.")
2078
+ # Try to set from modal.config if available
2079
+ try:
2080
+ modal_token = modal.config._auth_config.token_id
2081
+ if modal_token:
2082
+ print("✅ Found token in modal.config")
2083
+ # Set it in environment for consistency
2084
+ os.environ["MODAL_TOKEN_ID"] = modal_token
2085
+ except Exception as e:
2086
+ print(f"⚠️ Error accessing modal.config: {e}")
2087
+
2088
+ # If still no token, try to get workspace name as authentication test
2089
+ if not modal_token:
2090
+ # This will raise an exception if not authenticated
2091
+ workspace = modal.config.get_current_workspace_name()
2092
+ print(f"✅ Modal authentication verified (workspace: {workspace})")
2093
+ else:
2094
+ print(f"✅ Modal token found (length: {len(modal_token)})")
2095
+ # Explicitly set the token in modal config
2096
+ modal.config._auth_config.token_id = modal_token
2097
+ print("✅ Token explicitly set in modal.config")
2077
2098
  except modal.exception.AuthError:
2078
2099
  print("\n" + "="*80)
2079
2100
  print("🔑 MODAL AUTHENTICATION REQUIRED")
@@ -2160,6 +2181,29 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
2160
2181
  print(f" - Current workspace: {workspace}")
2161
2182
  except Exception as e:
2162
2183
  print(f" - Error getting workspace: {e}")
2184
+
2185
+ # Verify token is valid by trying a simple Modal operation
2186
+ try:
2187
+ print("🔍 Verifying Modal token validity...")
2188
+ # Try to access Modal API
2189
+ if not modal_token:
2190
+ print("❌ No Modal token available. Cannot proceed.")
2191
+ return None
2192
+
2193
+ # Set token directly in modal config again to be sure
2194
+ modal.config._auth_config.token_id = modal_token
2195
+
2196
+ # Try to list volumes as a simple API test
2197
+ try:
2198
+ test_vol = modal.Volume.list()
2199
+ print(f"✅ Modal token is valid! Successfully listed volumes.")
2200
+ except Exception as vol_err:
2201
+ print(f"❌ Token validation failed: {vol_err}")
2202
+ print("Please check that your Modal token is valid and properly set.")
2203
+ return None
2204
+ except Exception as e:
2205
+ print(f"❌ Error during token validation: {e}")
2206
+ return None
2163
2207
 
2164
2208
  # Create SSH-enabled image
2165
2209
  ssh_image = (