gitarsenal-cli 1.9.65 → 1.9.66

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.
Files changed (72) hide show
  1. package/.venv_status.json +1 -1
  2. package/bin/gitarsenal.js +24 -0
  3. package/kill_claude/.claude/settings.local.json +9 -0
  4. package/kill_claude/README.md +265 -0
  5. package/kill_claude/__pycache__/bash_output_tool.cpython-313.pyc +0 -0
  6. package/kill_claude/__pycache__/bash_tool.cpython-313.pyc +0 -0
  7. package/kill_claude/__pycache__/claude_code_agent.cpython-313.pyc +0 -0
  8. package/kill_claude/__pycache__/edit_tool.cpython-313.pyc +0 -0
  9. package/kill_claude/__pycache__/exit_plan_mode_tool.cpython-313.pyc +0 -0
  10. package/kill_claude/__pycache__/glob_tool.cpython-313.pyc +0 -0
  11. package/kill_claude/__pycache__/grep_tool.cpython-313.pyc +0 -0
  12. package/kill_claude/__pycache__/kill_bash_tool.cpython-313.pyc +0 -0
  13. package/kill_claude/__pycache__/ls_tool.cpython-313.pyc +0 -0
  14. package/kill_claude/__pycache__/multiedit_tool.cpython-313.pyc +0 -0
  15. package/kill_claude/__pycache__/notebook_edit_tool.cpython-313.pyc +0 -0
  16. package/kill_claude/__pycache__/read_tool.cpython-313.pyc +0 -0
  17. package/kill_claude/__pycache__/task_tool.cpython-313.pyc +0 -0
  18. package/kill_claude/__pycache__/todo_write_tool.cpython-313.pyc +0 -0
  19. package/kill_claude/__pycache__/web_fetch_tool.cpython-313.pyc +0 -0
  20. package/kill_claude/__pycache__/web_search_tool.cpython-313.pyc +0 -0
  21. package/kill_claude/__pycache__/write_tool.cpython-313.pyc +0 -0
  22. package/kill_claude/claude_code_agent.py +848 -0
  23. package/kill_claude/prompts/claude-code-agent-prompts.md +65 -0
  24. package/kill_claude/prompts/claude-code-environment-context.md +100 -0
  25. package/kill_claude/prompts/claude-code-git-workflows.md +151 -0
  26. package/kill_claude/prompts/claude-code-hook-system.md +94 -0
  27. package/kill_claude/prompts/claude-code-response-formatting.md +79 -0
  28. package/kill_claude/prompts/claude-code-security-constraints.md +87 -0
  29. package/kill_claude/prompts/claude-code-system-prompt.md +136 -0
  30. package/kill_claude/prompts/claude-code-system-reminders.md +50 -0
  31. package/kill_claude/prompts/claude-code-task-workflows.md +114 -0
  32. package/kill_claude/prompts/claude-code-thinking-mode-prompts.md +39 -0
  33. package/kill_claude/prompts/claude-code-tool-prompts.md +339 -0
  34. package/kill_claude/prompts/claude-code-tool-usage-policies.md +87 -0
  35. package/kill_claude/requirements.txt +1 -0
  36. package/kill_claude/tools/__init__.py +1 -0
  37. package/kill_claude/tools/__pycache__/bash_output_tool.cpython-313.pyc +0 -0
  38. package/kill_claude/tools/__pycache__/bash_tool.cpython-313.pyc +0 -0
  39. package/kill_claude/tools/__pycache__/edit_tool.cpython-313.pyc +0 -0
  40. package/kill_claude/tools/__pycache__/exit_plan_mode_tool.cpython-313.pyc +0 -0
  41. package/kill_claude/tools/__pycache__/glob_tool.cpython-313.pyc +0 -0
  42. package/kill_claude/tools/__pycache__/grep_tool.cpython-313.pyc +0 -0
  43. package/kill_claude/tools/__pycache__/kill_bash_tool.cpython-313.pyc +0 -0
  44. package/kill_claude/tools/__pycache__/ls_tool.cpython-313.pyc +0 -0
  45. package/kill_claude/tools/__pycache__/multiedit_tool.cpython-313.pyc +0 -0
  46. package/kill_claude/tools/__pycache__/notebook_edit_tool.cpython-313.pyc +0 -0
  47. package/kill_claude/tools/__pycache__/read_tool.cpython-313.pyc +0 -0
  48. package/kill_claude/tools/__pycache__/task_tool.cpython-313.pyc +0 -0
  49. package/kill_claude/tools/__pycache__/todo_write_tool.cpython-313.pyc +0 -0
  50. package/kill_claude/tools/__pycache__/web_fetch_tool.cpython-313.pyc +0 -0
  51. package/kill_claude/tools/__pycache__/web_search_tool.cpython-313.pyc +0 -0
  52. package/kill_claude/tools/__pycache__/write_tool.cpython-313.pyc +0 -0
  53. package/kill_claude/tools/bash_output_tool.py +47 -0
  54. package/kill_claude/tools/bash_tool.py +79 -0
  55. package/kill_claude/tools/edit_tool.py +60 -0
  56. package/kill_claude/tools/exit_plan_mode_tool.py +42 -0
  57. package/kill_claude/tools/glob_tool.py +46 -0
  58. package/kill_claude/tools/grep_tool.py +105 -0
  59. package/kill_claude/tools/kill_bash_tool.py +38 -0
  60. package/kill_claude/tools/ls_tool.py +44 -0
  61. package/kill_claude/tools/multiedit_tool.py +111 -0
  62. package/kill_claude/tools/notebook_edit_tool.py +64 -0
  63. package/kill_claude/tools/read_tool.py +61 -0
  64. package/kill_claude/tools/task_tool.py +67 -0
  65. package/kill_claude/tools/todo_write_tool.py +114 -0
  66. package/kill_claude/tools/web_fetch_tool.py +55 -0
  67. package/kill_claude/tools/web_search_tool.py +58 -0
  68. package/kill_claude/tools/write_tool.py +46 -0
  69. package/lib/sandbox.js +3 -0
  70. package/package.json +1 -1
  71. package/python/test_modalSandboxScript.py +128 -294
  72. package/python/gitarsenal.py +0 -488
@@ -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())