code-aide 1.11.1__tar.gz → 1.11.3__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.1 → code_aide-1.11.3}/PKG-INFO +1 -1
  2. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/__init__.py +1 -1
  3. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/config.py +18 -9
  4. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/operations.py +6 -7
  5. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_config.py +62 -0
  6. {code_aide-1.11.1 → code_aide-1.11.3}/.github/workflows/ci.yml +0 -0
  7. {code_aide-1.11.1 → code_aide-1.11.3}/.github/workflows/publish.yml +0 -0
  8. {code_aide-1.11.1 → code_aide-1.11.3}/.gitignore +0 -0
  9. {code_aide-1.11.1 → code_aide-1.11.3}/.gitlab-ci.yml +0 -0
  10. {code_aide-1.11.1 → code_aide-1.11.3}/.pre-commit-config.yaml +0 -0
  11. {code_aide-1.11.1 → code_aide-1.11.3}/AGENTS.md +0 -0
  12. {code_aide-1.11.1 → code_aide-1.11.3}/CLAUDE.md +0 -0
  13. {code_aide-1.11.1 → code_aide-1.11.3}/LICENSE +0 -0
  14. {code_aide-1.11.1 → code_aide-1.11.3}/README.md +0 -0
  15. {code_aide-1.11.1 → code_aide-1.11.3}/TODO.md +0 -0
  16. {code_aide-1.11.1 → code_aide-1.11.3}/pyproject.toml +0 -0
  17. {code_aide-1.11.1 → code_aide-1.11.3}/script-archive/README.md +0 -0
  18. {code_aide-1.11.1 → code_aide-1.11.3}/script-archive/amp-install.sh +0 -0
  19. {code_aide-1.11.1 → code_aide-1.11.3}/script-archive/claude-install.sh +0 -0
  20. {code_aide-1.11.1 → code_aide-1.11.3}/script-archive/cursor-install.sh +0 -0
  21. {code_aide-1.11.1 → code_aide-1.11.3}/specs/auto-migrate-deprecated-installs.md +0 -0
  22. {code_aide-1.11.1 → code_aide-1.11.3}/specs/claude-native-installer-migration.md +0 -0
  23. {code_aide-1.11.1 → code_aide-1.11.3}/specs/missing-coding-llm-cli-tools.md +0 -0
  24. {code_aide-1.11.1 → code_aide-1.11.3}/specs/pre-commit-uv-setup.md +0 -0
  25. {code_aide-1.11.1 → code_aide-1.11.3}/specs/remove-bundled-version-baseline.md +0 -0
  26. {code_aide-1.11.1 → code_aide-1.11.3}/specs/unify-upgrade-eligibility-with-shared-evaluator.md +0 -0
  27. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/__main__.py +0 -0
  28. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/commands_actions.py +0 -0
  29. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/commands_tools.py +0 -0
  30. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/console.py +0 -0
  31. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/constants.py +0 -0
  32. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/data/tools.json +0 -0
  33. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/detection.py +0 -0
  34. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/entry.py +0 -0
  35. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/install.py +0 -0
  36. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/install_types.py +0 -0
  37. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/prereqs.py +0 -0
  38. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/status.py +0 -0
  39. {code_aide-1.11.1 → code_aide-1.11.3}/src/code_aide/versions.py +0 -0
  40. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_commands_actions.py +0 -0
  41. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_commands_tools.py +0 -0
  42. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_console.py +0 -0
  43. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_constants.py +0 -0
  44. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_detection.py +0 -0
  45. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_install.py +0 -0
  46. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_install_types.py +0 -0
  47. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_operations.py +0 -0
  48. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_status.py +0 -0
  49. {code_aide-1.11.1 → code_aide-1.11.3}/tests/test_versions.py +0 -0
  50. {code_aide-1.11.1 → code_aide-1.11.3}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-aide
3
- Version: 1.11.1
3
+ Version: 1.11.3
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
@@ -1,3 +1,3 @@
1
1
  """code-aide - Manage AI coding CLI tools."""
2
2
 
3
- __version__ = "1.11.1"
3
+ __version__ = "1.11.3"
@@ -66,20 +66,29 @@ DYNAMIC_FIELDS = ["latest_version", "latest_date", "install_sha256"]
66
66
 
67
67
 
68
68
  def merge_cached_versions(tools: dict, cache: dict) -> None:
69
- """Merge cached dynamic fields into tool definitions in-place."""
69
+ """Merge cached dynamic fields into tool definitions in-place.
70
+
71
+ For install_sha256, the bundled value takes precedence when it differs
72
+ from the cache, since a new release with an updated hash means the
73
+ cache is stale.
74
+ """
70
75
  cached_tools = cache.get("tools", {})
71
76
  for tool_key, tool_data in tools.items():
72
77
  if tool_key in cached_tools:
73
78
  for field in DYNAMIC_FIELDS:
74
79
  if field in cached_tools[tool_key]:
