aioli-cli 0.1.45__tar.gz → 0.1.48__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 (124) hide show
  1. aioli_cli-0.1.48/.gitignore +20 -0
  2. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/PKG-INFO +22 -17
  3. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/README.md +21 -16
  4. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/pyproject.toml +24 -10
  5. aioli_cli-0.1.48/src/aioli_cli/backend_manager.py +1764 -0
  6. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_cli/main.py +217 -4
  7. aioli_cli-0.1.48/src/aioli_cli/managed.py +252 -0
  8. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_cli/readiness.py +110 -5
  9. aioli_cli-0.1.48/src/aioli_cli/registry.py +91 -0
  10. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_cli/setup.py +333 -78
  11. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/__init__.py +14 -0
  12. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/advise.py +119 -1
  13. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/config.py +84 -0
  14. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/fetch.py +578 -47
  15. aioli_cli-0.1.48/src/aioli_contract/model_ids.py +161 -0
  16. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/probe.py +52 -13
  17. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/readiness.py +25 -1
  18. aioli_cli-0.1.48/src/aioli_contract/short_verb.py +47 -0
  19. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/cli.py +134 -1
  20. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/config.py +52 -17
  21. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/data/models.toml +37 -0
  22. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/launcher.py +358 -30
  23. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/models.py +34 -1
  24. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/models_data.py +139 -8
  25. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_master/cli.py +15 -2
  26. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_master/ops.py +32 -8
  27. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/minimax_comfy.py +40 -1
  28. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/process.py +114 -25
  29. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/yue2.py +13 -0
  30. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/cli_commands/generate_cmd.py +117 -11
  31. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/core/generate.py +56 -2
  32. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/models_data.py +15 -2
  33. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/plugin.py +9 -1
  34. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/presets.py +11 -2
  35. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/server.py +106 -32
  36. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/transport/client.py +180 -10
  37. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_podcast/cast.py +59 -3
  38. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_podcast/cli.py +22 -3
  39. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_podcast/episode.py +125 -9
  40. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/cli.py +100 -10
  41. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/models_data.py +8 -0
  42. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/wgp.py +65 -2
  43. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/cli/generate.py +71 -6
  44. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/core/generation.py +41 -5
  45. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/kokoro.py +7 -2
  46. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/voxcpm.py +3 -2
  47. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/models_data.py +22 -0
  48. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/plugin.py +9 -1
  49. aioli_cli-0.1.45/.gitignore +0 -11
  50. aioli_cli-0.1.45/src/aioli_cli/registry.py +0 -50
  51. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/LICENSE +0 -0
  52. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_cli/_plugins.py +0 -0
  53. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_cli/fetch_ui.py +0 -0
  54. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_cli/status.py +0 -0
  55. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/doctor.py +0 -0
  56. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_contract/ui.py +0 -0
  57. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/__init__.py +0 -0
  58. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/companions.py +0 -0
  59. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/doctor.py +0 -0
  60. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/gpu.py +0 -0
  61. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/plugin.py +0 -0
  62. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/presets.py +0 -0
  63. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/progress.py +0 -0
  64. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/stub.py +0 -0
  65. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_image/ui.py +0 -0
  66. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_master/doctor.py +0 -0
  67. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_master/plugin.py +0 -0
  68. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/__init__.py +0 -0
  69. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/__init__.py +0 -0
  70. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/acestep.py +0 -0
  71. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/base.py +0 -0
  72. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/llm_caption.py +0 -0
  73. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/backends/stub.py +0 -0
  74. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/cli_commands/__init__.py +0 -0
  75. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/cli_commands/backend_cmd.py +0 -0
  76. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/cli_commands/inspire_cmd.py +0 -0
  77. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/cli_commands/models_cmd.py +0 -0
  78. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/client.py +0 -0
  79. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/config.py +0 -0
  80. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/config_data/default.toml +0 -0
  81. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/core/__init__.py +0 -0
  82. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/core/formats.py +0 -0
  83. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/core/jobs.py +0 -0
  84. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/core/layout.py +0 -0
  85. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/doctor.py +0 -0
  86. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/generator.py +0 -0
  87. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/history.py +0 -0
  88. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/jsonstore.py +0 -0
  89. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/models.py +0 -0
  90. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/paths.py +0 -0
  91. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/prompts.py +0 -0
  92. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/transport/__init__.py +0 -0
  93. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_music/tui.py +0 -0
  94. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_podcast/doctor.py +0 -0
  95. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_podcast/feed.py +0 -0
  96. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_podcast/plugin.py +0 -0
  97. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_podcast/script.py +0 -0
  98. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/__init__.py +0 -0
  99. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/doctor.py +0 -0
  100. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/paths.py +0 -0
  101. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/plugin.py +0 -0
  102. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/stub.py +0 -0
  103. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_video/worker.py +0 -0
  104. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/__init__.py +0 -0
  105. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/cli/doctor.py +0 -0
  106. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/cli/engines_cmd.py +0 -0
  107. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/cli/models_cmd.py +0 -0
  108. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/cli/profiles.py +0 -0
  109. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/config/__init__.py +0 -0
  110. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/config/settings.py +0 -0
  111. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/core/__init__.py +0 -0
  112. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/core/model_manager.py +0 -0
  113. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/core/profiles.py +0 -0
  114. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/core/registry.py +0 -0
  115. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/core/types.py +0 -0
  116. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/devices.py +0 -0
  117. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/doctor.py +0 -0
  118. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/__init__.py +0 -0
  119. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/chatterbox.py +0 -0
  120. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/moss.py +0 -0
  121. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/piper.py +0 -0
  122. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/qwen3.py +0 -0
  123. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/stub.py +0 -0
  124. {aioli_cli-0.1.45 → aioli_cli-0.1.48}/src/aioli_voice/engines/xtts.py +0 -0
