delegate-agent-cli 0.11.0__py3-none-any.whl

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 (54) hide show
  1. delegate_agent/__init__.py +5 -0
  2. delegate_agent/archived_logs.py +44 -0
  3. delegate_agent/argv_builders.py +423 -0
  4. delegate_agent/argv_utils.py +36 -0
  5. delegate_agent/capability_commands.py +99 -0
  6. delegate_agent/cli.py +987 -0
  7. delegate_agent/cli_parser.py +1627 -0
  8. delegate_agent/command_errors.py +29 -0
  9. delegate_agent/command_help.py +1264 -0
  10. delegate_agent/config.py +1117 -0
  11. delegate_agent/config_commands.py +143 -0
  12. delegate_agent/constants.py +50 -0
  13. delegate_agent/describe_payload.py +1018 -0
  14. delegate_agent/errors.py +32 -0
  15. delegate_agent/git_utils.py +180 -0
  16. delegate_agent/harness_events.py +719 -0
  17. delegate_agent/inspection_commands.py +104 -0
  18. delegate_agent/isolation.py +316 -0
  19. delegate_agent/json_types.py +18 -0
  20. delegate_agent/log_output.py +78 -0
  21. delegate_agent/private_io.py +109 -0
  22. delegate_agent/profile_commands.py +42 -0
  23. delegate_agent/profile_guard.py +116 -0
  24. delegate_agent/profiles.py +389 -0
  25. delegate_agent/prompt_instructions.py +39 -0
  26. delegate_agent/prompt_transport.py +12 -0
  27. delegate_agent/reasoning.py +916 -0
  28. delegate_agent/redaction.py +193 -0
  29. delegate_agent/rendering.py +573 -0
  30. delegate_agent/request_build.py +1681 -0
  31. delegate_agent/request_models.py +191 -0
  32. delegate_agent/retention.py +321 -0
  33. delegate_agent/run_metadata.py +78 -0
  34. delegate_agent/run_output_commands.py +645 -0
  35. delegate_agent/run_registry.py +747 -0
  36. delegate_agent/run_status.py +300 -0
  37. delegate_agent/runner.py +1830 -0
  38. delegate_agent/safe_workspace.py +821 -0
  39. delegate_agent/snapshot_view.py +229 -0
  40. delegate_agent/wait_cancel_commands.py +559 -0
  41. delegate_agent/worktree_commands.py +218 -0
  42. delegate_agent/worktree_execution.py +654 -0
  43. delegate_agent/worktree_gc.py +529 -0
  44. delegate_agent/worktree_mgmt.py +782 -0
  45. delegate_agent/worktree_records.py +232 -0
  46. delegate_agent/worktree_remove.py +547 -0
  47. delegate_agent/worktree_summary.py +242 -0
  48. delegate_agent/wsl.py +65 -0
  49. delegate_agent_cli-0.11.0.dist-info/METADATA +325 -0
  50. delegate_agent_cli-0.11.0.dist-info/RECORD +54 -0
  51. delegate_agent_cli-0.11.0.dist-info/WHEEL +5 -0
  52. delegate_agent_cli-0.11.0.dist-info/entry_points.txt +2 -0
  53. delegate_agent_cli-0.11.0.dist-info/licenses/LICENSE +21 -0
  54. delegate_agent_cli-0.11.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,32 @@
