conduct-cli 0.4.32__tar.gz → 0.4.33__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.32 → conduct_cli-0.4.33}/PKG-INFO +1 -1
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/pyproject.toml +1 -1
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli/guard.py +41 -5
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli/main.py +1 -1
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli.egg-info/PKG-INFO +1 -1
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/README.md +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/setup.cfg +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/setup.py +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli/mcp_server.py +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli.egg-info/requires.txt +0 -0
- {conduct_cli-0.4.32 → conduct_cli-0.4.33}/src/conduct_cli.egg-info/top_level.txt +0 -0
|
@@ -31,11 +31,44 @@ import time
|
|
|
31
31
|
import urllib.request
|
|
32
32
|
from pathlib import Path
|
|
33
33
|
|
|
34
|
-
GUARD_DIR
|
|
35
|
-
POLICY_PATH
|
|
36
|
-
CONFIG_PATH
|
|
37
|
-
BUDGET_CACHE_PATH
|
|
38
|
-
BUDGET_CACHE_TTL
|
|
34
|
+
GUARD_DIR = Path.home() / ".conductguard"
|
|
35
|
+
POLICY_PATH = GUARD_DIR / "policy.json"
|
|
36
|
+
CONFIG_PATH = GUARD_DIR / "config.json"
|
|
37
|
+
BUDGET_CACHE_PATH = GUARD_DIR / "budget_cache.json"
|
|
38
|
+
BUDGET_CACHE_TTL = 300 # 5 minutes
|
|
39
|
+
VERSION_CACHE_PATH = GUARD_DIR / "version_cache.json"
|
|
40
|
+
VERSION_CACHE_TTL = 60 # 1 minute — matches server poll window
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _maybe_sync_policy():
|
|
44
|
+
"""Check server policy version once per minute; re-download if stale. Never raises."""
|
|
45
|
+
try:
|
|
46
|
+
cfg = json.loads(CONFIG_PATH.read_text()) if CONFIG_PATH.exists() else {}
|
|
47
|
+
workspace_id = cfg.get("workspace_id")
|
|
48
|
+
api_key = cfg.get("api_key", "")
|
|
49
|
+
api_url = cfg.get("api_url", "https://api.conductai.ai").rstrip("/")
|
|
50
|
+
if not workspace_id:
|
|
51
|
+
return
|
|
52
|
+
# Check cache TTL
|
|
53
|
+
if VERSION_CACHE_PATH.exists():
|
|
54
|
+
cache = json.loads(VERSION_CACHE_PATH.read_text())
|
|
55
|
+
if time.time() - cache.get("ts", 0) < VERSION_CACHE_TTL:
|
|
56
|
+
return
|
|
57
|
+
# Fetch current version from server
|
|
58
|
+
url = f"{api_url}/guard/policies/sync?workspace_id={workspace_id}"
|
|
59
|
+
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {api_key}"} if api_key else {})
|
|
60
|
+
with urllib.request.urlopen(req, timeout=2) as resp:
|
|
61
|
+
remote = json.loads(resp.read())
|
|
62
|
+
remote_version = remote.get("version", "")
|
|
63
|
+
# Compare to local
|
|
64
|
+
local_version = ""
|
|
65
|
+
if POLICY_PATH.exists():
|
|
66
|
+
local_version = json.loads(POLICY_PATH.read_text()).get("version", "")
|
|
67
|
+
if remote_version != local_version:
|
|
68
|
+
POLICY_PATH.write_text(json.dumps(remote, indent=2))
|
|
69
|
+
VERSION_CACHE_PATH.write_text(json.dumps({"ts": time.time(), "version": remote_version}))
|
|
70
|
+
except Exception:
|
|
71
|
+
pass # Never block a tool call due to sync failure
|
|
39
72
|
|
|
40
73
|
|
|
41
74
|
def _load_budget_cache():
|
|
@@ -366,6 +399,9 @@ def main():
|
|
|
366
399
|
except Exception:
|
|
367
400
|
sys.exit(0)
|
|
368
401
|
|
|
402
|
+
# Policy version check (cached 60s) — auto-syncs if server version differs
|
|
403
|
+
_maybe_sync_policy()
|
|
404
|
+
|
|
369
405
|
# Hard budget cap (cached 5 min)
|
|
370
406
|
hard_blocked, reason = _load_budget_cache()
|
|
371
407
|
if hard_blocked is None:
|
|
@@ -218,7 +218,7 @@ def _write_codex_mcp_config() -> bool:
|
|
|
218
218
|
content = config_path.read_text() if config_path.exists() else ""
|
|
219
219
|
if "conduct-mcp" in content:
|
|
220
220
|
return True
|
|
221
|
-
mcp_block = '\n[
|
|
221
|
+
mcp_block = '\n[mcp_servers.conduct]\ncommand = "conduct-mcp"\nargs = []\n'
|
|
222
222
|
config_path.write_text(content + mcp_block)
|
|
223
223
|
return True
|
|
224
224
|
except Exception:
|
|
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
|