@@ -0,0 +1,20 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+
5
+ # caches de herramientas (I6): un `git add -A` no debe commitearlas
6
+ .mypy_cache/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+
10
+ # cobertura (I4): artefactos del run, se regeneran
11
+ .coverage
12
+ coverage.xml
13
+
14
+ # web
15
+ web/node_modules/
16
+ web/dist/
17
+ web/.astro/
18
+
19
+ dist/
20
+ .kaudit/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: aioli-cli
3
- Version: 0.1.45
3
+ Version: 0.1.48
4
4
  Summary: aioli — local-first AI media suite CLI (images, video, music, voice, podcast)
5
5
  Author: aioli contributors
6
6
  License: MIT
@@ -57,10 +57,10 @@ Description-Content-Type: text/markdown
57
57
 
58
58
  | Plugin | Produces | Example |
59
59
  | --- | --- | --- |
60
- | 🎙️ `voice` | Cloned or synthetic voice as WAV (native Spanish with chatterbox, free CPU drafts with piper) | `aioli voice generate "Hola mundo" --profile vega --engine chatterbox -o hola.wav` |
61
- | 🎵 `music` | Full song (vocals + instruments) from a style and your lyrics — it sings in Spanish | `aioli music generate --preset reggae-consciente --backend yue2 -l my-lyrics.txt -o track.mp3` |
62
- | 🖼️ `image` | Image from text, editing, inpainting or character reference (~9 s with FLUX-klein-4b) | `aioli image generate "a robot garlic" -m z_image_turbo` |
63
- | 🎬 `video` | MP4 clip with synced audio from text or image | `aioli video generate "a robot garlic dancing" --frames 81 -o ajo.mp4` |
60
+ | 🎙️ `voice` | Cloned or synthetic voice as WAV (native Spanish with chatterbox, free CPU drafts with piper) | `aioli voice "Hola mundo" --profile vega -o hola.wav` |
61
+ | 🎵 `music` | Full song (vocals + instruments) from a style and your lyrics — it sings in Spanish | `aioli music --preset reggae-consciente -l my-lyrics.txt -o track.mp3` |
62
+ | 🖼️ `image` | Image from text, editing, inpainting or character reference (~9 s with FLUX-klein-4b) | `aioli image "a robot garlic"` |
63
+ | 🎬 `video` | MP4 clip with synced audio from text or image | `aioli video "a robot garlic dancing" --frames 81 -o ajo.mp4` |
64
64
  | 🎧 `master` | Audio finishing with ffmpeg: mix, ducking, denoise, `-16 LUFS` | `aioli master loudnorm mix.wav -o final.wav` |
