hypercli-cli 0.8.5__tar.gz → 0.8.7__tar.gz

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 (22) hide show
  1. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/PKG-INFO +4 -4
  2. hypercli_cli-0.8.7/hypercli_cli/__init__.py +1 -0
  3. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/claw.py +51 -0
  4. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/instances.py +102 -27
  5. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/jobs.py +41 -6
  6. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/renders.py +48 -3
  7. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/tui/job_monitor.py +5 -2
  8. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/wallet.py +17 -12
  9. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/pyproject.toml +4 -4
  10. hypercli_cli-0.8.5/hypercli_cli/__init__.py +0 -1
  11. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/.gitignore +0 -0
  12. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/README.md +0 -0
  13. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/billing.py +0 -0
  14. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/cli.py +0 -0
  15. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/comfyui.py +0 -0
  16. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/flow.py +0 -0
  17. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/keys.py +0 -0
  18. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/llm.py +0 -0
  19. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/onboard.py +0 -0
  20. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/output.py +0 -0
  21. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/tui/__init__.py +0 -0
  22. {hypercli_cli-0.8.5 → hypercli_cli-0.8.7}/hypercli_cli/user.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypercli-cli
3
- Version: 0.8.5
3
+ Version: 0.8.7
4
4
  Summary: CLI for HyperCLI - GPU orchestration and LLM API
5
5
  Project-URL: Homepage, https://hypercli.com
6
6
  Project-URL: Documentation, https://docs.hypercli.com
@@ -9,7 +9,7 @@ Author-email: HyperCLI <support@hypercli.com>
9
9
  License: MIT
10
10
  Requires-Python: >=3.10
11
11
  Requires-Dist: httpx>=0.27.0
12
- Requires-Dist: hypercli-sdk>=0.7.1
12
+ Requires-Dist: hypercli-sdk>=0.8.7
13
13
  Requires-Dist: mutagen>=1.47.0
14
14
  Requires-Dist: openai>=2.8.1
15
15
  Requires-Dist: pyyaml>=6.0
@@ -19,11 +19,11 @@ Requires-Dist: websocket-client>=1.6.0
19
19
  Provides-Extra: all
20
20
  Requires-Dist: argon2-cffi>=25.0.0; extra == 'all'
21
21
  Requires-Dist: eth-account>=0.13.0; extra == 'all'
22
- Requires-Dist: hypercli-sdk[comfyui]>=0.7.1; extra == 'all'
22
+ Requires-Dist: hypercli-sdk[comfyui]>=0.8.7; extra == 'all'
23
23
  Requires-Dist: web3>=7.0.0; extra == 'all'
24
24
  Requires-Dist: x402[evm,httpx]>=2.0.0; extra == 'all'
25
25
  Provides-Extra: comfyui
26
- Requires-Dist: hypercli-sdk[comfyui]>=0.7.1; extra == 'comfyui'
26
+ Requires-Dist: hypercli-sdk[comfyui]>=0.8.7; extra == 'comfyui'
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: pytest>=8.0.0; extra == 'dev'
29
29
  Requires-Dist: ruff>=0.3.0; extra == 'dev'
