gitarsenal-cli 1.9.65 → 1.9.67
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/bin/gitarsenal.js +24 -0
- package/kill_claude/.claude/settings.local.json +9 -0
- package/kill_claude/README.md +265 -0
- package/kill_claude/__pycache__/bash_output_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/bash_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/claude_code_agent.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/edit_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/exit_plan_mode_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/glob_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/grep_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/kill_bash_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/ls_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/multiedit_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/notebook_edit_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/read_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/task_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/todo_write_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/web_fetch_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/web_search_tool.cpython-313.pyc +0 -0
- package/kill_claude/__pycache__/write_tool.cpython-313.pyc +0 -0
- package/kill_claude/claude_code_agent.py +848 -0
- package/kill_claude/prompts/claude-code-agent-prompts.md +65 -0
- package/kill_claude/prompts/claude-code-environment-context.md +100 -0
- package/kill_claude/prompts/claude-code-git-workflows.md +151 -0
- package/kill_claude/prompts/claude-code-hook-system.md +94 -0
- package/kill_claude/prompts/claude-code-response-formatting.md +79 -0
- package/kill_claude/prompts/claude-code-security-constraints.md +87 -0
- package/kill_claude/prompts/claude-code-system-prompt.md +136 -0
- package/kill_claude/prompts/claude-code-system-reminders.md +50 -0
- package/kill_claude/prompts/claude-code-task-workflows.md +114 -0
- package/kill_claude/prompts/claude-code-thinking-mode-prompts.md +39 -0
- package/kill_claude/prompts/claude-code-tool-prompts.md +339 -0
- package/kill_claude/prompts/claude-code-tool-usage-policies.md +87 -0
- package/kill_claude/requirements.txt +1 -0
- package/kill_claude/tools/__init__.py +1 -0
- package/kill_claude/tools/__pycache__/bash_output_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/bash_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/edit_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/exit_plan_mode_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/glob_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/grep_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/kill_bash_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/ls_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/multiedit_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/notebook_edit_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/read_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/task_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/todo_write_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/web_fetch_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/web_search_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/__pycache__/write_tool.cpython-313.pyc +0 -0
- package/kill_claude/tools/bash_output_tool.py +47 -0
- package/kill_claude/tools/bash_tool.py +79 -0
- package/kill_claude/tools/edit_tool.py +60 -0
- package/kill_claude/tools/exit_plan_mode_tool.py +42 -0
- package/kill_claude/tools/glob_tool.py +46 -0
- package/kill_claude/tools/grep_tool.py +105 -0
- package/kill_claude/tools/kill_bash_tool.py +38 -0
- package/kill_claude/tools/ls_tool.py +44 -0
- package/kill_claude/tools/multiedit_tool.py +111 -0
- package/kill_claude/tools/notebook_edit_tool.py +64 -0
- package/kill_claude/tools/read_tool.py +61 -0
- package/kill_claude/tools/task_tool.py +67 -0
- package/kill_claude/tools/todo_write_tool.py +114 -0
- package/kill_claude/tools/web_fetch_tool.py +55 -0
- package/kill_claude/tools/web_search_tool.py +58 -0
- package/kill_claude/tools/write_tool.py +46 -0
- package/lib/sandbox.js +3 -0
- package/package.json +1 -1
- package/python/test_modalSandboxScript.py +144 -295
- package/python/gitarsenal.py +0 -488
package/python/gitarsenal.py
DELETED
|
@@ -1,488 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
GitArsenal CLI - Main entry point
|
|
4
|
-
|
|
5
|
-
This script provides a user-friendly interface to the GitArsenal CLI tools.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import argparse
|
|
9
|
-
import sys
|
|
10
|
-
import os
|
|
11
|
-
import subprocess
|
|
12
|
-
import json
|
|
13
|
-
from pathlib import Path
|
|
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
|
-
|
|
25
|
-
# Import authentication manager
|
|
26
|
-
try:
|
|
27
|
-
from auth_manager import AuthManager
|
|
28
|
-
except ImportError:
|
|
29
|
-
print("⚠️ Warning: auth_manager module not found. Authentication will be disabled.")
|
|
30
|
-
AuthManager = None
|
|
31
|
-
|
|
32
|
-
def check_modal_auth():
|
|
33
|
-
"""Check if Modal is authenticated and set up the built-in token if needed"""
|
|
34
|
-
try:
|
|
35
|
-
# Set up the built-in token first
|
|
36
|
-
from setup_modal_token import setup_modal_token
|
|
37
|
-
setup_modal_token()
|
|
38
|
-
|
|
39
|
-
# Try to run a simple Modal command to check authentication
|
|
40
|
-
result = subprocess.run(["modal", "app", "list"],
|
|
41
|
-
capture_output=True, text=True, timeout=10)
|
|
42
|
-
|
|
43
|
-
# If the command was successful, Modal is authenticated
|
|
44
|
-
if result.returncode == 0:
|
|
45
|
-
return True
|
|
46
|
-
|
|
47
|
-
# If we get here, there might be an issue with the Modal CLI itself
|
|
48
|
-
print(f"⚠️ Modal command returned error: {result.stderr}")
|
|
49
|
-
print("This could be a temporary issue with the Modal service.")
|
|
50
|
-
print("The built-in token should work automatically without any user action.")
|
|
51
|
-
return True # Return True anyway to continue with the operation
|
|
52
|
-
|
|
53
|
-
except FileNotFoundError:
|
|
54
|
-
print("\n" + "="*80)
|
|
55
|
-
print("❌ MODAL CLI NOT INSTALLED")
|
|
56
|
-
print("="*80)
|
|
57
|
-
print("GitArsenal requires the Modal CLI to be installed.")
|
|
58
|
-
print("\nTo install Modal CLI, run:")
|
|
59
|
-
print(" pip install modal")
|
|
60
|
-
print("="*80)
|
|
61
|
-
return False
|
|
62
|
-
except Exception as e:
|
|
63
|
-
print(f"⚠️ Error checking Modal authentication: {e}")
|
|
64
|
-
return False
|
|
65
|
-
|
|
66
|
-
def check_proxy_config():
|
|
67
|
-
"""Check if Modal proxy configuration exists and is valid"""
|
|
68
|
-
try:
|
|
69
|
-
from gitarsenal_proxy_client import GitArsenalProxyClient
|
|
70
|
-
|
|
71
|
-
# Initialize client
|
|
72
|
-
client = GitArsenalProxyClient()
|
|
73
|
-
|
|
74
|
-
# Check if configuration exists
|
|
75
|
-
config = client.load_config()
|
|
76
|
-
|
|
77
|
-
# Set default proxy URL to localhost since we're running the proxy locally
|
|
78
|
-
default_url = "http://127.0.0.1:5001"
|
|
79
|
-
|
|
80
|
-
if not config.get("proxy_url"):
|
|
81
|
-
print(f"⚠️ Modal proxy URL not configured. Setting to default: {default_url}")
|
|
82
|
-
|
|
83
|
-
# Update configuration with default URL
|
|
84
|
-
config["proxy_url"] = default_url
|
|
85
|
-
client.save_config(config)
|
|
86
|
-
client.base_url = default_url
|
|
87
|
-
|
|
88
|
-
print(f"✅ Set default proxy URL: {default_url}")
|
|
89
|
-
|
|
90
|
-
# Set a default API key if missing
|
|
91
|
-
if not config.get("api_key"):
|
|
92
|
-
print("⚠️ API key not configured. Setting a default key...")
|
|
93
|
-
|
|
94
|
-
# Use a default API key for local development
|
|
95
|
-
default_api_key = "gitarsenal-default-key"
|
|
96
|
-
config["api_key"] = default_api_key
|
|
97
|
-
client.save_config(config)
|
|
98
|
-
client.api_key = default_api_key
|
|
99
|
-
|
|
100
|
-
print("✅ Set default API key for local proxy")
|
|
101
|
-
|
|
102
|
-
# Verify connection to proxy
|
|
103
|
-
print(f"🔍 Testing connection to proxy at {client.base_url}...")
|
|
104
|
-
health = client.health_check()
|
|
105
|
-
if not health["success"]:
|
|
106
|
-
print(f"⚠️ Could not connect to Modal proxy at {client.base_url}")
|
|
107
|
-
print(f" Error: {health.get('error', 'Unknown error')}")
|
|
108
|
-
print(" Make sure the proxy server is running with:")
|
|
109
|
-
print(" python modal_proxy_service.py")
|
|
110
|
-
return False
|
|
111
|
-
|
|
112
|
-
print(f"✅ Connected to Modal proxy at {client.base_url}")
|
|
113
|
-
return True
|
|
114
|
-
|
|
115
|
-
except ImportError:
|
|
116
|
-
print("⚠️ GitArsenalProxyClient module not found")
|
|
117
|
-
return False
|
|
118
|
-
except Exception as e:
|
|
119
|
-
print(f"⚠️ Error checking proxy configuration: {e}")
|
|
120
|
-
return False
|
|
121
|
-
|
|
122
|
-
def _check_authentication(auth_manager):
|
|
123
|
-
"""Check if user is authenticated, prompt for login if not"""
|
|
124
|
-
if auth_manager.is_authenticated():
|
|
125
|
-
user = auth_manager.get_current_user()
|
|
126
|
-
print(f"✅ Authenticated as: {user['username']}")
|
|
127
|
-
return True
|
|
128
|
-
|
|
129
|
-
print("\n🔐 Authentication required")
|
|
130
|
-
return auth_manager.interactive_auth_flow()
|
|
131
|
-
|
|
132
|
-
def _handle_auth_commands(auth_manager, args):
|
|
133
|
-
"""Handle authentication-related commands"""
|
|
134
|
-
import getpass
|
|
135
|
-
|
|
136
|
-
if args.login:
|
|
137
|
-
print("\n🔐 LOGIN")
|
|
138
|
-
username = input("Username: ").strip()
|
|
139
|
-
password = getpass.getpass("Password: ").strip()
|
|
140
|
-
if auth_manager.login_user(username, password):
|
|
141
|
-
print("✅ Login successful!")
|
|
142
|
-
else:
|
|
143
|
-
print("❌ Login failed.")
|
|
144
|
-
|
|
145
|
-
elif args.register:
|
|
146
|
-
print("\n🔐 REGISTRATION")
|
|
147
|
-
username = input("Username (min 3 characters): ").strip()
|
|
148
|
-
email = input("Email: ").strip()
|
|
149
|
-
password = getpass.getpass("Password (min 8 characters): ").strip()
|
|
150
|
-
confirm_password = getpass.getpass("Confirm password: ").strip()
|
|
151
|
-
|
|
152
|
-
if password != confirm_password:
|
|
153
|
-
print("❌ Passwords do not match.")
|
|
154
|
-
return
|
|
155
|
-
|
|
156
|
-
if auth_manager.register_user(username, email, password):
|
|
157
|
-
print("✅ Registration successful!")
|
|
158
|
-
# Auto-login after registration
|
|
159
|
-
if auth_manager.login_user(username, password):
|
|
160
|
-
print("✅ Auto-login successful!")
|
|
161
|
-
else:
|
|
162
|
-
print("❌ Registration failed.")
|
|
163
|
-
|
|
164
|
-
elif args.logout:
|
|
165
|
-
auth_manager.logout_user()
|
|
166
|
-
|
|
167
|
-
elif args.user_info:
|
|
168
|
-
auth_manager.show_user_info()
|
|
169
|
-
|
|
170
|
-
elif args.change_password:
|
|
171
|
-
if not auth_manager.is_authenticated():
|
|
172
|
-
print("❌ Not logged in. Please login first.")
|
|
173
|
-
return
|
|
174
|
-
|
|
175
|
-
current_password = getpass.getpass("Current password: ").strip()
|
|
176
|
-
new_password = getpass.getpass("New password (min 8 characters): ").strip()
|
|
177
|
-
confirm_password = getpass.getpass("Confirm new password: ").strip()
|
|
178
|
-
|
|
179
|
-
if new_password != confirm_password:
|
|
180
|
-
print("❌ New passwords do not match.")
|
|
181
|
-
return
|
|
182
|
-
|
|
183
|
-
if auth_manager.change_password(current_password, new_password):
|
|
184
|
-
print("✅ Password changed successfully!")
|
|
185
|
-
else:
|
|
186
|
-
print("❌ Failed to change password.")
|
|
187
|
-
|
|
188
|
-
elif args.delete_account:
|
|
189
|
-
if not auth_manager.is_authenticated():
|
|
190
|
-
print("❌ Not logged in. Please login first.")
|
|
191
|
-
return
|
|
192
|
-
|
|
193
|
-
password = getpass.getpass("Enter your password to confirm deletion: ").strip()
|
|
194
|
-
if auth_manager.delete_account(password):
|
|
195
|
-
print("✅ Account deleted successfully!")
|
|
196
|
-
else:
|
|
197
|
-
print("❌ Failed to delete account.")
|
|
198
|
-
|
|
199
|
-
elif args.store_api_key:
|
|
200
|
-
if not auth_manager.is_authenticated():
|
|
201
|
-
print("❌ Not logged in. Please login first.")
|
|
202
|
-
return
|
|
203
|
-
|
|
204
|
-
service = args.store_api_key
|
|
205
|
-
api_key = getpass.getpass(f"Enter {service} API key: ").strip()
|
|
206
|
-
|
|
207
|
-
if auth_manager.store_api_key(service, api_key):
|
|
208
|
-
print(f"✅ {service} API key stored successfully!")
|
|
209
|
-
else:
|
|
210
|
-
print(f"❌ Failed to store {service} API key.")
|
|
211
|
-
|
|
212
|
-
elif args.auth:
|
|
213
|
-
# Interactive authentication management
|
|
214
|
-
while True:
|
|
215
|
-
print("\n" + "="*60)
|
|
216
|
-
print("🔐 AUTHENTICATION MANAGEMENT")
|
|
217
|
-
print("="*60)
|
|
218
|
-
print("1. Login")
|
|
219
|
-
print("2. Register")
|
|
220
|
-
print("3. Show user info")
|
|
221
|
-
print("4. Change password")
|
|
222
|
-
print("5. Store API key")
|
|
223
|
-
print("6. Delete account")
|
|
224
|
-
print("7. Logout")
|
|
225
|
-
print("8. Exit")
|
|
226
|
-
|
|
227
|
-
choice = input("\nSelect an option (1-8): ").strip()
|
|
228
|
-
|
|
229
|
-
if choice == "1":
|
|
230
|
-
username = input("Username: ").strip()
|
|
231
|
-
password = getpass.getpass("Password: ").strip()
|
|
232
|
-
auth_manager.login_user(username, password)
|
|
233
|
-
elif choice == "2":
|
|
234
|
-
username = input("Username (min 3 characters): ").strip()
|
|
235
|
-
email = input("Email: ").strip()
|
|
236
|
-
password = getpass.getpass("Password (min 8 characters): ").strip()
|
|
237
|
-
confirm_password = getpass.getpass("Confirm password: ").strip()
|
|
238
|
-
if password == confirm_password:
|
|
239
|
-
auth_manager.register_user(username, email, password)
|
|
240
|
-
else:
|
|
241
|
-
print("❌ Passwords do not match.")
|
|
242
|
-
elif choice == "3":
|
|
243
|
-
auth_manager.show_user_info()
|
|
244
|
-
elif choice == "4":
|
|
245
|
-
if auth_manager.is_authenticated():
|
|
246
|
-
current_password = getpass.getpass("Current password: ").strip()
|
|
247
|
-
new_password = getpass.getpass("New password (min 8 characters): ").strip()
|
|
248
|
-
confirm_password = getpass.getpass("Confirm new password: ").strip()
|
|
249
|
-
if new_password == confirm_password:
|
|
250
|
-
auth_manager.change_password(current_password, new_password)
|
|
251
|
-
else:
|
|
252
|
-
print("❌ New passwords do not match.")
|
|
253
|
-
else:
|
|
254
|
-
print("❌ Not logged in.")
|
|
255
|
-
elif choice == "5":
|
|
256
|
-
if auth_manager.is_authenticated():
|
|
257
|
-
service = input("Service name (e.g., openai, modal): ").strip()
|
|
258
|
-
api_key = getpass.getpass(f"Enter {service} API key: ").strip()
|
|
259
|
-
auth_manager.store_api_key(service, api_key)
|
|
260
|
-
else:
|
|
261
|
-
print("❌ Not logged in.")
|
|
262
|
-
elif choice == "6":
|
|
263
|
-
if auth_manager.is_authenticated():
|
|
264
|
-
password = getpass.getpass("Enter your password to confirm deletion: ").strip()
|
|
265
|
-
auth_manager.delete_account(password)
|
|
266
|
-
else:
|
|
267
|
-
print("❌ Not logged in.")
|
|
268
|
-
elif choice == "7":
|
|
269
|
-
auth_manager.logout_user()
|
|
270
|
-
elif choice == "8":
|
|
271
|
-
print("👋 Goodbye!")
|
|
272
|
-
break
|
|
273
|
-
else:
|
|
274
|
-
print("❌ Invalid option. Please try again.")
|
|
275
|
-
|
|
276
|
-
def main():
|
|
277
|
-
"""Main entry point for the GitArsenal CLI"""
|
|
278
|
-
parser = argparse.ArgumentParser(description="GitArsenal CLI - Tools for AI development")
|
|
279
|
-
subparsers = parser.add_subparsers(dest="command", help="Command to run")
|
|
280
|
-
|
|
281
|
-
# Authentication arguments (global)
|
|
282
|
-
parser.add_argument('--skip-auth', action='store_true', help='Skip authentication check (for development)')
|
|
283
|
-
parser.add_argument('--login', action='store_true', help='Login to GitArsenal')
|
|
284
|
-
parser.add_argument('--register', action='store_true', help='Register new account')
|
|
285
|
-
parser.add_argument('--logout', action='store_true', help='Logout from GitArsenal')
|
|
286
|
-
parser.add_argument('--user-info', action='store_true', help='Show current user information')
|
|
287
|
-
parser.add_argument('--change-password', action='store_true', help='Change password')
|
|
288
|
-
parser.add_argument('--delete-account', action='store_true', help='Delete account')
|
|
289
|
-
parser.add_argument('--store-api-key', type=str, help='Store API key for a service (e.g., openai, modal)')
|
|
290
|
-
parser.add_argument('--auth', action='store_true', help='Manage authentication (login, register, logout)')
|
|
291
|
-
|
|
292
|
-
# SSH command
|
|
293
|
-
ssh_parser = subparsers.add_parser("ssh", help="Create a Modal SSH container")
|
|
294
|
-
ssh_parser.add_argument("--gpu", type=str, default="A10G", help="GPU type (default: A10G)")
|
|
295
|
-
ssh_parser.add_argument("--repo-url", type=str, help="Repository URL to clone")
|
|
296
|
-
ssh_parser.add_argument("--repo-name", type=str, help="Repository name override")
|
|
297
|
-
ssh_parser.add_argument("--volume-name", type=str, help="Volume name for persistent storage")
|
|
298
|
-
ssh_parser.add_argument("--timeout", type=int, default=60, help="Container timeout in minutes (default: 60)")
|
|
299
|
-
ssh_parser.add_argument("--use-proxy", action="store_true", help="Use Modal proxy service instead of direct Modal API")
|
|
300
|
-
ssh_parser.add_argument("--wait", action="store_true", help="Wait for container to be ready")
|
|
301
|
-
ssh_parser.add_argument("--interactive", action="store_true", help="Run in interactive mode with prompts")
|
|
302
|
-
|
|
303
|
-
# Sandbox command
|
|
304
|
-
sandbox_parser = subparsers.add_parser("sandbox", help="Create a Modal sandbox")
|
|
305
|
-
sandbox_parser.add_argument("--gpu", type=str, default="A10G", help="GPU type (default: A10G)")
|
|
306
|
-
sandbox_parser.add_argument("--repo-url", type=str, help="Repository URL to clone")
|
|
307
|
-
sandbox_parser.add_argument("--repo-name", type=str, help="Repository name override")
|
|
308
|
-
sandbox_parser.add_argument("--volume-name", type=str, help="Volume name for persistent storage")
|
|
309
|
-
sandbox_parser.add_argument("--use-proxy", action="store_true", help="Use Modal proxy service instead of direct Modal API")
|
|
310
|
-
sandbox_parser.add_argument("--wait", action="store_true", help="Wait for container to be ready")
|
|
311
|
-
|
|
312
|
-
# Proxy commands
|
|
313
|
-
proxy_parser = subparsers.add_parser("proxy", help="Modal proxy service commands")
|
|
314
|
-
proxy_subparsers = proxy_parser.add_subparsers(dest="proxy_command", help="Proxy command to run")
|
|
315
|
-
|
|
316
|
-
# Proxy configure command
|
|
317
|
-
proxy_configure_parser = proxy_subparsers.add_parser("configure", help="Configure proxy settings")
|
|
318
|
-
|
|
319
|
-
# Proxy status command
|
|
320
|
-
proxy_status_parser = proxy_subparsers.add_parser("status", help="Check proxy status")
|
|
321
|
-
|
|
322
|
-
# Proxy SSH command
|
|
323
|
-
proxy_ssh_parser = proxy_subparsers.add_parser("ssh", help="Create SSH container through proxy")
|
|
324
|
-
proxy_ssh_parser.add_argument("--gpu", type=str, default="A10G", help="GPU type (default: A10G)")
|
|
325
|
-
proxy_ssh_parser.add_argument("--repo-url", type=str, help="Repository URL to clone")
|
|
326
|
-
proxy_ssh_parser.add_argument("--repo-name", type=str, help="Repository name override")
|
|
327
|
-
proxy_ssh_parser.add_argument("--volume-name", type=str, help="Volume name for persistent storage")
|
|
328
|
-
proxy_ssh_parser.add_argument("--timeout", type=int, default=60, help="Container timeout in minutes (default: 60)")
|
|
329
|
-
proxy_ssh_parser.add_argument("--wait", action="store_true", help="Wait for container to be ready")
|
|
330
|
-
|
|
331
|
-
# Parse arguments
|
|
332
|
-
args = parser.parse_args()
|
|
333
|
-
|
|
334
|
-
# Handle authentication commands first
|
|
335
|
-
if AuthManager and (args.login or args.register or args.logout or args.user_info or
|
|
336
|
-
args.change_password or args.delete_account or args.store_api_key or args.auth):
|
|
337
|
-
auth_manager = AuthManager()
|
|
338
|
-
_handle_auth_commands(auth_manager, args)
|
|
339
|
-
return
|
|
340
|
-
|
|
341
|
-
# Check authentication for main commands (unless skipped)
|
|
342
|
-
if AuthManager and not args.skip_auth and args.command:
|
|
343
|
-
auth_manager = AuthManager()
|
|
344
|
-
if not _check_authentication(auth_manager):
|
|
345
|
-
print("\n❌ Authentication required. Please login or register first.")
|
|
346
|
-
print("Use --login to login or --register to create an account.")
|
|
347
|
-
print("Use --skip-auth to bypass authentication for development.")
|
|
348
|
-
return
|
|
349
|
-
|
|
350
|
-
if args.command == "ssh":
|
|
351
|
-
if args.use_proxy:
|
|
352
|
-
# Use proxy service for SSH container
|
|
353
|
-
print("🚀 Creating SSH container through proxy...")
|
|
354
|
-
if check_proxy_config():
|
|
355
|
-
from gitarsenal_proxy_client import GitArsenalProxyClient
|
|
356
|
-
client = GitArsenalProxyClient()
|
|
357
|
-
result = client.create_ssh_container(
|
|
358
|
-
gpu_type=args.gpu,
|
|
359
|
-
repo_url=args.repo_url,
|
|
360
|
-
repo_name=args.repo_name,
|
|
361
|
-
volume_name=args.volume_name,
|
|
362
|
-
timeout=args.timeout,
|
|
363
|
-
wait=args.wait
|
|
364
|
-
)
|
|
365
|
-
if result:
|
|
366
|
-
print("✅ SSH container created successfully through proxy service")
|
|
367
|
-
print(f"📋 Container ID: {result.get('container_id')}")
|
|
368
|
-
print(f"🔐 SSH Password: {result.get('ssh_password')}")
|
|
369
|
-
if not args.wait:
|
|
370
|
-
print("\n⚠️ Container creation is asynchronous. Use --wait flag to wait for it to be ready.")
|
|
371
|
-
print(" You can check the status later using the container ID above.")
|
|
372
|
-
else:
|
|
373
|
-
print("❌ Failed to create SSH container through proxy service")
|
|
374
|
-
else:
|
|
375
|
-
print("❌ Proxy configuration failed or was cancelled.")
|
|
376
|
-
else:
|
|
377
|
-
# Use direct Modal API for SSH container
|
|
378
|
-
print("🚀 Creating SSH container...")
|
|
379
|
-
if check_modal_auth():
|
|
380
|
-
# Import the SSH container creation function
|
|
381
|
-
from test_modalSandboxScript import create_modal_ssh_container
|
|
382
|
-
result = create_modal_ssh_container(
|
|
383
|
-
args.gpu,
|
|
384
|
-
repo_url=args.repo_url,
|
|
385
|
-
repo_name=args.repo_name,
|
|
386
|
-
volume_name=args.volume_name,
|
|
387
|
-
timeout_minutes=args.timeout,
|
|
388
|
-
interactive=args.interactive
|
|
389
|
-
)
|
|
390
|
-
if result:
|
|
391
|
-
print("✅ SSH container created successfully")
|
|
392
|
-
else:
|
|
393
|
-
print("❌ Failed to create SSH container")
|
|
394
|
-
else:
|
|
395
|
-
print("❌ Modal authentication failed or was cancelled.")
|
|
396
|
-
|
|
397
|
-
elif args.command == "sandbox":
|
|
398
|
-
if args.use_proxy:
|
|
399
|
-
# Use proxy service for sandbox
|
|
400
|
-
print("🚀 Creating sandbox through proxy...")
|
|
401
|
-
if check_proxy_config():
|
|
402
|
-
from gitarsenal_proxy_client import GitArsenalProxyClient
|
|
403
|
-
client = GitArsenalProxyClient()
|
|
404
|
-
result = client.create_sandbox(
|
|
405
|
-
gpu_type=args.gpu,
|
|
406
|
-
repo_url=args.repo_url,
|
|
407
|
-
repo_name=args.repo_name,
|
|
408
|
-
volume_name=args.volume_name,
|
|
409
|
-
wait=args.wait
|
|
410
|
-
)
|
|
411
|
-
if result:
|
|
412
|
-
print("✅ Sandbox created successfully through proxy service")
|
|
413
|
-
else:
|
|
414
|
-
print("❌ Failed to create sandbox through proxy service")
|
|
415
|
-
else:
|
|
416
|
-
print("❌ Proxy configuration failed or was cancelled.")
|
|
417
|
-
else:
|
|
418
|
-
# Use direct Modal API for sandbox
|
|
419
|
-
print("🚀 Creating sandbox...")
|
|
420
|
-
if check_modal_auth():
|
|
421
|
-
# Import the sandbox creation function
|
|
422
|
-
from test_modalSandboxScript import create_modal_sandbox
|
|
423
|
-
result = create_modal_sandbox(
|
|
424
|
-
args.gpu,
|
|
425
|
-
repo_url=args.repo_url,
|
|
426
|
-
repo_name=args.repo_name,
|
|
427
|
-
volume_name=args.volume_name
|
|
428
|
-
)
|
|
429
|
-
if result:
|
|
430
|
-
print("✅ Sandbox created successfully")
|
|
431
|
-
else:
|
|
432
|
-
print("❌ Failed to create sandbox")
|
|
433
|
-
else:
|
|
434
|
-
print("❌ Modal authentication failed or was cancelled.")
|
|
435
|
-
|
|
436
|
-
elif args.command == "proxy":
|
|
437
|
-
if args.proxy_command == "configure":
|
|
438
|
-
# Configure proxy settings
|
|
439
|
-
from gitarsenal_proxy_client import GitArsenalProxyClient
|
|
440
|
-
client = GitArsenalProxyClient()
|
|
441
|
-
client.configure(interactive=True)
|
|
442
|
-
|
|
443
|
-
elif args.proxy_command == "status":
|
|
444
|
-
# Check proxy status
|
|
445
|
-
from gitarsenal_proxy_client import GitArsenalProxyClient
|
|
446
|
-
client = GitArsenalProxyClient()
|
|
447
|
-
response = client.health_check()
|
|
448
|
-
if response["success"]:
|
|
449
|
-
print(f"✅ Proxy service is running: {response['data']['message']}")
|
|
450
|
-
else:
|
|
451
|
-
print(f"❌ Proxy service health check failed: {response['error']}")
|
|
452
|
-
|
|
453
|
-
elif args.proxy_command == "ssh":
|
|
454
|
-
# Create SSH container through proxy
|
|
455
|
-
print("🚀 Creating SSH container through proxy...")
|
|
456
|
-
if check_proxy_config():
|
|
457
|
-
from gitarsenal_proxy_client import GitArsenalProxyClient
|
|
458
|
-
client = GitArsenalProxyClient()
|
|
459
|
-
result = client.create_ssh_container(
|
|
460
|
-
gpu_type=args.gpu,
|
|
461
|
-
repo_url=args.repo_url,
|
|
462
|
-
repo_name=args.repo_name,
|
|
463
|
-
volume_name=args.volume_name,
|
|
464
|
-
timeout=args.timeout,
|
|
465
|
-
wait=args.wait
|
|
466
|
-
)
|
|
467
|
-
if result:
|
|
468
|
-
print("✅ SSH container created successfully through proxy service")
|
|
469
|
-
print(f"📋 Container ID: {result.get('container_id')}")
|
|
470
|
-
print(f"🔐 SSH Password: {result.get('ssh_password')}")
|
|
471
|
-
if not args.wait:
|
|
472
|
-
print("\n⚠️ Container creation is asynchronous. Use --wait flag to wait for it to be ready.")
|
|
473
|
-
print(" You can check the status later using the container ID above.")
|
|
474
|
-
else:
|
|
475
|
-
print("❌ Failed to create SSH container through proxy service")
|
|
476
|
-
else:
|
|
477
|
-
print("❌ Proxy configuration failed or was cancelled.")
|
|
478
|
-
|
|
479
|
-
else:
|
|
480
|
-
print("❌ Unknown proxy command. Available commands: configure, status, ssh")
|
|
481
|
-
|
|
482
|
-
else:
|
|
483
|
-
parser.print_help()
|
|
484
|
-
|
|
485
|
-
return 0
|
|
486
|
-
|
|
487
|
-
if __name__ == "__main__":
|
|
488
|
-
sys.exit(main())
|