code-aide 1.11.5__tar.gz → 1.12.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.
- {code_aide-1.11.5 → code_aide-1.12.0}/PKG-INFO +1 -1
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/__init__.py +1 -1
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/commands_tools.py +5 -4
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/config.py +61 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_commands_tools.py +7 -6
- {code_aide-1.11.5 → code_aide-1.12.0}/.github/workflows/ci.yml +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/.github/workflows/publish.yml +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/.gitignore +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/.gitlab-ci.yml +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/.pre-commit-config.yaml +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/AGENTS.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/CLAUDE.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/LICENSE +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/README.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/TODO.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/pyproject.toml +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/script-archive/README.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/script-archive/amp-install.sh +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/script-archive/claude-install.sh +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/script-archive/cursor-install.sh +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/specs/auto-migrate-deprecated-installs.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/specs/claude-native-installer-migration.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/specs/missing-coding-llm-cli-tools.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/specs/pre-commit-uv-setup.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/specs/remove-bundled-version-baseline.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/specs/unify-upgrade-eligibility-with-shared-evaluator.md +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/__main__.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/commands_actions.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/console.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/constants.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/data/tools.json +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/detection.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/entry.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/install.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/install_types.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/operations.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/prereqs.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/status.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/src/code_aide/versions.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_commands_actions.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_config.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_console.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_constants.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_detection.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_install.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_install_types.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_operations.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_status.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/tests/test_versions.py +0 -0
- {code_aide-1.11.5 → code_aide-1.12.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-aide
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.12.0
|
|
4
4
|
Summary: Manage AI coding CLI tools (Claude, Copilot, Cursor, Gemini, Amp, Codex)
|
|
5
5
|
Project-URL: Homepage, https://github.com/dajobe/code-aide
|
|
6
6
|
Project-URL: Repository, https://github.com/dajobe/code-aide
|
|
@@ -7,6 +7,7 @@ import platform
|
|
|
7
7
|
import shutil
|
|
8
8
|
from typing import List
|
|
9
9
|
|
|
10
|
+
from code_aide.config import ensure_versions_cache
|
|
10
11
|
from code_aide.constants import Colors, PACKAGE_MANAGERS, TOOLS
|
|
11
12
|
from code_aide.detection import (
|
|
12
13
|
format_install_method,
|
|
@@ -142,7 +143,7 @@ def _compact_version_status(
|
|
|
142
143
|
return (ver, f"{Colors.GREEN}ok{Colors.NC}")
|
|
143
144
|
if version_state == VersionDisplayState.OUTDATED:
|
|
144
145
|
return (ver, f"{Colors.YELLOW}old{Colors.NC}")
|
|
145
|
-
return (ver, "")
|
|
146
|
+
return (ver, "?")
|
|
146
147
|
|
|
147
148
|
|
|
148
149
|
def _generic_version_annotation(
|
|
@@ -160,6 +161,7 @@ def _generic_version_annotation(
|
|
|
160
161
|
|
|
161
162
|
def cmd_status_compact() -> None:
|
|
162
163
|
"""Show compact one-line-per-tool status."""
|
|
164
|
+
ensure_versions_cache(TOOLS)
|
|
163
165
|
rows: list[tuple[str, str, str, str, str]] = []
|
|
164
166
|
for tool_name, tool_config in TOOLS.items():
|
|
165
167
|
name = tool_config["command"]
|
|
@@ -181,9 +183,7 @@ def cmd_status_compact() -> None:
|
|
|
181
183
|
assessment.installed_version, assessment.version_state
|
|
182
184
|
)
|
|
183
185
|
|
|
184
|
-
state =
|
|
185
|
-
if ver_status:
|
|
186
|
-
state = ver_status
|
|
186
|
+
state = ver_status if ver_status else "?"
|
|
187
187
|
|
|
188
188
|
rows.append((name, state, ver, method, tool_path))
|
|
189
189
|
|
|
@@ -216,6 +216,7 @@ def cmd_status(args: argparse.Namespace) -> None:
|
|
|
216
216
|
if getattr(args, "compact", False):
|
|
217
217
|
cmd_status_compact()
|
|
218
218
|
return
|
|
219
|
+
ensure_versions_cache(TOOLS)
|
|
219
220
|
print("AI Coding CLI Tools Status:")
|
|
220
221
|
print("=" * 70)
|
|
221
222
|
print()
|
|
@@ -8,6 +8,7 @@ bundled defaults with cached data.
|
|
|
8
8
|
import importlib.resources
|
|
9
9
|
import json
|
|
10
10
|
import os
|
|
11
|
+
import time
|
|
11
12
|
|
|
12
13
|
from code_aide.install_types import InstallType, parse_install_type
|
|
13
14
|
|
|
@@ -62,6 +63,9 @@ def save_versions_cache(data: dict) -> None:
|
|
|
62
63
|
f.write("\n")
|
|
63
64
|
|
|
64
65
|
|
|
66
|
+
# Cache is considered stale after 24 hours.
|
|
67
|
+
CACHE_MAX_AGE_SECONDS = 86400
|
|
68
|
+
|
|
65
69
|
DYNAMIC_FIELDS = ["latest_version", "latest_date", "install_sha256"]
|
|
66
70
|
|
|
67
71
|
|
|
@@ -129,3 +133,60 @@ def save_updated_versions(tools: dict) -> None:
|
|
|
129
133
|
if entry:
|
|
130
134
|
cache_data["tools"][tool_key] = entry
|
|
131
135
|
save_versions_cache(cache_data)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def versions_cache_is_fresh() -> bool:
|
|
139
|
+
"""Return True if the versions cache exists and is less than 24h old."""
|
|
140
|
+
cache_path = get_versions_cache_path()
|
|
141
|
+
try:
|
|
142
|
+
age = time.time() - os.path.getmtime(cache_path)
|
|
143
|
+
return age < CACHE_MAX_AGE_SECONDS
|
|
144
|
+
except OSError:
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def refresh_versions_cache(tools: dict) -> None:
|
|
149
|
+
"""Fetch latest versions from upstream and update tools dict in-place.
|
|
150
|
+
|
|
151
|
+
Called automatically by status commands when the cache is missing or
|
|
152
|
+
stale. Only updates latest_version and latest_date (not install_sha256).
|
|
153
|
+
"""
|
|
154
|
+
# Import here to avoid circular dependency (versions imports constants
|
|
155
|
+
# which imports config).
|
|
156
|
+
from code_aide.versions import (
|
|
157
|
+
check_npm_tool,
|
|
158
|
+
check_script_tool,
|
|
159
|
+
normalize_version,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
for name, tool_config in tools.items():
|
|
163
|
+
install_type = parse_install_type(tool_config.get("install_type"))
|
|
164
|
+
try:
|
|
165
|
+
if install_type == InstallType.NPM:
|
|
166
|
+
result = check_npm_tool(name, tool_config)
|
|
167
|
+
elif install_type in (InstallType.SCRIPT, InstallType.DIRECT_DOWNLOAD):
|
|
168
|
+
if "install_url" not in tool_config:
|
|
169
|
+
continue
|
|
170
|
+
result = check_script_tool(name, tool_config)
|
|
171
|
+
else:
|
|
172
|
+
continue
|
|
173
|
+
except Exception:
|
|
174
|
+
continue
|
|
175
|
+
|
|
176
|
+
if result["status"] == "error":
|
|
177
|
+
continue
|
|
178
|
+
|
|
179
|
+
version = result.get("version", "-")
|
|
180
|
+
if version and version != "-":
|
|
181
|
+
tool_config["latest_version"] = normalize_version(version)
|
|
182
|
+
date = result.get("date", "-")
|
|
183
|
+
if date and date != "-":
|
|
184
|
+
tool_config["latest_date"] = date
|
|
185
|
+
|
|
186
|
+
save_updated_versions(tools)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def ensure_versions_cache(tools: dict) -> None:
|
|
190
|
+
"""Refresh versions cache if missing or stale, updating tools in-place."""
|
|
191
|
+
if not versions_cache_is_fresh():
|
|
192
|
+
refresh_versions_cache(tools)
|
|
@@ -38,10 +38,11 @@ class TestCmdList(unittest.TestCase):
|
|
|
38
38
|
self.assertIn("System Information:", output)
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
@mock.patch.object(commands_tools, "ensure_versions_cache")
|
|
41
42
|
class TestCmdStatus(unittest.TestCase):
|
|
42
43
|
"""Tests for cmd_status."""
|
|
43
44
|
|
|
44
|
-
def test_shows_upgradeable_count_for_outdated_tool(self):
|
|
45
|
+
def test_shows_upgradeable_count_for_outdated_tool(self, _mock_cache):
|
|
45
46
|
tools = {
|
|
46
47
|
"x": {
|
|
47
48
|
"name": "Example Tool",
|
|
@@ -87,7 +88,7 @@ class TestCmdStatus(unittest.TestCase):
|
|
|
87
88
|
self.assertIn("tool(s) can be upgraded", output)
|
|
88
89
|
self.assertIn(": x.", output)
|
|
89
90
|
|
|
90
|
-
def test_brew_current_upstream_lag_does_not_count_as_upgradeable(self):
|
|
91
|
+
def test_brew_current_upstream_lag_does_not_count_as_upgradeable(self, _mock_cache):
|
|
91
92
|
tools = {
|
|
92
93
|
"x": {
|
|
93
94
|
"name": "Example Tool",
|
|
@@ -143,7 +144,7 @@ class TestCmdStatus(unittest.TestCase):
|
|
|
143
144
|
self.assertIn("upstream: 2.0.0", output)
|
|
144
145
|
self.assertNotIn("tool(s) can be upgraded", output)
|
|
145
146
|
|
|
146
|
-
def test_installed_newer_than_catalog_shows_up_to_date(self):
|
|
147
|
+
def test_installed_newer_than_catalog_shows_up_to_date(self, _mock_cache):
|
|
147
148
|
"""When the binary is newer than latest_version, do not nag update-versions."""
|
|
148
149
|
tools = {
|
|
149
150
|
"x": {
|
|
@@ -190,7 +191,7 @@ class TestCmdStatus(unittest.TestCase):
|
|
|
190
191
|
self.assertNotIn("Configured version outdated", output)
|
|
191
192
|
self.assertNotIn("update-versions", output)
|
|
192
193
|
|
|
193
|
-
def test_status_shows_migration_warning(self):
|
|
194
|
+
def test_status_shows_migration_warning(self, _mock_cache):
|
|
194
195
|
"""cmd_status shows migration warning for deprecated install."""
|
|
195
196
|
tools = {
|
|
196
197
|
"x": {
|
|
@@ -237,7 +238,7 @@ class TestCmdStatus(unittest.TestCase):
|
|
|
237
238
|
self.assertIn("configured method is script", output)
|
|
238
239
|
self.assertIn("tool(s) need migration", output)
|
|
239
240
|
|
|
240
|
-
def test_compact_status_shows_ok_for_brew_tool_with_catalog_lag(self):
|
|
241
|
+
def test_compact_status_shows_ok_for_brew_tool_with_catalog_lag(self, _mock_cache):
|
|
241
242
|
tools = {
|
|
242
243
|
"x": {
|
|
243
244
|
"name": "Example Tool",
|
|
@@ -283,7 +284,7 @@ class TestCmdStatus(unittest.TestCase):
|
|
|
283
284
|
self.assertIn("ok", output)
|
|
284
285
|
self.assertNotIn("old", output)
|
|
285
286
|
|
|
286
|
-
def test_list_shows_migration_warning(self):
|
|
287
|
+
def test_list_shows_migration_warning(self, _mock_cache):
|
|
287
288
|
"""cmd_list shows migration warning for deprecated install."""
|
|
288
289
|
tools = {
|
|
289
290
|
"x": {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{code_aide-1.11.5 → code_aide-1.12.0}/specs/unify-upgrade-eligibility-with-shared-evaluator.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|