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,218 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+ from typing import TextIO
7
+
8
+ from delegate_agent import rendering as delegate_rendering
9
+ from delegate_agent import run_registry, worktree_mgmt
10
+ from delegate_agent.json_types import JsonObject
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class WorktreeCommand:
15
+ action: str | None
16
+ json_mode: bool = False
17
+ handle: str | None = None
18
+ latest_harness: str | None = None
19
+ harness: str | None = None
20
+ group: str | None = None
21
+ status: str | None = None
22
+ limit: int | None = None
23
+ no_auto_prune: bool = False
24
+ discard_uncommitted: bool = False
25
+ force_branch: bool = False
26
+ force: bool = False
27
+ keep_branch: bool = False
28
+ merged: bool = False
29
+ older_than_days: int | None = None
30
+ include_detached: bool = False
31
+ dry_run: bool = False
32
+
33
+
34
+ def _list_payload(command: WorktreeCommand, registry_root: Path, config: JsonObject) -> JsonObject:
35
+ auto_prune = worktree_mgmt.maybe_auto_prune(
36
+ registry_root,
37
+ config,
38
+ no_auto_prune=command.no_auto_prune,
39
+ )
40
+ payload = worktree_mgmt.list_worktrees(
41
+ registry_root,
42
+ harness=command.harness,
43
+ group=command.group,
44
+ status=command.status,
45
+ limit=command.limit or run_registry.DEFAULT_RUNS_LIMIT,
46
+ )
47
+ summary = payload.get("summary")
48
+ if isinstance(summary, dict):
49
+ summary["autoPruneMode"] = (
50
+ "suppressed"
51
+ if command.no_auto_prune
52
+ else "attempted"
53
+ if auto_prune is not None
54
+ else "disabled"
55
+ )
56
+ if auto_prune is not None and auto_prune.get("skipped") is not True:
57
+ summary["readOnly"] = False
58
+ if auto_prune is not None:
59
+ payload["autoPrune"] = auto_prune
60
+ if auto_prune.get("ok") is False and auto_prune.get("skipped") is not True:
61
+ payload["ok"] = False
62
+ exit_code = auto_prune.get("exitCode")
63
+ payload["exitCode"] = (
64
+ exit_code if isinstance(exit_code, int) else worktree_mgmt.WORKTREE_ERROR_EXIT_CODE
65
+ )
66
+ return payload
67
+
68
+
69
+ def _show_payload(command: WorktreeCommand, registry_root: Path, _config: JsonObject) -> JsonObject:
70
+ return worktree_mgmt.show_worktree(
71
+ registry_root,
72
+ handle=command.handle,
73
+ latest_harness=command.latest_harness,
74
+ )
75
+
76
+
77
+ def _remove_payload(
78
+ command: WorktreeCommand, registry_root: Path, _config: JsonObject
79
+ ) -> JsonObject:
80
+ if command.group is not None:
81
+ removed: list[JsonObject] = []
82
+ errors: list[JsonObject] = []
83
+ matches = [
84
+ record
85
+ for record in worktree_mgmt.load_persistent_records(registry_root)
86
+ if record.get("group") == command.group
87
+ ]
88
+ if not matches:
89
+ raise worktree_mgmt.WorktreeManagementError(
90
+ {
91
+ "ok": False,
92
+ "code": "no_matching_worktrees",
93
+ "message": f"No persistent worktrees found for group: {command.group}",
94
+ "group": command.group,
95
+ "matched": 0,
96
+ "retrySafe": False,
97
+ }
98
+ )
99
+ for record in matches:
100
+ handle = str(record.get("alias") or record.get("runId"))
101
+ try:
102
+ removed.append(
103
+ worktree_mgmt.remove_worktree(
104
+ registry_root,
105
+ handle=handle,
106
+ discard_uncommitted=command.discard_uncommitted,
107
+ force_branch=command.force_branch,
108
+ keep_branch=command.keep_branch,
109
+ force=command.force,
110
+ )
111
+ )
112
+ if removed[-1].get("ok") is False:
113
+ errors.append(removed[-1])
114
+ except worktree_mgmt.WorktreeManagementError as exc:
115
+ errors.append(exc.payload)
116
+ return {
117
+ "schema": worktree_mgmt.SCHEMA_REMOVE,
118
+ "ok": not errors,
119
+ "group": command.group,
120
+ "matched": len(matches),
121
+ "removed": removed,
122
+ "errors": errors,
123
+ **({"exitCode": worktree_mgmt.WORKTREE_ERROR_EXIT_CODE} if errors else {}),
124
+ }
125
+ if command.handle is None:
126
+ raise worktree_mgmt.WorktreeManagementError(
127
+ {
128
+ "ok": False,
129
+ "code": "missing_handle",
130
+ "message": "worktree remove requires a handle.",
131
+ "retrySafe": False,
132
+ }
133
+ )
134
+ return worktree_mgmt.remove_worktree(
135
+ registry_root,
136
+ handle=command.handle,
137
+ discard_uncommitted=command.discard_uncommitted,
138
+ force_branch=command.force_branch,
139
+ keep_branch=command.keep_branch,
140
+ force=command.force,
141
+ )
142
+
143
+
144
+ def _prune_payload(
145
+ command: WorktreeCommand, registry_root: Path, _config: JsonObject
146
+ ) -> JsonObject:
147
+ return worktree_mgmt.prune_worktrees(
148
+ registry_root,
149
+ merged=command.merged,
150
+ older_than_days=command.older_than_days,
151
+ harness=command.harness,
152
+ group=command.group,
153
+ include_detached=command.include_detached,
154
+ dry_run=command.dry_run,
155
+ discard_uncommitted=command.discard_uncommitted,
156
+ force_branch=command.force_branch,
157
+ force=command.force,
158
+ )
159
+
160
+
161
+ def _gc_payload(command: WorktreeCommand, registry_root: Path, _config: JsonObject) -> JsonObject:
162
+ return worktree_mgmt.gc_worktrees(
163
+ registry_root,
164
+ dry_run=command.dry_run,
165
+ )
166
+
167
+
168
+ PayloadBuilder = Callable[[WorktreeCommand, Path, JsonObject], JsonObject]
169
+ TextRenderer = Callable[[JsonObject, TextIO], None]
170
+ ACTION_DISPATCH: dict[str, tuple[PayloadBuilder, TextRenderer]] = {
171
+ "list": (_list_payload, delegate_rendering.render_worktree_list_text),
172
+ "show": (_show_payload, delegate_rendering.render_worktree_show_text),
173
+ "remove": (_remove_payload, delegate_rendering.render_worktree_remove_text),
174
+ "prune": (_prune_payload, delegate_rendering.render_worktree_prune_text),
175
+ "gc": (_gc_payload, delegate_rendering.render_worktree_gc_text),
176
+ }
177
+
178
+
179
+ def emit(
180
+ command: WorktreeCommand,
181
+ *,
182
+ workspace_path: str,
183
+ config: JsonObject,
184
+ stdout: TextIO,
185
+ ) -> int:
186
+ registry_root = run_registry.registry_root_if_exists(Path(workspace_path))
187
+ if registry_root is None:
188
+ raise worktree_mgmt.WorktreeManagementError(
189
+ {
190
+ "ok": False,
191
+ "code": "no_registry",
192
+ "message": "No Delegate run registry exists in this workspace.",
193
+ "sourceGitRoot": workspace_path,
194
+ "nextActions": ["run a tracked delegate command first"],
195
+ "retrySafe": False,
196
+ }
197
+ )
198
+ action = command.action
199
+ if action not in ACTION_DISPATCH:
200
+ raise worktree_mgmt.WorktreeManagementError(
201
+ {
202
+ "ok": False,
203
+ "code": "unknown_worktree_action",
204
+ "message": f"Unknown worktree action: {action}",
205
+ "sourceGitRoot": workspace_path,
206
+ "retrySafe": False,
207
+ }
208
+ )
209
+ build_payload, render_text = ACTION_DISPATCH[action]
210
+ payload = build_payload(command, registry_root, config)
211
+ if command.json_mode:
212
+ delegate_rendering.print_json(payload, stdout)
213
+ else:
214
+ render_text(payload, stdout)
215
+ if payload.get("ok") is False:
216
+ exit_code = payload.get("exitCode")
217
+ return exit_code if isinstance(exit_code, int) else worktree_mgmt.WORKTREE_ERROR_EXIT_CODE
218
+ return 0