conduct-cli 0.7.46__tar.gz → 0.7.48__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.
Files changed (48) hide show
  1. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/PKG-INFO +1 -1
  2. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/pyproject.toml +1 -1
  3. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/guard.py +44 -23
  4. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli.egg-info/PKG-INFO +1 -1
  5. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/README.md +0 -0
  6. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/setup.cfg +0 -0
  7. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/setup.py +0 -0
  8. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/__init__.py +0 -0
  9. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/api.py +0 -0
  10. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/guardmcp.py +0 -0
  11. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/__init__.py +0 -0
  12. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/base.py +0 -0
  13. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/posttooluse.py +0 -0
  14. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/precompact.py +0 -0
  15. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/pretooluse.py +0 -0
  16. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/session_parser.py +0 -0
  17. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/session_report_push.py +0 -0
  18. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/session_start.py +0 -0
  19. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/hooks/stop.py +0 -0
  20. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/log_util.py +0 -0
  21. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/main.py +0 -0
  22. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/mcp_server.py +0 -0
  23. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/memory.py +0 -0
  24. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/paxel.py +0 -0
  25. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli/tool_groups.py +0 -0
  26. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
  27. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
  28. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli.egg-info/entry_points.txt +0 -0
  29. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli.egg-info/requires.txt +0 -0
  30. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/src/conduct_cli.egg-info/top_level.txt +0 -0
  31. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_advisory_and_hook.py +0 -0
  32. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_api_client.py +0 -0
  33. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_bash_operator_signature.py +0 -0
  34. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_blast_radius.py +0 -0
  35. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_cmd_run.py +0 -0
  36. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_command_word_matcher.py +0 -0
  37. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_drain_daemon_health.py +0 -0
  38. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_guard_policy.py +0 -0
  39. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_guard_savings.py +0 -0
  40. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_hook_dispatch.py +0 -0
  41. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_instruction_files.py +0 -0
  42. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_journal_drain.py +0 -0
  43. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_log_util.py +0 -0
  44. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_proxy_coverage.py +0 -0
  45. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_proxy_env.py +0 -0
  46. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_signed_policy.py +0 -0
  47. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_switch.py +0 -0
  48. {conduct_cli-0.7.46 → conduct_cli-0.7.48}/tests/test_token_lifecycle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.7.46
3
+ Version: 0.7.48
4
4
  Summary: CLI for Conduct AI — secure, govern, install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "conduct-cli"
7
- version = "0.7.46"
7
+ version = "0.7.48"
8
8
  description = "CLI for Conduct AI — secure, govern, install agents, manage projects, run tests"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -474,31 +474,51 @@ def _patch_claude_desktop_proxy(api_url: str, agent_token: str) -> None:
474
474
 
475
475
 
476
476
  def _patch_copilot_mcp(agent_token: str, api_url: str) -> None:
