cdx-manager 0.25.5 → 0.25.7

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.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  <br clear="left"/>
6
6
 
7
- [![License](https://img.shields.io/badge/license-MIT-4C8BF5)](LICENSE) ![Version](https://img.shields.io/badge/version-v0.25.5-4C8BF5) ![Python](https://img.shields.io/badge/python-3.9%2B-3776AB?logo=python&logoColor=white)
7
+ [![License](https://img.shields.io/badge/license-MIT-4C8BF5)](LICENSE) ![Version](https://img.shields.io/badge/version-v0.25.7-4C8BF5) ![Python](https://img.shields.io/badge/python-3.9%2B-3776AB?logo=python&logoColor=white)
8
8
 
9
9
  **The right AI coding account, when you need it.** CDX Manager keeps your Codex and Claude accounts in separate profiles, shows which ones have quota, and helps you pick the next usable session from your terminal.
10
10
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.25.5
1
+ 0.25.7
@@ -0,0 +1,15 @@
1
+ # CDX Manager 0.25.6
2
+
3
+ Release date: 2026-11-02
4
+
5
+ This patch release fixes provider update detection and verifies installed versions after updates.
6
+
7
+ ## Fixes
8
+
9
+ - Detect advertised provider updaters and version output on both stdout and stderr. After an update, verify the installed version and report failure if it is missing, unchanged, downgraded, or still below the published version. Successful text output shows the version transition, and JSON results include before, after, and latest versions. (#87)
10
+ - Fall back to the latest stable GitHub release when Ollama's vendor API returns an empty, invalid, or failed response. Keep Linux Ollama updates manual, with an explicit maintenance reason. (#87)
11
+
12
+ ## Maintenance
13
+
14
+ - Record tray companion checksums for v0.25.5. (`b64a372f9ab4abb61f1440943fca19703ad555eb`)
15
+ - Record release archive checksums for v0.25.5. (`1218145eae4201e40b8140e7a94cbcec18454e17`)
@@ -0,0 +1,15 @@
1
+ # CDX Manager 0.25.7
2
+
3
+ Release date: 2026-11-02
4
+
5
+ This patch release corrects Antigravity CLI update detection and verification.
6
+
7
+ ## Fixes
8
+
9
+ - Stop comparing Antigravity CLI (`agy`) versions against the editor release feed. Report the latest CLI version as unknown and let the native `agy update` command check and apply updates after confirmation, including with `--yes`. Inventory collection remains read-only. (#89)
10
+ - Accept a successful updater's explicit `You are already on the latest version.` message on stdout or stderr when the installed version is unchanged. Otherwise require a verified version increase reaching the published version when known, and preserve updater failures. (#89)
11
+
12
+ ## Maintenance
13
+
14
+ - Record tray companion checksums for v0.25.6. (`53500823f04edb69be9563d327645148439644a6`)
15
+ - Record release archive checksums for v0.25.6. (`974dfb0cac31963883456bda4beddb19b8940152`)
@@ -2,7 +2,13 @@
2
2
 
3
3
  ## Truthful workstation updates
4
4
 
5
- - Verify latest versions from npm, RTK GitHub releases, and Antigravity/Ollama vendor update endpoints with short read-only probes. Report `unknown` on unavailable evidence; reserve `up_to_date` for identical known versions, including Ponytail revisions.
5
+ - Stop querying the editor release feed for the Antigravity CLI: its versions do not match `agy`. Keep `latest_version: null` and `status: unknown`, while still running the native `agy update` with `--yes` or confirmation. No read-only latest-version check is documented by `agy update --help`.
6
+ - Accept a successful native updater's `You are already on the latest version.` message when the installed version is unchanged, or verify a version increase against the published version when known. Preserve updater failures and unknown inventory status. Cover the real Antigravity output line, version increases, failures, and JSON/text uncertainty.
7
+
8
+ - Detect advertised native updater subcommands in both stdout and stderr; use Antigravity's known `agy update` command directly. Verify the installed CLI version after updating, fail unverified updates unless an unchanged version is explicitly confirmed current by the updater, and expose before/after versions without hiding major upgrades.
9
+ - Fall back from empty or failed Ollama vendor responses (including Linux HTTP 204) to the latest stable `ollama/ollama` GitHub release. Keep Linux updates manual with `update_available`, a null command, and a service-safety reason; never replace a potentially active binary or restart models automatically.
10
+
11
+ - Verify latest versions from npm, RTK GitHub releases, and Ollama vendor update endpoints with short read-only probes. Report `unknown` on unavailable evidence; reserve `up_to_date` for identical known versions, including Ponytail revisions.
6
12
  - Preserve the existing JSON fields and `update_available` status, show uncertainty and manual-update reasons in text, and apply only supported native commands or verified Homebrew package upgrades. Cover matching/outdated versions, source failures, missing tools, and command execution with faked sources.
7
13
 
8
14
  ## Dependency security
@@ -738,6 +738,28 @@
738
738
  "x86_64-pc-windows-msvc": "8e2c1925f025a7227ef909f27e8b4696c03bb5a86e0c61c989da6a942b5638a6",
739
739
  "x86_64-unknown-linux-musl": "9ae1164abc3ff4b30d25c44696569855138f8ac0e3b6e1c3451c716d20f221fa"
740
740
  }
741
+ },
742
+ "v0.25.5": {
743
+ "github_tarball_sha256": "4a2ece21e32f59a84d8bc7b2a565817c6c90bb314f179319bc19cf85a0c71a60",
744
+ "github_zip_sha256": "959de4dca501fd53c937f4045936b12acbea58d255a4e3cae510ec82a230bef8",
745
+ "tray_assets": {
746
+ "aarch64-apple-darwin": "727c4ded1ee4d9d8ed9853badcb10efd1cc76bd6dcd6012b6739920d42e6273c",
747
+ "aarch64-unknown-linux-musl": "9270224db6be83d4a4787f9b523a6fa059267f56ed1cf12f022f65bf68c0474f",
748
+ "x86_64-apple-darwin": "10c555671cdeb3ce4c0372f6f8a48e6cfeac9132e980c466fe5a8978dc1a2862",
749
+ "x86_64-pc-windows-msvc": "85945b30580cb82c64ece94652ae0633a6156dfd85e02108c0d4b7676cab9911",
750
+ "x86_64-unknown-linux-musl": "7c5a23938b84c5952be71b5956ed3167c218d05ce661940b0c86f2dde2d8221f"
751
+ }
752
+ },
753
+ "v0.25.6": {
754
+ "github_tarball_sha256": "27663ea4f9c70aafb1d2180d36563ab10d91b9cb336cb3285ed4fd610e698bed",
755
+ "github_zip_sha256": "ba645956971ddd9446389717ad48a74dfb426ff7290c5ebc100ca9e3c2a91d3f",
756
+ "tray_assets": {
757
+ "aarch64-apple-darwin": "41b8d1a0b098407a49fc66ef2b49fbf8283f46f6393f34fae05d0ee3b84fcd1b",
758
+ "aarch64-unknown-linux-musl": "ba88584f8ba6399572961feb4d7bcc056096d3aa398d863bc0e248e57086434e",
759
+ "x86_64-apple-darwin": "ddd032fe6306585397c4c4a461de28cafea5519eb08502224fb5ad87a249b05a",
760
+ "x86_64-pc-windows-msvc": "5c3c4be1dcf6801ed0ed73bef8840deb379e2724d9728f983498d0fe5a99c542",
761
+ "x86_64-unknown-linux-musl": "ba91c1378b78e529da3af35c7e649ed2063ba27963ef91949f1aabe9e3fe2a0f"
762
+ }
741
763
  }
742
764
  }
743
765
  }
package/docs/cli.md CHANGED
@@ -560,26 +560,47 @@ Versions and commands are explicitly `null` when unavailable.
560
560
  - `not_installed`: the executable is absent; no installation is guessed.
561
561
 
562
562
  Checks use the npm registry for Codex and `@anthropic-ai/claude-code`, GitHub's
563
- `rtk-ai/rtk` latest stable release, the original Antigravity editor's vendor
564
- `/releases` feed for `agy`, and Ollama's own `/api/update` endpoint with the local
563
+ `rtk-ai/rtk` latest stable release, and Ollama's own `/api/update` endpoint with the local
565
564
  OS/architecture and baseline version `0.0.0`. Ollama's local `/api/version` reports
566
565
  an installed server, not the latest published release, and is not used.
567
- Antigravity Hub and IDE 2 have separate feeds and are not substituted for `agy`.
566
+ Antigravity's editor `/releases` feed does not describe the `agy` CLI and is not
567
+ queried. `agy update --help` documents no read-only version check, so its latest
568
+ CLI version stays unknown (`latest_version: null`, `status: unknown`). CDX still
569
+ includes `agy update`, the CLI's own updater, in the plan. It runs only with
570
+ `--yes` or confirmation. Inventory collection never runs that updater.
568
571
  HTTP and read-only CLI probes have a five-second timeout; source failures leave
569
572
  `latest_version: null` and `status: unknown`. Ponytail also reports `unknown`
570
- when its remote revision is unavailable. An empty Ollama response (including
571
- HTTP 204 without a published version) remains `unknown`; a different platform
572
- is never substituted to manufacture a match.
573
+ when its remote revision is unavailable. An empty, failed, or invalid Ollama
574
+ response (including Linux HTTP 204) falls back to the latest stable GitHub
575
+ release for `ollama/ollama`. If that source also fails, status is `unknown`;
576
+ a different platform's vendor response is never substituted.
573
577
 
574
578
  For an outdated tool, CDX uses a native update command advertised by its
575
- `--help` (including Claude and Antigravity when available), Codex's updater,
579
+ `--help` on either stdout or stderr (including Claude and RTK
580
+ when available), Codex's updater,
576
581
  or Homebrew only when the resolved executable belongs to a Caskroom/Cellar
577
582
  package. An outdated tool without such a path retains `update_available`,
578
583
  `update_command: null`, and a human-readable `reason`; it requires the vendor's
579
- manual update mechanism. Source uncertainty never schedules a guessed install.
584
+ manual update mechanism. On Linux, Ollama always retains `update_available`
585
+ with `update_command: null` and an explicit maintenance reason: its installer
586
+ writes system paths and may restart a service. A binary in `~/.local/bin` can
587
+ also serve running models, so CDX neither replaces it nor restarts services.
588
+ Arrange a manual maintenance window. Source uncertainty never schedules a guessed install.
580
589
  The text table shows `UNKNOWN` and the reason, and an empty action list makes
581
590
  no claim that all tools are current. JSON consumers, including external
582
591
  remote-ops auto-update scripts, should inspect statuses separately from successful
583
592
  command execution: exit code zero means no attempted action failed, not that
584
593
  every installed tool was verified current. With `--yes`, the returned plan is the
585
594
  pre-update inventory; `results` records attempted actions and their exit codes.
595
+
596
+ After each successful tool update command, CDX probes the CLI version again.
597
+ A raised version succeeds when it reaches the published release, if known.
598
+ An unchanged version also succeeds when the updater explicitly reports
599
+ `You are already on the latest version.` on stdout or stderr and exits zero;
600
+ this does not change an `unknown` inventory status to `up_to_date`.
601
+ Otherwise an unchanged, unreadable, downgraded, or still older-than-published
602
+ version makes the action fail, even if the updater exited zero. Successful text output
603
+ shows the before/after versions, including major upgrades. JSON keeps the
604
+ pre-update plan and existing result fields; tool verification adds
605
+ `version_before`, `version_after`, and `latest_version` to successful-command
606
+ results, plus `reason` and a nonzero `returncode` if verification fails.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdx-manager",
3
- "version": "0.25.5",
3
+ "version": "0.25.7",
4
4
  "description": "Terminal session manager for Codex and Claude accounts.",
5
5
  "license": "MIT",
6
6
  "author": "Alexandre Agostini",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cdx-manager"
7
- version = "0.25.5"
7
+ version = "0.25.7"
8
8
  description = "Terminal session manager for Codex and Claude accounts."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9.2"
@@ -52,7 +52,8 @@ def _format_update_all_result(result, use_color=False):
52
52
  if result.get("skipped"):
53
53
  return _warn(f"skipped: {result['name']} (blocked by {result['blocked_by']})", use_color)
54
54
  if result.get("returncode") == 0:
55
- return _success(f"done: {result['name']}", use_color)
55
+ versions = f" ({result['version_before']} -> {result['version_after']})" if "version_after" in result else ""
56
+ return _success(f"done: {result['name']}{versions}", use_color)
56
57
  detail = str(result.get("stderr") or result.get("stdout") or "No error output.").strip().replace("\n", " ")
57
58
  detail = detail[-500:]
58
59
  command = shlex.join(result.get("command") or [])
package/src/update_all.py CHANGED
@@ -19,7 +19,6 @@ _TOOLS = (
19
19
  ("rtk", "rtk"),
20
20
  )
21
21
  _SOURCE_TIMEOUT = 5
22
- _ANTIGRAVITY_RELEASES = "https://antigravity-auto-updater-974169037036.us-central1.run.app/releases"
23
22
  _PONYTAIL_URL = "https://github.com/DietrichGebert/ponytail.git"
24
23
 
25
24
 
@@ -56,7 +55,7 @@ def _version(command, env, runner):
56
55
  result = _run([command, "--version"], env, runner, timeout=_SOURCE_TIMEOUT)
57
56
  if result["returncode"]:
58
57
  return None
59
- text = (result["stdout"] or result["stderr"] or "").strip()
58
+ text = "\n".join((result["stdout"] or "", result["stderr"] or "")).strip()
60
59
  # Ollama can print the server version before the CLI version.
61
60
  client = re.search(r"client version is (\S+)", text)
62
61
  match = client or re.search(r"\b(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)\b", text)
@@ -79,15 +78,22 @@ def _latest_version(name):
79
78
  if release.get("draft") or release.get("prerelease"):
80
79
  return None
81
80
  return _parse_version(release["tag_name"])
82
- if name == PROVIDER_ANTIGRAVITY:
83
- # agy belongs to the original editor, whose feed differs from Hub and IDE 2.
84
- return _parse_version(_fetch_json(_ANTIGRAVITY_RELEASES)[0]["version"])
85
81
  if name == PROVIDER_OLLAMA:
86
82
  arch = {"x86_64": "amd64", "aarch64": "arm64"}.get(platform.machine().lower(), platform.machine().lower())
87
83
  query = urlencode({"os": platform.system().lower(), "arch": arch, "version": "0.0.0"})
88
- release = _fetch_json(f"https://ollama.com/api/update?{query}")
89
- # The vendor updater extracts the release tag from the artifact URL.
90
- return _parse_version(os.path.basename(os.path.dirname(urlparse(release["url"]).path)))
84
+ try:
85
+ release = _fetch_json(f"https://ollama.com/api/update?{query}")
86
+ # The vendor updater extracts the release tag from the artifact URL.
87
+ version = _parse_version(os.path.basename(os.path.dirname(urlparse(release["url"]).path)))
88
+ if version:
89
+ return version
90
+ except Exception:
91
+ # Linux can return HTTP 204 with no JSON body.
92
+ pass
93
+ release = _fetch_json("https://api.github.com/repos/ollama/ollama/releases/latest")
94
+ if release.get("draft") or release.get("prerelease"):
95
+ return None
96
+ return _parse_version(release["tag_name"])
91
97
  except Exception:
92
98
  # A failed or changed source is uncertainty, never evidence of currency.
93
99
  return None
@@ -101,6 +107,10 @@ def _newer(latest, current):
101
107
 
102
108
 
103
109
  def _native_update_command(name, command, path, env, runner):
110
+ if name == PROVIDER_ANTIGRAVITY:
111
+ return [command, "update"]
112
+ if name == PROVIDER_OLLAMA and platform.system().lower() == "linux":
113
+ return None
104
114
  real_path = os.path.realpath(path)
105
115
  cask = re.search(r"/Caskroom/([^/]+)/", real_path)
106
116
  formula = re.search(r"/Cellar/([^/]+)/", real_path)
@@ -111,7 +121,7 @@ def _native_update_command(name, command, path, env, runner):
111
121
  return [command, "update"]
112
122
  help_result = _run([command, "--help"], env, runner, timeout=_SOURCE_TIMEOUT)
113
123
  if help_result["returncode"] == 0:
114
- help_text = help_result["stdout"]
124
+ help_text = "\n".join((help_result["stdout"] or "", help_result["stderr"] or ""))
115
125
  for subcommand in ("self-update", "update", "--update"):
116
126
  if re.search(r"(?m)^\s*" + re.escape(subcommand) + r"(?:\s|$)", help_text):
117
127
  return [command, subcommand]
@@ -153,9 +163,17 @@ def collect_update_all_plan(service, env=None, runner=None):
153
163
  steps.append({"name": name, "command": item["update_command"], "env": {}})
154
164
  else:
155
165
  item["reason"] = "No supported CLI updater or verified Homebrew installation; use the vendor's updater manually."
166
+ if name == PROVIDER_OLLAMA and platform.system().lower() == "linux":
167
+ item["reason"] = ("No supported safe automatic Linux update: Ollama's installer writes system paths and may restart a service. "
168
+ "Even a user-local binary may serve running models; arrange a manual maintenance window.")
156
169
  else:
157
170
  item["status"] = "unknown"
158
171
  item["reason"] = "Latest version unavailable from the official source." if not latest else "Installed version unavailable or does not match the published release."
172
+ if name == PROVIDER_ANTIGRAVITY:
173
+ # The editor release feed does not describe agy's CLI versions.
174
+ item["reason"] = "Latest CLI version unknown; agy update checks and applies its own updates."
175
+ item["update_command"] = _native_update_command(name, command, path, env, runner)
176
+ steps.append({"name": name, "command": item["update_command"], "env": {}})
159
177
  items.append(item)
160
178
 
161
179
  rtk_available = any(item["name"] == "rtk" and item["installed"] for item in items)
@@ -214,6 +232,18 @@ def apply_update_all_plan(plan, service, env=None, runner=None, progress=None):
214
232
  continue
215
233
  result = _run(step["command"], {**env, **step.get("env", {})}, runner, timeout=120)
216
234
  result = {"name": step["name"], "command": step["command"], **result}
235
+ item = next((item for item in plan.get("items", []) if item["name"] == step["name"]), None)
236
+ if result["returncode"] == 0 and item:
237
+ after = _version(item["command"], env, runner)
238
+ result.update(version_before=item["version"], version_after=after, latest_version=item["latest_version"])
239
+ output = "\n".join((result["stdout"], result["stderr"]))
240
+ reports_current = bool(re.search(r"(?im)^\s*You are already on the latest version\.\s*$", output))
241
+ advanced = (_newer(after, item["version"]) and
242
+ (not item["latest_version"] or after == item["latest_version"] or _newer(after, item["latest_version"])))
243
+ if not (advanced or (after and after == item["version"] and reports_current)):
244
+ result["returncode"] = 1
245
+ result["reason"] = "Update verification failed: installed version did not advance to the expected release and updater did not confirm it is current."
246
+ result["stderr"] = (result["stderr"] + "\n" + result["reason"]).strip()
217
247
  results.append(result)
218
248
  if result["returncode"] == 0 and step.get("id"):
219
249
  completed.add(step["id"])