cdx-manager 0.9.10 → 0.9.12
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 +1 -1
- package/changelogs/CHANGELOGS_0_9_11.md +44 -0
- package/changelogs/CHANGELOGS_0_9_12.md +36 -0
- package/checksums/release-archives.json +8 -0
- package/package.json +1 -1
- package/pyproject.toml +5 -2
- package/src/backup_bundle.py +0 -1
- package/src/claude_usage.py +19 -3
- package/src/cli.py +27 -9
- package/src/cli_args.py +631 -0
- package/src/cli_commands.py +117 -1020
- package/src/cli_helpers.py +385 -0
- package/src/cli_render.py +0 -1
- package/src/cli_view.py +1 -20
- package/src/context_store.py +1 -2
- package/src/logics_view.py +0 -1
- package/src/notify.py +0 -1
- package/src/provider_runtime.py +9 -33
- package/src/run_command.py +1 -1
- package/src/run_registry.py +2 -2
- package/src/run_usage.py +1 -2
- package/src/session_service.py +7 -20
- package/src/session_store.py +2 -2
- package/src/status_source.py +0 -19
- package/src/status_view.py +1 -1
- package/src/update_check.py +1 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CDX Manager
|
|
2
2
|
|
|
3
|
-
[](LICENSE) ](LICENSE)  
|
|
4
4
|
|
|
5
5
|
**Run multiple Codex, Claude, Antigravity, and Ollama sessions from one terminal. Switch between accounts instantly.**
|
|
6
6
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# CDX Manager 0.9.11
|
|
2
|
+
|
|
3
|
+
## Highlights
|
|
4
|
+
|
|
5
|
+
- Hardened transcript cleanup so captured handoff logs strip ANSI and control-sequence noise before reuse.
|
|
6
|
+
- Broadened lint coverage with Ruff's bugbear rules and fixed the newly surfaced issues.
|
|
7
|
+
- Split the CLI facade into dedicated argument and helper modules, reducing the size of the main command surface without changing user-facing commands.
|
|
8
|
+
|
|
9
|
+
## Changes
|
|
10
|
+
|
|
11
|
+
### Transcript and status reliability
|
|
12
|
+
|
|
13
|
+
Script-captured transcripts now remove additional terminal control noise before they are parsed or copied into handoff context.
|
|
14
|
+
|
|
15
|
+
Status and session helper internals also gained focused validation coverage for merge behavior, malformed records, and rate-limit parsing.
|
|
16
|
+
|
|
17
|
+
### CLI maintainability
|
|
18
|
+
|
|
19
|
+
The CLI command layer now reuses shared JSON, table, and parser helpers from extracted modules. The public CLI entrypoint remains stable, while tests can exercise smaller units directly.
|
|
20
|
+
|
|
21
|
+
Shared OAuth token cleanup and JWT decoding helpers were deduplicated into the Claude usage path so provider status code uses the same parsing behavior in one place.
|
|
22
|
+
|
|
23
|
+
### Validation coverage
|
|
24
|
+
|
|
25
|
+
Ruff now checks a wider rule set, including bugbear rules, while keeping only deferred stylistic exceptions out of the release gate.
|
|
26
|
+
|
|
27
|
+
New regression tests cover:
|
|
28
|
+
|
|
29
|
+
- Codex rate-limit payload parsing
|
|
30
|
+
- provider launch argument construction
|
|
31
|
+
- session status merge and validation helpers
|
|
32
|
+
- handoff transcript control-sequence cleanup
|
|
33
|
+
|
|
34
|
+
## Validation
|
|
35
|
+
|
|
36
|
+
- `npm run release:validate`
|
|
37
|
+
- `npm run lint`
|
|
38
|
+
- `npm test`
|
|
39
|
+
- `logics-manager lint --require-status`
|
|
40
|
+
- `logics-manager audit`
|
|
41
|
+
- `git diff --check`
|
|
42
|
+
- `npm --cache /private/tmp/cdx-npm-cache pack --dry-run`
|
|
43
|
+
- `python -m build`
|
|
44
|
+
- `python -m twine check dist/*`
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# CDX Manager 0.9.12
|
|
2
|
+
|
|
3
|
+
## Highlights
|
|
4
|
+
|
|
5
|
+
- Prevented accidental concurrent launches that reuse the same provider profile and can invalidate shared OAuth credentials.
|
|
6
|
+
- Made Claude add/login prefer `claude setup-token` so new Claude sessions use the long-lived token flow by default.
|
|
7
|
+
|
|
8
|
+
## Changes
|
|
9
|
+
|
|
10
|
+
### Session launch safety
|
|
11
|
+
|
|
12
|
+
`cdx` now detects when another live session already uses the same provider profile before launching a new one.
|
|
13
|
+
|
|
14
|
+
On an interactive terminal, the CLI asks for confirmation before starting the second session. In non-interactive contexts, the launch fails with a clear message so automation does not silently create conflicting sessions.
|
|
15
|
+
|
|
16
|
+
This protects profiles that share one credentials file, where concurrent token refreshes can rotate credentials and log out the other session.
|
|
17
|
+
|
|
18
|
+
### Claude token setup
|
|
19
|
+
|
|
20
|
+
Claude add and login flows now route through `claude setup-token` by default, which produces a longer-lived token than the standard login flow.
|
|
21
|
+
|
|
22
|
+
When this setup-token flow succeeds, stale Claude credentials are removed so the newly configured token is the one used at launch. The existing `--setup-token` flag remains accepted for compatibility.
|
|
23
|
+
|
|
24
|
+
Regression coverage verifies the default Claude setup-token behavior, stale credential cleanup, and compatibility of the retained flag.
|
|
25
|
+
|
|
26
|
+
## Validation
|
|
27
|
+
|
|
28
|
+
- `npm run release:validate`
|
|
29
|
+
- `npm run lint`
|
|
30
|
+
- `npm test`
|
|
31
|
+
- `logics-manager lint --require-status`
|
|
32
|
+
- `logics-manager audit`
|
|
33
|
+
- `git diff --check`
|
|
34
|
+
- `npm --cache /private/tmp/cdx-npm-cache pack --dry-run`
|
|
35
|
+
- `python -m build`
|
|
36
|
+
- `python -m twine check dist/*`
|
|
@@ -104,6 +104,14 @@
|
|
|
104
104
|
"v0.9.9": {
|
|
105
105
|
"github_tarball_sha256": "092c564803dd9a674250040ac308055de3701aa993237f257676403c24eb1318",
|
|
106
106
|
"github_zip_sha256": "0fbd8de7a97cde5aef14f23036def2e34dd690c2aa78ef93ddfeef0bb3e9547b"
|
|
107
|
+
},
|
|
108
|
+
"v0.9.10": {
|
|
109
|
+
"github_tarball_sha256": "4e876d3552eca1b441492a36606f2f0583bff9523801a923d834fe2a4da3c644",
|
|
110
|
+
"github_zip_sha256": "b6c9435f7e36558ac8698dbd6d6c4888e58c64a08d2b06c3bcbb45ce2cd25f7c"
|
|
111
|
+
},
|
|
112
|
+
"v0.9.11": {
|
|
113
|
+
"github_tarball_sha256": "8ab8f673af4ad9c0e4fd64110d47285a1de02c095fd0f6d79eb67e061255093d",
|
|
114
|
+
"github_zip_sha256": "ee5fffa543b8a02c082a180c624d31951c5ff662d492132cd83d4f099da70441"
|
|
107
115
|
}
|
|
108
116
|
}
|
|
109
117
|
}
|
package/package.json
CHANGED
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.9.
|
|
7
|
+
version = "0.9.12"
|
|
8
8
|
description = "Terminal session manager for Codex and Claude accounts."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -67,4 +67,7 @@ target-version = "py39"
|
|
|
67
67
|
line-length = 140
|
|
68
68
|
|
|
69
69
|
[tool.ruff.lint]
|
|
70
|
-
select = ["
|
|
70
|
+
select = ["E", "F", "W", "I", "UP", "B"]
|
|
71
|
+
# Deferred / stylistic-only: E501 (140-col overflows), E741/E731 naming & lambda
|
|
72
|
+
# style. Not chasing these now; logic-catching rules (F, bugbear B) stay on.
|
|
73
|
+
ignore = ["E501", "E741", "E731"]
|
package/src/backup_bundle.py
CHANGED
package/src/claude_usage.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import base64
|
|
1
2
|
import json
|
|
2
3
|
import os
|
|
3
4
|
import re
|
|
4
5
|
import subprocess
|
|
5
6
|
import sys
|
|
6
|
-
import urllib.request
|
|
7
7
|
import urllib.error
|
|
8
|
+
import urllib.request
|
|
8
9
|
from datetime import datetime, timezone
|
|
9
10
|
|
|
10
11
|
from .errors import CdxError
|
|
@@ -28,10 +29,25 @@ def _clean_oauth_token(token):
|
|
|
28
29
|
return text
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
def _decode_jwt_claims(token):
|
|
33
|
+
if not token or "." not in str(token):
|
|
34
|
+
return {}
|
|
35
|
+
parts = str(token).split(".")
|
|
36
|
+
if len(parts) < 2:
|
|
37
|
+
return {}
|
|
38
|
+
payload = parts[1]
|
|
39
|
+
padding = "=" * (-len(payload) % 4)
|
|
40
|
+
try:
|
|
41
|
+
decoded = base64.urlsafe_b64decode(payload + padding)
|
|
42
|
+
return json.loads(decoded.decode("utf-8"))
|
|
43
|
+
except (ValueError, json.JSONDecodeError, UnicodeDecodeError):
|
|
44
|
+
return {}
|
|
45
|
+
|
|
46
|
+
|
|
31
47
|
def _read_claude_credentials(auth_home):
|
|
32
48
|
cred_path = os.path.join(auth_home, ".claude", ".credentials.json")
|
|
33
49
|
try:
|
|
34
|
-
with open(cred_path,
|
|
50
|
+
with open(cred_path, encoding="utf-8") as f:
|
|
35
51
|
data = json.load(f)
|
|
36
52
|
creds = data.get("claudeAiOauth") if isinstance(data, dict) else None
|
|
37
53
|
token = _clean_oauth_token(creds.get("accessToken")) if isinstance(creds, dict) else None
|
|
@@ -42,7 +58,7 @@ def _read_claude_credentials(auth_home):
|
|
|
42
58
|
|
|
43
59
|
anthropic_cred_path = os.path.join(auth_home, "credentials", "default.json")
|
|
44
60
|
try:
|
|
45
|
-
with open(anthropic_cred_path,
|
|
61
|
+
with open(anthropic_cred_path, encoding="utf-8") as f:
|
|
46
62
|
data = json.load(f)
|
|
47
63
|
token = _clean_oauth_token(data.get("access_token") if isinstance(data, dict) else None)
|
|
48
64
|
if token:
|
package/src/cli.py
CHANGED
|
@@ -8,38 +8,38 @@ from .cli_commands import (
|
|
|
8
8
|
API_SCHEMA_VERSION,
|
|
9
9
|
STATUS_USAGE,
|
|
10
10
|
handle_add,
|
|
11
|
+
handle_can_resume,
|
|
11
12
|
handle_clean,
|
|
12
13
|
handle_config,
|
|
13
14
|
handle_configs,
|
|
14
|
-
handle_can_resume,
|
|
15
15
|
handle_context,
|
|
16
16
|
handle_copy,
|
|
17
|
-
handle_doctor,
|
|
18
17
|
handle_disable,
|
|
18
|
+
handle_doctor,
|
|
19
19
|
handle_enable,
|
|
20
20
|
handle_export,
|
|
21
|
-
handle_import,
|
|
22
21
|
handle_handoff,
|
|
23
22
|
handle_history,
|
|
23
|
+
handle_import,
|
|
24
24
|
handle_last,
|
|
25
25
|
handle_launch,
|
|
26
|
+
handle_launch_setting_alias,
|
|
26
27
|
handle_login,
|
|
27
28
|
handle_logout,
|
|
28
|
-
handle_launch_setting_alias,
|
|
29
|
-
handle_notify,
|
|
30
29
|
handle_next,
|
|
30
|
+
handle_notify,
|
|
31
31
|
handle_remove,
|
|
32
|
-
handle_repair,
|
|
33
32
|
handle_rename,
|
|
33
|
+
handle_repair,
|
|
34
34
|
handle_resume,
|
|
35
35
|
handle_run,
|
|
36
36
|
handle_run_report,
|
|
37
37
|
handle_run_status,
|
|
38
38
|
handle_runs,
|
|
39
39
|
handle_select,
|
|
40
|
+
handle_set,
|
|
40
41
|
handle_stats,
|
|
41
42
|
handle_status,
|
|
42
|
-
handle_set,
|
|
43
43
|
handle_unset,
|
|
44
44
|
handle_update,
|
|
45
45
|
handle_view,
|
|
@@ -66,7 +66,25 @@ from .status_view import (
|
|
|
66
66
|
)
|
|
67
67
|
from .update_check import check_for_update, check_logics_manager_for_update
|
|
68
68
|
|
|
69
|
-
VERSION = "0.9.
|
|
69
|
+
VERSION = "0.9.12"
|
|
70
|
+
|
|
71
|
+
# Public surface: this module is a facade. Names below are imported above
|
|
72
|
+
# purely to be re-exported (consumed by tests and external callers); listing
|
|
73
|
+
# them here documents that and stops F401 from treating them as dead imports.
|
|
74
|
+
__all__ = [
|
|
75
|
+
"STATUS_USAGE",
|
|
76
|
+
"LOG_ROTATE_BYTES",
|
|
77
|
+
"_format_blocking_quota",
|
|
78
|
+
"_format_reset_time",
|
|
79
|
+
"_format_status_detail",
|
|
80
|
+
"_format_status_rows",
|
|
81
|
+
"_pad_table",
|
|
82
|
+
"_rotate_log_if_needed",
|
|
83
|
+
"_visible_len",
|
|
84
|
+
"cli_entry",
|
|
85
|
+
"format_json_error",
|
|
86
|
+
"main",
|
|
87
|
+
]
|
|
70
88
|
|
|
71
89
|
|
|
72
90
|
_COMMAND_HANDLERS = {
|
|
@@ -427,7 +445,7 @@ def cli_entry():
|
|
|
427
445
|
sys.stderr.write(f"{format_json_error(error)}\n")
|
|
428
446
|
else:
|
|
429
447
|
sys.stderr.write(f"{format_error(error)}\n")
|
|
430
|
-
raise SystemExit(error.exit_code)
|
|
448
|
+
raise SystemExit(error.exit_code) from None
|
|
431
449
|
|
|
432
450
|
|
|
433
451
|
if __name__ == "__main__":
|