conduct-cli 0.7.31__tar.gz → 0.7.34__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 (44) hide show
  1. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/PKG-INFO +1 -1
  2. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/pyproject.toml +1 -1
  3. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/api.py +18 -5
  4. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/main.py +35 -2
  5. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli.egg-info/PKG-INFO +1 -1
  6. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/README.md +0 -0
  7. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/setup.cfg +0 -0
  8. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/setup.py +0 -0
  9. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/__init__.py +0 -0
  10. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/guard.py +0 -0
  11. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/guardmcp.py +0 -0
  12. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/__init__.py +0 -0
  13. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/base.py +0 -0
  14. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/posttooluse.py +0 -0
  15. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/precompact.py +0 -0
  16. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/pretooluse.py +0 -0
  17. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/session_parser.py +0 -0
  18. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/session_report_push.py +0 -0
  19. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/session_start.py +0 -0
  20. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/hooks/stop.py +0 -0
  21. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/log_util.py +0 -0
  22. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/mcp_server.py +0 -0
  23. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/memory.py +0 -0
  24. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/paxel.py +0 -0
  25. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli/tool_groups.py +0 -0
  26. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
  27. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
  28. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli.egg-info/entry_points.txt +0 -0
  29. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli.egg-info/requires.txt +0 -0
  30. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/src/conduct_cli.egg-info/top_level.txt +0 -0
  31. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_advisory_and_hook.py +0 -0
  32. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_bash_operator_signature.py +0 -0
  33. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_blast_radius.py +0 -0
  34. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_command_word_matcher.py +0 -0
  35. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_drain_daemon_health.py +0 -0
  36. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_guard_policy.py +0 -0
  37. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_guard_savings.py +0 -0
  38. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_hook_dispatch.py +0 -0
  39. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_journal_drain.py +0 -0
  40. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_log_util.py +0 -0
  41. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_proxy_coverage.py +0 -0
  42. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_proxy_env.py +0 -0
  43. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_signed_policy.py +0 -0
  44. {conduct_cli-0.7.31 → conduct_cli-0.7.34}/tests/test_switch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.7.31
3
+ Version: 0.7.34
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.31"
7
+ version = "0.7.34"
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" }
@@ -6,7 +6,20 @@ import urllib.error
6
6
 
7
7
  RED = "\033[31m"
8
8
  RESET = "\033[0m"
9
- DEV_WORKSPACE = "00000000-0000-0000-0000-000000000001"
9
+
10
+ _HINTS = {
11
+ 401: "run `conduct login` to re-authenticate",
12
+ 403: "check your permissions or run `conduct login`",
13
+ 404: "not found — check the agent name or run ID",
14
+ 429: "rate limited — wait a moment and try again",
15
+ }
16
+
17
+
18
+ def _friendly(code: int, detail: str) -> str:
19
+ hint = _HINTS.get(code)
20
+ if hint and hint.lower() not in detail.lower():
21
+ return f"{detail} — {hint}"
22
+ return detail
10
23
 
11
24
 
12
25
  def headers(workspace_id: str, token=None, content_type="application/json", api_key=None) -> dict:
@@ -31,10 +44,10 @@ def req(method: str, url: str, hdrs: dict, body=None, timeout: int = 30) -> dict
31
44
  detail = json.loads(raw).get("detail", raw)
32
45
  except Exception:
33
46
  detail = raw
34
- print(f"{RED}HTTP {e.code}: {detail} [{url}]{RESET}")
47
+ print(f"{RED}{_friendly(e.code, detail)}{RESET}")
35
48
  sys.exit(1)
36
49
  except (socket.timeout, TimeoutError):
37
- print(f"{RED}Request timed out: {url}{RESET}")
50
+ print(f"{RED}Request timed out — check your network connection{RESET}")
38
51
  sys.exit(1)
39
52
 
40
53
 
