cdx-manager 0.26.3 → 0.26.5

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.26.3-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.26.5-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.26.3
1
+ 0.26.5
@@ -0,0 +1,17 @@
1
+ # CDX Manager 0.26.4
2
+
3
+ Release date: 2026-11-05
4
+
5
+ ## Fixes
6
+
7
+ - Show Claude messages typed while the agent is working in conversation pages
8
+ (#112, `7baa22a4604317b5c6fffa1eb8ddb7c8726c283d`). Render human queued
9
+ messages as user entries, including text accompanying pasted images and
10
+ oversized attachments, while keeping image bodies out of conversation output.
11
+
12
+ ## Maintenance
13
+
14
+ - Record tray companion checksums for v0.26.3
15
+ (`c3e861fb6a216ec0c721cff8bb07043921891457`).
16
+ - Record release archive checksums for v0.26.3
17
+ (`da760da0f3b859b017a68d2f4bdde71c38ca883f`).
@@ -0,0 +1,17 @@
1
+ # CDX Manager 0.26.5
2
+
3
+ Release date: 2026-11-06
4
+
5
+ ## Fixes
6
+
7
+ - Skip Claude `isMeta` user records in conversation views (#114,
8
+ `03de3770d257cc9643e542d1dbd3120e9ae71ff4`). Hide harness notes such as
9
+ image size hints and caveats, and classify oversized tool results as tool
10
+ entries so they no longer appear as operator messages.
11
+
12
+ ## Maintenance
13
+
14
+ - Record tray companion checksums for v0.26.4
15
+ (`4b42be1314c4b575369858d05e3e932687e5c8df`).
16
+ - Record release archive checksums for v0.26.4
17
+ (`67014979a69c853aa4d27c89577ce022760f6514`).
@@ -826,6 +826,28 @@
826
826
  "x86_64-pc-windows-msvc": "7846a4b56ec3006428b9778cbee3e0c1fabea8f279ca9183cf34abb460bb4c29",
827
827
  "x86_64-unknown-linux-musl": "d761aa0bbda8661c842f0b18e438c047ec023d30ed733d0044d1663ddd480355"
828
828
  }
829
+ },
830
+ "v0.26.3": {
831
+ "github_tarball_sha256": "19f55a4b7ccc2de8a05aeee23039749f782214460368de5ce2aa90ee051c5c7e",
832
+ "github_zip_sha256": "67042371673a27de37f6accd5c4cea9128d4a2a8bdd382173a56ffb3bbb34e53",
833
+ "tray_assets": {
834
+ "aarch64-apple-darwin": "520b94d699dce57b381b6efb16f6afd5bf162218437bdaedfe3c152cbf95f42d",
835
+ "aarch64-unknown-linux-musl": "fdd710a5eeba7fbc545518b011f81acbb72087e201c8c577c2eff629bb2130ff",
836
+ "x86_64-apple-darwin": "082c8ea57b34295f24ecbad701d81df37860f25f645f1c3c59382407ff94e865",
837
+ "x86_64-pc-windows-msvc": "7b9d9fc24dd5d4285a5cac7e746614654deaebe197ab38fa6e1c302da34e0358",
838
+ "x86_64-unknown-linux-musl": "51ea6902917697f5d16ef994bb01d0d0c6293b60c8f26b3735cb08925b3af616"
839
+ }
840
+ },
841
+ "v0.26.4": {
842
+ "github_tarball_sha256": "a691b54a120807f7b56ec36aca35fa5efd95f75f589dda4d8fdece51c5a32ccf",
843
+ "github_zip_sha256": "53247a7f57d0429d10c12326d5aa46862a97d8dc93835744a0ff88ddf898667b",
844
+ "tray_assets": {
845
+ "aarch64-apple-darwin": "4fbf37673acaf84b053d2f8607162690155a625406d82b77a9dbf388ac77a102",
846
+ "aarch64-unknown-linux-musl": "85041278763597ca90fa25791e82b6db53b96e31a9f2aa421160d8c113e6a381",
847
+ "x86_64-apple-darwin": "0a4c1f503a7da6c8aa13e8d30d836f5d1cc44c1ac1e24534279801e6eeb3d661",
848
+ "x86_64-pc-windows-msvc": "40e0a2e7d72cacbf2fa5fc241484e901228e44214f053c1c1defede62045624b",
849
+ "x86_64-unknown-linux-musl": "f24dea41496fa347b64873066b6b57fbbca6480c4bef1769a3bcd47e3dcb6b34"
850
+ }
829
851
  }