65
65
  | 📻 `podcast` | MP3 episode + show notes from a script (voices + music bed + pauses) | `aioli podcast episode script.md -o ./ep1` |
66
66
 
@@ -69,7 +69,7 @@ with these commands. No accounts, no subscription.
69
69
 
70
70
  ## How it works
71
71
 
72
- 1. `aioli setup` inspects your machine and tells you what fits your GPU.
72
+ 1. `aioli install` inspects your machine and tells you what fits your GPU.
73
73
  2. `aioli models download` fetches verified weights (sha256, resumable)
74
74
  into `~/.local/share/aioli` (or wherever `AIOLI_MODELS_DIR` points).
75
75
  3. You generate locally: not a byte leaves your machine. No accounts, no
@@ -79,15 +79,16 @@ with these commands. No accounts, no subscription.
79
79
  ## Install
80
80
 
81
81
  ```bash
82
- curl -fsSL https://aioli.es/install.sh | sh # installs uv+ffmpeg if missing → doctor → setup → status
83
- # …or truly by hand (needs `uv`, Python ≥3.12 and `ffmpeg`):
84
- uv tool install aioli-cli # extras: aioli-cli[voice-piper,music-storage]
85
- aioli setup # tells you what fits your GPU, downloads weights
86
- aioli doctor # preflight: CUDA, ffmpeg, models, VRAM
82
+ curl -fsSL https://aioli.es/install.sh | sh # installs uv+ffmpeg if missing → doctor → setup → status (setup = vía compat del instalador; equivale a `aioli install`)
83
+ # …or truly by hand (needs `uv`, Python ≥3.12 and `ffmpeg`) — two commands, no extras:
84
+ uv tool install aioli-cli # the CLI only (base dist, sin extras)
85
+ aioli setup # usage screen: tick what you want; the assistant installs piper/kokoro and downloads only that
86
+ aioli doctor # preflight: CUDA, ffmpeg, models, VRAM
87
+ # advanced alternative: `uv tool install "aioli-cli[voice-piper,music-storage]"` still works; torch worlds stay manual (`--with`, see plugins/voice/README.md)
87
88
  ```
88
89
 
89
90
  For top-tier image and video (Flux, LTX), accept their license on
90
- huggingface.co and export `HF_TOKEN` (read-only token) before `setup`.
91
+ huggingface.co and export `HF_TOKEN` (read-only token) before install.
91
92
 
92
93
  > 🔒 Paranoid (good): the installer lives in the repo's `install.sh`.
93
94
  > It only uses the network for `astral.sh` (uv), GitHub and HuggingFace.
@@ -104,27 +105,31 @@ huggingface.co and export `HF_TOKEN` (read-only token) before `setup`.
104
105
  | Disk | 15 GB (one plugin) | 100 GB (full set ≈ 60 GB) |
105
106
  | Account | — | free HuggingFace (for Flux and LTX, licensed) |
106
107
 
