amina-cli 0.2.9__tar.gz → 0.3.0__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 (105) hide show
  1. {amina_cli-0.2.9 → amina_cli-0.3.0}/PKG-INFO +1 -1
  2. {amina_cli-0.2.9 → amina_cli-0.3.0}/pyproject.toml +1 -1
  3. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/__init__.py +1 -1
  4. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/jobs_cmd.py +10 -0
  5. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/__init__.py +28 -5
  6. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/hydrophobicity.py +3 -3
  7. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/mmseqs2_cluster.py +3 -3
  8. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/residue_accessibility.py +3 -3
  9. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/rmsd.py +3 -3
  10. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/sasa.py +3 -3
  11. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/simple_rmsd.py +3 -3
  12. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/surface_charge.py +3 -3
  13. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/usalign.py +3 -3
  14. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/esm_if1.py +3 -3
  15. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/protein_mc.py +4 -4
  16. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/proteinmpnn.py +3 -3
  17. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/rfdiffusion.py +4 -4
  18. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/boltz2.py +1 -2
  19. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/esmfold.py +3 -3
  20. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/openfold3.py +4 -5
  21. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/protenix.py +4 -5
  22. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/autodock_vina.py +3 -3
  23. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/diffdock.py +3 -3
  24. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/dockq.py +3 -3
  25. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/emngly.py +3 -3
  26. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/glycosylation_ensemble.py +3 -3
  27. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/interface_identifier.py +3 -3
  28. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/isoglyp.py +3 -3
  29. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/lmngly.py +3 -3
  30. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/p2rank.py +3 -3
  31. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/pesto.py +3 -3
  32. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/properties/aminosol.py +3 -3
  33. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/properties/esm1v.py +3 -3
  34. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/properties/esm2_embedding.py +3 -3
  35. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/activesite_verifier.py +3 -3
  36. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/chain_select.py +3 -3
  37. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/distance_calculator.py +3 -3
  38. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/maxit_convert.py +3 -3
  39. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/mol_size_calculator.py +3 -3
  40. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/obabel_convert.py +3 -3
  41. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/pdb_bfactor_overwrite.py +3 -3
  42. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/pdb_quality_assessment.py +3 -3
  43. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/pdb_to_fasta.py +3 -3
  44. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/protein_relaxer.py +4 -4
  45. {amina_cli-0.2.9 → amina_cli-0.3.0}/.gitignore +0 -0
  46. {amina_cli-0.2.9 → amina_cli-0.3.0}/LICENSE +0 -0
  47. {amina_cli-0.2.9 → amina_cli-0.3.0}/README.md +0 -0
  48. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/auth.py +0 -0
  49. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/client.py +0 -0
  50. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/__init__.py +0 -0
  51. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/auth_cmd.py +0 -0
  52. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/run_cmd.py +0 -0
  53. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/__init__.py +0 -0
  54. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/hydrophobicity.yaml +0 -0
  55. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/mmseqs2_cluster.yaml +0 -0
  56. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/residue_accessibility.yaml +0 -0
  57. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/rmsd.yaml +0 -0
  58. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/sasa.yaml +0 -0
  59. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/simple_rmsd.yaml +0 -0
  60. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/surface_charge.yaml +0 -0
  61. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/analysis/docs/usalign.yaml +0 -0
  62. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/__init__.py +0 -0
  63. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/docs/esm_if1.yaml +0 -0
  64. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/docs/protein_mc.yaml +0 -0
  65. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/docs/proteinmpnn.yaml +0 -0
  66. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/design/docs/rfdiffusion.yaml +0 -0
  67. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/display.py +0 -0
  68. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/doccard.py +0 -0
  69. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/__init__.py +0 -0
  70. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/docs/boltz2.yaml +0 -0
  71. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/docs/esmfold.yaml +0 -0
  72. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/docs/openfold3.yaml +0 -0
  73. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/folding/docs/protenix.yaml +0 -0
  74. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/__init__.py +0 -0
  75. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/autodock_vina.yaml +0 -0
  76. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/diffdock.yaml +0 -0
  77. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/dockq.yaml +0 -0
  78. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/emngly.yaml +0 -0
  79. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/glycosylation_ensemble.yaml +0 -0
  80. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/interface_identifier.yaml +0 -0
  81. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/isoglyp.yaml +0 -0
  82. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/lmngly.yaml +0 -0
  83. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/p2rank.yaml +0 -0
  84. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/interactions/docs/pesto.yaml +0 -0
  85. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/properties/__init__.py +0 -0
  86. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/properties/docs/aminosol.yaml +0 -0
  87. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/properties/docs/esm1v.yaml +0 -0
  88. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/properties/docs/esm2_embedding.yaml +0 -0
  89. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/__init__.py +0 -0
  90. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/activesite_verifier.yaml +0 -0
  91. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/chain_select.yaml +0 -0
  92. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/distance_calculator.yaml +0 -0
  93. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/maxit_convert.yaml +0 -0
  94. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/mol_size_calculator.yaml +0 -0
  95. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/obabel_convert.yaml +0 -0
  96. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/pdb_bfactor_overwrite.yaml +0 -0
  97. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/pdb_cleaner.yaml +0 -0
  98. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/pdb_quality_assessment.yaml +0 -0
  99. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/pdb_to_fasta.yaml +0 -0
  100. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/docs/protein_relaxer.yaml +0 -0
  101. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools/utilities/pdb_cleaner.py +0 -0
  102. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/commands/tools_cmd.py +0 -0
  103. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/main.py +0 -0
  104. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/registry.py +0 -0
  105. {amina_cli-0.2.9 → amina_cli-0.3.0}/src/amina_cli/storage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amina-cli