@@ -0,0 +1 @@
1
+ __version__ = "0.8.7"
@@ -304,6 +304,57 @@ def plans(
304
304
  console.print("Subscribe with: [bold]hyper claw subscribe <plan_id> <amount>[/bold]")
305
305
 
306
306
 
307
+ @app.command("models")
308
+ def models(
309
+ dev: bool = typer.Option(False, "--dev", help="Use dev API"),
310
+ json_output: bool = typer.Option(False, "--json", help="Print raw JSON response"),
311
+ ):
312
+ """List available HyperClaw models from the public /models endpoint."""
313
+ import httpx
314
+
315
+ api_base = DEV_API_BASE if dev else PROD_API_BASE
316
+ url = f"{api_base}/models"
317
+
318
+ try:
319
+ response = httpx.get(url, timeout=15)
320
+ response.raise_for_status()
321
+ payload = response.json()
322
+ except Exception as e:
323
+ console.print(f"[red]❌ Failed to fetch models from {url}: {e}[/red]")
324
+ raise typer.Exit(1)
325
+
326
+ models_data = payload.get("models")
327
+ if not isinstance(models_data, list):
328
+ console.print("[red]❌ Unexpected /models response shape (expected top-level models list)[/red]")
329
+ if json_output:
330
+ console.print_json(json.dumps(payload))
331
+ raise typer.Exit(1)
332
+
333
+ if json_output:
334
+ console.print_json(json.dumps(payload))
335
+ return
336
+
337
+ table = Table(title="HyperClaw Models")
338
+ table.add_column("Model ID", style="cyan")
339
+ table.add_column("Context", style="blue")
340
+ table.add_column("Vision", style="green")
341
+ table.add_column("Tools", style="green")
342
+ table.add_column("Reasoning", style="magenta")
343
+
344
+ for model in models_data:
345
+ model_id = str(model.get("id", ""))
346
+ context_length = model.get("context_length", "")
347
+ vision = "yes" if model.get("supports_vision") else "no"
348
+ tools = "yes" if model.get("supports_tools") else "no"
349
+ reasoning = "yes" if model.get("supports_reasoning") else "no"
350
+ table.add_row(model_id, str(context_length), vision, tools, reasoning)
351
+
352
+ console.print()
353
+ console.print(table)
354
+ console.print()
355
+ console.print(f"Source: {url}")
356
+
357
+
307
358
  OPENCLAW_CONFIG_PATH = Path.home() / ".openclaw" / "openclaw.json"
308
359
 
309
360
 
@@ -1,7 +1,7 @@
1
1
  """hyper instances commands"""
2
2
  import typer
3
3
  from typing import Optional
4
- from hypercli import HyperCLI
4
+ from hypercli import HyperCLI, X402Client
5
5
  from .output import output, console, success, spinner
6
6
 
7
7
  app = typer.Typer(help="GPU instances - browse and launch")
@@ -193,12 +193,20 @@ def launch(
193
193
  port: Optional[list[str]] = typer.Option(None, "--port", "-p", help="Ports (name:port)"),
194
194
  registry_user: Optional[str] = typer.Option(None, "--registry-user", help="Private registry username"),
195
195
  registry_password: Optional[str] = typer.Option(None, "--registry-password", help="Private registry password"),
196
+ x402: bool = typer.Option(False, "--x402", help="Pay per-use via embedded x402 wallet"),
197
+ amount: Optional[float] = typer.Option(None, "--amount", help="USDC amount to spend with --x402"),
196
198
  follow: bool = typer.Option(False, "--follow", "-f", help="Follow logs after creation"),
197
199
  cancel_on_exit: bool = typer.Option(False, "--cancel-on-exit", help="Cancel job when exiting with Ctrl+C"),
198
200
  fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
199
201
  ):
200
- """Launch a new GPU instance"""
201
- client = get_client()
202
+ """Launch a new GPU instance
203
+
204
+ Examples:
205
+ hyper instances launch nvidia/cuda:12.6.3-base-ubuntu22.04 -c 'nvidia-smi && sleep 60'
206
+ hyper instances launch nvidia/cuda:12.6.3-base-ubuntu22.04 -g l4 -r kr -c 'nvidia-smi' -t 120
207
+ hyper instances launch my-registry.com/my-image:latest -g h100 -n 8 -c 'python train.py'
208
+ hyper instances launch nvidia/cuda:12.6.3-base-ubuntu22.04 --x402 --amount 2.5
209
+ """
202
210
 
203
211
  # Parse env vars
204
212
  env_dict = None
@@ -223,32 +231,99 @@ def launch(
223
231
  if registry_user and registry_password:
224
232
  registry_auth = {"username": registry_user, "password": registry_password}
225
233
 
226
- with spinner("Launching instance..."):
227
- job = client.jobs.create(
228
- image=image,
229
- command=command,
230
- gpu_type=gpu,
231
- gpu_count=count,
232
- region=region,
233
- runtime=runtime,
234
- interruptible=interruptible,
235
- env=env_dict,
236
- ports=ports_dict,
237
- registry_auth=registry_auth,
238
- )
239
-
240
- if fmt == "json":
241
- output(job, "json")
234
+ # Auto-wrap command in sh -c if it contains shell operators
235
+ if command and any(op in command for op in ["&&", "||", "|", ";", ">", "<", "$"]):
236
+ command = f'sh -c "{command}"'
237
+
238
+ follow_api_key = None
239
+
240
+ if x402:
241
+ if amount is None:
242
+ raise typer.BadParameter("--amount is required when using --x402")
243
+ if amount <= 0:
244
+ raise typer.BadParameter("--amount must be greater than 0")
245
+ if runtime is not None:
246
+ console.print("[yellow]Ignoring --runtime with --x402 (runtime is computed from payment amount).[/yellow]")
247
+
248
+ from .wallet import require_wallet_deps, load_wallet
249
+
250
+ require_wallet_deps()
251
+ account = load_wallet()
252
+ x402_client = X402Client()
253
+
254
+ with spinner("Launching instance with x402..."):
255
+ x402_job = x402_client.create_job(
256
+ amount=amount,
257
+ account=account,
258
+ image=image,
259
+ command=command,
260
+ gpu_type=gpu,
261
+ gpu_count=count,
262
+ region=region,
263
+ interruptible=interruptible,
264
+ env=env_dict,
265
+ ports=ports_dict,
266
+ registry_auth=registry_auth,
267
+ )
268
+ job = x402_job.job
269
+ follow_api_key = x402_job.access_key
270
+
271
+ if fmt == "json":
272
+ output(
273
+ {
274
+ "job": job.__dict__,
275
+ "access_key": x402_job.access_key,
276
+ "status_url": x402_job.status_url,
277
+ "logs_url": x402_job.logs_url,
278
+ "cancel_url": x402_job.cancel_url,
279
+ },
280
+ "json",
281
+ )
282
+ else:
283
+ success(f"Instance launched: {job.job_id}")
284
+ console.print(f" State: {job.state}")
285
+ console.print(f" GPU: {job.gpu_type} x{job.gpu_count}")
286
+ console.print(f" Region: {job.region}")
287
+ console.print(f" Price: ${job.price_per_hour:.2f}/hr")
288
+ if job.hostname:
289
+ console.print(f" Hostname: {job.hostname}")
290
+ console.print(f" Access Key: {x402_job.access_key}")
291
+ console.print(f" Status URL: {x402_job.status_url}")
292
+ console.print(f" Logs URL: {x402_job.logs_url}")
293
+ console.print(f" Cancel URL: {x402_job.cancel_url}")
242
294
  else:
243
- success(f"Instance launched: {job.job_id}")
244
- console.print(f" State: {job.state}")
245
- console.print(f" GPU: {job.gpu_type} x{job.gpu_count}")
246
- console.print(f" Region: {job.region}")
247
- console.print(f" Price: ${job.price_per_hour:.2f}/hr")
248
- if job.hostname:
249
- console.print(f" Hostname: {job.hostname}")
295
+ client = get_client()
296
+
297
+ with spinner("Launching instance..."):
298
+ job = client.jobs.create(
299
+ image=image,
300
+ command=command,
301
+ gpu_type=gpu,
302
+ gpu_count=count,
303
+ region=region,
304
+ runtime=runtime,
305
+ interruptible=interruptible,
306
+ env=env_dict,
307
+ ports=ports_dict,
308
+ registry_auth=registry_auth,
309
+ )
310
+
311
+ if fmt == "json":
312
+ output(job, "json")
313
+ else:
314
+ success(f"Instance launched: {job.job_id}")
315
+ console.print(f" State: {job.state}")
316
+ console.print(f" GPU: {job.gpu_type} x{job.gpu_count}")
317
+ console.print(f" Region: {job.region}")
318
+ console.print(f" Price: ${job.price_per_hour:.2f}/hr")
319
+ if job.hostname:
320
+ console.print(f" Hostname: {job.hostname}")
250
321
 
251
322
  if follow:
252
323
  console.print()
253
324
  from .tui.job_monitor import run_job_monitor
254
- run_job_monitor(job.job_id, cancel_on_exit=cancel_on_exit)
325
+
326
+ if follow_api_key:
327
+ run_job_monitor(job.job_id, cancel_on_exit=cancel_on_exit, api_key=follow_api_key)
328
+ else:
329
+ run_job_monitor(job.job_id, cancel_on_exit=cancel_on_exit)
@@ -45,18 +45,28 @@ def get_job(
45
45
  @app.command("logs")
46
46
  def logs(
47
47
  job_id: str = typer.Argument(..., help="Job ID"),
48
- follow: bool = typer.Option(False, "--follow", "-f", help="Stream logs"),
49
- cancel_on_exit: bool = typer.Option(False, "--cancel-on-exit", help="Cancel job when exiting with Ctrl+C"),
48
+ follow: bool = typer.Option(False, "--follow", "-f", help="Stream logs via WebSocket"),
49
+ tail: int = typer.Option(None, "--tail", "-n", help="Show last N lines"),
50
+ tui: bool = typer.Option(False, "--tui", help="Interactive TUI with metrics"),
51
+ cancel_on_exit: bool = typer.Option(False, "--cancel-on-exit", help="Cancel job when exiting with Ctrl+C (with --tui)"),
50
52
  ):
51
53
  """Get job logs"""
52
54
  client = get_client()
53
55
 
54
- if follow:
56
+ if tui:
55
57
  _follow_job(job_id, cancel_on_exit=cancel_on_exit)
58
+ elif follow:
59
+ _stream_logs(job_id)
56
60
  else:
57
- with spinner("Fetching logs..."):
58
- logs_str = client.jobs.logs(job_id)
59
- console.print(logs_str)
61
+ logs_str = client.jobs.logs(job_id)
62
+ if not logs_str:
63
+ print("(no logs)")
64
+ return
65
+ lines = logs_str.rstrip("\n").split("\n")
66
+ if tail:
67
+ lines = lines[-tail:]
68
+ for line in lines:
69
+ print(line)
60
70
 
61
71
 
62
72
  @app.command("metrics")
@@ -168,6 +178,31 @@ def _make_bar(value: float, max_val: float, warn: float = None, crit: float = No
168
178
  return f"[{color}]{bar}[/{color}]"
169
179
 
170
180
 
181
+ def _stream_logs(job_id: str):
182
+ """Stream logs via WebSocket (like tail -f)"""
183
+ import asyncio
184
+ from hypercli import stream_logs
185
+
186
+ client = get_client()
187
+
188
+ async def _run():
189
+ try:
190
+ await stream_logs(
191
+ client,
192
+ job_id,
193
+ on_line=lambda line: print(line),
194
+ fetch_initial=True,
195
+ fetch_final=True,
196
+ )
197
+ except KeyboardInterrupt:
198
+ pass
199
+
200
+ try:
201
+ asyncio.run(_run())
202
+ except KeyboardInterrupt:
203
+ pass
204
+
205
+
171
206
  def _follow_job(job_id: str, cancel_on_exit: bool = False):
172
207
  """Follow job with TUI"""
173
208
  from .tui.job_monitor import run_job_monitor
@@ -2,7 +2,7 @@
2
2
  import time
3
3
  import typer
4
4
  from typing import Optional
5
- from hypercli import HyperCLI
5
+ from hypercli import HyperCLI, X402Client
6
6
  from .output import output, console, success, spinner
7
7
 
8
8
  app = typer.Typer(help="Manage renders")
@@ -52,12 +52,13 @@ def create_render(
52
52
  gpu: str = typer.Option("L40S", "--gpu", "-g", help="GPU type"),
53
53
  region: Optional[str] = typer.Option(None, "--region", "-r", help="Region"),
54
54
  render_type: str = typer.Option("comfyui", "--type", "-t", help="Render type"),
55
+ x402: bool = typer.Option(False, "--x402", help="Pay per-use via embedded x402 wallet"),
56
+ amount: Optional[float] = typer.Option(None, "--amount", help="USDC amount to spend with --x402"),
55
57
  wait: bool = typer.Option(False, "--wait", "-w", help="Wait for completion"),
56
58
  notify_url: Optional[str] = typer.Option(None, "--notify", help="Webhook URL for completion"),
57
59
  fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
58
60
  ):
59
61
  """Create a new render"""
60
- client = get_client()
61
62
 
62
63
  params = {
63
64
  "template": template,
@@ -67,6 +68,51 @@ def create_render(
67
68
  if region:
68
69
  params["region"] = region
69
70
 
71
+ if x402:
72
+ if amount is None:
73
+ raise typer.BadParameter("--amount is required when using --x402")
74
+ if amount <= 0:
75
+ raise typer.BadParameter("--amount must be greater than 0")
76
+
77
+ from .wallet import require_wallet_deps, load_wallet
78
+
79
+ require_wallet_deps()
80
+ account = load_wallet()
81
+ x402_client = X402Client()
82
+
83
+ with spinner("Creating render with x402..."):
84
+ x402_render = x402_client.create_render(
85
+ amount=amount,
86
+ account=account,
87
+ params=params,
88
+ render_type=render_type,
89
+ notify_url=notify_url,
90
+ )
91
+ render = x402_render.render
92
+ wait_client = HyperCLI(api_key=x402_render.access_key)
93
+
94
+ if fmt == "json" and not wait:
95
+ output(
96
+ {
97
+ "render": render.__dict__,
98
+ "access_key": x402_render.access_key,
99
+ "status_url": x402_render.status_url,
100
+ "cancel_url": x402_render.cancel_url,
101
+ },
102
+ "json",
103
+ )
104
+ else:
105
+ console.print(f"[bold green]✓[/bold green] Render created: [cyan]{render.render_id}[/cyan]")
106
+ console.print(f" State: {render.state}")
107
+ console.print(f" Access Key: {x402_render.access_key}")
108
+ console.print(f" Status URL: {x402_render.status_url}")
109
+ console.print(f" Cancel URL: {x402_render.cancel_url}")
110
+
111
+ if wait:
112
+ _wait_for_render(wait_client, render.render_id, fmt)
113
+ return
114
+
115
+ client = get_client()
70
116
  with spinner("Creating render..."):
71
117
  render = client.renders.create(params=params, render_type=render_type, notify_url=notify_url)
72
118
 
@@ -79,7 +125,6 @@ def create_render(
79
125
  if wait:
80
126
  _wait_for_render(client, render.render_id, fmt)
81
127
 
82
-
83
128
  @app.command("status")
84
129
  def status(
85
130
  render_id: str = typer.Argument(..., help="Render ID"),
@@ -163,9 +163,10 @@ async def _run_job_monitor_async(
163
163
  status_q: Queue = None,
164
164
  stop_on_status_complete: bool = False,
165
165
  cancel_on_exit: bool = False,
166
+ api_key: str | None = None,
166
167
  ):
167
168
  """Async job monitor - uses SDK LogStream for logs"""
168
- client = HyperCLI()
169
+ client = HyperCLI(api_key=api_key) if api_key else HyperCLI()
169
170
  should_cancel = False
170
171
  logs: deque[str] = deque(maxlen=MAX_LOG_LINES)
171
172
  log_stream: Optional[LogStream] = None
@@ -340,6 +341,7 @@ def run_job_monitor(
340
341
  status_q: Queue = None,
341
342
  stop_on_status_complete: bool = False,
342
343
  cancel_on_exit: bool = False,
344
+ api_key: str | None = None,
343
345
  ):
344
346
  """Run the job monitor TUI (sync wrapper).
345
347
 
@@ -348,5 +350,6 @@ def run_job_monitor(
348
350
  status_q: Optional queue receiving JobStatus updates for status pane
349
351
  stop_on_status_complete: If True, exit when JobStatus.complete is True
350
352
  cancel_on_exit: If True, cancel the job when exiting via Ctrl+C
353
+ api_key: Optional bearer token (API key or x402 access key)
351
354
  """
352
- asyncio.run(_run_job_monitor_async(job_id, status_q, stop_on_status_complete, cancel_on_exit))
355
+ asyncio.run(_run_job_monitor_async(job_id, status_q, stop_on_status_complete, cancel_on_exit, api_key))
@@ -20,6 +20,7 @@ except ImportError:
20
20
 
21
21
  WALLET_DIR = Path.home() / ".hypercli"
22
22
  WALLET_PATH = WALLET_DIR / "wallet.json"
23
+ WALLET_PASSPHRASE_PATH = WALLET_DIR / "wallet.passphrase"
23
24
  BASE_RPC = "https://mainnet.base.org"
24
25
  USDC_CONTRACT = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
25
26
 
@@ -33,6 +34,20 @@ def require_wallet_deps():
33
34
  raise typer.Exit(1)
34
35
 
35
36
 
37
+
38
+ def _get_wallet_passphrase(prompt: str = "Unlock keystore passphrase: ") -> str:
39
+ passphrase_env = os.getenv("HYPERCLI_WALLET_PASSPHRASE")
40
+ if passphrase_env:
41
+ return passphrase_env
42
+
43
+ if WALLET_PASSPHRASE_PATH.exists():
44
+ passphrase_file = WALLET_PASSPHRASE_PATH.read_text().strip()
45
+ if passphrase_file:
46
+ console.print("[dim]Using passphrase from ~/.hypercli/wallet.passphrase[/dim]")
47
+ return passphrase_file
48
+
49
+ return getpass.getpass(prompt)
50
+
36
51
  @app.command("create")
37
52
  def create():
38
53
  """Create a new wallet with encrypted keystore"""
@@ -195,12 +210,7 @@ def balance():
195
210
  with open(WALLET_PATH) as f:
196
211
  keystore = json.load(f)
197
212
 
198
- # Get passphrase
199
- passphrase_env = os.getenv("HYPERCLI_WALLET_PASSPHRASE")
200
- if passphrase_env:
201
- passphrase = passphrase_env
202
- else:
203
- passphrase = getpass.getpass("Unlock keystore passphrase: ")
213
+ passphrase = _get_wallet_passphrase()
204
214
 
205
215
  try:
206
216
  private_key = Account.decrypt(keystore, passphrase)
@@ -503,12 +513,7 @@ def load_wallet():
503
513
  with open(WALLET_PATH) as f:
504
514
  keystore = json.load(f)
505
515
 
506
- # Get passphrase
507
- passphrase_env = os.getenv("HYPERCLI_WALLET_PASSPHRASE")
508
- if passphrase_env:
509
- passphrase = passphrase_env
510
- else:
511
- passphrase = getpass.getpass("Unlock keystore passphrase: ")
516
+ passphrase = _get_wallet_passphrase()
512
517
 
513
518
  try:
514
519
  private_key = Account.decrypt(keystore, passphrase)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hypercli-cli"
7
- version = "0.8.5"
7
+ version = "0.8.7"
8
8
  description = "CLI for HyperCLI - GPU orchestration and LLM API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -13,7 +13,7 @@ authors = [
13
13
  { name = "HyperCLI", email = "support@hypercli.com" }
14
14
  ]
15
15
  dependencies = [
16
- "hypercli-sdk>=0.7.1",
16
+ "hypercli-sdk>=0.8.7",
17
17
  "openai>=2.8.1",
18
18
  "typer>=0.20.0",
19
19
  "rich>=14.2.0",
@@ -25,7 +25,7 @@ dependencies = [
25
25
 
26
26
  [project.optional-dependencies]
27
27
  comfyui = [
28
- "hypercli-sdk[comfyui]>=0.7.1",
28
+ "hypercli-sdk[comfyui]>=0.8.7",
29
29
  ]
30
30
  wallet = [
31
31
  "x402[httpx,evm]>=2.0.0",
@@ -35,7 +35,7 @@ wallet = [
35
35
  "qrcode[pil]>=7.4.0",
36
36
  ]
37
37
  all = [
38
- "hypercli-sdk[comfyui]>=0.7.1",
38
+ "hypercli-sdk[comfyui]>=0.8.7",
39
39
  "x402[httpx,evm]>=2.0.0",
40
40
  "eth-account>=0.13.0",
41
41
  "web3>=7.0.0",
@@ -1 +0,0 @@
1
- __version__ = "0.8.3"
File without changes
File without changes