mtrx-cli 0.1.21 → 0.1.22
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 +79 -40
package/package.json
CHANGED
package/src/matrx/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.22"
|
|
@@ -579,33 +579,21 @@ def _build_gemini_env(
|
|
|
579
579
|
orchestration: dict | None = None,
|
|
580
580
|
) -> tuple[dict[str, str], str]:
|
|
581
581
|
matrx = state["auth"]["matrx"]
|
|
582
|
-
|
|
583
|
-
# For now, we don't have a specific 'gemini' auth section in state.py, but we can assume
|
|
584
|
-
# if direct route, we use env var.
|
|
582
|
+
proxy_root = ensure_root_url(matrx.get("base_url"))
|
|
585
583
|
proxy_base = ensure_v1_url(matrx.get("base_url"))
|
|
586
584
|
mx_key, matrx_auth_source = _resolve_matrx_route_key(state, env)
|
|
587
|
-
|
|
588
|
-
# Check for direct key in env or potentially saved elsewhere
|
|
589
|
-
direct_key = (env.get("GOOGLE_API_KEY") or "").strip()
|
|
585
|
+
direct_key = (env.get("GEMINI_API_KEY") or env.get("GOOGLE_API_KEY") or "").strip()
|
|
590
586
|
|
|
591
587
|
if route == "matrx":
|
|
592
588
|
if not mx_key:
|
|
593
589
|
raise ValueError("No Matrx key available. Run: mtrx login matrx --key mx_... or set MTRX_KEY")
|
|
594
|
-
|
|
595
|
-
# Clear existing Gemini config to force proxy usage
|
|
596
590
|
env.pop("MTRX_KEY", None)
|
|
597
|
-
|
|
598
591
|
group_id, project_id = _resolve_matrx_context_overrides(state, env)
|
|
599
592
|
session_id = str(uuid.uuid4())
|
|
600
593
|
runtime_agent_id = (
|
|
601
594
|
(orchestration or {}).get("agent_id")
|
|
602
595
|
or _runtime_agent_basename("gemini")[0]
|
|
603
596
|
)
|
|
604
|
-
|
|
605
|
-
# Build a project-aware proxy base URL so the proxy can identify the project
|
|
606
|
-
# even though Gemini CLI doesn't support custom request headers via env vars.
|
|
607
|
-
# We append matrx context as query params which the proxy reads.
|
|
608
|
-
proxy_base_with_ctx = proxy_base
|
|
609
597
|
ctx_params: list[str] = []
|
|
610
598
|
if project_id:
|
|
611
599
|
ctx_params.append(f"mtrx_project={project_id}")
|
|
@@ -613,31 +601,65 @@ def _build_gemini_env(
|
|
|
613
601
|
ctx_params.append(f"mtrx_session={session_id}")
|
|
614
602
|
if runtime_agent_id:
|
|
615
603
|
ctx_params.append(f"mtrx_agent={runtime_agent_id}")
|
|
616
|
-
|
|
617
|
-
|
|
604
|
+
git_branch, git_commit = _capture_git_context(_workspace_cwd(env))
|
|
605
|
+
if git_branch:
|
|
606
|
+
ctx_params.append(f"mtrx_branch={git_branch}")
|
|
607
|
+
if git_commit:
|
|
608
|
+
ctx_params.append(f"mtrx_commit={git_commit}")
|
|
609
|
+
|
|
610
|
+
query_suffix = f"?{'&'.join(ctx_params)}" if ctx_params else ""
|
|
611
|
+
env_snap = _capture_env_snapshot()
|
|
612
|
+
env_b64 = base64.b64encode(json.dumps(env_snap).encode()).decode() if env_snap else ""
|
|
613
|
+
custom_headers = [
|
|
614
|
+
f"x-matrx-key: {mx_key}",
|
|
615
|
+
f"x-matrx-agent-id: {runtime_agent_id}",
|
|
616
|
+
"x-matrx-provider: gemini_code",
|
|
617
|
+
f"x-matrx-session-id: {session_id}",
|
|
618
|
+
]
|
|
619
|
+
if group_id:
|
|
620
|
+
custom_headers.append(f"x-matrx-group: {group_id}")
|
|
621
|
+
if project_id:
|
|
622
|
+
custom_headers.append(f"x-matrx-project-id: {project_id}")
|
|
623
|
+
if git_branch:
|
|
624
|
+
custom_headers.append(f"x-matrx-branch: {git_branch}")
|
|
625
|
+
if git_commit:
|
|
626
|
+
custom_headers.append(f"x-matrx-commit: {git_commit}")
|
|
627
|
+
if env_b64:
|
|
628
|
+
custom_headers.append(f"x-matrx-env: {env_b64}")
|
|
618
629
|
|
|
619
|
-
|
|
620
|
-
env["
|
|
621
|
-
env["GEMINI_API_ENDPOINT"] =
|
|
622
|
-
env["
|
|
630
|
+
env["GOOGLE_GEMINI_BASE_URL"] = f"{proxy_base}/v1beta{query_suffix}"
|
|
631
|
+
env["GOOGLE_VERTEX_BASE_URL"] = f"{proxy_base}/v1beta{query_suffix}"
|
|
632
|
+
env["GEMINI_API_ENDPOINT"] = env["GOOGLE_GEMINI_BASE_URL"]
|
|
633
|
+
env["CODE_ASSIST_ENDPOINT"] = proxy_base
|
|
634
|
+
env["GEMINI_CLI_CUSTOM_HEADERS"] = ", ".join(custom_headers)
|
|
635
|
+
env["GEMINI_API_KEY_AUTH_MECHANISM"] = "bearer"
|
|
623
636
|
|
|
624
637
|
return env, matrx_auth_source
|
|
625
638
|
|
|
626
639
|
# Direct route: clear any matrx-managed env vars
|
|
627
640
|
env.pop("MTRX_KEY", None)
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
641
|
+
for key in (
|
|
642
|
+
"GOOGLE_GEMINI_BASE_URL",
|
|
643
|
+
"GOOGLE_VERTEX_BASE_URL",
|
|
644
|
+
"GEMINI_API_ENDPOINT",
|
|
645
|
+
"CODE_ASSIST_ENDPOINT",
|
|
646
|
+
):
|
|
647
|
+
value = (env.get(key) or "").strip()
|
|
648
|
+
if "matrx" in value.lower() or "mtrx.so" in value.lower():
|
|
649
|
+
env.pop(key, None)
|
|
650
|
+
|
|
651
|
+
custom_headers = (env.get("GEMINI_CLI_CUSTOM_HEADERS") or "").strip().lower()
|
|
652
|
+
if "x-matrx-" in custom_headers:
|
|
653
|
+
env.pop("GEMINI_CLI_CUSTOM_HEADERS", None)
|
|
654
|
+
if (env.get("GEMINI_API_KEY_AUTH_MECHANISM") or "").strip().lower() == "bearer":
|
|
655
|
+
env.pop("GEMINI_API_KEY_AUTH_MECHANISM", None)
|
|
656
|
+
|
|
657
|
+
if env.get("GEMINI_API_KEY") or env.get("GOOGLE_API_KEY"):
|
|
639
658
|
return env, "existing_google_env"
|
|
640
|
-
|
|
659
|
+
|
|
660
|
+
if direct_key:
|
|
661
|
+
return env, "existing_gemini_auth"
|
|
662
|
+
|
|
641
663
|
return env, "missing_auth"
|
|
642
664
|
|
|
643
665
|
|
|
@@ -906,26 +928,40 @@ def _validate_gemini_launch_plan(plan: LaunchPlan, state: dict) -> None:
|
|
|
906
928
|
return
|
|
907
929
|
|
|
908
930
|
expected_base_url = ensure_v1_url(state.get("auth", {}).get("matrx", {}).get("base_url"))
|
|
931
|
+
expected_gemini_base = f"{expected_base_url}/v1beta"
|
|
909
932
|
|
|
910
933
|
base_url = (plan.env.get("GOOGLE_GEMINI_BASE_URL") or "").strip()
|
|
911
934
|
if not base_url:
|
|
912
935
|
base_url = (plan.env.get("GEMINI_API_ENDPOINT") or "").strip()
|
|
913
936
|
|
|
914
937
|
if not base_url:
|
|
915
|
-
raise ValueError("Gemini Matrx route is missing GOOGLE_GEMINI_BASE_URL
|
|
938
|
+
raise ValueError("Gemini Matrx route is missing GOOGLE_GEMINI_BASE_URL")
|
|
916
939
|
|
|
917
|
-
# Strip query params before comparing (project_id context may be appended as ?mtrx_project=...)
|
|
918
940
|
base_url_no_qs = base_url.split("?")[0].rstrip("/")
|
|
919
|
-
expected_no_qs =
|
|
941
|
+
expected_no_qs = expected_gemini_base.rstrip("/")
|
|
920
942
|
if base_url_no_qs != expected_no_qs:
|
|
921
943
|
raise ValueError(
|
|
922
|
-
"Gemini Matrx route must use the Matrx
|
|
944
|
+
"Gemini Matrx route must use the Matrx Gemini-native base URL. "
|
|
923
945
|
f"Got: {base_url}"
|
|
924
946
|
)
|
|
925
947
|
|
|
926
|
-
|
|
927
|
-
if
|
|
928
|
-
raise ValueError("Gemini Matrx route is missing a
|
|
948
|
+
vertex_base = (plan.env.get("GOOGLE_VERTEX_BASE_URL") or "").strip()
|
|
949
|
+
if vertex_base and vertex_base.split("?")[0].rstrip("/") != expected_no_qs:
|
|
950
|
+
raise ValueError("Gemini Matrx route is missing a Matrx GOOGLE_VERTEX_BASE_URL")
|
|
951
|
+
|
|
952
|
+
code_assist_endpoint = (plan.env.get("CODE_ASSIST_ENDPOINT") or "").strip().rstrip("/")
|
|
953
|
+
if code_assist_endpoint != expected_base_url.rstrip("/"):
|
|
954
|
+
raise ValueError("Gemini Matrx route is missing a Matrx CODE_ASSIST_ENDPOINT")
|
|
955
|
+
|
|
956
|
+
custom_headers = (plan.env.get("GEMINI_CLI_CUSTOM_HEADERS") or "").strip().lower()
|
|
957
|
+
if "x-matrx-key:" not in custom_headers:
|
|
958
|
+
raise ValueError("Gemini Matrx route is missing GEMINI_CLI_CUSTOM_HEADERS with X-Matrx-Key")
|
|
959
|
+
if "x-matrx-provider: gemini_code" not in custom_headers:
|
|
960
|
+
raise ValueError("Gemini Matrx route is missing GEMINI_CLI_CUSTOM_HEADERS with X-Matrx-Provider=gemini_code")
|
|
961
|
+
if "x-matrx-session-id:" not in custom_headers:
|
|
962
|
+
raise ValueError("Gemini Matrx route is missing GEMINI_CLI_CUSTOM_HEADERS with X-Matrx-Session-Id")
|
|
963
|
+
if "x-matrx-agent-id:" not in custom_headers:
|
|
964
|
+
raise ValueError("Gemini Matrx route is missing GEMINI_CLI_CUSTOM_HEADERS with X-Matrx-Agent-Id")
|
|
929
965
|
|
|
930
966
|
|
|
931
967
|
def _validate_codex_launch_plan(plan: LaunchPlan, state: dict) -> None:
|
|
@@ -991,10 +1027,13 @@ def describe_launch_plan(plan: LaunchPlan, state: dict) -> list[str]:
|
|
|
991
1027
|
if plan.tool == "gemini":
|
|
992
1028
|
base_url = ensure_v1_url(state.get("auth", {}).get("matrx", {}).get("base_url"))
|
|
993
1029
|
_, project_id = _resolve_matrx_context_overrides(state, dict(plan.env))
|
|
1030
|
+
custom_headers = (plan.env.get("GEMINI_CLI_CUSTOM_HEADERS") or "").strip()
|
|
994
1031
|
lines = [
|
|
995
1032
|
"Launching gemini via Matrx",
|
|
996
|
-
f"
|
|
1033
|
+
f" gemini_base_url: {plan.env.get('GOOGLE_GEMINI_BASE_URL') or ''}",
|
|
1034
|
+
f" code_assist_endpoint: {plan.env.get('CODE_ASSIST_ENDPOINT') or ''}",
|
|
997
1035
|
f" auth_source: {plan.auth_source}",
|
|
1036
|
+
f" custom_headers_present: {bool(custom_headers)}",
|
|
998
1037
|
" runtime_route: env injection",
|
|
999
1038
|
" persistent_route: disabled",
|
|
1000
1039
|
]
|