107
- `aioli setup` detects your machine (tier `patata/modesta/capaz/bicha` —
108
+ `aioli install` detects your machine (tier `patata/modesta/capaz/bicha` —
108
109
  yes, potato to beast) and only downloads what fits. Weights are sha256
109
110
  verified and resume if your connection drops.
110
111
 
111
112
  ## Usage
112
113
 
114
+ Camino feliz: `aioli install` → `aioli <plugin> "texto"` → `aioli doctor`
115
+ (solo si algo falla). Per-model recipes live in `docs/USAGE.md`.
116
+
113
117
  ```bash
114
118
  # image: text → PNG (editing, inpainting and reference available)
115
- aioli image generate "a lighthouse in the fog" -m z_image_turbo
119
+ aioli image "a lighthouse in the fog"
120
+ aioli image "a lighthouse in the fog" -m z-image-turbo -o faro.png
116
121
 
117
122
  # music: style + your lyrics → full song
118
- aioli music generate "cheerful rumba" --backend yue2
123
+ aioli music "cheerful rumba" -l my-lyrics.txt -o track.mp3
119
124
  aioli music generate --preset reggae-consciente -l my-lyrics.txt -o track.mp3
120
125
 
121
126
  # voice: create profile, add a sample with its transcript, generate
122
127
  aioli voice profiles create vega --language es
123
128
  aioli voice profiles add-sample vega ref.wav -t "exact audio transcript"
124
- aioli voice generate "Hola mundo" --profile vega --engine chatterbox -o hola.wav
129
+ aioli voice "Hola mundo" --profile vega --engine chatterbox -o hola.wav
125
130
 
126
131
  # video: text or image → clip with audio
127
- aioli video generate "a robot garlic dancing" --frames 81 -o ajo.mp4
132
+ aioli video "a robot garlic dancing" --frames 81 -o ajo.mp4
128
133
 
129
134
  # podcast: script with [VOICES], [MUSIC:] and [PAUSE:] → episode + notes
130
135
  aioli podcast episode script.md -o ./ep1
@@ -25,10 +25,10 @@
25
25
 
26
26
  | Plugin | Produces | Example |
27
27
  | --- | --- | --- |
28
- | 🎙️ `voice` | Cloned or synthetic voice as WAV (native Spanish with chatterbox, free CPU drafts with piper) | `aioli voice generate "Hola mundo" --profile vega --engine chatterbox -o hola.wav` |
29
- | 🎵 `music` | Full song (vocals + instruments) from a style and your lyrics — it sings in Spanish | `aioli music generate --preset reggae-consciente --backend yue2 -l my-lyrics.txt -o track.mp3` |
30
- | 🖼️ `image` | Image from text, editing, inpainting or character reference (~9 s with FLUX-klein-4b) | `aioli image generate "a robot garlic" -m z_image_turbo` |
31
- | 🎬 `video` | MP4 clip with synced audio from text or image | `aioli video generate "a robot garlic dancing" --frames 81 -o ajo.mp4` |
28
+ | 🎙️ `voice` | Cloned or synthetic voice as WAV (native Spanish with chatterbox, free CPU drafts with piper) | `aioli voice "Hola mundo" --profile vega -o hola.wav` |
29
+ | 🎵 `music` | Full song (vocals + instruments) from a style and your lyrics — it sings in Spanish | `aioli music --preset reggae-consciente -l my-lyrics.txt -o track.mp3` |
30
+ | 🖼️ `image` | Image from text, editing, inpainting or character reference (~9 s with FLUX-klein-4b) | `aioli image "a robot garlic"` |
31
+ | 🎬 `video` | MP4 clip with synced audio from text or image | `aioli video "a robot garlic dancing" --frames 81 -o ajo.mp4` |
32
32
  | 🎧 `master` | Audio finishing with ffmpeg: mix, ducking, denoise, `-16 LUFS` | `aioli master loudnorm mix.wav -o final.wav` |
33
33
  | 📻 `podcast` | MP3 episode + show notes from a script (voices + music bed + pauses) | `aioli podcast episode script.md -o ./ep1` |
34
34
 
@@ -37,7 +37,7 @@ with these commands. No accounts, no subscription.
37
37
 
38
38
  ## How it works
39
39
 
40
- 1. `aioli setup` inspects your machine and tells you what fits your GPU.
40
+ 1. `aioli install` inspects your machine and tells you what fits your GPU.
41
41
  2. `aioli models download` fetches verified weights (sha256, resumable)
42
42
  into `~/.local/share/aioli` (or wherever `AIOLI_MODELS_DIR` points).
43
43
  3. You generate locally: not a byte leaves your machine. No accounts, no
@@ -47,15 +47,16 @@ with these commands. No accounts, no subscription.
47
47
  ## Install
48
48
 
49
49
  ```bash
50
- curl -fsSL https://aioli.es/install.sh | sh # installs uv+ffmpeg if missing → doctor → setup → status
51
- # …or truly by hand (needs `uv`, Python ≥3.12 and `ffmpeg`):
52
- uv tool install aioli-cli # extras: aioli-cli[voice-piper,music-storage]
53
- aioli setup # tells you what fits your GPU, downloads weights
54
- aioli doctor # preflight: CUDA, ffmpeg, models, VRAM
50
+ curl -fsSL https://aioli.es/install.sh | sh # installs uv+ffmpeg if missing → doctor → setup → status (setup = vía compat del instalador; equivale a `aioli install`)
51
+ # …or truly by hand (needs `uv`, Python ≥3.12 and `ffmpeg`) — two commands, no extras:
52
+ uv tool install aioli-cli # the CLI only (base dist, sin extras)
53
+ aioli setup # usage screen: tick what you want; the assistant installs piper/kokoro and downloads only that
54
+ aioli doctor # preflight: CUDA, ffmpeg, models, VRAM
55
+ # advanced alternative: `uv tool install "aioli-cli[voice-piper,music-storage]"` still works; torch worlds stay manual (`--with`, see plugins/voice/README.md)
55
56
  ```
56
57
 
57
58
  For top-tier image and video (Flux, LTX), accept their license on
58
- huggingface.co and export `HF_TOKEN` (read-only token) before `setup`.
59
+ huggingface.co and export `HF_TOKEN` (read-only token) before install.
59
60
 
60
61
  > 🔒 Paranoid (good): the installer lives in the repo's `install.sh`.
61
62
  > It only uses the network for `astral.sh` (uv), GitHub and HuggingFace.
@@ -72,27 +73,31 @@ huggingface.co and export `HF_TOKEN` (read-only token) before `setup`.
72
73
  | Disk | 15 GB (one plugin) | 100 GB (full set ≈ 60 GB) |
73
74
  | Account | — | free HuggingFace (for Flux and LTX, licensed) |
74
75
 
75
- `aioli setup` detects your machine (tier `patata/modesta/capaz/bicha` —
76
+ `aioli install` detects your machine (tier `patata/modesta/capaz/bicha` —
76
77
  yes, potato to beast) and only downloads what fits. Weights are sha256
77
78
  verified and resume if your connection drops.
78
79
 
79
80
  ## Usage
80
81
 
82
+ Camino feliz: `aioli install` → `aioli <plugin> "texto"` → `aioli doctor`
83
+ (solo si algo falla). Per-model recipes live in `docs/USAGE.md`.
84
+
81
85
  ```bash
82
86
  # image: text → PNG (editing, inpainting and reference available)
83
- aioli image generate "a lighthouse in the fog" -m z_image_turbo
87
+ aioli image "a lighthouse in the fog"
88
+ aioli image "a lighthouse in the fog" -m z-image-turbo -o faro.png
84
89
 
85
90
  # music: style + your lyrics → full song
86
- aioli music generate "cheerful rumba" --backend yue2
91
+ aioli music "cheerful rumba" -l my-lyrics.txt -o track.mp3
87
92
  aioli music generate --preset reggae-consciente -l my-lyrics.txt -o track.mp3
88
93
 
89
94
  # voice: create profile, add a sample with its transcript, generate
90
95
  aioli voice profiles create vega --language es
91
96
  aioli voice profiles add-sample vega ref.wav -t "exact audio transcript"
92
- aioli voice generate "Hola mundo" --profile vega --engine chatterbox -o hola.wav
97
+ aioli voice "Hola mundo" --profile vega --engine chatterbox -o hola.wav
93
98
 
94
99
  # video: text or image → clip with audio
95
- aioli video generate "a robot garlic dancing" --frames 81 -o ajo.mp4
100
+ aioli video "a robot garlic dancing" --frames 81 -o ajo.mp4
96
101
 
97
102
  # podcast: script with [VOICES], [MUSIC:] and [PAUSE:] → episode + notes
98
103
  aioli podcast episode script.md -o ./ep1
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aioli-cli"
3
- version = "0.1.45"
3
+ version = "0.1.48"
4
4
  description = "aioli — local-first AI media suite CLI (images, video, music, voice, podcast)"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -100,6 +100,12 @@ only-include = [
100
100
  "LICENSE",
101
101
  ]
102
102
 
103
+ # Gate de tipos canónico del repo: `mypy src` (los 8 paquetes del wheel único,
104
+ # 111 ficheros en verde). `libs/*` y `plugins/*` no aportan código (ver ADR-005),
105
+ # así que un typecheck por miembro sería un falso scope. Lo consume wave-gate.
106
+ [tool.wave-gate]
107
+ typecheck = "mypy src"
108
+
103
109
  [tool.pytest.ini_options]
104
110
  pythonpath = ["src"]
105
111
  testpaths = [
@@ -111,7 +117,11 @@ testpaths = [
111
117
  "plugins/podcast/tests",
112
118
  "plugins/master/tests",
113
119
  ]
114
- addopts = "-q"
120
+ # I4 (2026-10-05, wave-7/T28): cobertura MEDIDA en el run normal (pytest-cov,
121
+ # dev dep). Sin `fail-under` ni exclusiones: medir no es un gate, y un umbral
122
+ # inventado sin baseline sería ruido. Regresión de config:
123
+ # `libs/contract/tests/test_bootstrap.py::TestCoverageConfig`.
124
+ addopts = "-q --cov=src --cov-report=term-missing --cov-report=xml"
115
125
  # Markers: "network" sube a upstream real (gasta red y disco). Opt-in via
116
126
  # AIOLI_NET_TESTS=1, lo activa el job smoke-bundles de release.yml.
117
127
  markers = [
@@ -121,6 +131,7 @@ markers = [
121
131
  [dependency-groups]
122
132
  dev = [
123
133
  "pytest>=8.0",
134
+ "pytest-cov>=7.0", # I4: cobertura del run normal (term-missing + xml)
124
135
  "pillow>=10.0", # solo tests (stubs de imagen); nunca en dependencies
125
136
  # H0.4: tooling de CI pineado aqui (no en `uvx` run-steps) para que
126
137
  # dependabot lo renueve: no ve herramientas invocadas con `uvx` en los
@@ -161,15 +172,18 @@ ignore_missing_imports = true
161
172
  module = ["soundfile", "soundfile.*", "tqdm"]
162
173
  ignore_missing_imports = true
163
174
 
164
- # Out-of-venv checkers (session lens) run mypy WITHOUT the project venv:
165
- # pytest (dev dep) and aioli_contract (workspace pkg in libs/contract, editable
166
- # in .venv) don't resolve there and mypy reports import-not-found — false
167
- # positive. In the real env they resolve (`.venv/bin/python -c "import pytest,
168
- # aioli_contract"` OK; ruff + pytest --collect-only green on libs/contract/tests).
169
- # ignore_missing_imports only fires when resolution fails, so the repo's own
170
- # venv runs keep full checking.
175
+ # I3 (2026-10-05, wave-7/T27): los paquetes PROPIOS (`aioli_*`) salen de aquí.
176
+ # Estaban por el falso positivo F-10 (mypy sin venv no resolvía `src/`), pero
177
+ # `ignore_missing_imports` sobre un paquete propio silencia justo lo que debe
178
+ # fallar: un import roto de `aioli_contract`/`aioli_cli`/... pasaba verde.
179
+ # `mypy_path = "src"` + `explicit_package_bases` ya resuelven los paquetes
180
+ # propios con la config leída desde la raíz, que es como lo ejecuta wave-gate y
181
+ # el job `test` de release.yml. Regresión:
182
+ # `libs/contract/tests/test_models_import.py::TestOwnImports`.
183
+ # pytest (dev dep) sí sigue fuera del venv en algunos lenses: ese override se
184
+ # queda.
171
185
  [[tool.mypy.overrides]]
172
- module = ["pytest", "pytest.*", "aioli_contract", "aioli_contract.*"]
186
+ module = ["pytest", "pytest.*"]
173
187
  ignore_missing_imports = true
174
188
 
175
189
  # DEBT: aioli_music.core.jobs imports aioli_music.core.storage, which does not