gitarsenal-cli 1.4.7 → 1.4.9

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.4.7",
3
+ "version": "1.4.9",
4
4
  "description": "CLI tool for creating Modal sandboxes with GitHub repositories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -944,8 +944,8 @@ def create_modal_sandbox(gpu_type, repo_url=None, repo_name=None, setup_commands
944
944
  'T4': {'gpu': 'T4', 'memory': 16},
945
945
  'L4': {'gpu': 'L4', 'memory': 24},
946
946
  'A10G': {'gpu': 'A10G', 'memory': 24},
947
- 'A100-40GB': {'gpu': 'A100-SXM4-40GB', 'memory': 40},
948
- 'A100-80GB': {'gpu': 'A100-80GB', 'memory': 80},
947
+ 'A100-40': {'gpu': 'A100-SXM4-40GB', 'memory': 40},
948
+ 'A100-80': {'gpu': 'A100-80', 'memory': 80},
949
949
  'L40S': {'gpu': 'L40S', 'memory': 48},
950
950
  'H100': {'gpu': 'H100', 'memory': 80},
951
951
  'H200': {'gpu': 'H200', 'memory': 141},
@@ -4096,63 +4096,123 @@ def get_setup_commands_from_gitingest(repo_url):
4096
4096
 
4097
4097
  def prompt_for_gpu():
4098
4098
  """
4099
- Prompt the user to select a GPU type from available options.
4099
+ Prompt the user to select a GPU type from available options using arrow keys.
4100
4100
  Returns the selected GPU type.
4101
4101
  """
4102
+ import sys
4103
+ import tty
4104
+ import termios
4105
+
4102
4106
  # Define available GPU types and their specifications
4103
4107
  gpu_specs = {
4104
4108
  'T4': {'gpu': 'T4', 'memory': '16GB'},
4105
4109
  'L4': {'gpu': 'L4', 'memory': '24GB'},
4106
4110
  'A10G': {'gpu': 'A10G', 'memory': '24GB'},
4107
- 'A100-40GB': {'gpu': 'A100-SXM4-40GB', 'memory': '40GB'},
4108
- 'A100-80GB': {'gpu': 'A100-80GB', 'memory': '80GB'},
4111
+ 'A100-40': {'gpu': 'A100-40GB', 'memory': '40GB'},
4112
+ 'A100-80': {'gpu': 'A100-80GB', 'memory': '80GB'},
4109
4113
  'L40S': {'gpu': 'L40S', 'memory': '48GB'},
4110
4114
  'H100': {'gpu': 'H100', 'memory': '80GB'},
4111
4115
  'H200': {'gpu': 'H200', 'memory': '141GB'},
4112
4116
  'B200': {'gpu': 'B200', 'memory': '141GB'}
4113
4117
  }
4114
4118
 
4115
- print("\nšŸ“Š Available GPU Options:")
4116
- print("ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”")
4117
- print("│ GPU Type │ Memory │")
4118
- print("ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤")
4119
-
4120
- # Create a list to keep track of valid options
4121
- options = []
4119
+ # Create a list of options
4120
+ options = list(gpu_specs.keys())
4121
+ selected_index = 2 # Default to A10G (index 2)
4122
4122
 
4123
- # Display GPU options
4124
- for i, (gpu_type, specs) in enumerate(gpu_specs.items(), 1):
4125
- options.append(gpu_type)
4126
- print(f"│ {i}. {gpu_type:<8} │ {specs['memory']:<7} │")
4123
+ def get_key():
4124
+ """Get a single keypress from the user."""
4125
+ fd = sys.stdin.fileno()
4126
+ old_settings = termios.tcgetattr(fd)
4127
+ try:
4128
+ tty.setraw(sys.stdin.fileno())
4129
+ ch = sys.stdin.read(1)
4130
+ if ch == '\x1b': # Escape sequence
4131
+ ch2 = sys.stdin.read(1)
4132
+ if ch2 == '[':
4133
+ ch3 = sys.stdin.read(1)
4134
+ if ch3 == 'A':
4135
+ return 'UP'
4136
+ elif ch3 == 'B':
4137
+ return 'DOWN'
4138
+ elif ch == '\r' or ch == '\n':
4139
+ return 'ENTER'
4140
+ elif ch == '\x03': # Ctrl+C
4141
+ return 'CTRL_C'
4142
+ return ch
4143
+ finally:
4144
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
4145
+
4146
+ def display_menu():
4147
+ """Display the GPU selection menu with current selection highlighted."""
4148
+ print("\nšŸ“Š Available GPU Options:")
4149
+ print("ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”")
4150
+ print("│ GPU Type │ Memory │")
4151
+ print("ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤")
4152
+
4153
+ for i, gpu_type in enumerate(options):
4154
+ specs = gpu_specs[gpu_type]
4155
+ # Calculate proper spacing for alignment
4156
+ number_part = f"{i+1}."
4157
+ if i == selected_index:
4158
+ prefix = "> "
4159
+ suffix = " ←"
4160
+ else:
4161
+ prefix = " "
4162
+ suffix = ""
4163
+
4164
+ # Ensure consistent width for GPU type column
4165
+ gpu_display = f"{prefix}{number_part} {gpu_type}"
4166
+ gpu_padded = f"{gpu_display:<12}" # Fixed width for GPU column
4167
+
4168
+ print(f"│ {gpu_padded} │ {specs['memory']:<7} │{suffix}")
4169
+
4170
+ print("ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜")
4171
+ print("Use ↑/↓ arrows to select, Enter to confirm, Ctrl+C to cancel")
4127
4172
 