830
852
  }
831
853
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdx-manager",
3
- "version": "0.26.3",
3
+ "version": "0.26.5",
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.26.3"
7
+ version = "0.26.5"
8
8
  description = "Terminal session manager for Codex and Claude accounts."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9.2"
@@ -50,7 +50,16 @@ def _tool_name(message, names, result=False):
50
50
 
51
51
  def _conversation_record(provider, kind):
52
52
  # Provider bookkeeping can carry the same text as real conversation records.
53
- return kind == "response_item" if provider == "codex" else kind in ("user", "assistant")
53
+ # Claude Code records messages typed while the agent works as queued_command attachments.
54
+ return kind == "response_item" if provider == "codex" else kind in ("user", "assistant", "attachment")
55
+
56
+
57
+ def _queued_prompt(record):
58
+ attachment = record.get("attachment")
59
+ if (not isinstance(attachment, dict) or attachment.get("type") != "queued_command"
60
+ or (attachment.get("origin") or {}).get("kind") != "human"):
61
+ return None
62
+ return attachment.get("prompt")
54
63
 
55
64
 
56
65
  _CLAUDE_HARNESS = re.compile(
@@ -90,6 +99,9 @@ def _entries(provider, record, names):
90
99
  return []
91
100
  if not _conversation_record(provider, record.get("type")):
92
101
  return []
102
+ # Claude Code marks its own user-role notes (image size hints, caveats) as isMeta.
103
+ if provider == "claude" and record.get("isMeta"):
104
+ return []
93
105
  stamp = record.get("timestamp")
94
106
  try:
95
107
  datetime.fromisoformat(stamp.replace("Z", "+00:00"))
@@ -97,6 +109,9 @@ def _entries(provider, record, names):
97
109
  stamp = None
98
110
  if provider == "codex":
99
111
  message = record.get("payload")
112
+ elif record.get("type") == "attachment":
113
+ prompt = _queued_prompt(record)
114
+ message = {"role": "user", "content": prompt} if isinstance(prompt, (str, list)) else None
100
115
  else:
101
116
  message = record.get("message")
102
117
  if not isinstance(message, dict):
@@ -180,6 +195,18 @@ def _oversized_entry(provider, prefix):
180
195
  value = None
181
196
  if not _conversation_record(provider, value):
182
197
  return None
198
+ if value == "attachment":
199
+ # An oversized queued message carries a pasted image; keep its leading text when readable.
200
+ attachment = _field_start(prefix, "attachment")
201
+ if attachment is None or '"queued_command"' not in prefix[attachment:attachment + 200]:
202
+ return None
203
+ text = _field_start(prefix, "text", prefix.find("{", prefix.find('"prompt"', attachment)))
204
+ try:
205
+ text, _ = json.JSONDecoder().raw_decode(prefix, text) if text is not None else ("", 0)
206
+ except (ValueError, RecursionError):
207
+ text = ""
208
+ blocks = _claude_user_content([{"type": "text", "text": text}]) if isinstance(text, str) else []
209
+ return _entry("user", blocks[0]["text"] if blocks else "")
183
210
  message = _field_start(prefix, "payload" if provider == "codex" else "message")
184
211
  if message is None or prefix[message:message + 1] != "{":
185
212
  return None
@@ -190,6 +217,11 @@ def _oversized_entry(provider, prefix):
190
217
  value, _ = json.JSONDecoder().raw_decode(prefix, role) if role is not None else (None, 0)
191
218
  except (ValueError, RecursionError):
192
219
  value = None
220
+ if provider == "claude" and value == "user":
221
+ # A large tool result (an image read) is tool output, never an operator message.
222
+ content = _field_start(prefix, "content", message)
223
+ if content is not None and '"tool_result"' in prefix[content:content + 300]:
224
+ return _entry("tool", name="tool", summary="Result recorded")
193
225
  return _entry(value if value in ("user", "assistant", "tool") else "tool",
194
226
  "[élément trop volumineux ignoré]")
195
227