devagent-cli 3.3.0__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.
Files changed (44) hide show
  1. devagent_cli-3.7.5/PKG-INFO +163 -0
  2. devagent_cli-3.7.5/README.md +137 -0
  3. devagent_cli-3.7.5/devagent/__init__.py +1 -0
  4. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/agent.py +27 -9
  5. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/cli.py +10 -2
  6. devagent_cli-3.7.5/devagent/tools/env_detector.py +44 -0
  7. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/test_runner.py +22 -1
  8. devagent_cli-3.7.5/devagent/utils/environment.py +129 -0
  9. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/utils/logger.py +2 -1
  10. devagent_cli-3.7.5/devagent_cli.egg-info/PKG-INFO +163 -0
  11. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent_cli.egg-info/SOURCES.txt +2 -0
  12. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/pyproject.toml +1 -1
  13. devagent_cli-3.3.0/PKG-INFO +0 -479
  14. devagent_cli-3.3.0/README.md +0 -453
  15. devagent_cli-3.3.0/devagent/__init__.py +0 -1
  16. devagent_cli-3.3.0/devagent_cli.egg-info/PKG-INFO +0 -479
  17. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/LICENSE +0 -0
  18. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/__init__.py +0 -0
  19. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/llm.py +0 -0
  20. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/memory.py +0 -0
  21. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/patcher.py +0 -0
  22. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/planner.py +0 -0
  23. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/reviewer.py +0 -0
  24. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/sandbox.py +0 -0
  25. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/app/state.py +0 -0
  26. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/__init__.py +0 -0
  27. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/benchmark_runner.py +0 -0
  28. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/file_map.py +0 -0
  29. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/file_ops.py +0 -0
  30. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/git_tools.py +0 -0
  31. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/linter.py +0 -0
  32. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/search.py +0 -0
  33. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/semantic_search.py +0 -0
  34. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/tools/surgical_patcher.py +0 -0
  35. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/utils/__init__.py +0 -0
  36. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/utils/ast_utils.py +0 -0
  37. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/utils/config.py +0 -0
  38. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/utils/metrics.py +0 -0
  39. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent/utils/safety.py +0 -0
  40. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent_cli.egg-info/dependency_links.txt +0 -0
  41. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent_cli.egg-info/entry_points.txt +0 -0
  42. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent_cli.egg-info/requires.txt +0 -0
  43. {devagent_cli-3.3.0 → devagent_cli-3.7.5}/devagent_cli.egg-info/top_level.txt +0 -0
  44. {devagent_cli-3.3.0 → 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
+ ![DevAgent Showcase](readme-image.png)
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
+ [![PyPI version](https://badge.fury.io/py/devagent-cli.svg)](https://badge.fury.io/py/devagent-cli)
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
36
+ [![Ollama](https://img.shields.io/badge/Ollama-Local%20LLM-black.svg?logo=ollama)](https://ollama.ai)
37
+ [![Safety: Sandboxed](https://img.shields.io/badge/Safety-Sandboxed-success.svg)](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
+ ![DevAgent Showcase](readme-image.png)
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
+ [![PyPI version](https://badge.fury.io/py/devagent-cli.svg)](https://badge.fury.io/py/devagent-cli)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
10
+ [![Ollama](https://img.shields.io/badge/Ollama-Local%20LLM-black.svg?logo=ollama)](https://ollama.ai)
11
+ [![Safety: Sandboxed](https://img.shields.io/badge/Safety-Sandboxed-success.svg)](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 'run_tests' to identify the failure.
74
- 2. For large files (>50 lines), use 'get_file_map' FIRST to see the structure.
75
- 3. USE 'read_file' with line ranges (e.g. file.py:L10-L50) for targeted reading.
76
- 4. USE 'surgical_patch' for logic fixes. Format: file.py | <SEARCH> | <REPLACE>
77
- 5. ALWAYS use full relative paths.
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
- self.state.observations.append(observation[:2000])
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": observation[:500],
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][/green] {reason}")
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][/green] {f}")
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
- cmd = ["python", "-m", "pytest", "-v", "--tb=short", "-c", temp_config]
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": observation[:2000],
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 "",