amina-cli 0.4.0__tar.gz → 0.4.1__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.4.0 → amina_cli-0.4.1}/PKG-INFO +1 -1
  2. {amina_cli-0.4.0 → amina_cli-0.4.1}/pyproject.toml +1 -1
  3. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/__init__.py +1 -1
  4. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/jobs_cmd.py +4 -1
  5. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/__init__.py +91 -9
  6. {amina_cli-0.4.0 → amina_cli-0.4.1}/.gitignore +0 -0
  7. {amina_cli-0.4.0 → amina_cli-0.4.1}/LICENSE +0 -0
  8. {amina_cli-0.4.0 → amina_cli-0.4.1}/README.md +0 -0
  9. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/auth.py +0 -0
  10. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/client.py +0 -0
  11. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/__init__.py +0 -0
  12. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/auth_cmd.py +0 -0
  13. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/run_cmd.py +0 -0
  14. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/__init__.py +0 -0
  15. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/hydrophobicity.yaml +0 -0
  16. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/mmseqs2_cluster.yaml +0 -0
  17. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/residue_accessibility.yaml +0 -0
  18. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/rmsd.yaml +0 -0
  19. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/sasa.yaml +0 -0
  20. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/simple_rmsd.yaml +0 -0
  21. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/surface_charge.yaml +0 -0
  22. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/docs/usalign.yaml +0 -0
  23. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/hydrophobicity.py +0 -0
  24. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/mmseqs2_cluster.py +0 -0
  25. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/residue_accessibility.py +0 -0
  26. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/rmsd.py +0 -0
  27. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/sasa.py +0 -0
  28. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/simple_rmsd.py +0 -0
  29. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/surface_charge.py +0 -0
  30. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/analysis/usalign.py +0 -0
  31. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/__init__.py +0 -0
  32. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/docs/esm_if1.yaml +0 -0
  33. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/docs/protein_mc.yaml +0 -0
  34. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/docs/proteinmpnn.yaml +0 -0
  35. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/docs/rfdiffusion.yaml +0 -0
  36. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/esm_if1.py +0 -0
  37. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/protein_mc.py +0 -0
  38. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/proteinmpnn.py +0 -0
  39. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/design/rfdiffusion.py +0 -0
  40. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/display.py +0 -0
  41. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/doccard.py +0 -0
  42. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/__init__.py +0 -0
  43. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/boltz2.py +0 -0
  44. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/docs/boltz2.yaml +0 -0
  45. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/docs/esmfold.yaml +0 -0
  46. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/docs/openfold3.yaml +0 -0
  47. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/docs/protenix.yaml +0 -0
  48. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/esmfold.py +0 -0
  49. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/openfold3.py +0 -0
  50. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/folding/protenix.py +0 -0
  51. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/__init__.py +0 -0
  52. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/autodock_vina.py +0 -0
  53. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/diffdock.py +0 -0
  54. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/dockq.py +0 -0
  55. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/autodock_vina.yaml +0 -0
  56. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/diffdock.yaml +0 -0
  57. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/dockq.yaml +0 -0
  58. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/emngly.yaml +0 -0
  59. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/glycosylation_ensemble.yaml +0 -0
  60. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/interface_identifier.yaml +0 -0
  61. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/isoglyp.yaml +0 -0
  62. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/lmngly.yaml +0 -0
  63. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/p2rank.yaml +0 -0
  64. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/docs/pesto.yaml +0 -0
  65. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/emngly.py +0 -0
  66. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/glycosylation_ensemble.py +0 -0
  67. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/interface_identifier.py +0 -0
  68. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/isoglyp.py +0 -0
  69. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/lmngly.py +0 -0
  70. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/p2rank.py +0 -0
  71. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/interactions/pesto.py +0 -0
  72. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/properties/__init__.py +0 -0
  73. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/properties/aminosol.py +0 -0
  74. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/properties/docs/aminosol.yaml +0 -0
  75. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/properties/docs/esm1v.yaml +0 -0
  76. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/properties/docs/esm2_embedding.yaml +0 -0
  77. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/properties/esm1v.py +0 -0
  78. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/properties/esm2_embedding.py +0 -0
  79. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/__init__.py +0 -0
  80. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/activesite_verifier.py +0 -0
  81. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/chain_select.py +0 -0
  82. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/distance_calculator.py +0 -0
  83. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/activesite_verifier.yaml +0 -0
  84. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/chain_select.yaml +0 -0
  85. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/distance_calculator.yaml +0 -0
  86. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/maxit_convert.yaml +0 -0
  87. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/mol_size_calculator.yaml +0 -0
  88. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/obabel_convert.yaml +0 -0
  89. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/pdb_bfactor_overwrite.yaml +0 -0
  90. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/pdb_cleaner.yaml +0 -0
  91. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/pdb_quality_assessment.yaml +0 -0
  92. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/pdb_to_fasta.yaml +0 -0
  93. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/docs/protein_relaxer.yaml +0 -0
  94. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/maxit_convert.py +0 -0
  95. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/mol_size_calculator.py +0 -0
  96. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/obabel_convert.py +0 -0
  97. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/pdb_bfactor_overwrite.py +0 -0
  98. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/pdb_cleaner.py +0 -0
  99. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/pdb_quality_assessment.py +0 -0
  100. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/pdb_to_fasta.py +0 -0
  101. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools/utilities/protein_relaxer.py +0 -0
  102. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/commands/tools_cmd.py +0 -0
  103. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/main.py +0 -0
  104. {amina_cli-0.4.0 → amina_cli-0.4.1}/src/amina_cli/registry.py +0 -0
  105. {amina_cli-0.4.0 → amina_cli-0.4.1}/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.4.0