4128
- print("ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜")
4173
+ # Clear screen and show initial menu
4174
+ print("\033[2J\033[H", end="") # Clear screen and move cursor to top
4175
+ display_menu()
4129
4176
 
4130
- # Prompt for selection
4131
4177
  while True:
4132
4178
  try:
4133
- choice = input("\nšŸ” Select GPU type (number or name, default is A10G): ").strip()
4134
-
4135
- # Default to A10G if empty
4136
- if not choice:
4137
- return "A10G"
4179
+ key = get_key()
4138
4180
 
4139
- # Check if input is a number
4140
- if choice.isdigit():
4141
- index = int(choice) - 1
4142
- if 0 <= index < len(options):
4143
- return options[index]
4144
- else:
4145
- print(f"āŒ Invalid selection. Please enter a number between 1 and {len(options)}.")
4146
- # Check if input is a valid GPU type
4147
- elif choice in options:
4148
- return choice
4149
- else:
4150
- print(f"āŒ Invalid GPU type. Please select from the available options.")
4181
+ if key == 'UP':
4182
+ selected_index = (selected_index - 1) % len(options)
4183
+ print("\033[2J\033[H", end="") # Clear screen
4184
+ display_menu()
4185
+ elif key == 'DOWN':
4186
+ selected_index = (selected_index + 1) % len(options)
4187
+ print("\033[2J\033[H", end="") # Clear screen
4188
+ display_menu()
4189
+ elif key == 'ENTER':
4190
+ selected_gpu = options[selected_index]
4191
+ print(f"\nāœ… Selected GPU: {selected_gpu}")
4192
+ return selected_gpu
4193
+ elif key == 'CTRL_C':
4194
+ print("\nšŸ›‘ Selection cancelled.")
4195
+ sys.exit(1)
4196
+
4151
4197
  except KeyboardInterrupt:
4152
4198
  print("\nšŸ›‘ Selection cancelled.")
4153
4199
  sys.exit(1)
4154
4200
  except Exception as e:
4155
- print(f"āŒ Error: {e}")
4201
+ print(f"\nāŒ Error: {e}")
4202
+ # Fall back to simple input method
4203
+ try:
4204
+ choice = input("\nšŸ” Select GPU type (number or name, default is A10G): ").strip()
4205
+ if not choice:
4206
+ return "A10G"
4207
+ if choice.isdigit():
4208
+ index = int(choice) - 1
4209
+ if 0 <= index < len(options):
4210
+ return options[index]
4211
+ elif choice in options:
4212
+ return choice
4213
+ return "A10G"
4214
+ except:
4215
+ return "A10G"
4156
4216
 
4157
4217
  # Replace the existing GPU argument parsing in the main section
4158
4218
  if __name__ == "__main__":
@@ -4227,6 +4287,18 @@ if __name__ == "__main__":
4227
4287
  gpu_type = prompt_for_gpu()
4228
4288
  args.gpu = gpu_type
4229
4289
 
4290
+ # Display configuration after GPU selection
4291
+ print("\nšŸ“‹ Container Configuration:")
4292
+ print(f"Repository URL: {args.repo_url or 'Not specified'}")
4293
+ print(f"GPU Type: {gpu_type}")
4294
+ print(f"Volume: {args.volume_name or 'None'}")
4295
+ if args.use_api:
4296
+ print("Setup Commands: Auto-detect from repository")
4297
+ elif args.setup_commands:
4298
+ print(f"Setup Commands: {len(args.setup_commands)} custom commands")
4299
+ else:
4300
+ print("Setup Commands: Auto-detect from repository")
4301
+
4230
4302
  # Interactive mode or missing required arguments
4231
4303
  if args.interactive or not args.repo_url or not args.volume_name:
4232
4304
  # Get repository URL if not provided