conduct-cli 0.4.15__tar.gz → 0.4.17__tar.gz
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.
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/PKG-INFO +1 -1
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/pyproject.toml +1 -1
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli/guard.py +44 -22
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli.egg-info/PKG-INFO +1 -1
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/README.md +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/setup.cfg +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/setup.py +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli/main.py +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli.egg-info/requires.txt +0 -0
- {conduct_cli-0.4.15 → conduct_cli-0.4.17}/src/conduct_cli.egg-info/top_level.txt +0 -0
|
@@ -55,11 +55,14 @@ def _fetch_budget_status():
|
|
|
55
55
|
cfg = json.loads(CONFIG_PATH.read_text()) if CONFIG_PATH.exists() else {}
|
|
56
56
|
except Exception:
|
|
57
57
|
return False, None
|
|
58
|
-
workspace_id
|
|
59
|
-
|
|
58
|
+
workspace_id = cfg.get("workspace_id")
|
|
59
|
+
clerk_user_id = cfg.get("clerk_user_id") or ""
|
|
60
|
+
api_url = cfg.get("api_url", "https://api.conductai.ai").rstrip("/")
|
|
60
61
|
if not workspace_id:
|
|
61
62
|
return False, None
|
|
62
63
|
url = f"{api_url}/guard/spend/budget-check?workspace_id={workspace_id}"
|
|
64
|
+
if clerk_user_id:
|
|
65
|
+
url += f"&clerk_user_id={clerk_user_id}"
|
|
63
66
|
try:
|
|
64
67
|
with urllib.request.urlopen(urllib.request.Request(url), timeout=5) as resp:
|
|
65
68
|
data = json.loads(resp.read())
|
|
@@ -399,6 +402,24 @@ if __name__ == "__main__":
|
|
|
399
402
|
main()
|
|
400
403
|
'''
|
|
401
404
|
|
|
405
|
+
# ── Hook write helper ─────────────────────────────────────────────────────────
|
|
406
|
+
|
|
407
|
+
def _write_hook(path: Path) -> None:
|
|
408
|
+
"""Write _HOOK_SCRIPT to path, then py_compile-validate it.
|
|
409
|
+
Raises RuntimeError if the written file fails to compile — prevents
|
|
410
|
+
silently deploying a syntactically broken hook."""
|
|
411
|
+
import py_compile, tempfile, os
|
|
412
|
+
path.write_text(_HOOK_SCRIPT)
|
|
413
|
+
path.chmod(0o755)
|
|
414
|
+
try:
|
|
415
|
+
py_compile.compile(str(path), doraise=True)
|
|
416
|
+
except py_compile.PyCompileError as exc:
|
|
417
|
+
path.unlink(missing_ok=True)
|
|
418
|
+
raise RuntimeError(
|
|
419
|
+
f"hook.py failed syntax check after write — hook NOT installed.\n{exc}"
|
|
420
|
+
) from exc
|
|
421
|
+
|
|
422
|
+
|
|
402
423
|
# ── Guard config helpers ──────────────────────────────────────────────────────
|
|
403
424
|
|
|
404
425
|
def _load_guard_config() -> dict:
|
|
@@ -666,16 +687,18 @@ def cmd_guard_install(args):
|
|
|
666
687
|
print(f" {GRAY}Guard not installed for this workspace — skipping{RESET}")
|
|
667
688
|
return
|
|
668
689
|
|
|
669
|
-
member_token
|
|
670
|
-
user_email
|
|
690
|
+
member_token = result.get("member_token") or ""
|
|
691
|
+
user_email = result.get("user_email") or ""
|
|
692
|
+
clerk_user_id = result.get("clerk_user_id") or ""
|
|
671
693
|
|
|
672
694
|
# Persist guard config — include api_key so CLI commands can authenticate
|
|
673
695
|
_save_guard_config({
|
|
674
|
-
"workspace_id":
|
|
675
|
-
"member_token":
|
|
676
|
-
"user_email":
|
|
677
|
-
"
|
|
678
|
-
"
|
|
696
|
+
"workspace_id": workspace_id,
|
|
697
|
+
"member_token": member_token,
|
|
698
|
+
"user_email": user_email,
|
|
699
|
+
"clerk_user_id": clerk_user_id,
|
|
700
|
+
"api_key": api_key,
|
|
701
|
+
"api_url": server,
|
|
679
702
|
})
|
|
680
703
|
|
|
681
704
|
# Download policies
|
|
@@ -693,8 +716,7 @@ def cmd_guard_install(args):
|
|
|
693
716
|
|
|
694
717
|
# Write hook script
|
|
695
718
|
hook_path = GUARD_DIR / "hook.py"
|
|
696
|
-
hook_path
|
|
697
|
-
hook_path.chmod(0o755)
|
|
719
|
+
_write_hook(hook_path)
|
|
698
720
|
|
|
699
721
|
# Install PreToolUse hooks — Claude Code + Codex (real interception)
|
|
700
722
|
_install_claude_hook(hook_path)
|
|
@@ -743,8 +765,7 @@ def cmd_guard_join(args):
|
|
|
743
765
|
|
|
744
766
|
# Write hook script
|
|
745
767
|
hook_path = GUARD_DIR / "hook.py"
|
|
746
|
-
hook_path
|
|
747
|
-
hook_path.chmod(0o755)
|
|
768
|
+
_write_hook(hook_path)
|
|
748
769
|
print(f" {GREEN}Hook script written:{RESET} {hook_path}")
|
|
749
770
|
|
|
750
771
|
# Install PreToolUse hook in ~/.claude/settings.json
|
|
@@ -776,8 +797,7 @@ def cmd_guard_sync(args):
|
|
|
776
797
|
|
|
777
798
|
# Refresh hook script + re-register in all tools
|
|
778
799
|
hook_path = GUARD_DIR / "hook.py"
|
|
779
|
-
hook_path
|
|
780
|
-
hook_path.chmod(0o755)
|
|
800
|
+
_write_hook(hook_path)
|
|
781
801
|
_install_claude_hook(hook_path)
|
|
782
802
|
_install_codex_hook(hook_path)
|
|
783
803
|
cfg2 = _load_guard_config()
|
|
@@ -794,19 +814,21 @@ def cmd_guard_status(args):
|
|
|
794
814
|
api_key = cfg.get("api_key", "")
|
|
795
815
|
base_url = _api_url(cfg)
|
|
796
816
|
|
|
797
|
-
# Auto-refresh user_email into config if
|
|
798
|
-
if not user_email and api_key:
|
|
817
|
+
# Auto-refresh user_email + clerk_user_id into config if missing
|
|
818
|
+
if (not user_email or not cfg.get("clerk_user_id")) and api_key:
|
|
799
819
|
try:
|
|
800
820
|
installed = _req("GET", f"{base_url}/guard/config/installed", api_key=api_key)
|
|
801
821
|
fetched_email = installed.get("user_email") or ""
|
|
822
|
+
fetched_clerk = installed.get("clerk_user_id") or ""
|
|
802
823
|
if fetched_email:
|
|
803
824
|
cfg["user_email"] = fetched_email
|
|
804
|
-
_save_guard_config(cfg)
|
|
805
|
-
# Rewrite hook script so future events carry the email
|
|
806
|
-
hook_path = GUARD_DIR / "hook.py"
|
|
807
|
-
hook_path.write_text(_HOOK_SCRIPT)
|
|
808
|
-
hook_path.chmod(0o755)
|
|
809
825
|
user_email = fetched_email
|
|
826
|
+
if fetched_clerk:
|
|
827
|
+
cfg["clerk_user_id"] = fetched_clerk
|
|
828
|
+
_save_guard_config(cfg)
|
|
829
|
+
# Rewrite hook script so future events carry the email
|
|
830
|
+
hook_path = GUARD_DIR / "hook.py"
|
|
831
|
+
_write_hook(hook_path)
|
|
810
832
|
except Exception:
|
|
811
833
|
pass
|
|
812
834
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|