3
+ Version: 0.4.1
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.4.0"
3
+ version = "0.4.1"
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.4.0"
12
+ __version__ = "0.4.1"
@@ -824,7 +824,10 @@ def _find_submission_files(root: Path, recursive: bool) -> list[tuple[str, Path]
824
824
 
825
825
  Returns a list of ``(job_id, dir_containing_submission)`` tuples. Files
826
826
  that fail to parse or lack a ``job_id`` field are skipped silently — they
827
- weren't written by ``amina run --background``.
827
+ correspond to runs that aborted before the gateway returned (submit error,
828
+ interrupt, network failure), leaving the up-front input record without
829
+ any job-tracking fields ever being merged in. There is no server-side
830
+ job to reconcile in those cases.
828
831
  """
829
832
  pattern = "**/submission.json" if recursive else "*/submission.json"
830
833
  found: list[tuple[str, Path]] = []
@@ -8,6 +8,7 @@ Each tool file exports METADATA dict and register() function.
8
8
  import importlib
9
9
  import json
10
10
  import os
11
+ import sys
11
12
  from pathlib import Path
12
13
  from typing import Iterator, Optional
13
14
  import typer
@@ -15,6 +16,7 @@ from rich.console import Console
15
16
  from rich.panel import Panel
16
17
  from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
17
18
 
19
+ from amina_cli import __version__ as _CLI_VERSION
18
20
  from amina_cli.commands.tools.display import render_tool_output
19
21
 
20
22
  console = Console()
@@ -23,6 +25,17 @@ console = Console()
23
25
  err_console = Console(stderr=True)
24
26
 
25
27
 
28
+ def _reproducibility_fields() -> dict:
29
+ """Fields recorded in submission.json so a run can be re-executed exactly.
30
+
31
+ ``argv`` is the literal ``sys.argv`` of the current process — the user's
32
+ command-line invocation, preserved as a list. ``cli_version`` pins the
33
+ amina-cli version that built the request, so future readers can match the
34
+ parameter shape against the release that produced it.
35
+ """
36
+ return {"cli_version": _CLI_VERSION, "argv": list(sys.argv)}
37
+
38
+
26
39
  def _is_truthy_env(name: str) -> bool:
27
40
  """Standard env-var boolean read.
28
41
 
@@ -124,6 +137,11 @@ def run_tool_with_progress(
124
137
  console.print("[red]Error:[/red] --output / -o is required")
125
138
  raise typer.Exit(1)
126
139
 
140
+ # Snapshot once at function entry so the early and late submission.json
141
+ # writes agree on argv even if a caller (e.g. tests) mutates sys.argv
142
+ # mid-run.
143
+ repro = _reproducibility_fields()
144
+
127
145
  # Handle background submission
128
146
  if background:
129
147
  # Resolved before the try so error handlers can route to stderr
@@ -135,6 +153,20 @@ def run_tool_with_progress(
135
153
  tool_info = get_tool(tool_name)
136
154
  display_name = tool_info.get("display_name", tool_name) if tool_info else tool_name
137
155
 
156
+ # Early submission.json write — before any network call — so a
157
+ # reproducibility record exists even if submission fails (auth,
158
+ # credits, validation, network). Overwritten below with the
159
+ # augmented record once submit_tool_sync returns successfully.
160
+ output_dir.mkdir(parents=True, exist_ok=True)
161
+ submission_path = output_dir / "submission.json"
162
+ submission_path.write_text(
163
+ json.dumps(
164
+ {"tool_name": tool_name, "params": params, **repro},
165
+ indent=2,
166
+ default=str,
167
+ )
168
+ )
169
+
138
170
  if json_mode:
139
171
  # No spinner output to stdout when the caller wants JSON.
140
172
  result = submit_tool_sync(tool_name, params)
@@ -147,13 +179,30 @@ def run_tool_with_progress(
147
179
  progress.add_task(f"Submitting {display_name}...", total=None)
148
180
  result = submit_tool_sync(tool_name, params)
149
181
 
150
- # Save to local job history
151
- save_job(result)
152
-
153
- # Persist the structured submission payload for downstream agents/scripts
154
- output_dir.mkdir(parents=True, exist_ok=True)
155
- submission_path = output_dir / "submission.json"
156
- submission_path.write_text(json.dumps(result, indent=2, default=str))
182
+ # Save to local job history. Soft-fail on filesystem errors —
183
+ # the job is already submitted and being billed, so a stale
184
+ # local cache must not surface as a traceback that hides the
185
+ # job_id from the user.
186
+ warn_console = err_console if json_mode else console
187
+ try:
188
+ save_job(result)
189
+ except OSError as e:
190
+ warn_console.print(f"[yellow]Warning:[/yellow] Could not update local job history: {e}")
191
+
192
+ # Overwrite submission.json with the augmented record: input fields
193
+ # from the early write, plus the gateway tracking fields returned
194
+ # by submit_tool_sync (job_id, call_id, status, etc.). Soft-fail
195
+ # for the same reason as save_job above.
196
+ submission_record = {
197
+ "tool_name": tool_name,
198
+ "params": params,
199
+ **repro,
200
+ **result,
201
+ }
202
+ try:
203
+ submission_path.write_text(json.dumps(submission_record, indent=2, default=str))
204
+ except OSError as e:
205
+ warn_console.print(f"[yellow]Warning:[/yellow] Could not write {submission_path}: {e}")
157
206
 
158
207
  if json_mode:
159
208
  # Single-line JSON on stdout; nothing else, ever, in this branch.
@@ -276,6 +325,20 @@ def run_tool_with_progress(
276
325
  tool_info = get_tool(tool_name)
277
326
  display_name = tool_info.get("display_name", tool_name) if tool_info else tool_name
278
327
 
328
+ # Persist a reproducibility record up-front: written before submission so
329
+ # the user-facing inputs, CLI version, and argv survive mid-run failures,
330
+ # interrupts, or network errors. response.json (written after the run)
331
+ # captures the result side.
332
+ output_dir.mkdir(parents=True, exist_ok=True)
333
+ submission_path = output_dir / "submission.json"
334
+ submission_path.write_text(
335
+ json.dumps(
336
+ {"tool_name": tool_name, "params": params, **repro},
337
+ indent=2,
338
+ default=str,
339
+ )
340
+ )
341
+
279
342
  # Track queue position for progress updates
280
343
  queue_position_holder = {"position": 0, "is_queued": False}
281
344
 
@@ -337,9 +400,28 @@ def run_tool_with_progress(
337
400
 
338
401
  # Persist the structured response payload (success or failure) so agents
339
402
  # and scripts can read metrics/warnings/cost without re-parsing stdout.
340
- output_dir.mkdir(parents=True, exist_ok=True)
403
+ # Soft-fail on filesystem errors — the job has already run and been
404
+ # billed, so a disk hiccup must not surface as a traceback.
341
405
  response_path = output_dir / "response.json"
342
- response_path.write_text(json.dumps(result, indent=2, default=str))
406
+ try:
407
+ response_path.write_text(json.dumps(result, indent=2, default=str))
408
+ except OSError as e:
409
+ console.print(f"[yellow]Warning:[/yellow] Could not write {response_path}: {e}")
410
+
411
+ # Overwrite submission.json with the augmented record. Spreading
412
+ # **result mirrors the background path so consumers see the same
413
+ # shape on both, and the status field reflects what the worker
414
+ # actually reported. Soft-fail for the same reason as response.json.
415
+ submission_record = {
416
+ "tool_name": tool_name,
417
+ "params": params,
418
+ **repro,
419
+ **result,
420
+ }
421
+ try:
422
+ submission_path.write_text(json.dumps(submission_record, indent=2, default=str))
423
+ except OSError as e:
424
+ console.print(f"[yellow]Warning:[/yellow] Could not write {submission_path}: {e}")
343
425
 
344
426
  _display_result(result, downloaded, output_dir, params, tool_info, response_path)
345
427
 
File without changes
File without changes
File without changes