@@ -50,10 +63,10 @@ def req_text(method: str, url: str, hdrs: dict, body_text: str, timeout: int = 3
50
63
  detail = json.loads(raw).get("detail", raw)
51
64
  except Exception:
52
65
  detail = raw
53
- print(f"{RED}HTTP {e.code}: {detail} [{url}]{RESET}")
66
+ print(f"{RED}{_friendly(e.code, detail)}{RESET}")
54
67
  sys.exit(1)
55
68
  except (socket.timeout, TimeoutError):
56
- print(f"{RED}Request timed out: {url}{RESET}")
69
+ print(f"{RED}Request timed out — check your network connection{RESET}")
57
70
  sys.exit(1)
58
71
 
59
72
 
@@ -160,6 +160,17 @@ def _stream_run(server: str, workflow_id: str, run_id: str, workspace_id: str, t
160
160
  elif kind == "brain_tool_call":
161
161
  summary = payload.get("summary", payload.get("tool", ""))
162
162
  print(f" · {summary}{RESET}")
163
+ elif kind == "guard_check":
164
+ n = payload.get("rules_checked", 0)
165
+ block_type = payload.get("block_type", "")
166
+ if payload.get("warnings"):
167
+ for w in payload["warnings"]:
168
+ print(f"{YELLOW} ⚠ [guard:{block_type}] {w.get('rule_id', '')}: {w.get('message', '')}{RESET}")
169
+ elif payload.get("audited"):
170
+ for a in payload["audited"]:
171
+ print(f"{BLUE} ● [guard:{block_type}] {a.get('rule_id', '')}: {a.get('message', '')}{RESET}")
172
+ else:
173
+ print(f"{GREEN} ✓ [guard:{block_type}] {n} rules checked — passed{RESET}")
163
174
  elif kind == "run_completed":
164
175
  print(f"{BOLD}{GREEN} ✓ done{RESET}")
165
176
  elif kind == "run_failed":
@@ -453,7 +464,11 @@ def _exchange_clerk_token(api_url: str, clerk_token: str, workspace_id: str) ->
453
464
  }
454
465
  except urllib.error.HTTPError as e:
455
466
  body_text = e.read().decode(errors="replace")
456
- print(f"{RED}Token exchange failed ({e.code}): {body_text[:120]}{RESET}")
467
+ try:
468
+ detail = json.loads(body_text).get("detail", body_text)
469
+ except Exception:
470
+ detail = body_text[:120]
471
+ print(f"{RED}Login failed: {detail} — run `conduct login` to try again{RESET}")
457
472
  sys.exit(1)
458
473
 
459
474
 
@@ -2509,6 +2524,23 @@ def cmd_run(args):
2509
2524
  except Exception:
2510
2525
  pass # validate endpoint is best-effort; backend will re-check on /trigger
2511
2526
 
2527
+ # Full preflight validation — credentials, auth chain, proxy, block config.
2528
+ # Blocks on errors so bad runs never start.
2529
+ try:
2530
+ vr = api.req("POST", f"{server}/workflows/{workflow_id}/validate", json_h, {})
2531
+ v_errors = (vr or {}).get("errors") or []
2532
+ if v_errors:
2533
+ print(f"{RED}✗ Cannot start run — preflight validation failed:{RESET}\n")
2534
+ for e in v_errors:
2535
+ lbl = e.get("label") or e.get("block_id") or "?"
2536
+ print(f" {YELLOW}⚠ [{lbl}]{RESET} {e.get('message', '')}")
2537
+ print()
2538
+ sys.exit(2)
2539
+ except SystemExit:
2540
+ raise
2541
+ except Exception:
2542
+ pass # best-effort — don't block run if validate endpoint itself errors
2543
+
2512
2544
  # Fix 3: /trigger returns run_id, not id.
2513
2545
  if getattr(args, "max_turns", None):
2514
2546
  body["__max_turns"] = args.max_turns
@@ -2998,7 +3030,8 @@ def cmd_skill(args):
2998
3030
  msg = json.loads(body).get("detail", body)
2999
3031
  except Exception:
3000
3032
  msg = body
3001
- print(f"{RED}Error {e.code}: {msg}{RESET}")
3033
+ from conduct_cli.api import _friendly
3034
+ print(f"{RED}{_friendly(e.code, msg)}{RESET}")
3002
3035
  sys.exit(1)
3003
3036
 
3004
3037
  if skill_command == "list":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.7.31
3
+ Version: 0.7.34
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