3
- Version: 0.2.9
3
+ Version: 0.3.0
4
4
  Summary: CLI for AminoAnalytica protein engineering platform
5
5
  Project-URL: Homepage, https://aminoanalytica.com
6
6
  Project-URL: Documentation, https://docs.aminoanalytica.com
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "amina-cli"
3
- version = "0.2.9"
3
+ version = "0.3.0"
4
4
  description = "CLI for AminoAnalytica protein engineering platform"
5
5
  readme = "README.md"
6
6
  license = {text = "Apache-2.0"}
@@ -9,4 +9,4 @@ Quick start:
9
9
  amina run esmfold --sequence "MKFLILLFNILCLFPVLAADNH"
10
10
  """
11
11
 
12
- __version__ = "0.2.9"
12
+ __version__ = "0.3.0"
@@ -468,12 +468,20 @@ def download(
468
468
 
469
469
  # Download results
470
470
  result = status_result.get("result", {})
471
+
472
+ # Persist the structured response payload so it matches the on-disk layout
473
+ # produced by `amina run <tool> -o <dir>` (response.json alongside artifacts).
474
+ output.mkdir(parents=True, exist_ok=True)
475
+ response_path = output / "response.json"
476
+ response_path.write_text(json.dumps(result, indent=2, default=str))
477
+
471
478
  try:
472
479
  downloaded = download_results(result, output)
473
480
  if downloaded:
474
481
  console.print(f"[green]\u2713[/green] Downloaded {len(downloaded)} file(s) to {output}/")
475
482
  for path in downloaded:
476
483
  console.print(f" - {path.name}")
484
+ console.print(f" - {response_path.name}")
477
485
  # Also display tool response data alongside files
478
486
  if result.get("data"):
479
487
  from amina_cli.commands.tools import get_tool
@@ -482,6 +490,7 @@ def download(
482
490
  tool_metadata = get_tool(job_info.get("tool_name", ""))
483
491
  render_tool_output(result, tool_metadata)
484
492
  else:
493
+ console.print(f"[green]\u2713[/green] Saved response to {response_path}")
485
494
  # Show tool response data even when there are no files
486
495
  if result.get("data"):
487
496
  from amina_cli.commands.tools import get_tool
@@ -496,6 +505,7 @@ def download(
496
505
  signed_urls = result.get("signed_urls", {})
497
506
  if signed_urls:
498
507
  console.print(f"[yellow]Warning:[/yellow] Could not download automatically: {e}")
508
+ console.print(f"[dim]Response saved to {response_path}[/dim]")
499
509
  console.print("\n[bold]Files available at:[/bold]")
500
510
  for file_type, url in signed_urls.items():
501
511
  if url:
@@ -6,6 +6,7 @@ Each tool file exports METADATA dict and register() function.
6
6
  """
