mtrx-cli 0.1.20 → 0.1.21
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/package.json +1 -1
- package/src/matrx/__init__.py +1 -1
- package/src/matrx/cli/launcher.py +10 -0
- package/src/matrx/cli/main.py +62 -4
package/package.json
CHANGED
package/src/matrx/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.21"
|
|
@@ -537,6 +537,11 @@ def _build_codex_env(
|
|
|
537
537
|
header_parts.append(f'"X-Matrx-Group" = "{group_id}"')
|
|
538
538
|
if project_id:
|
|
539
539
|
header_parts.append(f'"X-Matrx-Project-Id" = "{project_id}"')
|
|
540
|
+
_git_branch, _git_commit = _capture_git_context(_workspace_cwd(env))
|
|
541
|
+
if _git_branch:
|
|
542
|
+
header_parts.append(f'"X-Matrx-Branch" = "{_git_branch}"')
|
|
543
|
+
if _git_commit:
|
|
544
|
+
header_parts.append(f'"X-Matrx-Commit" = "{_git_commit}"')
|
|
540
545
|
if env_b64:
|
|
541
546
|
header_parts.append(f'"X-Matrx-Env" = "{env_b64}"')
|
|
542
547
|
headers_str = ", ".join(header_parts)
|
|
@@ -680,6 +685,11 @@ def _build_claude_env(
|
|
|
680
685
|
custom_headers += f"\nx-matrx-group: {group_id}"
|
|
681
686
|
if project_id:
|
|
682
687
|
custom_headers += f"\nx-matrx-project-id: {project_id}"
|
|
688
|
+
_git_branch, _git_commit = _capture_git_context(_workspace_cwd(env))
|
|
689
|
+
if _git_branch:
|
|
690
|
+
custom_headers += f"\nx-matrx-branch: {_git_branch}"
|
|
691
|
+
if _git_commit:
|
|
692
|
+
custom_headers += f"\nx-matrx-commit: {_git_commit}"
|
|
683
693
|
if env_b64:
|
|
684
694
|
custom_headers += f"\nx-matrx-env: {env_b64}"
|
|
685
695
|
env["ANTHROPIC_CUSTOM_HEADERS"] = custom_headers
|
package/src/matrx/cli/main.py
CHANGED
|
@@ -466,10 +466,13 @@ def _cmd_login(args) -> int:
|
|
|
466
466
|
|
|
467
467
|
key = (args.key or "").strip()
|
|
468
468
|
if provider == "matrx":
|
|
469
|
+
url_changed = False
|
|
469
470
|
if args.base_url:
|
|
470
471
|
state["auth"]["matrx"]["base_url"] = args.base_url.strip()
|
|
472
|
+
url_changed = True
|
|
471
473
|
if args.app_url:
|
|
472
474
|
state["auth"]["matrx"]["app_url"] = args.app_url.strip()
|
|
475
|
+
url_changed = True
|
|
473
476
|
elif not state["auth"]["matrx"].get("app_url"):
|
|
474
477
|
state["auth"]["matrx"]["app_url"] = ensure_app_url(
|
|
475
478
|
None,
|
|
@@ -484,13 +487,14 @@ def _cmd_login(args) -> int:
|
|
|
484
487
|
except ValueError as exc:
|
|
485
488
|
print(str(exc), file=sys.stderr)
|
|
486
489
|
return 1
|
|
487
|
-
if changed:
|
|
490
|
+
if changed or url_changed:
|
|
488
491
|
path = save_state(state)
|
|
489
492
|
print(f"Saved {args.provider} credentials to {path}")
|
|
490
493
|
print(f"Matrx base URL: {ensure_v1_url(state['auth']['matrx']['base_url'])}")
|
|
491
494
|
return 0
|
|
492
|
-
|
|
493
|
-
|
|
495
|
+
if not url_changed:
|
|
496
|
+
print("Matrx login did not change the current state", file=sys.stderr)
|
|
497
|
+
return 1
|
|
494
498
|
|
|
495
499
|
if not key:
|
|
496
500
|
print("--key is required for this login command", file=sys.stderr)
|
|
@@ -585,11 +589,18 @@ def _cmd_status() -> int:
|
|
|
585
589
|
print("Active project: none (run: mtrx project switch <name>)")
|
|
586
590
|
|
|
587
591
|
print("Defaults:")
|
|
592
|
+
for tool in ("codex", "claude", "gemini", "cursor"):
|
|
593
|
+
route = configured_route(state, tool) or "not set"
|
|
594
|
+
print(f" {tool}: {route}")
|
|
588
595
|
print("Auth:")
|
|
596
|
+
config_base = auth["matrx"].get("base_url")
|
|
597
|
+
env_base = (os.environ.get("MATRX_BASE_URL") or "").strip()
|
|
598
|
+
effective_base = ensure_v1_url(env_base or config_base)
|
|
599
|
+
base_source = "MATRX_BASE_URL env" if env_base else "config"
|
|
589
600
|
print(
|
|
590
601
|
" matrx: "
|
|
591
602
|
f"{mask_secret(auth['matrx'].get('key'))} "
|
|
592
|
-
f"({
|
|
603
|
+
f"({effective_base}) [{base_source}]"
|
|
593
604
|
)
|
|
594
605
|
print(f" matrx app: {ensure_app_url(auth['matrx'].get('app_url'), base_url=auth['matrx'].get('base_url'))}")
|
|
595
606
|
print(f" openai: {mask_secret(auth['openai'].get('key'))}")
|
|
@@ -617,6 +628,24 @@ def _cmd_status() -> int:
|
|
|
617
628
|
proxy_running = is_proxy_running()
|
|
618
629
|
print(f" cursor proxy: {'running' if proxy_running else 'not running'}")
|
|
619
630
|
|
|
631
|
+
# Matrx API proxy health (when base_url configured)
|
|
632
|
+
base_url = auth["matrx"].get("base_url")
|
|
633
|
+
if base_url:
|
|
634
|
+
try:
|
|
635
|
+
health_url = f"{ensure_root_url(base_url).rstrip('/')}/health/wiring"
|
|
636
|
+
with httpx.Client(timeout=5) as client:
|
|
637
|
+
resp = client.get(health_url)
|
|
638
|
+
if resp.status_code == 200:
|
|
639
|
+
data = resp.json()
|
|
640
|
+
wiring = "ok" if data.get("proxy_wiring_ok") else "incomplete"
|
|
641
|
+
kv = data.get("key_vault", {})
|
|
642
|
+
enc = "configured" if kv.get("encryption_configured") else "not configured"
|
|
643
|
+
print(f" matrx proxy: reachable (wiring={wiring}, key_vault={enc})")
|
|
644
|
+
else:
|
|
645
|
+
print(f" matrx proxy: HTTP {resp.status_code}")
|
|
646
|
+
except Exception as exc:
|
|
647
|
+
print(f" matrx proxy: unreachable ({exc})")
|
|
648
|
+
|
|
620
649
|
print("Executables:")
|
|
621
650
|
print(f" codex: {find_executable('codex') or 'not found'}")
|
|
622
651
|
print(f" claude: {find_executable('claude') or 'not found'}")
|
|
@@ -822,6 +851,35 @@ def _cmd_doctor() -> int:
|
|
|
822
851
|
else:
|
|
823
852
|
print(f"[warn] {tool} native config not configured")
|
|
824
853
|
|
|
854
|
+
# Proxy health check — when using matrx route, verify server is reachable
|
|
855
|
+
base_url = state.get("auth", {}).get("matrx", {}).get("base_url")
|
|
856
|
+
mx_key = matrx_key or workspace_matrx_key or env_matrx_key
|
|
857
|
+
if base_url and mx_key:
|
|
858
|
+
try:
|
|
859
|
+
health_url = f"{ensure_root_url(base_url).rstrip('/')}/health/wiring"
|
|
860
|
+
with httpx.Client(timeout=10) as client:
|
|
861
|
+
resp = client.get(health_url)
|
|
862
|
+
if resp.status_code == 200:
|
|
863
|
+
data = resp.json()
|
|
864
|
+
if data.get("proxy_wiring_ok"):
|
|
865
|
+
print("[ok] Matrx proxy reachable and wired")
|
|
866
|
+
else:
|
|
867
|
+
comps = data.get("components", {})
|
|
868
|
+
missing = [k for k, v in comps.items() if not v]
|
|
869
|
+
print(f"[warn] Matrx proxy incomplete: missing {missing}")
|
|
870
|
+
kv = data.get("key_vault", {})
|
|
871
|
+
if not kv.get("encryption_configured"):
|
|
872
|
+
print(
|
|
873
|
+
"[warn] Key vault encryption not configured on server — "
|
|
874
|
+
"provider keys may fail to decrypt; set KEY_VAULT_ENCRYPTION_KEY"
|
|
875
|
+
)
|
|
876
|
+
else:
|
|
877
|
+
print(f"[warn] Matrx proxy health check failed: {resp.status_code}")
|
|
878
|
+
except httpx.HTTPError as exc:
|
|
879
|
+
print(f"[warn] Matrx proxy unreachable: {exc}")
|
|
880
|
+
except Exception as exc:
|
|
881
|
+
print(f"[warn] Matrx proxy check failed: {exc}")
|
|
882
|
+
|
|
825
883
|
return 1 if failures else 0
|
|
826
884
|
|
|
827
885
|
|