code-aide 1.11.5__tar.gz → 1.12.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 (50) hide show
  1. {code_aide-1.11.5 → code_aide-1.12.1}/PKG-INFO +1 -1
  2. {code_aide-1.11.5 → code_aide-1.12.1}/script-archive/amp-install.sh +11 -5
  3. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/__init__.py +1 -1
  4. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/commands_tools.py +5 -4
  5. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/config.py +61 -0
  6. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/data/tools.json +1 -1
  7. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_commands_tools.py +7 -6
  8. {code_aide-1.11.5 → code_aide-1.12.1}/.github/workflows/ci.yml +0 -0
  9. {code_aide-1.11.5 → code_aide-1.12.1}/.github/workflows/publish.yml +0 -0
  10. {code_aide-1.11.5 → code_aide-1.12.1}/.gitignore +0 -0
  11. {code_aide-1.11.5 → code_aide-1.12.1}/.gitlab-ci.yml +0 -0
  12. {code_aide-1.11.5 → code_aide-1.12.1}/.pre-commit-config.yaml +0 -0
  13. {code_aide-1.11.5 → code_aide-1.12.1}/AGENTS.md +0 -0
  14. {code_aide-1.11.5 → code_aide-1.12.1}/CLAUDE.md +0 -0
  15. {code_aide-1.11.5 → code_aide-1.12.1}/LICENSE +0 -0
  16. {code_aide-1.11.5 → code_aide-1.12.1}/README.md +0 -0
  17. {code_aide-1.11.5 → code_aide-1.12.1}/TODO.md +0 -0
  18. {code_aide-1.11.5 → code_aide-1.12.1}/pyproject.toml +0 -0
  19. {code_aide-1.11.5 → code_aide-1.12.1}/script-archive/README.md +0 -0
  20. {code_aide-1.11.5 → code_aide-1.12.1}/script-archive/claude-install.sh +0 -0
  21. {code_aide-1.11.5 → code_aide-1.12.1}/script-archive/cursor-install.sh +0 -0
  22. {code_aide-1.11.5 → code_aide-1.12.1}/specs/auto-migrate-deprecated-installs.md +0 -0
  23. {code_aide-1.11.5 → code_aide-1.12.1}/specs/claude-native-installer-migration.md +0 -0
  24. {code_aide-1.11.5 → code_aide-1.12.1}/specs/missing-coding-llm-cli-tools.md +0 -0
  25. {code_aide-1.11.5 → code_aide-1.12.1}/specs/pre-commit-uv-setup.md +0 -0
  26. {code_aide-1.11.5 → code_aide-1.12.1}/specs/remove-bundled-version-baseline.md +0 -0
  27. {code_aide-1.11.5 → code_aide-1.12.1}/specs/unify-upgrade-eligibility-with-shared-evaluator.md +0 -0
  28. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/__main__.py +0 -0
  29. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/commands_actions.py +0 -0
  30. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/console.py +0 -0
  31. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/constants.py +0 -0
  32. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/detection.py +0 -0
  33. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/entry.py +0 -0
  34. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/install.py +0 -0
  35. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/install_types.py +0 -0
  36. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/operations.py +0 -0
  37. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/prereqs.py +0 -0
  38. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/status.py +0 -0
  39. {code_aide-1.11.5 → code_aide-1.12.1}/src/code_aide/versions.py +0 -0
  40. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_commands_actions.py +0 -0
  41. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_config.py +0 -0
  42. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_console.py +0 -0
  43. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_constants.py +0 -0
  44. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_detection.py +0 -0
  45. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_install.py +0 -0
  46. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_install_types.py +0 -0
  47. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_operations.py +0 -0
  48. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_status.py +0 -0
  49. {code_aide-1.11.5 → code_aide-1.12.1}/tests/test_versions.py +0 -0
  50. {code_aide-1.11.5 → code_aide-1.12.1}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-aide
3
- Version: 1.11.5
3
+ Version: 1.12.1
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
@@ -10,6 +10,7 @@ AMP_HOME="${AMP_HOME:-$HOME/.amp}"
10
10
  BIN_DIR="$AMP_HOME/bin"
11
11
  STORAGE_BASE="https://static.ampcode.com"
12
12
  AMP_URL="${AMP_URL:-https://ampcode.com}"
13
+ AMP_VERSION="${AMP_VERSION:-}"
13
14
 
14
15
  # Colors for output
15
16
  RED='\033[0;31m'
@@ -231,12 +232,17 @@ install_amp_binary() {
231
232
  binary_name="amp.exe"
232
233
  fi
233
234
 
234
- # Fetch version first to ensure consistent downloads (avoids race conditions
235
- # where a new version is published mid-download)
236
- log "Fetching latest version..."
237
235
  local version
238
- version=$(fetch_latest_version)
239
- log "Installing version: $version"
236
+ if [[ -n "$AMP_VERSION" ]]; then
237
+ version="$AMP_VERSION"
238
+ log "Installing requested version: $version"
239
+ else
240
+ # Fetch version first to ensure consistent downloads (avoids race conditions
241
+ # where a new version is published mid-download)
242
+ log "Fetching latest version..."
243
+ version=$(fetch_latest_version)
244
+ log "Installing version: $version"
245
+ fi
240
246
 
241
247
  # Use versioned URLs if available, fall back to root for backwards compatibility
242
248
  local binary_url="$STORAGE_BASE/cli/${version}/amp-${platform}"
@@ -1,3 +1,3 @@
1
1
  """code-aide - Manage AI coding CLI tools."""
2
2
 
3
- __version__ = "1.11.5"
3
+ __version__ = "1.12.1"
@@ -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 = f"{Colors.GREEN}ok{Colors.NC}"
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)
@@ -63,7 +63,7 @@
63
63
  "command": "amp",
64
64
  "install_type": "script",
65
65
  "install_url": "https://ampcode.com/install.sh",
66
- "install_sha256": "c0b483182332ee38548b8b1aed967b58ab4e9bd143d2e20b74664d6f3053849b",
66
+ "install_sha256": "a529b01e1e3653ad3e77cf8e5ec1f2cede5d65c880a62e783a3365bbd825be6d",
67
67
  "version_url": "https://storage.googleapis.com/amp-public-assets-prod-0/cli/cli-version.txt",
68
68
  "prerequisites": [],
69
69
  "min_node_version": null,
@@ -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