devagent-cli 3.3.1__tar.gz → 3.7.5__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.7.5/PKG-INFO +163 -0
- devagent_cli-3.7.5/README.md +137 -0
- devagent_cli-3.7.5/devagent/__init__.py +1 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/agent.py +27 -9
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/cli.py +10 -2
- devagent_cli-3.7.5/devagent/tools/env_detector.py +44 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/test_runner.py +22 -1
- devagent_cli-3.7.5/devagent/utils/environment.py +129 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/utils/logger.py +2 -1
- devagent_cli-3.7.5/devagent_cli.egg-info/PKG-INFO +163 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent_cli.egg-info/SOURCES.txt +2 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/pyproject.toml +1 -1
- devagent_cli-3.3.1/PKG-INFO +0 -479
- devagent_cli-3.3.1/README.md +0 -453
- devagent_cli-3.3.1/devagent/__init__.py +0 -1
- devagent_cli-3.3.1/devagent_cli.egg-info/PKG-INFO +0 -479
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/LICENSE +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/__init__.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/llm.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/memory.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/patcher.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/planner.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/reviewer.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/sandbox.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/app/state.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/__init__.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/benchmark_runner.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/file_map.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/file_ops.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/git_tools.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/linter.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/search.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/semantic_search.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/tools/surgical_patcher.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/utils/__init__.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/utils/ast_utils.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/utils/config.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/utils/metrics.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent/utils/safety.py +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent_cli.egg-info/dependency_links.txt +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent_cli.egg-info/entry_points.txt +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent_cli.egg-info/requires.txt +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/devagent_cli.egg-info/top_level.txt +0 -0
- {devagent_cli-3.3.1 → devagent_cli-3.7.5}/setup.cfg +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devagent-cli
|
|
3
|
+
Version: 3.7.5
|
|
4
|
+
Summary: A local autonomous coding agent CLI powered by Ollama.
|
|
5
|
+
Author: Vedant Jadhav
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: ai,agent,coding,ollama,local,devagent,devagent-cli
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Topic :: Software Development :: Interpreters
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: rich
|
|
17
|
+
Requires-Dist: pytest
|
|
18
|
+
Requires-Dist: requests
|
|
19
|
+
Requires-Dist: ollama
|
|
20
|
+
Requires-Dist: faiss-cpu
|
|
21
|
+
Provides-Extra: semantic
|
|
22
|
+
Requires-Dist: sentence-transformers; extra == "semantic"
|
|
23
|
+
Provides-Extra: lint
|
|
24
|
+
Requires-Dist: flake8; extra == "lint"
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
|
|
27
|
+
# 🧠 DevAgent
|
|
28
|
+
### Execution-Grounded Orchestration for Autonomous Local Coding.
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+
|
|
32
|
+
[**🌐 Live Site**](https://devagent-cli.vercel.app/) • [**📦 PyPI**](https://pypi.org/project/devagent-cli/) • [**📜 Docs**](https://devagent-cli.vercel.app/docs)
|
|
33
|
+
|
|
34
|
+
[](https://badge.fury.io/py/devagent-cli)
|
|
35
|
+
[](LICENSE)
|
|
36
|
+
[](https://ollama.ai)
|
|
37
|
+
[](https://devagent-cli.vercel.app/benchmarks)
|
|
38
|
+
|
|
39
|
+
**DevAgent** is a research-grade, local-first coding agent runtime designed to bridge the gap between LLM-generated logic and production-ready execution integrity.
|
|
40
|
+
|
|
41
|
+
[Quick Start](#-quick-start) • [Architecture](#-high-integrity-architecture) • [Safety & Containment](#-safety-first-containment) • [Benchmarks](#-empirical-validation) • [Troubleshooting](docs/troubleshooting.md)
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🛡️ The Problem: The "LLM-Execution Gap"
|
|
48
|
+
Most autonomous coding agents fail because they operate in a vacuum. They generate code that looks correct but fails at runtime due to **environment drift**, **dependency conflicts**, or **invalid execution assumptions**.
|
|
49
|
+
|
|
50
|
+
DevAgent is **Execution-Grounded Orchestration**. It doesn't just guess code; it manages the entire lifecycle of a fix:
|
|
51
|
+
1. **Discovery**: Scans and maps the environment.
|
|
52
|
+
2. **Isolation**: Provisions a clean, sandboxed virtual environment.
|
|
53
|
+
3. **Repair**: Autonomously resolves missing dependencies.
|
|
54
|
+
4. **Validation**: Verifies patches against your actual test suite.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 🏗️ High-Integrity Architecture
|
|
59
|
+
DevAgent v3.4.1 implements a multi-layer orchestration stack designed for reliability over hype.
|
|
60
|
+
|
|
61
|
+
```mermaid
|
|
62
|
+
graph TD
|
|
63
|
+
subgraph "Orchestration Layer"
|
|
64
|
+
CLI[DevAgent CLI] --> Planner[Task Planner]
|
|
65
|
+
Planner --> Retrieval[Hierarchical Retrieval: FAISS + Ripgrep]
|
|
66
|
+
Retrieval --> Agent[ReAct Agent: Thought/Action/Observation]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
subgraph "Execution Layer"
|
|
70
|
+
Agent --> Patch[Surgical Patch Engine: Line-Level Diffs]
|
|
71
|
+
Patch --> Reviewer[Self-Review Loop: APPROVED/REVISE]
|
|
72
|
+
Reviewer --> Runtime[Environment Runtime]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
subgraph "The Maturity Layer"
|
|
76
|
+
Runtime --> Discovery[Auto-Dependency Discovery]
|
|
77
|
+
Discovery --> Isolation[Venv Isolation: .tmp_envs]
|
|
78
|
+
Isolation --> Repair[Autonomous Repair Loop: repair_environment]
|
|
79
|
+
Repair --> Validation[Validation Engine: pytest]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
Validation -- Pass --> Apply[Apply to Root Repo]
|
|
83
|
+
Validation -- Fail --> Agent
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 🚀 Quick Start
|
|
89
|
+
|
|
90
|
+
### 1. Installation
|
|
91
|
+
Install the CLI via PyPI. Ensure [Ollama](https://ollama.ai) is running locally.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install devagent-cli
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2. Verify Infrastructure
|
|
98
|
+
Check your local environment, connectivity, and dependency health.
|
|
99
|
+
```bash
|
|
100
|
+
devagent doctor
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3. Run Your First Task
|
|
104
|
+
Execute an autonomous fix on any repository.
|
|
105
|
+
```bash
|
|
106
|
+
devagent run --task "Implement input validation for the user login" --root ./my-project
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## ✨ Advanced Features
|
|
112
|
+
|
|
113
|
+
### 🔍 Hierarchical Retrieval
|
|
114
|
+
Instead of dumping your entire codebase into a context window, DevAgent uses a multi-tier search:
|
|
115
|
+
- **Global Map**: Scans the file structure to identify relevant modules.
|
|
116
|
+
- **Semantic Tier**: FAISS-powered vector search for conceptual matching.
|
|
117
|
+
- **Precision Tier**: Ripgrep for exact symbol/error discovery.
|
|
118
|
+
|
|
119
|
+
### 🏖️ Environment Isolation & Repair
|
|
120
|
+
DevAgent is the first local agent to treat the environment as a first-class citizen. It detects `requirements.txt` or `pyproject.toml`, creates an isolated `.tmp_envs/` runtime, and **autonomously installs missing packages** if it encounters a `ModuleNotFoundError`.
|
|
121
|
+
|
|
122
|
+
### 🩹 Surgical Patch Engine
|
|
123
|
+
Most agents ruin git history by rewriting entire files. DevAgent generates **line-level unified diffs**, applying only the necessary changes while preserving your code style, comments, and structure.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 🔐 Safety-First Containment
|
|
128
|
+
We built DevAgent for engineers who care about their host systems.
|
|
129
|
+
- **Dry-Run Mode**: Visualize every change before it happens.
|
|
130
|
+
- **Atomic Snapshots**: A safety restore point is created before every execution.
|
|
131
|
+
- **Instant Rollback**: Revert any agent intervention with `devagent rollback`.
|
|
132
|
+
- **Sandbox Isolation**: Every run is contained in a separate workspace until validation passes 100%.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 📊 Empirical Validation
|
|
137
|
+
We don't fake our success rates. DevAgent is evaluated against a public, messy benchmark suite.
|
|
138
|
+
|
|
139
|
+
| Metric | Result | Infrastructure Status |
|
|
140
|
+
| :--- | :--- | :--- |
|
|
141
|
+
| **Dependency Repair** | 95% | ✅ Production Ready |
|
|
142
|
+
| **Unit Bugfixes** | 80% | ✅ Highly Reliable |
|
|
143
|
+
| **Refactoring** | 20% | 📈 Improving (Model Bounded) |
|
|
144
|
+
| **Isolation Safety** | 100% | ✅ Absolute Containment |
|
|
145
|
+
|
|
146
|
+
> **Full Report**: [v3.4.1 Benchmark Analysis](docs/benchmarks.md)
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 🤝 Contributing
|
|
151
|
+
Built with a focus on **Systems Thinking**. PRs that improve orchestration reliability, environment detection, or patch precision are highly encouraged.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Clone and Install in Editable Mode
|
|
155
|
+
git clone https://github.com/VedantJadhav701/Developer-Code-Intelligence-Agent.git
|
|
156
|
+
pip install -e .
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
<div align="center">
|
|
162
|
+
**DevAgent — Local-First. Execution-Grounded. Infrastructure-Grade.**
|
|
163
|
+
</div>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# 🧠 DevAgent
|
|
2
|
+
### Execution-Grounded Orchestration for Autonomous Local Coding.
|
|
3
|
+
|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
[**🌐 Live Site**](https://devagent-cli.vercel.app/) • [**📦 PyPI**](https://pypi.org/project/devagent-cli/) • [**📜 Docs**](https://devagent-cli.vercel.app/docs)
|
|
7
|
+
|
|
8
|
+
[](https://badge.fury.io/py/devagent-cli)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://ollama.ai)
|
|
11
|
+
[](https://devagent-cli.vercel.app/benchmarks)
|
|
12
|
+
|
|
13
|
+
**DevAgent** is a research-grade, local-first coding agent runtime designed to bridge the gap between LLM-generated logic and production-ready execution integrity.
|
|
14
|
+
|
|
15
|
+
[Quick Start](#-quick-start) • [Architecture](#-high-integrity-architecture) • [Safety & Containment](#-safety-first-containment) • [Benchmarks](#-empirical-validation) • [Troubleshooting](docs/troubleshooting.md)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🛡️ The Problem: The "LLM-Execution Gap"
|
|
22
|
+
Most autonomous coding agents fail because they operate in a vacuum. They generate code that looks correct but fails at runtime due to **environment drift**, **dependency conflicts**, or **invalid execution assumptions**.
|
|
23
|
+
|
|
24
|
+
DevAgent is **Execution-Grounded Orchestration**. It doesn't just guess code; it manages the entire lifecycle of a fix:
|
|
25
|
+
1. **Discovery**: Scans and maps the environment.
|
|
26
|
+
2. **Isolation**: Provisions a clean, sandboxed virtual environment.
|
|
27
|
+
3. **Repair**: Autonomously resolves missing dependencies.
|
|
28
|
+
4. **Validation**: Verifies patches against your actual test suite.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🏗️ High-Integrity Architecture
|
|
33
|
+
DevAgent v3.4.1 implements a multi-layer orchestration stack designed for reliability over hype.
|
|
34
|
+
|
|
35
|
+
```mermaid
|
|
36
|
+
graph TD
|
|
37
|
+
subgraph "Orchestration Layer"
|
|
38
|
+
CLI[DevAgent CLI] --> Planner[Task Planner]
|
|
39
|
+
Planner --> Retrieval[Hierarchical Retrieval: FAISS + Ripgrep]
|
|
40
|
+
Retrieval --> Agent[ReAct Agent: Thought/Action/Observation]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
subgraph "Execution Layer"
|
|
44
|
+
Agent --> Patch[Surgical Patch Engine: Line-Level Diffs]
|
|
45
|
+
Patch --> Reviewer[Self-Review Loop: APPROVED/REVISE]
|
|
46
|
+
Reviewer --> Runtime[Environment Runtime]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
subgraph "The Maturity Layer"
|
|
50
|
+
Runtime --> Discovery[Auto-Dependency Discovery]
|
|
51
|
+
Discovery --> Isolation[Venv Isolation: .tmp_envs]
|
|
52
|
+
Isolation --> Repair[Autonomous Repair Loop: repair_environment]
|
|
53
|
+
Repair --> Validation[Validation Engine: pytest]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Validation -- Pass --> Apply[Apply to Root Repo]
|
|
57
|
+
Validation -- Fail --> Agent
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 🚀 Quick Start
|
|
63
|
+
|
|
64
|
+
### 1. Installation
|
|
65
|
+
Install the CLI via PyPI. Ensure [Ollama](https://ollama.ai) is running locally.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install devagent-cli
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 2. Verify Infrastructure
|
|
72
|
+
Check your local environment, connectivity, and dependency health.
|
|
73
|
+
```bash
|
|
74
|
+
devagent doctor
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 3. Run Your First Task
|
|
78
|
+
Execute an autonomous fix on any repository.
|
|
79
|
+
```bash
|
|
80
|
+
devagent run --task "Implement input validation for the user login" --root ./my-project
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## ✨ Advanced Features
|
|
86
|
+
|
|
87
|
+
### 🔍 Hierarchical Retrieval
|
|
88
|
+
Instead of dumping your entire codebase into a context window, DevAgent uses a multi-tier search:
|
|
89
|
+
- **Global Map**: Scans the file structure to identify relevant modules.
|
|
90
|
+
- **Semantic Tier**: FAISS-powered vector search for conceptual matching.
|
|
91
|
+
- **Precision Tier**: Ripgrep for exact symbol/error discovery.
|
|
92
|
+
|
|
93
|
+
### 🏖️ Environment Isolation & Repair
|
|
94
|
+
DevAgent is the first local agent to treat the environment as a first-class citizen. It detects `requirements.txt` or `pyproject.toml`, creates an isolated `.tmp_envs/` runtime, and **autonomously installs missing packages** if it encounters a `ModuleNotFoundError`.
|
|
95
|
+
|
|
96
|
+
### 🩹 Surgical Patch Engine
|
|
97
|
+
Most agents ruin git history by rewriting entire files. DevAgent generates **line-level unified diffs**, applying only the necessary changes while preserving your code style, comments, and structure.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 🔐 Safety-First Containment
|
|
102
|
+
We built DevAgent for engineers who care about their host systems.
|
|
103
|
+
- **Dry-Run Mode**: Visualize every change before it happens.
|
|
104
|
+
- **Atomic Snapshots**: A safety restore point is created before every execution.
|
|
105
|
+
- **Instant Rollback**: Revert any agent intervention with `devagent rollback`.
|
|
106
|
+
- **Sandbox Isolation**: Every run is contained in a separate workspace until validation passes 100%.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 📊 Empirical Validation
|
|
111
|
+
We don't fake our success rates. DevAgent is evaluated against a public, messy benchmark suite.
|
|
112
|
+
|
|
113
|
+
| Metric | Result | Infrastructure Status |
|
|
114
|
+
| :--- | :--- | :--- |
|
|
115
|
+
| **Dependency Repair** | 95% | ✅ Production Ready |
|
|
116
|
+
| **Unit Bugfixes** | 80% | ✅ Highly Reliable |
|
|
117
|
+
| **Refactoring** | 20% | 📈 Improving (Model Bounded) |
|
|
118
|
+
| **Isolation Safety** | 100% | ✅ Absolute Containment |
|
|
119
|
+
|
|
120
|
+
> **Full Report**: [v3.4.1 Benchmark Analysis](docs/benchmarks.md)
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 🤝 Contributing
|
|
125
|
+
Built with a focus on **Systems Thinking**. PRs that improve orchestration reliability, environment detection, or patch precision are highly encouraged.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Clone and Install in Editable Mode
|
|
129
|
+
git clone https://github.com/VedantJadhav701/Developer-Code-Intelligence-Agent.git
|
|
130
|
+
pip install -e .
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
<div align="center">
|
|
136
|
+
**DevAgent — Local-First. Execution-Grounded. Infrastructure-Grade.**
|
|
137
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.4.1"
|
|
@@ -21,6 +21,10 @@ import re
|
|
|
21
21
|
import os
|
|
22
22
|
import time
|
|
23
23
|
from typing import Any
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
from rich.panel import Panel
|
|
26
|
+
|
|
27
|
+
console = Console()
|
|
24
28
|
|
|
25
29
|
from devagent.app.llm import query, query_with_context
|
|
26
30
|
from devagent.app.reviewer import review_code, revise_code
|
|
@@ -31,6 +35,7 @@ from devagent.app.memory import WorkingMemory, chunk_project, SemanticIndex
|
|
|
31
35
|
from devagent.tools.search import search_code
|
|
32
36
|
from devagent.tools.file_ops import read_file, write_file, list_files
|
|
33
37
|
from devagent.tools.file_map import get_file_map
|
|
38
|
+
from devagent.tools.env_detector import get_environment_info, repair_environment
|
|
34
39
|
from devagent.tools.test_runner import run_tests
|
|
35
40
|
from devagent.tools.linter import lint_code
|
|
36
41
|
from devagent.tools.git_tools import git_diff, git_status
|
|
@@ -60,6 +65,8 @@ Current step: {step}/{max_steps}
|
|
|
60
65
|
Decide the SINGLE next action. Choose ONE:
|
|
61
66
|
- list_files: <relative_path>
|
|
62
67
|
- get_file_map: <relative_path>
|
|
68
|
+
- get_environment_info: <relative_path>
|
|
69
|
+
- repair_environment: <package_name>
|
|
63
70
|
- search_code: <keyword>
|
|
64
71
|
- semantic_search: <query>
|
|
65
72
|
- read_file: <relative_path>[:L<start>-<end>]
|
|
@@ -70,11 +77,13 @@ Decide the SINGLE next action. Choose ONE:
|
|
|
70
77
|
- git_diff
|
|
71
78
|
|
|
72
79
|
STRATEGY:
|
|
73
|
-
1. START by using '
|
|
74
|
-
2.
|
|
75
|
-
3. USE '
|
|
76
|
-
4.
|
|
77
|
-
5.
|
|
80
|
+
1. START by using 'get_environment_info' to understand the project runtime.
|
|
81
|
+
2. If tests fail with ModuleNotFoundError, use 'repair_environment' to fix the environment.
|
|
82
|
+
3. USE 'run_tests' to identify logic failures.
|
|
83
|
+
4. For large files (>50 lines), use 'get_file_map' FIRST to see the structure.
|
|
84
|
+
5. USE 'read_file' with line ranges (e.g. file.py:L10-L50) for targeted reading.
|
|
85
|
+
6. USE 'surgical_patch' for logic fixes. Format: file.py | <SEARCH> | <REPLACE>
|
|
86
|
+
7. ALWAYS use full relative paths.
|
|
78
87
|
|
|
79
88
|
Reply in this EXACT format (two lines only):
|
|
80
89
|
THOUGHT: <your reasoning>
|
|
@@ -96,7 +105,7 @@ Fix the bug. Output ONLY the COMPLETE Python code.
|
|
|
96
105
|
"""
|
|
97
106
|
|
|
98
107
|
EXTRACT_ACTION_PATTERN = re.compile(
|
|
99
|
-
r"ACTION:\s*(get_file_map|search_code|semantic_search|read_file|write_file|surgical_patch|run_tests|lint_code|list_files|git_diff)\s*:?\s*(.*)",
|
|
108
|
+
r"ACTION:\s*(get_file_map|get_environment_info|repair_environment|search_code|semantic_search|read_file|write_file|surgical_patch|run_tests|lint_code|list_files|git_diff)\s*:?\s*(.*)",
|
|
100
109
|
re.IGNORECASE,
|
|
101
110
|
)
|
|
102
111
|
|
|
@@ -268,8 +277,10 @@ class Agent:
|
|
|
268
277
|
|
|
269
278
|
# STEP 2 — EXECUTE ACTION → OBSERVATION
|
|
270
279
|
observation = self._execute_action(action_name, action_arg)
|
|
271
|
-
self.state.last_observation = observation
|
|
272
|
-
|
|
280
|
+
self.state.last_observation = observation # Store and display result
|
|
281
|
+
obs_text = str(observation) if isinstance(observation, dict) else observation
|
|
282
|
+
self.state.observations.append(obs_text[:2000])
|
|
283
|
+
console.print(Panel(obs_text[:1000], title="Observation", border_style="green"))
|
|
273
284
|
|
|
274
285
|
self.state.explanations.append({
|
|
275
286
|
"type": "action",
|
|
@@ -329,10 +340,11 @@ class Agent:
|
|
|
329
340
|
)
|
|
330
341
|
|
|
331
342
|
# Store in history
|
|
343
|
+
obs_text = str(observation) if isinstance(observation, dict) else observation
|
|
332
344
|
self.state.history.append({
|
|
333
345
|
"step": step, "thought": thought,
|
|
334
346
|
"action": action_name, "action_arg": action_arg,
|
|
335
|
-
"observation":
|
|
347
|
+
"observation": obs_text[:500],
|
|
336
348
|
"review": review_text, "test_status": status,
|
|
337
349
|
})
|
|
338
350
|
|
|
@@ -463,6 +475,12 @@ class Agent:
|
|
|
463
475
|
elif action_name == "get_file_map":
|
|
464
476
|
return get_file_map(action_arg, root)
|
|
465
477
|
|
|
478
|
+
elif action_name == "get_environment_info":
|
|
479
|
+
return get_environment_info(root)
|
|
480
|
+
|
|
481
|
+
elif action_name == "repair_environment":
|
|
482
|
+
return repair_environment(action_arg, root)
|
|
483
|
+
|
|
466
484
|
elif action_name == "semantic_search":
|
|
467
485
|
result = semantic_search(action_arg, root)
|
|
468
486
|
# Try to extract file from results
|
|
@@ -142,7 +142,7 @@ 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" [green]
|
|
145
|
+
console.print(f" [green]OK[/green] {reason}")
|
|
146
146
|
|
|
147
147
|
# Explain Mode
|
|
148
148
|
if config.explain and final_state.explanations:
|
|
@@ -187,7 +187,7 @@ def cmd_run(args):
|
|
|
187
187
|
result = sandbox.apply_to_project()
|
|
188
188
|
if result["applied"]:
|
|
189
189
|
for f in result["applied"]:
|
|
190
|
-
console.print(f" [green]
|
|
190
|
+
console.print(f" [green]OK[/green] {f}")
|
|
191
191
|
sandbox.destroy()
|
|
192
192
|
|
|
193
193
|
# Git operations
|
|
@@ -246,6 +246,14 @@ def cmd_doctor(args):
|
|
|
246
246
|
except:
|
|
247
247
|
checks.append(("[yellow]WARN[/yellow]", "FAISS not found (keyword search fallback active)"))
|
|
248
248
|
|
|
249
|
+
# Venv Check
|
|
250
|
+
try:
|
|
251
|
+
import venv
|
|
252
|
+
import ensurepip
|
|
253
|
+
checks.append(("[green]OK[/green]", "Virtual environment runtime (venv + pip) available"))
|
|
254
|
+
except:
|
|
255
|
+
checks.append(("[red]FAIL[/red]", "venv or ensurepip missing (required for Environment Isolation)"))
|
|
256
|
+
|
|
249
257
|
for status, msg in checks:
|
|
250
258
|
console.print(f" {status} {msg}")
|
|
251
259
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from devagent.utils.environment import EnvironmentDetector
|
|
3
|
+
|
|
4
|
+
def get_environment_info(project_path: str):
|
|
5
|
+
"""
|
|
6
|
+
Detects the project environment (pip, poetry, etc.) and lists dependencies.
|
|
7
|
+
Useful for understanding what the project needs to run.
|
|
8
|
+
"""
|
|
9
|
+
project_path = os.path.abspath(project_path)
|
|
10
|
+
detector = EnvironmentDetector(project_path)
|
|
11
|
+
info = detector.detect()
|
|
12
|
+
|
|
13
|
+
# Auto-setup venv if it's the first run or fingerprint missing install_success
|
|
14
|
+
fingerprint = detector.load_fingerprint(project_path)
|
|
15
|
+
if not fingerprint or not fingerprint.get("install_success"):
|
|
16
|
+
detector.setup_isolated_env()
|
|
17
|
+
info = detector.detect() # Refresh info
|
|
18
|
+
|
|
19
|
+
# Save fingerprint for observability
|
|
20
|
+
detector.save_fingerprint(info)
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
"status": "success",
|
|
24
|
+
"environment": {
|
|
25
|
+
"type": info.type,
|
|
26
|
+
"markers_found": info.markers,
|
|
27
|
+
"dependency_count": len(info.dependencies),
|
|
28
|
+
"dependencies": info.dependencies[:20] # Limit output
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def repair_environment(package_name: str, project_path: str):
|
|
33
|
+
"""
|
|
34
|
+
Attempts to install a missing package into the project environment.
|
|
35
|
+
Use this if you see ModuleNotFoundError or missing dependency errors.
|
|
36
|
+
"""
|
|
37
|
+
project_path = os.path.abspath(project_path)
|
|
38
|
+
detector = EnvironmentDetector(project_path)
|
|
39
|
+
success = detector.repair_dependencies(package_name)
|
|
40
|
+
|
|
41
|
+
if success:
|
|
42
|
+
return {"status": "success", "message": f"Successfully installed {package_name}"}
|
|
43
|
+
else:
|
|
44
|
+
return {"status": "error", "message": f"Failed to install {package_name}"}
|
|
@@ -45,7 +45,28 @@ def run_tests(project_root: str = ".", test_path: str = "") -> tuple[int, str]:
|
|
|
45
45
|
tf.write(config_content)
|
|
46
46
|
temp_config = tf.name
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
# ENVIRONMENT AWARENESS: Use venv python if available
|
|
49
|
+
python_exe = "python"
|
|
50
|
+
fingerprint_path = os.path.join(project_root, ".devagent_env.json")
|
|
51
|
+
if os.path.exists(fingerprint_path):
|
|
52
|
+
try:
|
|
53
|
+
import json
|
|
54
|
+
with open(fingerprint_path, 'r') as f:
|
|
55
|
+
data = json.load(f)
|
|
56
|
+
# Look for a valid python exe in .tmp_envs
|
|
57
|
+
env_path = os.path.join(project_root, ".tmp_envs", "validation_env")
|
|
58
|
+
if not os.path.exists(env_path):
|
|
59
|
+
# Fallback to test_env if that's what we used in the test
|
|
60
|
+
env_path = os.path.join(project_root, ".tmp_envs", "test_env")
|
|
61
|
+
|
|
62
|
+
v_exe = os.path.join(env_path, "Scripts", "python.exe") if os.name == "nt" else os.path.join(env_path, "bin", "python")
|
|
63
|
+
if os.path.exists(v_exe):
|
|
64
|
+
python_exe = v_exe
|
|
65
|
+
print(f" [ENV] Using isolated runtime: {python_exe}")
|
|
66
|
+
except:
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
cmd = [python_exe, "-m", "pytest", "-v", "--tb=short", "-c", temp_config]
|
|
49
70
|
if test_path:
|
|
50
71
|
cmd.append(test_path)
|
|
51
72
|
else:
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
from dataclasses import dataclass, field, asdict
|
|
4
|
+
from typing import List, Optional, Dict
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class EnvironmentInfo:
|
|
8
|
+
type: str = "unknown" # pip, poetry, conda, etc.
|
|
9
|
+
python_version: str = "unknown"
|
|
10
|
+
dependencies: List[str] = field(default_factory=list)
|
|
11
|
+
markers: List[str] = field(default_factory=list)
|
|
12
|
+
install_success: bool = False
|
|
13
|
+
last_fingerprint: Optional[float] = None
|
|
14
|
+
failures: List[str] = field(default_factory=list)
|
|
15
|
+
|
|
16
|
+
class EnvironmentDetector:
|
|
17
|
+
def __init__(self, project_path: str):
|
|
18
|
+
self.project_path = os.path.abspath(project_path)
|
|
19
|
+
self.markers = {
|
|
20
|
+
"requirements.txt": "pip",
|
|
21
|
+
"pyproject.toml": "modern/poetry/flit",
|
|
22
|
+
"poetry.lock": "poetry",
|
|
23
|
+
"Pipfile": "pipenv",
|
|
24
|
+
"environment.yml": "conda",
|
|
25
|
+
"setup.py": "setuptools"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def detect(self) -> EnvironmentInfo:
|
|
29
|
+
info = EnvironmentInfo()
|
|
30
|
+
found_markers = []
|
|
31
|
+
|
|
32
|
+
for marker, env_type in self.markers.items():
|
|
33
|
+
marker_path = os.path.join(self.project_path, marker)
|
|
34
|
+
if os.path.exists(marker_path):
|
|
35
|
+
found_markers.append(marker)
|
|
36
|
+
# Primary type detection (prioritize modern tools)
|
|
37
|
+
if info.type == "unknown" or env_type in ["poetry", "modern/poetry/flit"]:
|
|
38
|
+
info.type = env_type
|
|
39
|
+
|
|
40
|
+
info.markers = found_markers
|
|
41
|
+
|
|
42
|
+
# Try to parse dependencies from common files
|
|
43
|
+
if "requirements.txt" in found_markers:
|
|
44
|
+
info.dependencies.extend(self._parse_requirements())
|
|
45
|
+
|
|
46
|
+
return info
|
|
47
|
+
|
|
48
|
+
def _parse_requirements(self) -> List[str]:
|
|
49
|
+
req_path = os.path.join(self.project_path, "requirements.txt")
|
|
50
|
+
deps = []
|
|
51
|
+
try:
|
|
52
|
+
with open(req_path, 'r') as f:
|
|
53
|
+
for line in f:
|
|
54
|
+
line = line.strip()
|
|
55
|
+
if line and not line.startswith("#"):
|
|
56
|
+
deps.append(line)
|
|
57
|
+
except Exception:
|
|
58
|
+
pass
|
|
59
|
+
return deps
|
|
60
|
+
|
|
61
|
+
def setup_isolated_env(self, env_name: str = "validation_env") -> str:
|
|
62
|
+
"""Creates a venv and installs dependencies."""
|
|
63
|
+
env_path = os.path.join(self.project_path, ".tmp_envs", env_name)
|
|
64
|
+
python_exe = os.path.join(env_path, "Scripts", "python.exe") if os.name == "nt" else os.path.join(env_path, "bin", "python")
|
|
65
|
+
|
|
66
|
+
if os.path.exists(python_exe):
|
|
67
|
+
print(f"[ENV] Found existing virtual environment at {env_path}")
|
|
68
|
+
return python_exe
|
|
69
|
+
|
|
70
|
+
os.makedirs(os.path.dirname(env_path), exist_ok=True)
|
|
71
|
+
|
|
72
|
+
import venv
|
|
73
|
+
import subprocess
|
|
74
|
+
|
|
75
|
+
print(f"[ENV] Creating virtual environment at {env_path}...")
|
|
76
|
+
venv.create(env_path, with_pip=True)
|
|
77
|
+
|
|
78
|
+
info = self.detect()
|
|
79
|
+
|
|
80
|
+
# Install dependencies
|
|
81
|
+
if info.type == "pip":
|
|
82
|
+
req_path = os.path.join(self.project_path, "requirements.txt")
|
|
83
|
+
print(f"[ENV] Installing dependencies from {req_path}...")
|
|
84
|
+
try:
|
|
85
|
+
subprocess.check_call([python_exe, "-m", "pip", "install", "-r", req_path])
|
|
86
|
+
info.install_success = True
|
|
87
|
+
except subprocess.CalledProcessError as e:
|
|
88
|
+
info.failures.append(f"Install failed: {str(e)}")
|
|
89
|
+
info.install_success = False
|
|
90
|
+
|
|
91
|
+
# Validate installation
|
|
92
|
+
try:
|
|
93
|
+
subprocess.check_call([python_exe, "-m", "pip", "check"])
|
|
94
|
+
print("[ENV] Runtime health check passed.")
|
|
95
|
+
except subprocess.CalledProcessError:
|
|
96
|
+
print("[ENV] Runtime health check found conflicts.")
|
|
97
|
+
info.failures.append("Dependency conflicts detected.")
|
|
98
|
+
|
|
99
|
+
self.save_fingerprint(info)
|
|
100
|
+
return python_exe
|
|
101
|
+
|
|
102
|
+
def repair_dependencies(self, missing_package: str, env_name: str = "validation_env") -> bool:
|
|
103
|
+
"""Attempts to install a missing package into the venv."""
|
|
104
|
+
env_path = os.path.join(self.project_path, ".tmp_envs", env_name)
|
|
105
|
+
python_exe = os.path.join(env_path, "Scripts", "python.exe") if os.name == "nt" else os.path.join(env_path, "bin", "python")
|
|
106
|
+
|
|
107
|
+
if not os.path.exists(python_exe):
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
import subprocess
|
|
111
|
+
print(f"[ENV] Repairing environment: Installing missing package '{missing_package}'...")
|
|
112
|
+
try:
|
|
113
|
+
subprocess.check_call([python_exe, "-m", "pip", "install", missing_package])
|
|
114
|
+
return True
|
|
115
|
+
except subprocess.CalledProcessError:
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
def save_fingerprint(self, info: EnvironmentInfo):
|
|
119
|
+
fingerprint_path = os.path.join(self.project_path, ".devagent_env.json")
|
|
120
|
+
with open(fingerprint_path, 'w') as f:
|
|
121
|
+
json.dump(asdict(info), f, indent=2)
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def load_fingerprint(project_path: str) -> Optional[Dict]:
|
|
125
|
+
fingerprint_path = os.path.join(project_path, ".devagent_env.json")
|
|
126
|
+
if os.path.exists(fingerprint_path):
|
|
127
|
+
with open(fingerprint_path, 'r') as f:
|
|
128
|
+
return json.load(f)
|
|
129
|
+
return None
|
|
@@ -38,12 +38,13 @@ class AgentLogger:
|
|
|
38
38
|
patch_summary: str = "",
|
|
39
39
|
) -> None:
|
|
40
40
|
"""Log a complete agent iteration step."""
|
|
41
|
+
obs_text = str(observation) if isinstance(observation, dict) else observation
|
|
41
42
|
entry = {
|
|
42
43
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
43
44
|
"step": step,
|
|
44
45
|
"thought": thought,
|
|
45
46
|
"action": action,
|
|
46
|
-
"observation":
|
|
47
|
+
"observation": obs_text[:2000],
|
|
47
48
|
"review": review,
|
|
48
49
|
"test_result": test_result[:2000],
|
|
49
50
|
"latency": f"{latency:.2f}s" if latency else "",
|