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.
- delegate_agent/__init__.py +5 -0
- delegate_agent/archived_logs.py +44 -0
- delegate_agent/argv_builders.py +423 -0
- delegate_agent/argv_utils.py +36 -0
- delegate_agent/capability_commands.py +99 -0
- delegate_agent/cli.py +987 -0
- delegate_agent/cli_parser.py +1627 -0
- delegate_agent/command_errors.py +29 -0
- delegate_agent/command_help.py +1264 -0
- delegate_agent/config.py +1117 -0
- delegate_agent/config_commands.py +143 -0
- delegate_agent/constants.py +50 -0
- delegate_agent/describe_payload.py +1018 -0
- delegate_agent/errors.py +32 -0
- delegate_agent/git_utils.py +180 -0
- delegate_agent/harness_events.py +719 -0
- delegate_agent/inspection_commands.py +104 -0
- delegate_agent/isolation.py +316 -0
- delegate_agent/json_types.py +18 -0
- delegate_agent/log_output.py +78 -0
- delegate_agent/private_io.py +109 -0
- delegate_agent/profile_commands.py +42 -0
- delegate_agent/profile_guard.py +116 -0
- delegate_agent/profiles.py +389 -0
- delegate_agent/prompt_instructions.py +39 -0
- delegate_agent/prompt_transport.py +12 -0
- delegate_agent/reasoning.py +916 -0
- delegate_agent/redaction.py +193 -0
- delegate_agent/rendering.py +573 -0
- delegate_agent/request_build.py +1681 -0
- delegate_agent/request_models.py +191 -0
- delegate_agent/retention.py +321 -0
- delegate_agent/run_metadata.py +78 -0
- delegate_agent/run_output_commands.py +645 -0
- delegate_agent/run_registry.py +747 -0
- delegate_agent/run_status.py +300 -0
- delegate_agent/runner.py +1830 -0
- delegate_agent/safe_workspace.py +821 -0
- delegate_agent/snapshot_view.py +229 -0
- delegate_agent/wait_cancel_commands.py +559 -0
- delegate_agent/worktree_commands.py +218 -0
- delegate_agent/worktree_execution.py +654 -0
- delegate_agent/worktree_gc.py +529 -0
- delegate_agent/worktree_mgmt.py +782 -0
- delegate_agent/worktree_records.py +232 -0
- delegate_agent/worktree_remove.py +547 -0
- delegate_agent/worktree_summary.py +242 -0
- delegate_agent/wsl.py +65 -0
- delegate_agent_cli-0.11.0.dist-info/METADATA +325 -0
- delegate_agent_cli-0.11.0.dist-info/RECORD +54 -0
- delegate_agent_cli-0.11.0.dist-info/WHEEL +5 -0
- delegate_agent_cli-0.11.0.dist-info/entry_points.txt +2 -0
- delegate_agent_cli-0.11.0.dist-info/licenses/LICENSE +21 -0
- 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
|