7
7
 
8
8
  import importlib
9
+ import json
9
10
  from pathlib import Path
10
11
  from typing import Iterator, Optional
11
12
  import typer
@@ -91,7 +92,7 @@ def run_tool_with_progress(
91
92
  Args:
92
93
  tool_name: Name of the tool to run
93
94
  params: Tool-specific parameters
94
- output_dir: Directory to save output files (required unless background=True)
95
+ output_dir: Directory to save output files (required)
95
96
  timeout: Request timeout in seconds (default: 10 hours)
96
97
  background: If True, submit job and return immediately without waiting
97
98
  """
@@ -106,6 +107,10 @@ def run_tool_with_progress(
106
107
  from amina_cli.registry import ToolNotFoundError
107
108
  from amina_cli.storage import download_results, StorageError
108
109
 
110
+ if output_dir is None:
111
+ console.print("[red]Error:[/red] --output / -o is required")
112
+ raise typer.Exit(1)
113
+
109
114
  # Handle background submission
110
115
  if background:
111
116
  try:
@@ -125,6 +130,11 @@ def run_tool_with_progress(
125
130
  # Save to local job history
126
131
  save_job(result)
127
132
 
133
+ # Persist the structured submission payload for downstream agents/scripts
134
+ output_dir.mkdir(parents=True, exist_ok=True)
135
+ submission_path = output_dir / "submission.json"
136
+ submission_path.write_text(json.dumps(result, indent=2, default=str))
137
+
128
138
  # Handle queued vs submitted status
129
139
  if result.get("status") == "queued":
130
140
  queue_position = result.get("queue_position", 0)
@@ -136,6 +146,7 @@ def run_tool_with_progress(
136
146
  console.print(f"\n[green]\u2713[/green] Job submitted: [bold]{result['job_id']}[/bold]")
137
147
  console.print(f" Tool: {display_name}")
138
148
  console.print(f" Call ID: {result.get('call_id', 'N/A')}")
149
+ console.print(f"[dim]Submission saved to {submission_path}[/dim]")
139
150
  console.print(f"\n[dim]Check status:[/dim] amina jobs status {result['job_id'][:8]}")
140
151
  console.print(f"[dim]Wait for completion:[/dim] amina jobs wait {result['job_id'][:8]}")
141
152
  console.print(f"[dim]Download results:[/dim] amina jobs download {result['job_id'][:8]} -o <output_dir>")
@@ -277,7 +288,13 @@ def run_tool_with_progress(
277
288
  else:
278
289
  console.print(f"\n[yellow]Warning:[/yellow] Download failed: {e}")
279
290
 
280
- _display_result(result, downloaded, output_dir, params, tool_info)
291
+ # Persist the structured response payload (success or failure) so agents
292
+ # and scripts can read metrics/warnings/cost without re-parsing stdout.
293
+ output_dir.mkdir(parents=True, exist_ok=True)
294
+ response_path = output_dir / "response.json"
295
+ response_path.write_text(json.dumps(result, indent=2, default=str))
296
+
297
+ _display_result(result, downloaded, output_dir, params, tool_info, response_path)
281
298
 
282
299
  except AuthenticationError as e:
283
300
  console.print(
@@ -405,6 +422,7 @@ def _display_result(
405
422
  output_dir: Path,
406
423
  input_params: dict | None = None,
407
424
  metadata: dict | None = None,
425
+ response_path: Path | None = None,
408
426
  ):
409
427
  """Display tool execution result using the generic renderer."""
410
428
  status = result.get("status", "unknown")
@@ -414,13 +432,16 @@ def _display_result(
414
432
  exec_time = result.get("execution_time_seconds", 0)
415
433
  time_str = f" ({exec_time:.1f}s)" if exec_time else ""
416
434
 
435
+ console.print(f"\n[green]\u2713[/green] Completed{time_str}")
417
436
  if downloaded:
418
- console.print(f"\n[green]\u2713[/green] Completed{time_str}")
419
437
  console.print(f"[green]\u2713[/green] Downloaded {len(downloaded)} file(s) to {output_dir}/")
420
438
  for path in downloaded:
421
439
  console.print(f" - {path.name}")
422
- else:
423
- console.print(f"\n[green]\u2713[/green] Completed{time_str}")
440
+ if response_path is not None:
441
+ console.print(f" - {response_path.name}")
442
+ elif response_path is not None:
443
+ console.print(f"[green]\u2713[/green] Saved to {output_dir}/")
444
+ console.print(f" - {response_path.name}")
424
445
 
425
446
  # Show cost charged (from gateway)
426
447
  cost_usd = result.get("cost_usd") or result.get("credits_charged", 0)
@@ -493,3 +514,5 @@ def _display_result(
493
514
  border_style="red",
494
515
  )
495
516
  )
517
+ if response_path is not None:
518
+ console.print(f"[dim]Response saved to {response_path}[/dim]")
@@ -31,7 +31,7 @@ def register(app: typer.Typer):
31
31
  None,
32
32
  "--output",
33
33
  "-o",
34
- help="Output directory for results (required unless --background)",
34
+ help="Output directory for results (required)",
35
35
  ),
36
36
  background: bool = typer.Option(
37
37
  False,
@@ -68,8 +68,8 @@ def register(app: typer.Typer):
68
68
  ):
69
69
  """For full documentation including parameters, metrics, and usage: amina tools hydrophobicity"""
70
70
  # Validate required options
71
- if output is None and not background:
72
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
71
+ if output is None:
72
+ console.print("[red]Error:[/red] --output / -o is required")
73
73
  raise typer.Exit(1)
74
74
 
75
75
  # Read PDB file content
@@ -48,7 +48,7 @@ def register(app: typer.Typer):
48
48
  None,
49
49
  "--output",
50
50
  "-o",
51
- help="Output directory for results (required unless --background)",
51
+ help="Output directory for results (required)",
52
52
  ),
53
53
  job_name: Optional[str] = typer.Option(
54
54
  None,
@@ -65,8 +65,8 @@ def register(app: typer.Typer):
65
65
  ):
66
66
  """For full documentation including parameters, metrics, and usage: amina tools mmseqs2-cluster"""
67
67
  # Validate output
68
- if output is None and not background:
69
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
68
+ if output is None:
69
+ console.print("[red]Error:[/red] --output / -o is required")
70
70
  raise typer.Exit(1)
71
71
 
72
72
  # Validate at least one FASTA file
@@ -31,7 +31,7 @@ def register(app: typer.Typer):
31
31
  None,
32
32
  "--output",
33
33
  "-o",
34
- help="Output directory for results (required unless --background)",
34
+ help="Output directory for results (required)",
35
35
  ),
36
36
  residues: Optional[str] = typer.Option(
37
37
  None,
@@ -65,8 +65,8 @@ def register(app: typer.Typer):
65
65
  ):
66
66
  """For full documentation including parameters, metrics, and usage: amina tools residue-accessibility"""
67
67
  # Validate required options
68
- if output is None and not background:
69
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
68
+ if output is None:
69
+ console.print("[red]Error:[/red] --output / -o is required")
70
70
  raise typer.Exit(1)
71
71
 
72
72
  # Validate residue format if provided
@@ -71,7 +71,7 @@ def register(app: typer.Typer):
71
71
  None,
72
72
  "--output",
73
73
  "-o",
74
- help="Output directory for results (required unless --background)",
74
+ help="Output directory for results (required)",
75
75
  ),
76
76
  background: bool = typer.Option(
77
77
  False,
@@ -88,8 +88,8 @@ def register(app: typer.Typer):
88
88
  ):
89
89
  """For full documentation including parameters, metrics, and usage: amina tools rmsd-analysis"""
90
90
  # Validate required options
91
- if output is None and not background:
92
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
91
+ if output is None:
92
+ console.print("[red]Error:[/red] --output / -o is required")
93
93
  raise typer.Exit(1)
94
94
 
95
95
  # Read file contents
@@ -31,7 +31,7 @@ def register(app: typer.Typer):
31
31
  None,
32
32
  "--output",
33
33
  "-o",
34
- help="Output directory for results (required unless --background)",
34
+ help="Output directory for results (required)",
35
35
  ),
36
36
  background: bool = typer.Option(
37
37
  False,
@@ -53,8 +53,8 @@ def register(app: typer.Typer):
53
53
  ):
54
54
  """For full documentation including parameters, metrics, and usage: amina tools sasa"""
55
55
  # Validate required options
56
- if output is None and not background:
57
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
56
+ if output is None:
57
+ console.print("[red]Error:[/red] --output / -o is required")
58
58
  raise typer.Exit(1)
59
59
 
60
60
  # Read PDB file content
@@ -48,7 +48,7 @@ def register(app: typer.Typer):
48
48
  None,
49
49
  "--output",
50
50
  "-o",
51
- help="Output directory for results (required unless --background)",
51
+ help="Output directory for results (required)",
52
52
  ),
53
53
  background: bool = typer.Option(
54
54
  False,
@@ -65,8 +65,8 @@ def register(app: typer.Typer):
65
65
  ):
66
66
  """For full documentation including parameters, metrics, and usage: amina tools simple-rmsd"""
67
67
  # Validate required options
68
- if output is None and not background:
69
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
68
+ if output is None:
69
+ console.print("[red]Error:[/red] --output / -o is required")
70
70
  raise typer.Exit(1)
71
71
 
72
72
  # Read file contents
@@ -31,7 +31,7 @@ def register(app: typer.Typer):
31
31
  None,
32
32
  "--output",
33
33
  "-o",
34
- help="Output directory for results (required unless --background)",
34
+ help="Output directory for results (required)",
35
35
  ),
36
36
  background: bool = typer.Option(
37
37
  False,
@@ -104,8 +104,8 @@ def register(app: typer.Typer):
104
104
  ):
105
105
  """For full documentation including parameters, metrics, and usage: amina tools surface-charge"""
106
106
  # Validate required options
107
- if output is None and not background:
108
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
107
+ if output is None:
108
+ console.print("[red]Error:[/red] --output / -o is required")
109
109
  raise typer.Exit(1)
110
110
 
111
111
  # Validate forcefield
@@ -63,7 +63,7 @@ def register(app: typer.Typer):
63
63
  None,
64
64
  "--output",
65
65
  "-o",
66
- help="Output directory for results (required unless --background)",
66
+ help="Output directory for results (required)",
67
67
  ),
68
68
  background: bool = typer.Option(
69
69
  False,
@@ -80,8 +80,8 @@ def register(app: typer.Typer):
80
80
  ):
81
81
  """For full documentation including parameters, metrics, and usage: amina tools usalign"""
82
82
  # Validate required options
83
- if output is None and not background:
84
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
83
+ if output is None:
84
+ console.print("[red]Error:[/red] --output / -o is required")
85
85
  raise typer.Exit(1)
86
86
 
87
87
  # Validate mode
@@ -72,7 +72,7 @@ def register(app: typer.Typer):
72
72
  None,
73
73
  "--output",
74
74
  "-o",
75
- help="Output directory for results (required unless --background)",
75
+ help="Output directory for results (required)",
76
76
  ),
77
77
  background: bool = typer.Option(
78
78
  False,
@@ -89,8 +89,8 @@ def register(app: typer.Typer):
89
89
  ):
90
90
  """For full documentation including parameters, metrics, and usage: amina tools esm-if1"""
91
91
  # Validate required options
92
- if output is None and not background:
93
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
92
+ if output is None:
93
+ console.print("[red]Error:[/red] --output / -o is required")
94
94
  raise typer.Exit(1)
95
95
 
96
96
  # Validate mode
@@ -55,7 +55,7 @@ def register(app: typer.Typer):
55
55
  None,
56
56
  "--output",
57
57
  "-o",
58
- help="Output directory for results (required unless --background)",
58
+ help="Output directory for results (required)",
59
59
  ),
60
60
  background: bool = typer.Option(
61
61
  False,
@@ -71,9 +71,9 @@ def register(app: typer.Typer):
71
71
  ),
72
72
  ):
73
73
  """For full documentation including parameters, metrics, and usage: amina tools protein-mc"""
74
- # Validate output is provided unless --background
75
- if output is None and not background:
76
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
74
+ # Validate output is provided
75
+ if output is None:
76
+ console.print("[red]Error:[/red] --output / -o is required")
77
77
  raise typer.Exit(1)
78
78
 
79
79
  # Validate input
@@ -70,7 +70,7 @@ def register(app: typer.Typer):
70
70
  None,
71
71
  "--output",
72
72
  "-o",
73
- help="Output directory for results (required unless --background)",
73
+ help="Output directory for results (required)",
74
74
  ),
75
75
  background: bool = typer.Option(
76
76
  False,
@@ -87,8 +87,8 @@ def register(app: typer.Typer):
87
87
  ):
88
88
  """For full documentation including parameters, metrics, and usage: amina tools proteinmpnn"""
89
89
  # Validate required options
90
- if output is None and not background:
91
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
90
+ if output is None:
91
+ console.print("[red]Error:[/red] --output / -o is required")
92
92
  raise typer.Exit(1)
93
93
 
94
94
  # Read PDB file content
@@ -42,7 +42,7 @@ def register(app: typer.Typer):
42
42
  None,
43
43
  "--output",
44
44
  "-o",
45
- help="Output directory for results (required unless --background)",
45
+ help="Output directory for results (required)",
46
46
  ),
47
47
  background: bool = typer.Option(
48
48
  False,
@@ -274,9 +274,9 @@ def register(app: typer.Typer):
274
274
  console.print(f"[red]Invalid JSON in --advanced-config: {e}[/red]")
275
275
  raise typer.Exit(1)
276
276
 
277
- # Validate output is provided unless --background
278
- if output is None and not background:
279
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
277
+ # Validate output is provided
278
+ if output is None:
279
+ console.print("[red]Error:[/red] --output / -o is required")
280
280
  raise typer.Exit(1)
281
281
 
282
282
  # Run the tool
@@ -8,6 +8,7 @@ import typer
8
8
  from pathlib import Path
9
9
  from typing import List, Optional, Set, Tuple
10
10
  from rich.console import Console
11
+ from amina_cli.commands.tools.doccard import load_doccard
11
12
 
12
13
 
13
14
  def parse_sequence_with_chain_id(value: str, used_chains: Set[str]) -> Tuple[Optional[str], str, bool]:
@@ -56,8 +57,6 @@ def parse_sequence_with_chain_id(value: str, used_chains: Set[str]) -> Tuple[Opt
56
57
 
57
58
  # METADATA loaded from doccard YAML — the single source of truth for tool documentation.
58
59
  # Parameter definitions are canonical in docs/boltz2.yaml — keep in sync with Typer options below.
59
- from amina_cli.commands.tools.doccard import load_doccard
60
-
61
60
  METADATA = load_doccard("folding", "boltz2")
62
61
 
63
62
  console = Console()
@@ -37,7 +37,7 @@ def register(app: typer.Typer):
37
37
  None,
38
38
  "--output",
39
39
  "-o",
40
- help="Output directory for results (required unless --background)",
40
+ help="Output directory for results (required)",
41
41
  ),
42
42
  job_name: Optional[str] = typer.Option(
43
43
  None,
@@ -54,8 +54,8 @@ def register(app: typer.Typer):
54
54
  ):
55
55
  """For full documentation including parameters, metrics, and usage: amina tools esmfold"""
56
56
  # Validate required options
57
- if output is None and not background:
58
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
57
+ if output is None:
58
+ console.print("[red]Error:[/red] --output / -o is required")
59
59
  raise typer.Exit(1)
60
60
 
61
61
  # Validate input
@@ -9,6 +9,7 @@ import typer
9
9
  from pathlib import Path
10
10
  from typing import List, Optional, Set, Tuple
11
11
  from rich.console import Console
12
+ from amina_cli.commands.tools.doccard import load_doccard
12
13
 
13
14
 
14
15
  def parse_sequence_with_chain_id(value: str, used_chains: Set[str]) -> Tuple[Optional[str], str]:
@@ -48,8 +49,6 @@ def parse_sequence_with_chain_id(value: str, used_chains: Set[str]) -> Tuple[Opt
48
49
 
49
50
  # METADATA loaded from doccard YAML — the single source of truth for tool documentation.
50
51
  # Parameter definitions are canonical in docs/openfold3.yaml — keep in sync with Typer options below.
51
- from amina_cli.commands.tools.doccard import load_doccard
52
-
53
52
  METADATA = load_doccard("folding", "openfold3")
54
53
 
55
54
  console = Console()
@@ -177,7 +176,7 @@ def register(app: typer.Typer):
177
176
  None,
178
177
  "--output",
179
178
  "-o",
180
- help="Output directory for results (required unless --background)",
179
+ help="Output directory for results (required)",
181
180
  ),
182
181
  job_name: Optional[str] = typer.Option(
183
182
  None,
@@ -194,8 +193,8 @@ def register(app: typer.Typer):
194
193
  ):
195
194
  """For full documentation including parameters, metrics, and usage: amina tools openfold3"""
196
195
  # Validate required options
197
- if output is None and not background:
198
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
196
+ if output is None:
197
+ console.print("[red]Error:[/red] --output / -o is required")
199
198
  raise typer.Exit(1)
200
199
 
201
200
  # Validate quality preset
@@ -5,6 +5,7 @@ import typer
5
5
  from pathlib import Path
6
6
  from typing import List, Optional, Set, Tuple, Union
7
7
  from rich.console import Console
8
+ from amina_cli.commands.tools.doccard import load_doccard
8
9
 
9
10
 
10
11
  def parse_sequence_with_chain_id(value: str, used_chains: Set[str]) -> Tuple[Optional[str], str]:
@@ -54,8 +55,6 @@ def _auto_chain_id(used_chains: Set[str]) -> str:
54
55
 
55
56
  # METADATA loaded from doccard YAML — the single source of truth for tool documentation.
56
57
  # Parameter definitions are canonical in docs/protenix.yaml — keep in sync with Typer options below.
57
- from amina_cli.commands.tools.doccard import load_doccard
58
-
59
58
  METADATA = load_doccard("folding", "protenix")
60
59
 
61
60
  console = Console()
@@ -222,7 +221,7 @@ def register(app: typer.Typer):
222
221
  None,
223
222
  "--output",
224
223
  "-o",
225
- help="Output directory for results (required unless --background)",
224
+ help="Output directory for results (required)",
226
225
  ),
227
226
  job_name: Optional[str] = typer.Option(
228
227
  None,
@@ -285,8 +284,8 @@ def register(app: typer.Typer):
285
284
  ions = ions or []
286
285
 
287
286
  # Validate required options
288
- if output is None and not background:
289
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
287
+ if output is None:
288
+ console.print("[red]Error:[/red] --output / -o is required")
290
289
  raise typer.Exit(1)
291
290
 
292
291
  # Count entities from flags
@@ -104,7 +104,7 @@ def register(app: typer.Typer):
104
104
  None,
105
105
  "--output",
106
106
  "-o",
107
- help="Output directory for results (required unless --background)",
107
+ help="Output directory for results (required)",
108
108
  ),
109
109
  background: bool = typer.Option(
110
110
  False,
@@ -121,8 +121,8 @@ def register(app: typer.Typer):
121
121
  ):
122
122
  """For full documentation including parameters, metrics, and usage: amina tools autodock-vina"""
123
123
  # Validate required options
124
- if output is None and not background:
125
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
124
+ if output is None:
125
+ console.print("[red]Error:[/red] --output / -o is required")
126
126
  raise typer.Exit(1)
127
127
 
128
128
  # Validate ligand input (exactly one of --ligand or --smiles)
@@ -70,7 +70,7 @@ def register(app: typer.Typer):
70
70
  None,
71
71
  "--output",
72
72
  "-o",
73
- help="Output directory for results (required unless --background)",
73
+ help="Output directory for results (required)",
74
74
  ),
75
75
  background: bool = typer.Option(
76
76
  False,
@@ -87,8 +87,8 @@ def register(app: typer.Typer):
87
87
  ):
88
88
  """For full documentation including parameters, metrics, and usage: amina tools diffdock"""
89
89
  # Validate required options
90
- if output is None and not background:
91
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
90
+ if output is None:
91
+ console.print("[red]Error:[/red] --output / -o is required")
92
92
  raise typer.Exit(1)
93
93
 
94
94
  # Validate protein input (exactly one required)
@@ -51,7 +51,7 @@ def register(app: typer.Typer):
51
51
  None,
52
52
  "--output",
53
53
  "-o",
54
- help="Output directory for results (required unless --background)",
54
+ help="Output directory for results (required)",
55
55
  ),
56
56
  background: bool = typer.Option(
57
57
  False,
@@ -68,8 +68,8 @@ def register(app: typer.Typer):
68
68
  ):
69
69
  """For full documentation including parameters, metrics, and usage: amina tools dockq"""
70
70
  # Validate required options
71
- if output is None and not background:
72
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
71
+ if output is None:
72
+ console.print("[red]Error:[/red] --output / -o is required")
73
73
  raise typer.Exit(1)
74
74
 
75
75
  # Read file contents
@@ -39,7 +39,7 @@ def register(app: typer.Typer):
39
39
  None,
40
40
  "--output",
41
41
  "-o",
42
- help="Output directory for results (required unless --background)",
42
+ help="Output directory for results (required)",
43
43
  ),
44
44
  background: bool = typer.Option(
45
45
  False,
@@ -56,8 +56,8 @@ def register(app: typer.Typer):
56
56
  ):
57
57
  """For full documentation including parameters, metrics, and usage: amina tools emngly"""
58
58
  # Validate required options
59
- if output is None and not background:
60
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
59
+ if output is None:
60
+ console.print("[red]Error:[/red] --output / -o is required")
61
61
  raise typer.Exit(1)
62
62
 
63
63
  # Read PDB file content
@@ -77,7 +77,7 @@ def register(app: typer.Typer):
77
77
  None,
78
78
  "--output",
79
79
  "-o",
80
- help="Output directory for results (required unless --background)",
80
+ help="Output directory for results (required)",
81
81
  ),
82
82
  background: bool = typer.Option(
83
83
  False,
@@ -94,8 +94,8 @@ def register(app: typer.Typer):
94
94
  ):
95
95
  """For full documentation including parameters, metrics, and usage: amina tools glycosylation-ensemble"""
96
96
  # Validate required options
97
- if output is None and not background:
98
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
97
+ if output is None:
98
+ console.print("[red]Error:[/red] --output / -o is required")
99
99
  raise typer.Exit(1)
100
100
 
101
101
  # Read PDB file content
@@ -39,7 +39,7 @@ def register(app: typer.Typer):
39
39
  None,
40
40
  "--output",
41
41
  "-o",
42
- help="Output directory for results (required unless --background)",
42
+ help="Output directory for results (required)",
43
43
  ),
44
44
  background: bool = typer.Option(
45
45
  False,
@@ -56,8 +56,8 @@ def register(app: typer.Typer):
56
56
  ):
57
57
  """For full documentation including parameters, metrics, and usage: amina tools interface-identifier"""
58
58
  # Validate required options
59
- if output is None and not background:
60
- console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
59
+ if output is None:
60
+ console.print("[red]Error:[/red] --output / -o is required")
61
61
  raise typer.Exit(1)
62
62
 
63
63
  # Read file content