1
+ """Process exit codes and the shared CLI error type.
2
+
3
+ This is a dependency leaf: it imports nothing from the rest of the package
4
+ (beyond JSON typing), so every other module can raise ``DelegateError``
5
+ without creating an import cycle through ``cli``.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from delegate_agent.json_types import JsonObject
11
+
12
+ EXIT_OK = 0
13
+ EXIT_USAGE = 2
14
+ EXIT_MISSING_BINARY = 3
15
+
16
+
17
+ class DelegateError(Exception):
18
+ def __init__(
19
+ self,
20
+ error: str,
21
+ message: str,
22
+ exit_code: int = EXIT_USAGE,
23
+ *,
24
+ diagnostics: JsonObject | None = None,
25
+ next_actions: list[str] | None = None,
26
+ ) -> None:
27
+ super().__init__(message)
28
+ self.error = error
29
+ self.message = message
30
+ self.exit_code = exit_code
31
+ self.diagnostics = diagnostics
32
+ self.next_actions = next_actions
@@ -0,0 +1,180 @@
1
+ from __future__ import annotations
2
+
3
+ import subprocess
4
+ from collections.abc import Callable
5
+ from pathlib import Path
6
+
7
+ GIT_QUICK_TIMEOUT_SECONDS = 10
8
+ GIT_MUTATION_TIMEOUT_SECONDS = 30
9
+ GIT_TIMEOUT_RETURN_CODE = 124
10
+
11
+
12
+ def timeout_completed_process(
13
+ command: list[str],
14
+ exc: subprocess.TimeoutExpired,
15
+ *,
16
+ timeout_seconds: int,
17
+ ) -> subprocess.CompletedProcess[str]:
18
+ return subprocess.CompletedProcess(
19
+ command,
20
+ GIT_TIMEOUT_RETURN_CODE,
21
+ exc.stdout or "",
22
+ f"git command timed out after {timeout_seconds}s",
23
+ )
24
+
25
+
26
+ def run_git(
27
+ cwd: str,
28
+ args: list[str],
29
+ *,
30
+ timeout_seconds: int = GIT_MUTATION_TIMEOUT_SECONDS,
31
+ ) -> subprocess.CompletedProcess[str]:
32
+ command = ["git", "-C", cwd, *args]
33
+ try:
34
+ return subprocess.run( # nosec B603 - fixed git argv is executed with shell=False and a timeout.
35
+ command,
36
+ text=True,
37
+ capture_output=True,
38
+ check=False,
39
+ timeout=timeout_seconds,
40
+ )
41
+ except subprocess.TimeoutExpired as exc:
42
+ return timeout_completed_process(
43
+ command,
44
+ exc,
45
+ timeout_seconds=timeout_seconds,
46
+ )
47
+
48
+
49
+ def git_stdout_or_warn(
50
+ cwd: str,
51
+ args: list[str],
52
+ *,
53
+ warnings: list[str],
54
+ timeout_seconds: int,
55
+ git_runner: Callable[..., subprocess.CompletedProcess[str]] = run_git,
56
+ ) -> str | None:
57
+ result = git_runner(cwd, args, timeout_seconds=timeout_seconds)
58
+ if result.returncode != 0:
59
+ detail = result.stderr.strip() or result.stdout.strip() or f"exit {result.returncode}"
60
+ warnings.append(f"git {' '.join(args)} failed: {detail}")
61
+ return None
62
+ return result.stdout.strip()
63
+
64
+
65
+ def rev_parse_verify(
66
+ cwd: str,
67
+ rev: str,
68
+ *,
69
+ warnings: list[str] | None = None,
70
+ timeout_seconds: int = GIT_QUICK_TIMEOUT_SECONDS,
71
+ git_runner: Callable[..., subprocess.CompletedProcess[str]] = run_git,
72
+ ) -> str | None:
73
+ args = ["rev-parse", "--verify", rev]
74
+ if warnings is not None:
75
+ return git_stdout_or_warn(
76
+ cwd,
77
+ args,
78
+ warnings=warnings,
79
+ timeout_seconds=timeout_seconds,
80
+ git_runner=git_runner,
81
+ )
82
+ result = git_runner(cwd, args, timeout_seconds=timeout_seconds)
83
+ if result.returncode != 0:
84
+ return None
85
+ return result.stdout.strip()
86
+
87
+
88
+ def timeout_completed_process_bytes(
89
+ command: list[str],
90
+ exc: subprocess.TimeoutExpired,
91
+ *,
92
+ timeout_seconds: int,
93
+ ) -> subprocess.CompletedProcess[bytes]:
94
+ stderr = exc.stderr or f"git command timed out after {timeout_seconds}s".encode()
95
+ if isinstance(stderr, str):
96
+ stderr = stderr.encode()
97
+ stdout = exc.stdout or b""
98
+ if isinstance(stdout, str):
99
+ stdout = stdout.encode()
100
+ return subprocess.CompletedProcess(
101
+ command,
102
+ GIT_TIMEOUT_RETURN_CODE,
103
+ stdout,
104
+ stderr,
105
+ )
106
+
107
+
108
+ def run_git_bytes(
109
+ cwd: str,
110
+ args: list[str],
111
+ *,
112
+ input_bytes: bytes | None = None,
113
+ timeout_seconds: int = GIT_MUTATION_TIMEOUT_SECONDS,
114
+ ) -> subprocess.CompletedProcess[bytes]:
115
+ command = ["git", "-C", cwd, *args]
116
+ try:
117
+ return subprocess.run( # nosec B603 - fixed git argv is executed with shell=False and a timeout.
118
+ command,
119
+ input=input_bytes,
120
+ capture_output=True,
121
+ check=False,
122
+ timeout=timeout_seconds,
123
+ )
124
+ except subprocess.TimeoutExpired as exc:
125
+ return timeout_completed_process_bytes(
126
+ command,
127
+ exc,
128
+ timeout_seconds=timeout_seconds,
129
+ )
130
+
131
+
132
+ def capture_git_metadata(
133
+ workspace_path: str,
134
+ ) -> tuple[str | None, str | None, str | None, str | None, str | None]:
135
+ """Capture read-only Git metadata used for isolation planning.
136
+
137
+ Returns ``(git_root, git_common_dir, head_oid, head_ref, branch_name)``.
138
+ All fields are ``None`` when the workspace is not a Git repo or Git cannot
139
+ answer the probes.
140
+ """
141
+ try:
142
+ root_result = run_git(
143
+ workspace_path,
144
+ ["rev-parse", "--show-toplevel"],
145
+ timeout_seconds=GIT_QUICK_TIMEOUT_SECONDS,
146
+ )
147
+ if root_result.returncode != 0:
148
+ return None, None, None, None, None
149
+ git_root = root_result.stdout.strip()
150
+
151
+ common_result = run_git(
152
+ workspace_path,
153
+ ["rev-parse", "--git-common-dir"],
154
+ timeout_seconds=GIT_QUICK_TIMEOUT_SECONDS,
155
+ )
156
+ git_common_dir = common_result.stdout.strip() if common_result.returncode == 0 else None
157
+ if git_common_dir and not git_common_dir.startswith("/"):
158
+ git_common_dir = str(Path(git_root) / git_common_dir)
159
+
160
+ oid_result = run_git(
161
+ workspace_path,
162
+ ["rev-parse", "HEAD"],
163
+ timeout_seconds=GIT_QUICK_TIMEOUT_SECONDS,
164
+ )
165
+ head_oid = oid_result.stdout.strip() if oid_result.returncode == 0 else None
166
+
167
+ ref_result = run_git(
168
+ workspace_path,
169
+ ["symbolic-ref", "--quiet", "HEAD"],
170
+ timeout_seconds=GIT_QUICK_TIMEOUT_SECONDS,
171
+ )
172
+ head_ref = ref_result.stdout.strip() if ref_result.returncode == 0 else None
173
+
174
+ branch_name = None
175
+ if head_ref and head_ref.startswith("refs/heads/"):
176
+ branch_name = head_ref[11:]
177
+
178
+ return git_root, git_common_dir, head_oid, head_ref, branch_name
179
+ except (FileNotFoundError, OSError, subprocess.SubprocessError):
180
+ return None, None, None, None, None