devagent-cli 3.2.2__tar.gz → 3.2.3__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.
- {devagent_cli-3.2.2/devagent_cli.egg-info → devagent_cli-3.2.3}/PKG-INFO +1 -1
- devagent_cli-3.2.3/devagent/__init__.py +1 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/agent.py +18 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/state.py +1 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/cli.py +16 -1
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/utils/config.py +2 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/utils/safety.py +20 -3
- {devagent_cli-3.2.2 → devagent_cli-3.2.3/devagent_cli.egg-info}/PKG-INFO +1 -1
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/pyproject.toml +1 -1
- devagent_cli-3.2.2/devagent/__init__.py +0 -1
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/LICENSE +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/README.md +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/__init__.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/llm.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/memory.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/patcher.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/planner.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/reviewer.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/app/sandbox.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/__init__.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/benchmark_runner.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/file_ops.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/git_tools.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/linter.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/search.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/semantic_search.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/surgical_patcher.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/tools/test_runner.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/utils/__init__.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/utils/logger.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent/utils/metrics.py +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent_cli.egg-info/SOURCES.txt +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent_cli.egg-info/dependency_links.txt +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent_cli.egg-info/entry_points.txt +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent_cli.egg-info/requires.txt +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/devagent_cli.egg-info/top_level.txt +0 -0
- {devagent_cli-3.2.2 → devagent_cli-3.2.3}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.2.3"
|
|
@@ -280,6 +280,12 @@ class Agent:
|
|
|
280
280
|
observation = self._execute_action(action_name, action_arg)
|
|
281
281
|
self.state.last_observation = observation
|
|
282
282
|
self.state.observations.append(observation[:2000])
|
|
283
|
+
|
|
284
|
+
self.state.explanations.append({
|
|
285
|
+
"type": "action",
|
|
286
|
+
"action": f"{action_name}: {action_arg}",
|
|
287
|
+
"reason": thought
|
|
288
|
+
})
|
|
283
289
|
|
|
284
290
|
# STEP 3 — GENERATE FIX (if we have a file in context)
|
|
285
291
|
code_fix = ""
|
|
@@ -555,9 +561,21 @@ class Agent:
|
|
|
555
561
|
print(f" [REVIEW] #{revision + 1}: {review_text[:100]}")
|
|
556
562
|
|
|
557
563
|
if approved:
|
|
564
|
+
self.state.explanations.append({
|
|
565
|
+
"type": "review",
|
|
566
|
+
"file": self.state.current_file,
|
|
567
|
+
"reason": review_text,
|
|
568
|
+
"status": "APPROVED"
|
|
569
|
+
})
|
|
558
570
|
return code_fix, review_text
|
|
559
571
|
|
|
560
572
|
self.metrics.patch_rejections += 1
|
|
573
|
+
self.state.explanations.append({
|
|
574
|
+
"type": "review",
|
|
575
|
+
"file": self.state.current_file,
|
|
576
|
+
"reason": review_text,
|
|
577
|
+
"status": "REJECTED"
|
|
578
|
+
})
|
|
561
579
|
print(f" [REVISE] Revising code (attempt {revision + 1})...")
|
|
562
580
|
code_fix = revise_code(code_fix, review_text, self.state.task)
|
|
563
581
|
code_fix = self._strip_code_fences(code_fix)
|
|
@@ -73,6 +73,7 @@ class AgentState:
|
|
|
73
73
|
# -- Trust & Confidence --
|
|
74
74
|
confidence_score: float = 0.0
|
|
75
75
|
confidence_reasons: list[str] = field(default_factory=list)
|
|
76
|
+
explanations: list[dict[str, str]] = field(default_factory=list)
|
|
76
77
|
|
|
77
78
|
def to_dict(self) -> dict[str, Any]:
|
|
78
79
|
"""Return a JSON-serialisable snapshot of the current state."""
|
|
@@ -142,7 +142,21 @@ def cmd_run(args):
|
|
|
142
142
|
if final_state.confidence_reasons:
|
|
143
143
|
console.print("\n[bold]Confidence Breakdown:[/bold]")
|
|
144
144
|
for reason in final_state.confidence_reasons:
|
|
145
|
-
console.print(f" [
|
|
145
|
+
console.print(f" [green]✓[/green] {reason}")
|
|
146
|
+
|
|
147
|
+
# Explain Mode
|
|
148
|
+
if config.explain and final_state.explanations:
|
|
149
|
+
console.print("\n" + "=" * 60)
|
|
150
|
+
console.print(" [bold cyan]TRACEABILITY REPORT (EXPLAIN MODE)[/bold cyan]")
|
|
151
|
+
console.print("=" * 60)
|
|
152
|
+
for exp in final_state.explanations:
|
|
153
|
+
if exp["type"] == "action":
|
|
154
|
+
console.print(f"\n[bold yellow]Selection:[/bold yellow] {exp['action']}")
|
|
155
|
+
console.print(f" [dim]Why:[/dim] {exp['reason']}")
|
|
156
|
+
elif exp["type"] == "review":
|
|
157
|
+
status_color = "green" if exp["status"] == "APPROVED" else "red"
|
|
158
|
+
console.print(f"\n[bold {status_color}]Review:[/bold {status_color}] {exp['file']} ({exp['status']})")
|
|
159
|
+
console.print(f" [dim]Logic:[/dim] {exp['reason']}")
|
|
146
160
|
|
|
147
161
|
# Sandbox apply / Dry Run
|
|
148
162
|
if sandbox and sandbox.is_active:
|
|
@@ -273,6 +287,7 @@ def main():
|
|
|
273
287
|
run_parser.add_argument("--auto-push", action="store_true", help="Auto-push after commit")
|
|
274
288
|
run_parser.add_argument("--interactive", "-i", action="store_true", help="Review changes before applying")
|
|
275
289
|
run_parser.add_argument("--dry-run", action="store_true", help="Run without applying any changes")
|
|
290
|
+
run_parser.add_argument("--explain", action="store_true", help="Explain why files were chosen and patches applied")
|
|
276
291
|
run_parser.add_argument("--verbose", action="store_true", help="Verbose output")
|
|
277
292
|
|
|
278
293
|
# Command: benchmark
|
|
@@ -54,6 +54,7 @@ class AgentConfig:
|
|
|
54
54
|
# ── Feature flags ──
|
|
55
55
|
sandbox: bool = True
|
|
56
56
|
dry_run: bool = False
|
|
57
|
+
explain: bool = False
|
|
57
58
|
auto_commit: bool = False
|
|
58
59
|
auto_push: bool = False # DISABLED by default — safety first
|
|
59
60
|
benchmark: bool = False
|
|
@@ -100,6 +101,7 @@ class AgentConfig:
|
|
|
100
101
|
verbose=getattr(args, "verbose", False),
|
|
101
102
|
sandbox=getattr(args, "sandbox", True),
|
|
102
103
|
dry_run=getattr(args, "dry_run", False),
|
|
104
|
+
explain=getattr(args, "explain", False),
|
|
103
105
|
auto_commit=getattr(args, "auto_commit", False),
|
|
104
106
|
auto_push=getattr(args, "auto_push", False),
|
|
105
107
|
benchmark=getattr(args, "benchmark", False),
|
|
@@ -5,6 +5,7 @@ Safety Manager — handles snapshots and rollbacks.
|
|
|
5
5
|
import os
|
|
6
6
|
import shutil
|
|
7
7
|
import time
|
|
8
|
+
import subprocess
|
|
8
9
|
from rich.console import Console
|
|
9
10
|
from devagent.tools.git_tools import is_git_repo
|
|
10
11
|
|
|
@@ -13,7 +14,7 @@ console = Console()
|
|
|
13
14
|
class SafetyManager:
|
|
14
15
|
def __init__(self, project_root: str):
|
|
15
16
|
self.root = os.path.abspath(project_root)
|
|
16
|
-
self.snapshot_dir = os.path.join(self.root, ".
|
|
17
|
+
self.snapshot_dir = os.path.join(self.root, ".devagent_backups")
|
|
17
18
|
|
|
18
19
|
def create_snapshot(self, task_id: str = "latest") -> str:
|
|
19
20
|
"""Create a safety snapshot of the current project state."""
|
|
@@ -40,13 +41,29 @@ class SafetyManager:
|
|
|
40
41
|
os.makedirs(os.path.dirname(target_file), exist_ok=True)
|
|
41
42
|
shutil.copy2(src_file, target_file)
|
|
42
43
|
|
|
44
|
+
# Save metadata
|
|
45
|
+
metadata = {
|
|
46
|
+
"task_id": task_id,
|
|
47
|
+
"timestamp": timestamp,
|
|
48
|
+
"root": self.root
|
|
49
|
+
}
|
|
50
|
+
with open(os.path.join(dest, "metadata.json"), "w") as f:
|
|
51
|
+
import json
|
|
52
|
+
json.dump(metadata, f, indent=2)
|
|
53
|
+
|
|
43
54
|
return dest
|
|
44
55
|
|
|
45
56
|
def rollback(self, snapshot_id: str = "latest") -> bool:
|
|
46
57
|
"""Rollback the project to a previous snapshot."""
|
|
47
58
|
if is_git_repo(self.root):
|
|
48
|
-
console.print("[bold yellow][SAFETY][/bold yellow] This is a Git repository.
|
|
49
|
-
|
|
59
|
+
console.print("[bold yellow][SAFETY][/bold yellow] This is a Git repository. Reverting all local changes...")
|
|
60
|
+
try:
|
|
61
|
+
subprocess.run(["git", "checkout", "."], cwd=self.root, check=True, capture_output=True)
|
|
62
|
+
console.print("[bold green]Git rollback complete.[/bold green]")
|
|
63
|
+
return True
|
|
64
|
+
except Exception as e:
|
|
65
|
+
console.print(f"[bold red][ERROR][/bold red] Git rollback failed: {e}")
|
|
66
|
+
return False
|
|
50
67
|
|
|
51
68
|
# Find latest snapshot if not specified
|
|
52
69
|
if not os.path.exists(self.snapshot_dir):
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.2.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|