agent-cli 0.67.1__py3-none-any.whl → 0.68.0__py3-none-any.whl
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.
- agent_cli/_requirements/mlx-whisper.txt +44 -85
- agent_cli/core/deps.py +102 -50
- agent_cli/core/utils.py +2 -2
- agent_cli/install/extras.py +38 -20
- {agent_cli-0.67.1.dist-info → agent_cli-0.68.0.dist-info}/METADATA +11 -4
- {agent_cli-0.67.1.dist-info → agent_cli-0.68.0.dist-info}/RECORD +9 -9
- {agent_cli-0.67.1.dist-info → agent_cli-0.68.0.dist-info}/WHEEL +0 -0
- {agent_cli-0.67.1.dist-info → agent_cli-0.68.0.dist-info}/entry_points.txt +0 -0
- {agent_cli-0.67.1.dist-info → agent_cli-0.68.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This file was autogenerated by uv via the following command:
|
|
2
2
|
# uv export --extra mlx-whisper --no-dev --no-emit-project --no-hashes
|
|
3
|
-
annotated-doc==0.0.4
|
|
3
|
+
annotated-doc==0.0.4 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
4
4
|
# via fastapi
|
|
5
5
|
annotated-types==0.7.0
|
|
6
6
|
# via pydantic
|
|
@@ -15,7 +15,7 @@ certifi==2026.1.4
|
|
|
15
15
|
# httpx
|
|
16
16
|
# requests
|
|
17
17
|
# sentry-sdk
|
|
18
|
-
charset-normalizer==3.4.4
|
|
18
|
+
charset-normalizer==3.4.4 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
19
19
|
# via requests
|
|
20
20
|
click==8.3.1
|
|
21
21
|
# via
|
|
@@ -35,19 +35,19 @@ email-validator==2.3.0
|
|
|
35
35
|
# via
|
|
36
36
|
# fastapi
|
|
37
37
|
# pydantic
|
|
38
|
-
fastapi==0.128.0
|
|
38
|
+
fastapi==0.128.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
39
39
|
# via agent-cli
|
|
40
|
-
fastapi-cli==0.0.20
|
|
40
|
+
fastapi-cli==0.0.20 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
41
41
|
# via fastapi
|
|
42
|
-
fastapi-cloud-cli==0.10.1
|
|
42
|
+
fastapi-cloud-cli==0.10.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
43
43
|
# via fastapi-cli
|
|
44
|
-
fastar==0.8.0
|
|
44
|
+
fastar==0.8.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
45
45
|
# via fastapi-cloud-cli
|
|
46
|
-
filelock==3.20.3
|
|
46
|
+
filelock==3.20.3 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
47
47
|
# via
|
|
48
48
|
# huggingface-hub
|
|
49
49
|
# torch
|
|
50
|
-
fsspec==2026.1.0
|
|
50
|
+
fsspec==2026.1.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
51
51
|
# via
|
|
52
52
|
# huggingface-hub
|
|
53
53
|
# torch
|
|
@@ -55,18 +55,18 @@ h11==0.16.0
|
|
|
55
55
|
# via
|
|
56
56
|
# httpcore
|
|
57
57
|
# uvicorn
|
|
58
|
-
hf-xet==1.2.0 ; platform_machine == '
|
|
58
|
+
hf-xet==1.2.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
59
59
|
# via huggingface-hub
|
|
60
60
|
httpcore==1.0.9
|
|
61
61
|
# via httpx
|
|
62
|
-
httptools==0.7.1
|
|
62
|
+
httptools==0.7.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
63
63
|
# via uvicorn
|
|
64
64
|
httpx==0.28.1
|
|
65
65
|
# via
|
|
66
66
|
# agent-cli
|
|
67
67
|
# fastapi
|
|
68
68
|
# fastapi-cloud-cli
|
|
69
|
-
huggingface-hub==0.36.0
|
|
69
|
+
huggingface-hub==0.36.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
70
70
|
# via mlx-whisper
|
|
71
71
|
idna==3.11
|
|
72
72
|
# via
|
|
@@ -74,77 +74,38 @@ idna==3.11
|
|
|
74
74
|
# email-validator
|
|
75
75
|
# httpx
|
|
76
76
|
# requests
|
|
77
|
-
jinja2==3.1.6
|
|
77
|
+
jinja2==3.1.6 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
78
78
|
# via
|
|
79
79
|
# fastapi
|
|
80
80
|
# torch
|
|
81
|
-
llvmlite==0.46.0
|
|
81
|
+
llvmlite==0.46.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
82
82
|
# via numba
|
|
83
83
|
markdown-it-py==4.0.0
|
|
84
84
|
# via rich
|
|
85
|
-
markupsafe==3.0.3
|
|
85
|
+
markupsafe==3.0.3 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
86
86
|
# via jinja2
|
|
87
87
|
mdurl==0.1.2
|
|
88
88
|
# via markdown-it-py
|
|
89
|
-
mlx==0.30.3
|
|
89
|
+
mlx==0.30.3 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
90
90
|
# via mlx-whisper
|
|
91
|
-
mlx-metal==0.30.3 ; sys_platform == 'darwin'
|
|
91
|
+
mlx-metal==0.30.3 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
92
92
|
# via mlx
|
|
93
|
-
mlx-whisper==0.4.3
|
|
93
|
+
mlx-whisper==0.4.3 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
94
94
|
# via agent-cli
|
|
95
|
-
more-itertools==10.8.0
|
|
95
|
+
more-itertools==10.8.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
96
96
|
# via mlx-whisper
|
|
97
|
-
mpmath==1.3.0
|
|
97
|
+
mpmath==1.3.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
98
98
|
# via sympy
|
|
99
|
-
networkx==3.6.1
|
|
99
|
+
networkx==3.6.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
100
100
|
# via torch
|
|
101
|
-
numba==0.63.1
|
|
101
|
+
numba==0.63.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
102
102
|
# via mlx-whisper
|
|
103
|
-
numpy==2.3.5
|
|
103
|
+
numpy==2.3.5 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
104
104
|
# via
|
|
105
105
|
# mlx-whisper
|
|
106
106
|
# numba
|
|
107
107
|
# scipy
|
|
108
|
-
|
|
109
|
-
# via
|
|
110
|
-
# nvidia-cudnn-cu12
|
|
111
|
-
# nvidia-cusolver-cu12
|
|
112
|
-
# torch
|
|
113
|
-
nvidia-cuda-cupti-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
114
|
-
# via torch
|
|
115
|
-
nvidia-cuda-nvrtc-cu12==12.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
116
|
-
# via torch
|
|
117
|
-
nvidia-cuda-runtime-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
118
|
-
# via torch
|
|
119
|
-
nvidia-cudnn-cu12==9.10.2.21 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
120
|
-
# via torch
|
|
121
|
-
nvidia-cufft-cu12==11.3.3.83 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
122
|
-
# via torch
|
|
123
|
-
nvidia-cufile-cu12==1.13.1.3 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
124
|
-
# via torch
|
|
125
|
-
nvidia-curand-cu12==10.3.9.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
126
|
-
# via torch
|
|
127
|
-
nvidia-cusolver-cu12==11.7.3.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
128
|
-
# via torch
|
|
129
|
-
nvidia-cusparse-cu12==12.5.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
130
|
-
# via
|
|
131
|
-
# nvidia-cusolver-cu12
|
|
132
|
-
# torch
|
|
133
|
-
nvidia-cusparselt-cu12==0.7.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
134
|
-
# via torch
|
|
135
|
-
nvidia-nccl-cu12==2.27.5 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
136
|
-
# via torch
|
|
137
|
-
nvidia-nvjitlink-cu12==12.8.93 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
138
|
-
# via
|
|
139
|
-
# nvidia-cufft-cu12
|
|
140
|
-
# nvidia-cusolver-cu12
|
|
141
|
-
# nvidia-cusparse-cu12
|
|
142
|
-
# torch
|
|
143
|
-
nvidia-nvshmem-cu12==3.3.20 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
144
|
-
# via torch
|
|
145
|
-
nvidia-nvtx-cu12==12.8.90 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
146
|
-
# via torch
|
|
147
|
-
packaging==25.0
|
|
108
|
+
packaging==25.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
148
109
|
# via huggingface-hub
|
|
149
110
|
psutil==7.2.1 ; sys_platform == 'win32'
|
|
150
111
|
# via agent-cli
|
|
@@ -157,9 +118,9 @@ pydantic==2.12.5
|
|
|
157
118
|
# pydantic-settings
|
|
158
119
|
pydantic-core==2.41.5
|
|
159
120
|
# via pydantic
|
|
160
|
-
pydantic-extra-types==2.11.0
|
|
121
|
+
pydantic-extra-types==2.11.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
161
122
|
# via fastapi
|
|
162
|
-
pydantic-settings==2.12.0
|
|
123
|
+
pydantic-settings==2.12.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
163
124
|
# via fastapi
|
|
164
125
|
pygments==2.19.2
|
|
165
126
|
# via rich
|
|
@@ -170,15 +131,15 @@ python-dotenv==1.2.1
|
|
|
170
131
|
# dotenv
|
|
171
132
|
# pydantic-settings
|
|
172
133
|
# uvicorn
|
|
173
|
-
python-multipart==0.0.21
|
|
134
|
+
python-multipart==0.0.21 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
174
135
|
# via fastapi
|
|
175
|
-
pyyaml==6.0.3
|
|
136
|
+
pyyaml==6.0.3 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
176
137
|
# via
|
|
177
138
|
# huggingface-hub
|
|
178
139
|
# uvicorn
|
|
179
|
-
regex==2026.1.15
|
|
140
|
+
regex==2026.1.15 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
180
141
|
# via tiktoken
|
|
181
|
-
requests==2.32.5
|
|
142
|
+
requests==2.32.5 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
182
143
|
# via
|
|
183
144
|
# huggingface-hub
|
|
184
145
|
# tiktoken
|
|
@@ -187,36 +148,34 @@ rich==14.2.0
|
|
|
187
148
|
# agent-cli
|
|
188
149
|
# rich-toolkit
|
|
189
150
|
# typer
|
|
190
|
-
rich-toolkit==0.17.1
|
|
151
|
+
rich-toolkit==0.17.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
191
152
|
# via
|
|
192
153
|
# fastapi-cli
|
|
193
154
|
# fastapi-cloud-cli
|
|
194
|
-
rignore==0.7.6
|
|
155
|
+
rignore==0.7.6 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
195
156
|
# via fastapi-cloud-cli
|
|
196
|
-
scipy==1.17.0
|
|
157
|
+
scipy==1.17.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
197
158
|
# via mlx-whisper
|
|
198
|
-
sentry-sdk==2.49.0
|
|
159
|
+
sentry-sdk==2.49.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
199
160
|
# via fastapi-cloud-cli
|
|
200
161
|
setproctitle==1.3.7
|
|
201
162
|
# via agent-cli
|
|
202
|
-
setuptools==80.9.0 ; python_full_version >= '3.12'
|
|
163
|
+
setuptools==80.9.0 ; python_full_version >= '3.12' and platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
203
164
|
# via torch
|
|
204
165
|
shellingham==1.5.4
|
|
205
166
|
# via typer
|
|
206
|
-
starlette==0.50.0
|
|
167
|
+
starlette==0.50.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
207
168
|
# via fastapi
|
|
208
|
-
sympy==1.14.0
|
|
169
|
+
sympy==1.14.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
209
170
|
# via torch
|
|
210
|
-
tiktoken==0.12.0
|
|
171
|
+
tiktoken==0.12.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
211
172
|
# via mlx-whisper
|
|
212
|
-
torch==2.9.1
|
|
173
|
+
torch==2.9.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
213
174
|
# via mlx-whisper
|
|
214
|
-
tqdm==4.67.1
|
|
175
|
+
tqdm==4.67.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
215
176
|
# via
|
|
216
177
|
# huggingface-hub
|
|
217
178
|
# mlx-whisper
|
|
218
|
-
triton==3.5.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
|
219
|
-
# via torch
|
|
220
179
|
typer==0.21.1
|
|
221
180
|
# via
|
|
222
181
|
# agent-cli
|
|
@@ -239,18 +198,18 @@ typing-inspection==0.4.2
|
|
|
239
198
|
# via
|
|
240
199
|
# pydantic
|
|
241
200
|
# pydantic-settings
|
|
242
|
-
urllib3==2.3.0
|
|
201
|
+
urllib3==2.3.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
243
202
|
# via
|
|
244
203
|
# requests
|
|
245
204
|
# sentry-sdk
|
|
246
|
-
uvicorn==0.40.0
|
|
205
|
+
uvicorn==0.40.0 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
247
206
|
# via
|
|
248
207
|
# fastapi
|
|
249
208
|
# fastapi-cli
|
|
250
209
|
# fastapi-cloud-cli
|
|
251
|
-
uvloop==0.22.1 ;
|
|
210
|
+
uvloop==0.22.1 ; platform_machine == 'arm64' and platform_python_implementation != 'PyPy' and sys_platform == 'darwin'
|
|
252
211
|
# via uvicorn
|
|
253
|
-
watchfiles==1.1.1
|
|
212
|
+
watchfiles==1.1.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
254
213
|
# via uvicorn
|
|
255
|
-
websockets==15.0.1
|
|
214
|
+
websockets==15.0.1 ; platform_machine == 'arm64' and sys_platform == 'darwin'
|
|
256
215
|
# via uvicorn
|
agent_cli/core/deps.py
CHANGED
|
@@ -4,19 +4,29 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import functools
|
|
6
6
|
import json
|
|
7
|
+
import os
|
|
7
8
|
from importlib.util import find_spec
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import TYPE_CHECKING, TypeVar
|
|
10
11
|
|
|
11
12
|
import typer
|
|
12
13
|
|
|
13
|
-
from agent_cli.
|
|
14
|
+
from agent_cli.config import load_config
|
|
15
|
+
from agent_cli.core.utils import console, print_error_message
|
|
14
16
|
|
|
15
17
|
if TYPE_CHECKING:
|
|
16
18
|
from collections.abc import Callable
|
|
17
19
|
|
|
18
20
|
F = TypeVar("F", bound="Callable[..., object]")
|
|
19
21
|
|
|
22
|
+
|
|
23
|
+
def _get_auto_install_setting() -> bool:
|
|
24
|
+
"""Check if auto-install is enabled (default: True)."""
|
|
25
|
+
if os.environ.get("AGENT_CLI_NO_AUTO_INSTALL", "").lower() in ("1", "true", "yes"):
|
|
26
|
+
return False
|
|
27
|
+
return load_config().get("settings", {}).get("auto_install_extras", True)
|
|
28
|
+
|
|
29
|
+
|
|
20
30
|
# Load extras from JSON file
|
|
21
31
|
_EXTRAS_FILE = Path(__file__).parent.parent / "_extras.json"
|
|
22
32
|
EXTRAS: dict[str, tuple[str, list[str]]] = {
|
|
@@ -44,95 +54,137 @@ def check_extra_installed(extra: str) -> bool:
|
|
|
44
54
|
return any(check_extra_installed(e) for e in extra.split("|"))
|
|
45
55
|
|
|
46
56
|
if extra not in EXTRAS:
|
|
47
|
-
return
|
|
57
|
+
return False # Unknown extra, trigger install attempt to surface error
|
|
48
58
|
_, packages = EXTRAS[extra]
|
|
49
59
|
|
|
50
60
|
# All packages must be installed
|
|
51
61
|
return all(_check_package_installed(pkg) for pkg in packages)
|
|
52
62
|
|
|
53
63
|
|
|
64
|
+
def _format_extra_item(extra: str) -> str:
|
|
65
|
+
"""Format a single extra as a list item with description."""
|
|
66
|
+
desc, _ = EXTRAS.get(extra, ("", []))
|
|
67
|
+
if desc:
|
|
68
|
+
return f" - '{extra}' ({desc})"
|
|
69
|
+
return f" - '{extra}'"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _format_install_commands(extras: list[str]) -> list[str]:
|
|
73
|
+
"""Format install commands for one or more extras."""
|
|
74
|
+
combined = ",".join(extras)
|
|
75
|
+
extras_args = " ".join(extras)
|
|
76
|
+
return [
|
|
77
|
+
"Install with:",
|
|
78
|
+
f' [bold cyan]uv tool install -p 3.13 "agent-cli\\[{combined}]"[/bold cyan]',
|
|
79
|
+
" # or",
|
|
80
|
+
f" [bold cyan]agent-cli install-extras {extras_args}[/bold cyan]",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
|
|
54
84
|
def get_install_hint(extra: str) -> str:
|
|
55
|
-
"""Get install command hint for
|
|
85
|
+
"""Get install command hint for a single extra.
|
|
56
86
|
|
|
57
87
|
Supports `|` syntax for alternatives: "piper|kokoro" shows both options.
|
|
58
88
|
"""
|
|
59
89
|
# Handle "extra1|extra2" syntax - show all options
|
|
60
90
|
if "|" in extra:
|
|
61
91
|
alternatives = extra.split("|")
|
|
62
|
-
options = []
|
|
63
|
-
for alt in alternatives:
|
|
64
|
-
desc, _ = EXTRAS.get(alt, ("", []))
|
|
65
|
-
options.append((alt, desc))
|
|
66
|
-
|
|
67
92
|
lines = ["This command requires one of:"]
|
|
68
|
-
for alt
|
|
69
|
-
if desc:
|
|
70
|
-
lines.append(f" - '{alt}' ({desc})")
|
|
71
|
-
else:
|
|
72
|
-
lines.append(f" - '{alt}'")
|
|
93
|
+
lines.extend(_format_extra_item(alt) for alt in alternatives)
|
|
73
94
|
lines.append("")
|
|
74
95
|
lines.append("Install one with:")
|
|
75
|
-
|
|
76
|
-
|
|
96
|
+
lines.extend(
|
|
97
|
+
f' [bold cyan]uv tool install -p 3.13 "agent-cli\\[{alt}]"[/bold cyan]'
|
|
98
|
+
for alt in alternatives
|
|
99
|
+
)
|
|
77
100
|
lines.append(" # or")
|
|
78
|
-
|
|
79
|
-
|
|
101
|
+
lines.extend(
|
|
102
|
+
f" [bold cyan]agent-cli install-extras {alt}[/bold cyan]" for alt in alternatives
|
|
103
|
+
)
|
|
80
104
|
return "\n".join(lines)
|
|
81
105
|
|
|
82
106
|
desc, _ = EXTRAS.get(extra, ("", []))
|
|
83
|
-
|
|
84
|
-
f"This command requires the '{extra}' extra",
|
|
85
|
-
]
|
|
107
|
+
header = f"This command requires the '{extra}' extra"
|
|
86
108
|
if desc:
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
header += f" ({desc})"
|
|
110
|
+
header += "."
|
|
111
|
+
|
|
112
|
+
lines = [header, ""]
|
|
113
|
+
lines.extend(_format_install_commands([extra]))
|
|
114
|
+
return "\n".join(lines)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def get_combined_install_hint(extras: list[str]) -> str:
|
|
118
|
+
"""Get a combined install hint for multiple missing extras."""
|
|
119
|
+
if len(extras) == 1:
|
|
120
|
+
return get_install_hint(extras[0])
|
|
121
|
+
|
|
122
|
+
lines = ["This command requires the following extras:"]
|
|
123
|
+
lines.extend(_format_extra_item(extra) for extra in extras)
|
|
89
124
|
lines.append("")
|
|
90
|
-
lines.
|
|
91
|
-
lines.append(f' uv tool install "agent-cli[{extra}]" -p 3.13')
|
|
92
|
-
lines.append(" # or")
|
|
93
|
-
lines.append(f" agent-cli install-extras {extra}")
|
|
125
|
+
lines.extend(_format_install_commands(extras))
|
|
94
126
|
return "\n".join(lines)
|
|
95
127
|
|
|
96
128
|
|
|
97
|
-
def
|
|
98
|
-
"""
|
|
129
|
+
def _try_auto_install(missing: list[str]) -> bool:
|
|
130
|
+
"""Attempt to auto-install missing extras. Returns True if successful."""
|
|
131
|
+
from agent_cli.install.extras import install_extras_programmatic # noqa: PLC0415
|
|
132
|
+
|
|
133
|
+
# Flatten alternatives (e.g., "piper|kokoro" -> just pick the first one)
|
|
134
|
+
extras_to_install = []
|
|
135
|
+
for extra in missing:
|
|
136
|
+
if "|" in extra:
|
|
137
|
+
# For alternatives, install the first option
|
|
138
|
+
extras_to_install.append(extra.split("|")[0])
|
|
139
|
+
else:
|
|
140
|
+
extras_to_install.append(extra)
|
|
99
141
|
|
|
100
|
-
|
|
101
|
-
|
|
142
|
+
console.print(
|
|
143
|
+
f"[yellow]Auto-installing missing extras: {', '.join(extras_to_install)}[/]",
|
|
144
|
+
)
|
|
145
|
+
return install_extras_programmatic(extras_to_install)
|
|
102
146
|
|
|
103
|
-
The decorator stores the required extras on the function for test validation.
|
|
104
147
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
148
|
+
def _check_and_install_extras(extras: tuple[str, ...]) -> list[str]:
|
|
149
|
+
"""Check for missing extras and attempt auto-install. Returns list of still-missing."""
|
|
150
|
+
missing = [e for e in extras if not check_extra_installed(e)]
|
|
151
|
+
if not missing:
|
|
152
|
+
return []
|
|
108
153
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
154
|
+
if not _get_auto_install_setting():
|
|
155
|
+
print_error_message(get_combined_install_hint(missing))
|
|
156
|
+
return missing
|
|
157
|
+
|
|
158
|
+
if not _try_auto_install(missing):
|
|
159
|
+
print_error_message("Auto-install failed.\n" + get_combined_install_hint(missing))
|
|
160
|
+
return missing
|
|
161
|
+
|
|
162
|
+
console.print("[green]Installation complete![/]")
|
|
163
|
+
still_missing = [e for e in extras if not check_extra_installed(e)]
|
|
164
|
+
if still_missing:
|
|
165
|
+
print_error_message(
|
|
166
|
+
"Auto-install completed but some dependencies are still missing.\n"
|
|
167
|
+
+ get_combined_install_hint(still_missing),
|
|
168
|
+
)
|
|
169
|
+
return still_missing
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def requires_extras(*extras: str) -> Callable[[F], F]:
|
|
173
|
+
"""Decorator to declare required extras for a command.
|
|
114
174
|
|
|
175
|
+
Auto-installs missing extras by default. Disable via AGENT_CLI_NO_AUTO_INSTALL=1
|
|
176
|
+
or config [settings] auto_install_extras = false.
|
|
115
177
|
"""
|
|
116
178
|
|
|
117
179
|
def decorator(func: F) -> F:
|
|
118
|
-
# Store extras on function for test introspection
|
|
119
180
|
func._required_extras = extras # type: ignore[attr-defined]
|
|
120
181
|
|
|
121
182
|
@functools.wraps(func)
|
|
122
183
|
def wrapper(*args: object, **kwargs: object) -> object:
|
|
123
|
-
|
|
124
|
-
# These don't need the actual dependencies, just manage processes or list info
|
|
125
|
-
if any(kwargs.get(flag) for flag in ("stop", "status", "toggle", "list_devices")):
|
|
126
|
-
return func(*args, **kwargs)
|
|
127
|
-
|
|
128
|
-
missing = [e for e in extras if not check_extra_installed(e)]
|
|
129
|
-
if missing:
|
|
130
|
-
for extra in missing:
|
|
131
|
-
print_error_message(get_install_hint(extra))
|
|
184
|
+
if _check_and_install_extras(extras):
|
|
132
185
|
raise typer.Exit(1)
|
|
133
186
|
return func(*args, **kwargs)
|
|
134
187
|
|
|
135
|
-
# Preserve the extras on wrapper too
|
|
136
188
|
wrapper._required_extras = extras # type: ignore[attr-defined]
|
|
137
189
|
return wrapper # type: ignore[return-value]
|
|
138
190
|
|
agent_cli/core/utils.py
CHANGED
|
@@ -211,8 +211,8 @@ def print_output_panel(
|
|
|
211
211
|
|
|
212
212
|
|
|
213
213
|
def print_error_message(message: str, suggestion: str | None = None) -> None:
|
|
214
|
-
"""Prints an error message in a panel."""
|
|
215
|
-
error_text = Text(message)
|
|
214
|
+
"""Prints an error message in a panel with rich markup support."""
|
|
215
|
+
error_text = Text.from_markup(message)
|
|
216
216
|
if suggestion:
|
|
217
217
|
error_text.append("\n\n")
|
|
218
218
|
error_text.append(suggestion)
|
agent_cli/install/extras.py
CHANGED
|
@@ -86,6 +86,38 @@ def _install_cmd() -> list[str]:
|
|
|
86
86
|
return cmd
|
|
87
87
|
|
|
88
88
|
|
|
89
|
+
def _install_extras_impl(extras: list[str], *, quiet: bool = False) -> bool:
|
|
90
|
+
"""Install extras. Returns True on success, False on failure."""
|
|
91
|
+
if _is_uv_tool_install():
|
|
92
|
+
current_extras = _get_current_uv_tool_extras()
|
|
93
|
+
new_extras = sorted(set(current_extras) | set(extras))
|
|
94
|
+
return _install_via_uv_tool(new_extras)
|
|
95
|
+
|
|
96
|
+
cmd = _install_cmd()
|
|
97
|
+
for extra in extras:
|
|
98
|
+
req_file = _requirements_path(extra)
|
|
99
|
+
if not quiet:
|
|
100
|
+
console.print(f"Installing [cyan]{extra}[/]...")
|
|
101
|
+
result = subprocess.run(
|
|
102
|
+
[*cmd, "-r", str(req_file)],
|
|
103
|
+
check=False,
|
|
104
|
+
capture_output=quiet,
|
|
105
|
+
)
|
|
106
|
+
if result.returncode != 0:
|
|
107
|
+
return False
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def install_extras_programmatic(extras: list[str], *, quiet: bool = False) -> bool:
|
|
112
|
+
"""Install extras programmatically (for auto-install feature)."""
|
|
113
|
+
available = _available_extras()
|
|
114
|
+
valid = [e for e in extras if e in available]
|
|
115
|
+
invalid = [e for e in extras if e not in available]
|
|
116
|
+
if invalid:
|
|
117
|
+
console.print(f"[yellow]Unknown extras (skipped): {', '.join(invalid)}[/]")
|
|
118
|
+
return bool(valid) and _install_extras_impl(valid, quiet=quiet)
|
|
119
|
+
|
|
120
|
+
|
|
89
121
|
@app.command("install-extras", rich_help_panel="Installation")
|
|
90
122
|
def install_extras(
|
|
91
123
|
extras: Annotated[list[str] | None, typer.Argument(help="Extras to install")] = None,
|
|
@@ -128,25 +160,11 @@ def install_extras(
|
|
|
128
160
|
print_error_message(f"Unknown extras: {invalid}. Use --list to see available.")
|
|
129
161
|
raise typer.Exit(1)
|
|
130
162
|
|
|
131
|
-
|
|
163
|
+
if not _install_extras_impl(extras):
|
|
164
|
+
print_error_message("Failed to install extras")
|
|
165
|
+
raise typer.Exit(1)
|
|
166
|
+
|
|
132
167
|
if _is_uv_tool_install():
|
|
133
|
-
current_extras = _get_current_uv_tool_extras()
|
|
134
|
-
new_extras = sorted(set(current_extras) | set(extras))
|
|
135
|
-
if not _install_via_uv_tool(new_extras):
|
|
136
|
-
print_error_message("Failed to reinstall via uv tool")
|
|
137
|
-
raise typer.Exit(1)
|
|
138
168
|
console.print("[green]Done! Extras will persist across uv tool upgrade.[/]")
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
# Standard pip/uv pip install for non-tool environments
|
|
142
|
-
cmd = _install_cmd()
|
|
143
|
-
|
|
144
|
-
for extra in extras:
|
|
145
|
-
req_file = _requirements_path(extra)
|
|
146
|
-
console.print(f"Installing [cyan]{extra}[/]...")
|
|
147
|
-
result = subprocess.run([*cmd, "-r", str(req_file)], check=False)
|
|
148
|
-
if result.returncode != 0:
|
|
149
|
-
print_error_message(f"Failed to install '{extra}'")
|
|
150
|
-
raise typer.Exit(1)
|
|
151
|
-
|
|
152
|
-
console.print("[green]Done![/]")
|
|
169
|
+
else:
|
|
170
|
+
console.print("[green]Done![/]")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.68.0
|
|
4
4
|
Summary: A suite of AI-powered command-line tools for text correction, audio transcription, and voice assistance.
|
|
5
5
|
Project-URL: Homepage, https://github.com/basnijholt/agent-cli
|
|
6
6
|
Author-email: Bas Nijholt <bas@nijho.lt>
|
|
@@ -52,8 +52,8 @@ Requires-Dist: pyyaml>=6.0.0; extra == 'memory'
|
|
|
52
52
|
Requires-Dist: transformers>=4.30.0; extra == 'memory'
|
|
53
53
|
Requires-Dist: watchfiles>=0.21.0; extra == 'memory'
|
|
54
54
|
Provides-Extra: mlx-whisper
|
|
55
|
-
Requires-Dist: fastapi[standard]; extra == 'mlx-whisper'
|
|
56
|
-
Requires-Dist: mlx-whisper>=0.4.0; extra == 'mlx-whisper'
|
|
55
|
+
Requires-Dist: fastapi[standard]; (sys_platform == 'darwin' and platform_machine == 'arm64') and extra == 'mlx-whisper'
|
|
56
|
+
Requires-Dist: mlx-whisper>=0.4.0; (sys_platform == 'darwin' and platform_machine == 'arm64') and extra == 'mlx-whisper'
|
|
57
57
|
Provides-Extra: piper
|
|
58
58
|
Requires-Dist: fastapi[standard]; extra == 'piper'
|
|
59
59
|
Requires-Dist: piper-tts>=1.2.0; extra == 'piper'
|
|
@@ -459,7 +459,14 @@ All necessary scripts are bundled with the package, so you can run these command
|
|
|
459
459
|
|
|
460
460
|
#### Installing Optional Extras
|
|
461
461
|
|
|
462
|
-
Some features require additional Python dependencies.
|
|
462
|
+
Some features require additional Python dependencies. By default, **agent-cli will auto-install missing extras** when you run a command that needs them. To disable this, set `AGENT_CLI_NO_AUTO_INSTALL=1` or add to your config file:
|
|
463
|
+
|
|
464
|
+
```toml
|
|
465
|
+
[settings]
|
|
466
|
+
auto_install_extras = false
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
You can also manually install extras with `install-extras`:
|
|
463
470
|
|
|
464
471
|
```bash
|
|
465
472
|
# List available extras
|
|
@@ -17,7 +17,7 @@ agent_cli/_requirements/faster-whisper.txt,sha256=QP8akE33gcjpHmim1zcbuPOvcOAxBG
|
|
|
17
17
|
agent_cli/_requirements/kokoro.txt,sha256=XzvT9FvzWvMQK_ClanO0DJoyo7kqcfoCeenTT_KA3R0,8868
|
|
18
18
|
agent_cli/_requirements/llm.txt,sha256=06gG3fOiye0R7bDNj2h4YmAt6WuOi1HUtuW_BBjcKMY,3459
|
|
19
19
|
agent_cli/_requirements/memory.txt,sha256=RmUGuRKJvXXL1nVCZCGOKy6zvbqyzUikx5zHymk1fok,7152
|
|
20
|
-
agent_cli/_requirements/mlx-whisper.txt,sha256=
|
|
20
|
+
agent_cli/_requirements/mlx-whisper.txt,sha256=EsCSvS0ydvCJO6FzffROhjkieNNqaGHDI2iUSCTSN_o,6626
|
|
21
21
|
agent_cli/_requirements/piper.txt,sha256=LGm1gQopXgpDbgjTyWJpWYwEjjHSb86DDn48qoHnZgU,3332
|
|
22
22
|
agent_cli/_requirements/rag.txt,sha256=5zDS0BtxcB0Ig8zw8IXWTMzgTmSTNj0MMzR9G9olrIc,8127
|
|
23
23
|
agent_cli/_requirements/server.txt,sha256=k4ALhN4oR2e4amz4_1lQ2_hxB6MXg5LaGtlfn5EOc-s,2881
|
|
@@ -40,13 +40,13 @@ agent_cli/core/__init__.py,sha256=c_knH7u9QgjsfMIil9NP4bVizHawLUMYoQWU4H9vMlQ,46
|
|
|
40
40
|
agent_cli/core/audio.py,sha256=43FpYe2Wu_BYK9xJ_55V4xHjHJeFwQ5aM-CQzlTryt8,15168
|
|
41
41
|
agent_cli/core/audio_format.py,sha256=zk3qlYMAlKYPz1enrjihQQspl_C218v1Rbcm7Uktlew,8773
|
|
42
42
|
agent_cli/core/chroma.py,sha256=Vb_ny7SzAIL9SCEGlYgYOqsdG9BgusFGMj0RUzb6W90,2728
|
|
43
|
-
agent_cli/core/deps.py,sha256=
|
|
43
|
+
agent_cli/core/deps.py,sha256=58zyHSJdzIAkJ0gZ7-snrASy8Ro9NePZmElch13r-SQ,6429
|
|
44
44
|
agent_cli/core/openai_proxy.py,sha256=f2kqxk6bAOeN7gOzU0JnyS-RYtXUcK5Gbsa_pBmlCv0,4470
|
|
45
45
|
agent_cli/core/process.py,sha256=Zay6beX4JUbkBHr6xbJxwVBjVFDABmRHQCXVPQH93r8,5916
|
|
46
46
|
agent_cli/core/reranker.py,sha256=Qv5ASGUdseLzI6eQRfNeQY-Lvv4SOgLOu56CpwmszDM,3779
|
|
47
47
|
agent_cli/core/sse.py,sha256=SddiWjHh7DENb1wmvf3wDvX-OhbaC61EceFwQxmDUEo,2232
|
|
48
48
|
agent_cli/core/transcription_logger.py,sha256=PVVfQK0leoB9JwUu5jYAhyRDBVq9exiPC0_KNXV8ggY,2057
|
|
49
|
-
agent_cli/core/utils.py,sha256=
|
|
49
|
+
agent_cli/core/utils.py,sha256=CrydXrpnD3nRX8zfN5i_17Qu2OhZxfor33mtptfRwho,16839
|
|
50
50
|
agent_cli/core/vad.py,sha256=67-EBjY-pTOf61VhrjVdDXgaNIBwWFFFccYth_1rQmg,6569
|
|
51
51
|
agent_cli/core/watch.py,sha256=MKgGxxMe0yLlu78-XXqO4ferCpu_ljNr4MAzOMDsuuo,1951
|
|
52
52
|
agent_cli/dev/__init__.py,sha256=doTYiUFEBpnOxsQA69HQP9AA4QHBN0DjuHSTGRq5Xbg,551
|
|
@@ -91,7 +91,7 @@ agent_cli/dev/terminals/warp.py,sha256=j-Jvz_BbWYC3QfLrvl4CbDh03c9OGRFmuCzjyB2ud
|
|
|
91
91
|
agent_cli/dev/terminals/zellij.py,sha256=GnQnopimb9XH67CZGHjnbVWpVSWhaLCATGJizCT5TkY,2321
|
|
92
92
|
agent_cli/install/__init__.py,sha256=JQPrOrtdNd1Y1NmQDkb3Nmm1qdyn3kPjhQwy9D8ryjI,124
|
|
93
93
|
agent_cli/install/common.py,sha256=WvnmcjnFTW0d1HZrKVGzj5Tg3q8Txk_ZOdc4a1MBFWI,3121
|
|
94
|
-
agent_cli/install/extras.py,sha256=
|
|
94
|
+
agent_cli/install/extras.py,sha256=BPIlMdDeUo-tsKb_9Ttx3799YsIV_yup79ESFNpoJ1o,5731
|
|
95
95
|
agent_cli/install/hotkeys.py,sha256=bwGoPeEKK6VI-IrKU8Q0RLMW9smkDNU7CdqD3Nbsd-w,1626
|
|
96
96
|
agent_cli/install/services.py,sha256=2s_7ThxaElKCuomBYTn4Z36TF_o_arNeyJ4f8Wh4jEI,2912
|
|
97
97
|
agent_cli/memory/__init__.py,sha256=8XNpVzP-qjF8o49A_eXsH_Rbp_FmxTIcknnvxq7vHms,162
|
|
@@ -188,8 +188,8 @@ agent_cli/services/asr.py,sha256=aRaCLVCygsJ15qyQEPECOZsdSrnlLPbyY4RwAqY0qIw,172
|
|
|
188
188
|
agent_cli/services/llm.py,sha256=Kwdo6pbMYI9oykF-RBe1iaL3KsYrNWTLdRSioewmsGQ,7199
|
|
189
189
|
agent_cli/services/tts.py,sha256=NX5Qnq7ddLI3mwm3nzhbR3zB1Os4Ip4sSVSjDZDTBcI,14855
|
|
190
190
|
agent_cli/services/wake_word.py,sha256=JFJ1SA22H4yko9DXiQ1t7fcoxeALLAe3iBrLs0z8rX4,4664
|
|
191
|
-
agent_cli-0.
|
|
192
|
-
agent_cli-0.
|
|
193
|
-
agent_cli-0.
|
|
194
|
-
agent_cli-0.
|
|
195
|
-
agent_cli-0.
|
|
191
|
+
agent_cli-0.68.0.dist-info/METADATA,sha256=0eWIbitl8b9hqUg_Fh8fjJNd2UJ91_qZDYdynfh60GU,156032
|
|
192
|
+
agent_cli-0.68.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
193
|
+
agent_cli-0.68.0.dist-info/entry_points.txt,sha256=FUv-fB2atLsPUk_RT4zqnZl1coz4_XHFwRALOKOF38s,97
|
|
194
|
+
agent_cli-0.68.0.dist-info/licenses/LICENSE,sha256=majJU6S9kC8R8bW39NVBHyv32Dq50FL6TDxECG2WVts,1068
|
|
195
|
+
agent_cli-0.68.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|