477
- """Keep ~/.copilot/mcp-config.json in sync with current agent token.
478
-
479
- Copilot's mcp-config.json uses SSE + Bearer — it can't run a local stdio binary
480
- the way Claude Code / Cursor can, so we write the SSE entry with a fresh token.
481
- """
482
- cfg_path = Path.home() / ".copilot" / "mcp-config.json"
483
- if not cfg_path.exists():
484
- return
485
- try:
486
- cfg = json.loads(cfg_path.read_text())
487
- except (json.JSONDecodeError, OSError):
488
- cfg = {}
489
- mcp = cfg.setdefault("mcpServers", {})
490
- entry = {
477
+ """Keep ~/.copilot/mcp-config.json and any .mcp.json in cwd in sync with current agent token."""
478
+ import shutil
479
+ sse_entry = {
491
480
  "type": "sse",
492
481
  "url": f"{api_url}/guard/mcp",
493
482
  "headers": {"Authorization": f"Bearer {agent_token}"},
494
483
  "tools": ["**"],
495
484
  }
496
- if mcp.get("conduct-guard") == entry:
497
- print(f" {GRAY}conduct-guard MCP already registered in GitHub Copilot{RESET}")
498
- return
499
- mcp["conduct-guard"] = entry
500
- cfg_path.write_text(json.dumps(cfg, indent=2))
501
- print(f" {GREEN}conduct-guard MCP registered in GitHub Copilot (SSE){RESET}")
485
+ booster_entry = {"command": "booster", "args": ["serve"]} if shutil.which("booster") else None
486
+
487
+ # ~/.copilot/mcp-config.json (global Copilot config)
488
+ global_path = Path.home() / ".copilot" / "mcp-config.json"
489
+ if global_path.exists():
490
+ _write_mcp_file(global_path, "conduct-guard", sse_entry, booster_entry, "GitHub Copilot (global)")
491
+
492
+ # .mcp.json in cwd (project-level, picked up by VS Code Copilot)
493
+ local_path = Path.cwd() / ".mcp.json"
494
+ if local_path.exists():
495
+ _write_mcp_file(local_path, "conduct-guard", sse_entry, booster_entry, "GitHub Copilot (.mcp.json)")
496
+
497
+
498
+ def _write_mcp_file(
499
+ cfg_path: Path,
500
+ guard_key: str,
501
+ sse_entry: dict,
502
+ booster_entry: dict | None,
503
+ label: str,
504
+ ) -> None:
505
+ try:
506
+ cfg = json.loads(cfg_path.read_text())
507
+ except (json.JSONDecodeError, OSError):
508
+ cfg = {}
509
+ mcp = cfg.setdefault("mcpServers", {})
510
+ changed = False
511
+ if mcp.get(guard_key) != sse_entry:
512
+ mcp[guard_key] = sse_entry
513
+ changed = True
514
+ print(f" {GREEN}conduct-guard MCP registered in {label}{RESET}")
515
+ else:
516
+ print(f" {GRAY}conduct-guard MCP already registered in {label}{RESET}")
517
+ if booster_entry and mcp.get("agent-booster") != booster_entry:
518
+ mcp["agent-booster"] = booster_entry
519
+ changed = True
520
+ if changed:
521
+ cfg_path.write_text(json.dumps(cfg, indent=2))
502
522
 
503
523
 
504
524
  _GUARD_RULES_TEXT = (
@@ -1084,7 +1104,7 @@ def _detect_ai_tools() -> list[dict]:
1084
1104
  def _check_json_mcp(path: Path) -> bool:
1085
1105
  try:
1086
1106
  d = json.loads(path.read_text()) if path.exists() else {}
1087
- return "conduct" in d.get("mcpServers", {})
1107
+ return any("conduct" in k for k in d.get("mcpServers", {}))
1088
1108
  except Exception:
1089
1109
  return False
1090
1110
 
@@ -1191,7 +1211,7 @@ def _detect_ai_tools() -> list[dict]:
1191
1211
  vscode_settings = next((p for p in vscode_candidates if p.exists()), None)
1192
1212
  try:
1193
1213
  d = json.loads(vscode_settings.read_text()) if vscode_settings else {}
1194
- mcp_reg = "conduct" in d.get("mcp", {}).get("servers", {})
1214
+ mcp_reg = any("conduct" in k for k in d.get("mcp", {}).get("servers", {}))
1195
1215
  except Exception:
1196
1216
  mcp_reg = False
1197
1217
  # Also check ~/.copilot/mcp-config.json (SSE entry written by guard sync)
@@ -2321,7 +2341,7 @@ def _discover_config_agents() -> list[tuple]:
2321
2341
  return "conduct" in text and "mcp_servers" in text
2322
2342
  import json as _j
2323
2343
  d = _j.loads(text)
2324
- return "conduct" in d.get("mcpServers", {})
2344
+ return any("conduct" in k for k in d.get("mcpServers", {}))
2325
2345
  except Exception:
2326
2346
  return False
2327
2347
 
@@ -2347,6 +2367,7 @@ def _discover_config_agents() -> list[tuple]:
2347
2367
  ("codex", home / ".codex", home / ".codex" / "config.toml", "mcp"),
2348
2368
  ("cursor", home / ".cursor", home / ".cursor" / "mcp.json", "mcp"),
2349
2369
  ("windsurf", home / ".codeium" / "windsurf", home / ".codeium" / "windsurf" / "mcp_config.json", "mcp"),
2370
+ ("copilot", home / ".copilot", home / ".copilot" / "mcp-config.json", "mcp"),
2350
2371
  ]
2351
2372
  for name, check_dir, config_path, _ in TOOLS:
2352
2373
  if check_dir.exists():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.7.46
3
+ Version: 0.7.48
4
4
  Summary: CLI for Conduct AI — secure, govern, install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: MIT
File without changes
File without changes
File without changes