devagent-cli 3.2.1__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.
Files changed (37) hide show
  1. {devagent_cli-3.2.1/devagent_cli.egg-info → devagent_cli-3.2.3}/PKG-INFO +11 -9
  2. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/README.md +10 -8
  3. devagent_cli-3.2.3/devagent/__init__.py +1 -0
  4. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/agent.py +21 -1
  5. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/state.py +1 -0
  6. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/cli.py +53 -6
  7. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/utils/config.py +4 -0
  8. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/utils/metrics.py +2 -0
  9. devagent_cli-3.2.3/devagent/utils/safety.py +90 -0
  10. {devagent_cli-3.2.1 → devagent_cli-3.2.3/devagent_cli.egg-info}/PKG-INFO +11 -9
  11. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent_cli.egg-info/SOURCES.txt +1 -0
  12. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/pyproject.toml +1 -1
  13. devagent_cli-3.2.1/devagent/__init__.py +0 -1
  14. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/LICENSE +0 -0
  15. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/__init__.py +0 -0
  16. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/llm.py +0 -0
  17. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/memory.py +0 -0
  18. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/patcher.py +0 -0
  19. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/planner.py +0 -0
  20. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/reviewer.py +0 -0
  21. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/app/sandbox.py +0 -0
  22. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/__init__.py +0 -0
  23. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/benchmark_runner.py +0 -0
  24. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/file_ops.py +0 -0
  25. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/git_tools.py +0 -0
  26. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/linter.py +0 -0
  27. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/search.py +0 -0
  28. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/semantic_search.py +0 -0
  29. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/surgical_patcher.py +0 -0
  30. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/tools/test_runner.py +0 -0
  31. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/utils/__init__.py +0 -0
  32. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent/utils/logger.py +0 -0
  33. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent_cli.egg-info/dependency_links.txt +0 -0
  34. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent_cli.egg-info/entry_points.txt +0 -0
  35. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent_cli.egg-info/requires.txt +0 -0
  36. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/devagent_cli.egg-info/top_level.txt +0 -0
  37. {devagent_cli-3.2.1 → devagent_cli-3.2.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devagent-cli
3
- Version: 3.2.1
3
+ Version: 3.2.3
4
4
  Summary: Professional Local autonomous coding agent powered by Ollama
5
5
  Author: Vedant Jadhav
6
6
  License: MIT
@@ -31,6 +31,7 @@ Dynamic: license-file
31
31
  ### A Lightweight Local Open-Source Miniature of Claude Code CLI
32
32
 
33
33
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
34
+ [![PyPI version](https://badge.fury.io/py/devagent-cli.svg)](https://badge.fury.io/py/devagent-cli)
34
35
  [![Python 3.11+](https://img.shields.io/badge/Python-3.11+-3776AB.svg?logo=python&logoColor=white)](https://www.python.org/)
35
36
  [![Ollama](https://img.shields.io/badge/Ollama-Local%20LLM-black.svg?logo=ollama)](https://ollama.ai)
36
37
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
@@ -140,16 +141,16 @@ devagent run --task "Fix the divide-by-zero bug" --root ./demo_project
140
141
  | `devagent models` | List available Ollama models |
141
142
  | `devagent version` | Show current version |
142
143
 
143
- ### New: Trust & Safety
144
-
145
- #### 🛡️ Reliability Hardening (v3.2.1+)
146
- DevAgent is now built for **Enterprise-grade reliability** in complex projects:
147
- - **Path Anchoring**: Automatically corrects "root hallucinations." If the agent targets a file in a subdirectory but assumes it's at the root, the system auto-anchors it to the correct project location.
148
- - **Forensic Test Detection**: Built-in intelligence to "see through" environment noise. It detects successful test runs even if unrelated parts of the repository have collection errors.
149
- - **Confidence Scoring**: Every fix is graded (0-100%) based on test results, surgical precision, and self-review quality.
144
+ ### 🛡️ Reliability & Safety (v3.2.1+)
145
+ DevAgent is built for **Enterprise-grade safety**:
146
+ - **Dry Run Mode**: Use `--dry-run` to see what the agent *would* do without touching your files.
147
+ - **Auto-Snapshot**: Creates a safety restore point before every run.
148
+ - **Rollback**: Revert the last agent changes instantly with `devagent rollback`.
149
+ - **Forensic Test Detection**: Detects successful test runs even in noisy environments.
150
+ - **Path Anchoring**: Automatically corrects "root hallucinations" for subdirectories.
150
151
 
151
152
  #### 🕹️ Interactive Mode
152
- Run with `--interactive` (or `-i`) to review diffs before they are applied to your project.
153
+ Run with `--interactive` (or `-i`) to review colorized diffs before they are applied to your project.
153
154
  ```bash
154
155
  devagent run --task "Fix bug" --interactive
155
156
  ```
@@ -161,6 +162,7 @@ devagent run --task "Fix bug" --interactive
161
162
  ```mermaid
162
163
  graph TD
163
164
  CLI[DevAgent CLI] --> Orchestrator[ReAct Orchestrator]
165
+ Orchestrator --> Safety[Safety Manager: Snapshots]
164
166
  Orchestrator --> Memory[Working Memory]
165
167
  Orchestrator --> Retrieval[Semantic Retrieval FAISS]
166
168
  Orchestrator --> Tools[Tool Suite: pytest, ripgrep, git]
@@ -5,6 +5,7 @@
5
5
  ### A Lightweight Local Open-Source Miniature of Claude Code CLI
6
6
 
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+ [![PyPI version](https://badge.fury.io/py/devagent-cli.svg)](https://badge.fury.io/py/devagent-cli)
8
9
  [![Python 3.11+](https://img.shields.io/badge/Python-3.11+-3776AB.svg?logo=python&logoColor=white)](https://www.python.org/)
9
10
  [![Ollama](https://img.shields.io/badge/Ollama-Local%20LLM-black.svg?logo=ollama)](https://ollama.ai)
10
11
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
@@ -114,16 +115,16 @@ devagent run --task "Fix the divide-by-zero bug" --root ./demo_project
114
115
  | `devagent models` | List available Ollama models |
115
116
  | `devagent version` | Show current version |
116
117
 
117
- ### New: Trust & Safety
118
-
119
- #### 🛡️ Reliability Hardening (v3.2.1+)
120
- DevAgent is now built for **Enterprise-grade reliability** in complex projects:
121
- - **Path Anchoring**: Automatically corrects "root hallucinations." If the agent targets a file in a subdirectory but assumes it's at the root, the system auto-anchors it to the correct project location.
122
- - **Forensic Test Detection**: Built-in intelligence to "see through" environment noise. It detects successful test runs even if unrelated parts of the repository have collection errors.
123
- - **Confidence Scoring**: Every fix is graded (0-100%) based on test results, surgical precision, and self-review quality.
118
+ ### 🛡️ Reliability & Safety (v3.2.1+)
119
+ DevAgent is built for **Enterprise-grade safety**:
120
+ - **Dry Run Mode**: Use `--dry-run` to see what the agent *would* do without touching your files.
121
+ - **Auto-Snapshot**: Creates a safety restore point before every run.
122
+ - **Rollback**: Revert the last agent changes instantly with `devagent rollback`.
123
+ - **Forensic Test Detection**: Detects successful test runs even in noisy environments.
124
+ - **Path Anchoring**: Automatically corrects "root hallucinations" for subdirectories.
124
125
 
125
126
  #### 🕹️ Interactive Mode
126
- Run with `--interactive` (or `-i`) to review diffs before they are applied to your project.
127
+ Run with `--interactive` (or `-i`) to review colorized diffs before they are applied to your project.
127
128
  ```bash
128
129
  devagent run --task "Fix bug" --interactive
129
130
  ```
@@ -135,6 +136,7 @@ devagent run --task "Fix bug" --interactive
135
136
  ```mermaid
136
137
  graph TD
137
138
  CLI[DevAgent CLI] --> Orchestrator[ReAct Orchestrator]
139
+ Orchestrator --> Safety[Safety Manager: Snapshots]
138
140
  Orchestrator --> Memory[Working Memory]
139
141
  Orchestrator --> Retrieval[Semantic Retrieval FAISS]
140
142
  Orchestrator --> Tools[Tool Suite: pytest, ripgrep, git]
@@ -0,0 +1 @@
1
+ __version__ = "3.2.3"
@@ -114,13 +114,14 @@ EXTRACT_ACTION_PATTERN = re.compile(
114
114
  class Agent:
115
115
  """ReAct agent with planner, retrieval, self-review, and sandbox support."""
116
116
 
117
- def __init__(self, task: str, project_root: str = ".", max_steps: int = 5):
117
+ def __init__(self, task: str, project_root: str = ".", max_steps: int = 5, dry_run: bool = False):
118
118
  self.state = AgentState(
119
119
  task=task,
120
120
  project_root=os.path.abspath(project_root),
121
121
  max_steps=max_steps,
122
122
  working_root=os.path.abspath(project_root),
123
123
  )
124
+ self.dry_run = dry_run
124
125
  self.logger = AgentLogger(log_dir=os.path.join(project_root, "logs"))
125
126
  self.metrics = RunMetrics(task=task)
126
127
  self.memory = WorkingMemory()
@@ -279,6 +280,12 @@ class Agent:
279
280
  observation = self._execute_action(action_name, action_arg)
280
281
  self.state.last_observation = observation
281
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
+ })
282
289
 
283
290
  # STEP 3 — GENERATE FIX (if we have a file in context)
284
291
  code_fix = ""
@@ -554,8 +561,21 @@ class Agent:
554
561
  print(f" [REVIEW] #{revision + 1}: {review_text[:100]}")
555
562
 
556
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
+ })
557
570
  return code_fix, review_text
558
571
 
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
+ })
559
579
  print(f" [REVISE] Revising code (attempt {revision + 1})...")
560
580
  code_fix = revise_code(code_fix, review_text, self.state.task)
561
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."""
@@ -92,15 +92,24 @@ def cmd_run(args):
92
92
  # Sandbox setup
93
93
  sandbox = None
94
94
  working_root = root
95
- if config.sandbox:
95
+ if config.sandbox or config.dry_run:
96
+ if config.dry_run:
97
+ console.print("[bold yellow][DRY RUN][/bold yellow] Agent will work in an isolated sandbox. No changes will be applied.")
96
98
  sandbox = SandboxManager(root)
97
99
  working_root = sandbox.create()
98
100
 
101
+ # Safety Snapshot
102
+ if not config.dry_run:
103
+ from devagent.utils.safety import SafetyManager
104
+ safety = SafetyManager(root)
105
+ safety.create_snapshot(task_id=config.task[:10].replace(" ", "_"))
106
+
99
107
  # Run agent
100
108
  agent = Agent(
101
109
  task=config.task,
102
110
  project_root=working_root,
103
111
  max_steps=config.max_steps,
112
+ dry_run=config.dry_run
104
113
  )
105
114
 
106
115
  start_time = time.time()
@@ -133,12 +142,35 @@ def cmd_run(args):
133
142
  if final_state.confidence_reasons:
134
143
  console.print("\n[bold]Confidence Breakdown:[/bold]")
135
144
  for reason in final_state.confidence_reasons:
136
- console.print(f" [dim] {reason}[/dim]")
137
-
138
- # Sandbox apply
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']}")
160
+
161
+ # Sandbox apply / Dry Run
139
162
  if sandbox and sandbox.is_active:
163
+ if config.dry_run:
164
+ console.print("\n[bold yellow][DRY RUN][/bold yellow] Completed. No changes applied.")
165
+ # Show diffs anyway to show what would have happened
166
+ for i, patch in enumerate(final_state.patches_applied):
167
+ console.print(f"\n[bold]Proposed Patch #{i+1}[/bold] for [cyan]{patch.get('file', 'unknown')}[/cyan]:")
168
+ console.print(f"[dim]{patch.get('diff', 'No diff available')}[/dim]")
169
+ sandbox.destroy()
170
+ return 0
171
+
140
172
  if final_state.status == "success":
141
- if getattr(args, "interactive", False):
173
+ if config.interactive:
142
174
  console.print("\n[bold yellow][INTERACTIVE][/bold yellow] Reviewing changes...")
143
175
  # Show diff for each applied patch
144
176
  for i, patch in enumerate(final_state.patches_applied):
@@ -159,7 +191,7 @@ def cmd_run(args):
159
191
  sandbox.destroy()
160
192
 
161
193
  # Git operations
162
- if final_state.status == "success" and config.auto_commit:
194
+ if final_state.status == "success" and config.auto_commit and not config.dry_run:
163
195
  _handle_git(root, config)
164
196
 
165
197
  return 0 if final_state.status == "success" else 1
@@ -231,6 +263,13 @@ def cmd_models(args):
231
263
  console.print("[red][ERROR][/red] Could not list Ollama models.")
232
264
  return 0
233
265
 
266
+ def cmd_rollback(args):
267
+ """Implementation of 'devagent rollback' command."""
268
+ from devagent.utils.safety import SafetyManager
269
+ root = os.path.abspath(getattr(args, "root", "."))
270
+ safety = SafetyManager(root)
271
+ return 0 if safety.rollback() else 1
272
+
234
273
  def main():
235
274
  parser = argparse.ArgumentParser(description="DevAgent CLI — Professional local coding agent.")
236
275
  parser.add_argument("--version", action="version", version=f"DevAgent v{__version__}")
@@ -247,6 +286,8 @@ def main():
247
286
  run_parser.add_argument("--auto-commit", action="store_true", help="Auto-commit on success")
248
287
  run_parser.add_argument("--auto-push", action="store_true", help="Auto-push after commit")
249
288
  run_parser.add_argument("--interactive", "-i", action="store_true", help="Review changes before applying")
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")
250
291
  run_parser.add_argument("--verbose", action="store_true", help="Verbose output")
251
292
 
252
293
  # Command: benchmark
@@ -260,6 +301,10 @@ def main():
260
301
  # Command: models
261
302
  subparsers.add_parser("models", help="List installed Ollama models")
262
303
 
304
+ # Command: rollback
305
+ roll_parser = subparsers.add_parser("rollback", help="Revert the last agent changes")
306
+ roll_parser.add_argument("--root", "-r", default=".", help="Project root")
307
+
263
308
  # Command: version
264
309
  subparsers.add_parser("version", help="Show version")
265
310
 
@@ -273,6 +318,8 @@ def main():
273
318
  sys.exit(cmd_doctor(args))
274
319
  elif args.command == "models":
275
320
  sys.exit(cmd_models(args))
321
+ elif args.command == "rollback":
322
+ sys.exit(cmd_rollback(args))
276
323
  elif args.command == "version":
277
324
  console.print(f"DevAgent CLI v{__version__}")
278
325
  else:
@@ -53,6 +53,8 @@ class AgentConfig:
53
53
 
54
54
  # ── Feature flags ──
55
55
  sandbox: bool = True
56
+ dry_run: bool = False
57
+ explain: bool = False
56
58
  auto_commit: bool = False
57
59
  auto_push: bool = False # DISABLED by default — safety first
58
60
  benchmark: bool = False
@@ -98,6 +100,8 @@ class AgentConfig:
98
100
  max_steps=getattr(args, "max_steps", 5),
99
101
  verbose=getattr(args, "verbose", False),
100
102
  sandbox=getattr(args, "sandbox", True),
103
+ dry_run=getattr(args, "dry_run", False),
104
+ explain=getattr(args, "explain", False),
101
105
  auto_commit=getattr(args, "auto_commit", False),
102
106
  auto_push=getattr(args, "auto_push", False),
103
107
  benchmark=getattr(args, "benchmark", False),
@@ -36,6 +36,7 @@ class RunMetrics:
36
36
  end_time: float = 0.0
37
37
  total_steps: int = 0
38
38
  retries: int = 0
39
+ patch_rejections: int = 0
39
40
  successes: int = 0
40
41
  failures: int = 0
41
42
  total_latency_s: float = 0.0
@@ -88,6 +89,7 @@ class RunMetrics:
88
89
  "task": self.task[:100],
89
90
  "total_steps": self.total_steps,
90
91
  "retries": self.retries,
92
+ "patch_rejections": self.patch_rejections,
91
93
  "successes": self.successes,
92
94
  "failures": self.failures,
93
95
  "total_latency_s": round(self.total_latency_s, 2),
@@ -0,0 +1,90 @@
1
+ """
2
+ Safety Manager — handles snapshots and rollbacks.
3
+ """
4
+
5
+ import os
6
+ import shutil
7
+ import time
8
+ import subprocess
9
+ from rich.console import Console
10
+ from devagent.tools.git_tools import is_git_repo
11
+
12
+ console = Console()
13
+
14
+ class SafetyManager:
15
+ def __init__(self, project_root: str):
16
+ self.root = os.path.abspath(project_root)
17
+ self.snapshot_dir = os.path.join(self.root, ".devagent_backups")
18
+
19
+ def create_snapshot(self, task_id: str = "latest") -> str:
20
+ """Create a safety snapshot of the current project state."""
21
+ if is_git_repo(self.root):
22
+ # For git repos, we rely on the user's ability to git checkout
23
+ # but we could also do a 'git stash' here for safety.
24
+ return "git"
25
+
26
+ # For non-git repos, we do a physical backup of .py files
27
+ os.makedirs(self.snapshot_dir, exist_ok=True)
28
+ timestamp = int(time.time())
29
+ dest = os.path.join(self.snapshot_dir, f"{task_id}_{timestamp}")
30
+
31
+ # Simple copy of python files
32
+ os.makedirs(dest, exist_ok=True)
33
+ for root, _, files in os.walk(self.root):
34
+ if ".devagent" in root or "venv" in root:
35
+ continue
36
+ for f in files:
37
+ if f.endswith(".py"):
38
+ src_file = os.path.join(root, f)
39
+ rel_path = os.path.relpath(src_file, self.root)
40
+ target_file = os.path.join(dest, rel_path)
41
+ os.makedirs(os.path.dirname(target_file), exist_ok=True)
42
+ shutil.copy2(src_file, target_file)
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
+
54
+ return dest
55
+
56
+ def rollback(self, snapshot_id: str = "latest") -> bool:
57
+ """Rollback the project to a previous snapshot."""
58
+ if is_git_repo(self.root):
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
67
+
68
+ # Find latest snapshot if not specified
69
+ if not os.path.exists(self.snapshot_dir):
70
+ console.print("[bold red][ERROR][/bold red] No snapshots found.")
71
+ return False
72
+
73
+ snapshots = sorted(os.listdir(self.snapshot_dir))
74
+ if not snapshots:
75
+ console.print("[bold red][ERROR][/bold red] No snapshots found.")
76
+ return False
77
+
78
+ target = os.path.join(self.snapshot_dir, snapshots[-1])
79
+ console.print(f"[bold yellow][SAFETY][/bold yellow] Rolling back from {target}...")
80
+
81
+ # Restore files
82
+ for root, _, files in os.walk(target):
83
+ for f in files:
84
+ src_file = os.path.join(root, f)
85
+ rel_path = os.path.relpath(src_file, target)
86
+ dest_file = os.path.join(self.root, rel_path)
87
+ shutil.copy2(src_file, dest_file)
88
+
89
+ console.print("[bold green]Rollback complete.[/bold green]")
90
+ return True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devagent-cli
3
- Version: 3.2.1
3
+ Version: 3.2.3
4
4
  Summary: Professional Local autonomous coding agent powered by Ollama
5
5
  Author: Vedant Jadhav
6
6
  License: MIT
@@ -31,6 +31,7 @@ Dynamic: license-file
31
31
  ### A Lightweight Local Open-Source Miniature of Claude Code CLI
32
32
 
33
33
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
34
+ [![PyPI version](https://badge.fury.io/py/devagent-cli.svg)](https://badge.fury.io/py/devagent-cli)
34
35
  [![Python 3.11+](https://img.shields.io/badge/Python-3.11+-3776AB.svg?logo=python&logoColor=white)](https://www.python.org/)
35
36
  [![Ollama](https://img.shields.io/badge/Ollama-Local%20LLM-black.svg?logo=ollama)](https://ollama.ai)
36
37
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
@@ -140,16 +141,16 @@ devagent run --task "Fix the divide-by-zero bug" --root ./demo_project
140
141
  | `devagent models` | List available Ollama models |
141
142
  | `devagent version` | Show current version |
142
143
 
143
- ### New: Trust & Safety
144
-
145
- #### 🛡️ Reliability Hardening (v3.2.1+)
146
- DevAgent is now built for **Enterprise-grade reliability** in complex projects:
147
- - **Path Anchoring**: Automatically corrects "root hallucinations." If the agent targets a file in a subdirectory but assumes it's at the root, the system auto-anchors it to the correct project location.
148
- - **Forensic Test Detection**: Built-in intelligence to "see through" environment noise. It detects successful test runs even if unrelated parts of the repository have collection errors.
149
- - **Confidence Scoring**: Every fix is graded (0-100%) based on test results, surgical precision, and self-review quality.
144
+ ### 🛡️ Reliability & Safety (v3.2.1+)
145
+ DevAgent is built for **Enterprise-grade safety**:
146
+ - **Dry Run Mode**: Use `--dry-run` to see what the agent *would* do without touching your files.
147
+ - **Auto-Snapshot**: Creates a safety restore point before every run.
148
+ - **Rollback**: Revert the last agent changes instantly with `devagent rollback`.
149
+ - **Forensic Test Detection**: Detects successful test runs even in noisy environments.
150
+ - **Path Anchoring**: Automatically corrects "root hallucinations" for subdirectories.
150
151
 
151
152
  #### 🕹️ Interactive Mode
152
- Run with `--interactive` (or `-i`) to review diffs before they are applied to your project.
153
+ Run with `--interactive` (or `-i`) to review colorized diffs before they are applied to your project.
153
154
  ```bash
154
155
  devagent run --task "Fix bug" --interactive
155
156
  ```
@@ -161,6 +162,7 @@ devagent run --task "Fix bug" --interactive
161
162
  ```mermaid
162
163
  graph TD
163
164
  CLI[DevAgent CLI] --> Orchestrator[ReAct Orchestrator]
165
+ Orchestrator --> Safety[Safety Manager: Snapshots]
164
166
  Orchestrator --> Memory[Working Memory]
165
167
  Orchestrator --> Retrieval[Semantic Retrieval FAISS]
166
168
  Orchestrator --> Tools[Tool Suite: pytest, ripgrep, git]
@@ -25,6 +25,7 @@ devagent/utils/__init__.py
25
25
  devagent/utils/config.py
26
26
  devagent/utils/logger.py
27
27
  devagent/utils/metrics.py
28
+ devagent/utils/safety.py
28
29
  devagent_cli.egg-info/PKG-INFO
29
30
  devagent_cli.egg-info/SOURCES.txt
30
31
  devagent_cli.egg-info/dependency_links.txt
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "devagent-cli"
7
- version = "3.2.1"
7
+ version = "3.2.3"
8
8
  description = "Professional Local autonomous coding agent powered by Ollama"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1 +0,0 @@
1
- __version__ = "3.2.1"
File without changes
File without changes