75
- if (
76
- field == "install_sha256"
77
- and parse_install_type(tool_data.get("install_type"))
78
- == InstallType.DIRECT_DOWNLOAD
79
- ):
80
- # Script checksum does not apply to tarball installs; ignore
81
- # stale cache from older releases or mistaken updates.
82
- continue
80
+ if field == "install_sha256":
81
+ install_type = parse_install_type(tool_data.get("install_type"))
82
+ if install_type == InstallType.DIRECT_DOWNLOAD:
83
+ # Script checksum does not apply to tarball installs;
84
+ # ignore stale cache from older releases.
85
+ continue
86
+ bundled_sha = tool_data.get("install_sha256")
87
+ cached_sha = cached_tools[tool_key][field]
88
+ if bundled_sha and cached_sha and bundled_sha != cached_sha:
89
+ # Bundled hash was updated in a newer release;
90
+ # discard stale cached hash.
91
+ continue
83
92
  tool_data[field] = cached_tools[tool_key][field]
84
93
 
85
94
 
@@ -195,8 +195,8 @@ def upgrade_tool(tool_name: str) -> UpgradeResult:
195
195
  if not pkg_name:
196
196
  error(f"No FreeBSD port configured for {tool_config['name']}")
197
197
  return UpgradeResult.FAILED
198
- cmd = ["sudo", "pkg", "upgrade", "-y"]
199
198
  pkg_repo = tool_config.get("freebsd_pkg_repo")
199
+ cmd = ["sudo", "pkg", "install", "-y", "-f"]
200
200
  if pkg_repo:
201
201
  cmd.extend(["-r", pkg_repo])
202
202
  cmd.append(pkg_name)
@@ -344,12 +344,11 @@ def remove_tool(tool_name: str) -> bool:
344
344
  if not pkg_name:
345
345
  error(f"No FreeBSD port configured for {tool_config['name']}")
346
346
  return False
347
- cmd = ["sudo", "pkg", "delete", "-y"]
348
- pkg_repo = tool_config.get("freebsd_pkg_repo")
349
- if pkg_repo:
350
- cmd.extend(["-r", pkg_repo])
351
- cmd.append(pkg_name)
352
- run_command(cmd, check=True, capture=False)
347
+ run_command(
348
+ ["sudo", "pkg", "delete", "-y", pkg_name],
349
+ check=True,
350
+ capture=False,
351
+ )
353
352
  success(f"{tool_config['name']} removed successfully")
354
353
 
355
354
  elif method == InstallMethod.SYSTEM:
@@ -146,5 +146,67 @@ class TestMergeInstallSha256DirectDownload(unittest.TestCase):
146
146
  self.assertNotIn("install_sha256", entry)
147
147
 
148
148
 
149
+ class TestMergeInstallSha256StaleCacheIgnored(unittest.TestCase):
150
+ """Stale cached install_sha256 must not override updated bundled hash."""
151
+
152
+ def test_bundled_sha256_wins_over_stale_cache(self):
153
+ tools = {
154
+ "amp": {
155
+ "install_type": "script",
156
+ "name": "Amp",
157
+ "command": "amp",
158
+ "install_sha256": "new_bundled_hash_from_release",
159
+ }
160
+ }
161
+ cache = {
162
+ "tools": {
163
+ "amp": {
164
+ "install_sha256": "old_cached_hash",
165
+ }
166
+ }
167
+ }
168
+ code_aide_config.merge_cached_versions(tools, cache)
169
+ self.assertEqual(
170
+ tools["amp"]["install_sha256"], "new_bundled_hash_from_release"
171
+ )
172
+
173
+ def test_cache_applies_when_bundled_sha256_absent(self):
174
+ tools = {
175
+ "amp": {
176
+ "install_type": "script",
177
+ "name": "Amp",
178
+ "command": "amp",
179
+ }
180
+ }
181
+ cache = {
182
+ "tools": {
183
+ "amp": {
184
+ "install_sha256": "cached_hash",
185
+ }
186
+ }
187
+ }
188
+ code_aide_config.merge_cached_versions(tools, cache)
189
+ self.assertEqual(tools["amp"]["install_sha256"], "cached_hash")
190
+
191
+ def test_cache_applies_when_sha256_matches_bundled(self):
192
+ tools = {
193
+ "amp": {
194
+ "install_type": "script",
195
+ "name": "Amp",
196
+ "command": "amp",
197
+ "install_sha256": "same_hash",
198
+ }
199
+ }
200
+ cache = {
201
+ "tools": {
202
+ "amp": {
203
+ "install_sha256": "same_hash",
204
+ }
205
+ }
206
+ }
207
+ code_aide_config.merge_cached_versions(tools, cache)
208
+ self.assertEqual(tools["amp"]["install_sha256"], "same_hash")
209
+
210
+
149
211
  if __name__ == "__main__":
150
212
  unittest.main()
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