opalacoder 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opalacoder/__init__.py +2 -0
- opalacoder/agents.py +233 -0
- opalacoder/agents.yaml +78 -0
- opalacoder/api_keys.py +75 -0
- opalacoder/cli.py +339 -0
- opalacoder/cli_commands.py +277 -0
- opalacoder/config.py +215 -0
- opalacoder/embeddings.py +85 -0
- opalacoder/i18n.py +249 -0
- opalacoder/orchestrator.py +381 -0
- opalacoder/planner.py +206 -0
- opalacoder/project.py +196 -0
- opalacoder/session.py +4 -0
- opalacoder/skills/generaldeveloper.md +52 -0
- opalacoder/skills/html_css_js.md +51 -0
- opalacoder/skills/opalacoder.md +37 -0
- opalacoder/skills/python_subprocess.md +11 -0
- opalacoder/skills/react_vite.md +6 -0
- opalacoder/skills.py +184 -0
- opalacoder/structured.py +113 -0
- opalacoder/terminal.py +186 -0
- opalacoder/tools.py +351 -0
- opalacoder/vcs.py +254 -0
- opalacoder-0.1.0.dist-info/METADATA +230 -0
- opalacoder-0.1.0.dist-info/RECORD +27 -0
- opalacoder-0.1.0.dist-info/WHEEL +4 -0
- opalacoder-0.1.0.dist-info/entry_points.txt +2 -0
opalacoder/vcs.py
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Version Control System (VCS) strategies for OpalaCoder."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import List, Callable
|
|
7
|
+
from agenticblocks.core.function_block import as_tool
|
|
8
|
+
|
|
9
|
+
from . import terminal as T
|
|
10
|
+
from .tools import AGENT_PROGRESS, _preview, get_project_path
|
|
11
|
+
|
|
12
|
+
# ─── Base Strategy ────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
class VersionControlStrategy(ABC):
|
|
15
|
+
def __init__(self, project_path: str):
|
|
16
|
+
self.project_path = os.path.abspath(project_path)
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def setup(self):
|
|
20
|
+
"""Initialize VCS environment (e.g. create shadow git, gitignore)."""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def pre_run(self, context_msg: str):
|
|
25
|
+
"""Called before the agent starts executing its plan."""
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def post_run(self, success: bool, msg: str = ""):
|
|
30
|
+
"""Called after the agent finishes its execution."""
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def get_tools(self) -> List[Callable]:
|
|
35
|
+
"""Return a list of git tools available to the agent."""
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def manual_commit(self, message: str) -> tuple[bool, str]:
|
|
40
|
+
"""Manually commit changes to the VCS."""
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def undo_last(self) -> tuple[bool, str]:
|
|
45
|
+
"""Undo the last change in the VCS."""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# ─── Shadow Git Helper ────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
def _run_shadow_git(command: str) -> subprocess.CompletedProcess:
|
|
52
|
+
"""Run a Git command using the internal shadow git directory."""
|
|
53
|
+
project_path = get_project_path()
|
|
54
|
+
shadow_dir = os.path.join(project_path, ".opalacoder", ".git")
|
|
55
|
+
|
|
56
|
+
# Ensure git dir config is passed
|
|
57
|
+
full_cmd = f"git --git-dir={shadow_dir} --work-tree={project_path} {command}"
|
|
58
|
+
|
|
59
|
+
return subprocess.run(
|
|
60
|
+
full_cmd,
|
|
61
|
+
shell=True,
|
|
62
|
+
capture_output=True,
|
|
63
|
+
text=True,
|
|
64
|
+
cwd=project_path
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def _init_shadow_git(project_path: str):
|
|
68
|
+
"""Initialize the shadow git repository if it doesn't exist."""
|
|
69
|
+
shadow_base = os.path.join(project_path, ".opalacoder")
|
|
70
|
+
shadow_dir = os.path.join(shadow_base, ".git")
|
|
71
|
+
gitignore_path = os.path.join(shadow_base, ".gitignore")
|
|
72
|
+
|
|
73
|
+
os.makedirs(shadow_base, exist_ok=True)
|
|
74
|
+
|
|
75
|
+
if not os.path.exists(shadow_dir):
|
|
76
|
+
# Init repo
|
|
77
|
+
cmd = f"git --git-dir={shadow_dir} --work-tree={project_path} init"
|
|
78
|
+
subprocess.run(cmd, shell=True, capture_output=True, cwd=project_path)
|
|
79
|
+
|
|
80
|
+
# Configure excludes file
|
|
81
|
+
if not os.path.exists(gitignore_path):
|
|
82
|
+
with open(gitignore_path, "w", encoding="utf-8") as f:
|
|
83
|
+
f.write(".env\nnode_modules/\n__pycache__/\n.venv/\n")
|
|
84
|
+
|
|
85
|
+
cmd_exclude = f"git --git-dir={shadow_dir} --work-tree={project_path} config core.excludesFile {gitignore_path}"
|
|
86
|
+
subprocess.run(cmd_exclude, shell=True, capture_output=True, cwd=project_path)
|
|
87
|
+
|
|
88
|
+
# Initial commit
|
|
89
|
+
_run_shadow_git("add .")
|
|
90
|
+
_run_shadow_git("commit -m 'Initial checkpoint (Auto)'")
|
|
91
|
+
|
|
92
|
+
def _auto_checkpoint(message: str):
|
|
93
|
+
"""Automatically create a checkpoint in the shadow git."""
|
|
94
|
+
_run_shadow_git("add .")
|
|
95
|
+
res = _run_shadow_git(f"commit -m '{message}'")
|
|
96
|
+
return res.returncode == 0
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# ─── Agent Git Tools ──────────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
@as_tool(name="git_status", description="Get the status of the internal version control. Shows modified/added files.")
|
|
102
|
+
def git_status() -> str:
|
|
103
|
+
AGENT_PROGRESS.update("git_status")
|
|
104
|
+
res = _run_shadow_git("status -s")
|
|
105
|
+
return res.stdout if res.stdout.strip() else "Working tree clean."
|
|
106
|
+
|
|
107
|
+
@as_tool(name="git_diff", description="Get the diff of the internal version control to see exact code changes.")
|
|
108
|
+
def git_diff() -> str:
|
|
109
|
+
AGENT_PROGRESS.update("git_diff")
|
|
110
|
+
res = _run_shadow_git("diff")
|
|
111
|
+
return res.stdout if res.stdout.strip() else "No changes."
|
|
112
|
+
|
|
113
|
+
@as_tool(name="git_commit", description="Commit all current changes to the internal version control. Use this to save milestones.")
|
|
114
|
+
def git_commit(message: str) -> str:
|
|
115
|
+
AGENT_PROGRESS.update("git_commit", _preview(message))
|
|
116
|
+
_run_shadow_git("add .")
|
|
117
|
+
res = _run_shadow_git(f'commit -m "{message}"')
|
|
118
|
+
if res.returncode == 0:
|
|
119
|
+
return f"Successfully committed: {message}"
|
|
120
|
+
return f"Failed to commit or nothing to commit. Stderr: {res.stderr}"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ─── Concrete Strategies ──────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
class AutoGitStrategy(VersionControlStrategy):
|
|
126
|
+
"""Deterministic mode: Shadow Git initialized, pre/post checkpoints enforced, NO tools given to agent."""
|
|
127
|
+
|
|
128
|
+
def setup(self):
|
|
129
|
+
_init_shadow_git(self.project_path)
|
|
130
|
+
T.info("Modo Auto VCS: Repositório interno inicializado/verificado.")
|
|
131
|
+
|
|
132
|
+
def pre_run(self, context_msg: str):
|
|
133
|
+
_auto_checkpoint("Pre-run checkpoint: Before executing plan")
|
|
134
|
+
|
|
135
|
+
def post_run(self, success: bool, msg: str = ""):
|
|
136
|
+
status = "Success" if success else "Failed"
|
|
137
|
+
_auto_checkpoint(f"Post-run checkpoint: {status}. {msg}")
|
|
138
|
+
|
|
139
|
+
def get_tools(self) -> List[Callable]:
|
|
140
|
+
return [] # No tools for the agent in auto mode
|
|
141
|
+
|
|
142
|
+
def manual_commit(self, message: str) -> tuple[bool, str]:
|
|
143
|
+
_run_shadow_git("add .")
|
|
144
|
+
res = _run_shadow_git(f"commit -m '{message}'")
|
|
145
|
+
if res.returncode == 0:
|
|
146
|
+
return True, "Committed."
|
|
147
|
+
return False, res.stderr
|
|
148
|
+
|
|
149
|
+
def undo_last(self) -> tuple[bool, str]:
|
|
150
|
+
res = _run_shadow_git("rev-parse HEAD~1")
|
|
151
|
+
if res.returncode != 0:
|
|
152
|
+
return False, "Cannot undo. No previous checkpoints."
|
|
153
|
+
_run_shadow_git("reset --hard HEAD~1")
|
|
154
|
+
_run_shadow_git("clean -fd")
|
|
155
|
+
return True, "Last change undone."
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class HybridGitStrategy(VersionControlStrategy):
|
|
159
|
+
"""Hybrid mode: Shadow Git initialized, agent has tools, orchestrator ensures safety checkpoints."""
|
|
160
|
+
|
|
161
|
+
def setup(self):
|
|
162
|
+
_init_shadow_git(self.project_path)
|
|
163
|
+
T.info("Modo Hybrid VCS: Repositório interno pronto. Agente tem ferramentas de Git.")
|
|
164
|
+
|
|
165
|
+
def pre_run(self, context_msg: str):
|
|
166
|
+
_auto_checkpoint("Pre-run checkpoint: Before executing plan")
|
|
167
|
+
|
|
168
|
+
def post_run(self, success: bool, msg: str = ""):
|
|
169
|
+
status = "Success" if success else "Failed"
|
|
170
|
+
_auto_checkpoint(f"Post-run checkpoint: {status}. {msg}")
|
|
171
|
+
|
|
172
|
+
def get_tools(self) -> List[Callable]:
|
|
173
|
+
return [git_status, git_diff, git_commit]
|
|
174
|
+
|
|
175
|
+
def manual_commit(self, message: str) -> tuple[bool, str]:
|
|
176
|
+
_run_shadow_git("add .")
|
|
177
|
+
res = _run_shadow_git(f"commit -m '{message}'")
|
|
178
|
+
if res.returncode == 0:
|
|
179
|
+
return True, "Committed."
|
|
180
|
+
return False, res.stderr
|
|
181
|
+
|
|
182
|
+
def undo_last(self) -> tuple[bool, str]:
|
|
183
|
+
res = _run_shadow_git("rev-parse HEAD~1")
|
|
184
|
+
if res.returncode != 0:
|
|
185
|
+
return False, "Cannot undo. No previous checkpoints."
|
|
186
|
+
_run_shadow_git("reset --hard HEAD~1")
|
|
187
|
+
_run_shadow_git("clean -fd")
|
|
188
|
+
return True, "Last change undone."
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class AgentDrivenGitStrategy(VersionControlStrategy):
|
|
192
|
+
"""Agent-driven mode: Orchestrator does nothing automatically. Agent gets tools and decides when to use them."""
|
|
193
|
+
|
|
194
|
+
def setup(self):
|
|
195
|
+
_init_shadow_git(self.project_path)
|
|
196
|
+
T.info("Modo Agent-Driven VCS: Agente tem controle total sobre o repositório interno.")
|
|
197
|
+
|
|
198
|
+
def pre_run(self, context_msg: str):
|
|
199
|
+
pass
|
|
200
|
+
|
|
201
|
+
def post_run(self, success: bool, msg: str = ""):
|
|
202
|
+
pass
|
|
203
|
+
|
|
204
|
+
def get_tools(self) -> List[Callable]:
|
|
205
|
+
return [git_status, git_diff, git_commit]
|
|
206
|
+
|
|
207
|
+
def manual_commit(self, message: str) -> tuple[bool, str]:
|
|
208
|
+
_run_shadow_git("add .")
|
|
209
|
+
res = _run_shadow_git(f"commit -m '{message}'")
|
|
210
|
+
if res.returncode == 0:
|
|
211
|
+
return True, "Committed."
|
|
212
|
+
return False, res.stderr
|
|
213
|
+
|
|
214
|
+
def undo_last(self) -> tuple[bool, str]:
|
|
215
|
+
res = _run_shadow_git("rev-parse HEAD~1")
|
|
216
|
+
if res.returncode != 0:
|
|
217
|
+
return False, "Cannot undo. No previous checkpoints."
|
|
218
|
+
_run_shadow_git("reset --hard HEAD~1")
|
|
219
|
+
_run_shadow_git("clean -fd")
|
|
220
|
+
return True, "Last change undone."
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class NoGitStrategy(VersionControlStrategy):
|
|
224
|
+
"""Null strategy: No version control at all."""
|
|
225
|
+
|
|
226
|
+
def setup(self):
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
def pre_run(self, context_msg: str):
|
|
230
|
+
pass
|
|
231
|
+
|
|
232
|
+
def post_run(self, success: bool, msg: str = ""):
|
|
233
|
+
pass
|
|
234
|
+
|
|
235
|
+
def get_tools(self) -> List[Callable]:
|
|
236
|
+
return []
|
|
237
|
+
|
|
238
|
+
def manual_commit(self, message: str) -> tuple[bool, str]:
|
|
239
|
+
return False, "VCS is disabled."
|
|
240
|
+
|
|
241
|
+
def undo_last(self) -> tuple[bool, str]:
|
|
242
|
+
return False, "VCS is disabled."
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def get_vcs_strategy(strategy_name: str, project_path: str) -> VersionControlStrategy:
|
|
246
|
+
"""Factory method to get the selected strategy."""
|
|
247
|
+
strategies = {
|
|
248
|
+
"auto": AutoGitStrategy,
|
|
249
|
+
"hybrid": HybridGitStrategy,
|
|
250
|
+
"agent_driven": AgentDrivenGitStrategy,
|
|
251
|
+
"none": NoGitStrategy
|
|
252
|
+
}
|
|
253
|
+
klass = strategies.get(strategy_name.lower(), HybridGitStrategy)
|
|
254
|
+
return klass(project_path)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opalacoder
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Autonomous coding agent with interactive planning and modular execution
|
|
5
|
+
Project-URL: Homepage, https://github.com/gilzamir/OpalaCoder
|
|
6
|
+
Project-URL: Bug Tracker, https://github.com/gilzamir/OpalaCoder/issues
|
|
7
|
+
Author-email: Gil Zamir <gilzamir@example.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Requires-Python: >=3.11
|
|
13
|
+
Requires-Dist: agenticblocks-io
|
|
14
|
+
Requires-Dist: instructor>=1.15.1
|
|
15
|
+
Requires-Dist: numpy>=1.21.0
|
|
16
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
17
|
+
Requires-Dist: pyyaml>=6.0
|
|
18
|
+
Requires-Dist: rich>=13.0.0
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# OpalaCoder
|
|
22
|
+
|
|
23
|
+
**OpalaCoder** is an autonomous coding agent with interactive planning, modular execution, and persistent project memory. It is designed to work well with small and less autonomous models while maintaining the feel of a fully autonomous agent. It is built using the **AgenticBlocks.IO** framework.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
### Project-Centric Context Management
|
|
30
|
+
OpalaCoder centers around **projects** rather than transient chat sessions. Every interaction happens within a named project with a fixed filesystem path. This anchors the LLM context, loads only project-relevant skills, scopes all file and terminal operations, and persists history effectively for both small local models and large hosted APIs.
|
|
31
|
+
|
|
32
|
+
### Advanced Semantic Router (Chain of Thought)
|
|
33
|
+
Uses an LLM for semantic routing with internal reasoning (Chain of Thought). It translates user demands to English internally, correctly deduces the intent, and seamlessly routes execution even for multilingual commands, injecting only the necessary context from specific **Skills** (`skills/*.md`).
|
|
34
|
+
|
|
35
|
+
### Dynamic Model Selection (Double Inference Architecture)
|
|
36
|
+
OpalaCoder dynamically evaluates task complexity. For trivial tasks, it uses a fast default model (e.g., `ollama/mistral-nemo`). If the task requires architectural refactoring or advanced complex logic, it automatically falls back to a more powerful alternative model configured via API keys.
|
|
37
|
+
|
|
38
|
+
### Interactive Planning
|
|
39
|
+
The agent receives a natural language demand, generates a high-level landscape plan, and enters a refinement loop with the user until the plan is approved. The approved plan is then automatically decomposed into executable sub-steps (subplans).
|
|
40
|
+
|
|
41
|
+
### Execution with Retry & Strategy Routing
|
|
42
|
+
OpalaCoder delegates orchestration to specialized strategies. Small models use a deterministic execution pipeline (DAG), while capable models can use a fully autonomous agent loop. If a sub-step fails, the agent retries (up to a configurable limit) by injecting the previous error into the context for self-correction.
|
|
43
|
+
|
|
44
|
+
### Execution Modes
|
|
45
|
+
|
|
46
|
+
| Mode | Behavior |
|
|
47
|
+
|--------|---------------|
|
|
48
|
+
| `plan` | Generates a plan and asks for user approval before executing (default) |
|
|
49
|
+
| `auto` | Executes everything without interruptions — ideal for automated pipelines |
|
|
50
|
+
| `edit` | Requests user confirmation only for sensitive operations (file creation/deletion, network calls, etc.) |
|
|
51
|
+
|
|
52
|
+
### Persistent Projects and CLI Commands
|
|
53
|
+
Each execution belongs to a named project with continuous memory. During the chat with OpalaCoder, you can interact with the state manager using native commands:
|
|
54
|
+
- `/help` or `/h`: Shows available commands.
|
|
55
|
+
- `/clear`: Clears the memory and history of the current project.
|
|
56
|
+
- `/rename <new_name>`: Renames the active project.
|
|
57
|
+
- `/list`: Lists all projects saved in SQLite.
|
|
58
|
+
- `/load <name>` and `/delete <name>`: Loads or deletes old projects. (Deleting also asks to delete the project directory).
|
|
59
|
+
- `/skills`: Lists available skills and highlights the active ones for the project.
|
|
60
|
+
- `/addskill <name>` and `/rmskill <name>`: Adds or removes specific skills for the current project.
|
|
61
|
+
- `/undo`: Reverts the last change made by the agent via internal shadow VCS.
|
|
62
|
+
- `/commit <msg>`: Forces a commit to the local shadow git control.
|
|
63
|
+
- `/exit` or `/quit`: Exits the application.
|
|
64
|
+
|
|
65
|
+
### Shadow Git (VCS)
|
|
66
|
+
Every project comes with an isolated "Shadow Git" (`.opalacoder/.git`) that automatically checkpoints the codebase before and after execution. This allows for safe iteration without muddying the user's main git repository, and enables the `/undo` command.
|
|
67
|
+
|
|
68
|
+
### Elegant Terminal
|
|
69
|
+
Formatted output with [Rich](https://github.com/Texel-io/rich): banners, progress spinners, plan panels, per-subplan status tables, and highlighted error reports.
|
|
70
|
+
|
|
71
|
+
### Modular Architecture
|
|
72
|
+
The code is divided into independent, easy-to-debug modules:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
opalacoder/
|
|
76
|
+
├── config.py Global settings (model, retries, mode, db, VCS)
|
|
77
|
+
├── terminal.py Rich output (banners, spinners, panels, tables)
|
|
78
|
+
├── project.py SQLite project management and state
|
|
79
|
+
├── vcs.py Internal shadow Git strategies (auto, hybrid, agent-driven)
|
|
80
|
+
├── agents.py LLM agent factories
|
|
81
|
+
├── planner.py Pipeline: panorama → refinement → decomposition
|
|
82
|
+
├── orchestrator.py Strategy-based execution (deterministic vs autonomous)
|
|
83
|
+
└── cli.py Argparse + project bootstrap + REPL
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Requirements
|
|
89
|
+
|
|
90
|
+
- Python 3.11+
|
|
91
|
+
- [agenticblocks](https://github.com/gilzamir/agenticblocks) installed in the virtual environment
|
|
92
|
+
- [Rich](https://github.com/Texel-io/rich): `pip install rich`
|
|
93
|
+
- An accessible LLM server (e.g., [Ollama](https://ollama.com) with `mistral-nemo`, or any model supported by [litellm](https://docs.litellm.ai))
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Installation
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Clone the repository
|
|
101
|
+
git clone <repository-url>
|
|
102
|
+
cd OpalaCoder
|
|
103
|
+
|
|
104
|
+
# Create and activate the virtual environment
|
|
105
|
+
python -m venv .env
|
|
106
|
+
source .env/bin/activate # Linux/macOS
|
|
107
|
+
# .env\Scripts\activate # Windows
|
|
108
|
+
|
|
109
|
+
# Install the dependencies
|
|
110
|
+
pip install -r requirements.txt
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Environment Variables (Optional)
|
|
114
|
+
|
|
115
|
+
Create a `.env` file in the project root to override defaults:
|
|
116
|
+
|
|
117
|
+
```env
|
|
118
|
+
# Default LLM model (any litellm supported string)
|
|
119
|
+
OPALA_MODEL=ollama/mistral-nemo
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## How to Run
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Activate the virtual environment
|
|
128
|
+
source .env/bin/activate
|
|
129
|
+
|
|
130
|
+
# Default execution (plan mode)
|
|
131
|
+
python main.py
|
|
132
|
+
|
|
133
|
+
# Choose execution mode
|
|
134
|
+
python main.py --mode auto
|
|
135
|
+
python main.py --mode plan
|
|
136
|
+
python main.py --mode edit
|
|
137
|
+
|
|
138
|
+
# Use another model
|
|
139
|
+
python main.py --model ollama/llama3
|
|
140
|
+
|
|
141
|
+
# Custom database path
|
|
142
|
+
python main.py --db /path/to/projects.db
|
|
143
|
+
|
|
144
|
+
# Show version
|
|
145
|
+
python main.py --version
|
|
146
|
+
|
|
147
|
+
# Help
|
|
148
|
+
python main.py --help
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Project Flow
|
|
154
|
+
|
|
155
|
+
```text
|
|
156
|
+
1. Banner + Mode Selection
|
|
157
|
+
↓
|
|
158
|
+
2. Project Configuration
|
|
159
|
+
├── New Project → Name, Path, Description -> LLM selects skills
|
|
160
|
+
└── Existing → Load context and skills
|
|
161
|
+
↓
|
|
162
|
+
3. User enters demand
|
|
163
|
+
↓
|
|
164
|
+
4. Agent generates landscape (high-level plan)
|
|
165
|
+
↓
|
|
166
|
+
5. Refinement loop (plan/edit modes)
|
|
167
|
+
├── User approves → proceeds
|
|
168
|
+
└── User suggests changes → agent refines and loops back to step 5
|
|
169
|
+
↓
|
|
170
|
+
6. Decomposition into subplans (SP-1, SP-2, …)
|
|
171
|
+
↓
|
|
172
|
+
7. Sequential execution by dependency
|
|
173
|
+
└── For each subplan:
|
|
174
|
+
├── Pre-run VCS checkpoint
|
|
175
|
+
├── Executes generated code (AgenticBlocks WorkflowGraph)
|
|
176
|
+
├── Success → Next subplan
|
|
177
|
+
└── Failure → Retry up to max_retries, then report error
|
|
178
|
+
├── Post-run VCS checkpoint
|
|
179
|
+
↓
|
|
180
|
+
8. Aggregation: Final synthesized result of the operation
|
|
181
|
+
↓
|
|
182
|
+
9. Result displayed + project saved
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Advanced Configuration
|
|
188
|
+
|
|
189
|
+
### Build & Test Commands
|
|
190
|
+
Run tests in the `tests` directory after implementing a new feature:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
python -m pytest
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Change the Default Model
|
|
197
|
+
|
|
198
|
+
Edit `opalacoder/config.py`:
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
DEFAULT_MODEL = "ollama/mistral-nemo" # change here
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Or use the environment variable `OPALA_MODEL`.
|
|
205
|
+
|
|
206
|
+
### Sensitive Operations
|
|
207
|
+
|
|
208
|
+
In `opalacoder/config.py`:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
SENSITIVE_OPS = {
|
|
212
|
+
"write_file", "delete_file", "run_shell",
|
|
213
|
+
"send_network_request", "create_user", "delete_user",
|
|
214
|
+
# add keywords here for operations that require confirmation in edit mode
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Security
|
|
221
|
+
|
|
222
|
+
- The `edit` mode requires explicit confirmation for operations affecting the filesystem, network, or user accounts.
|
|
223
|
+
- Generated code is executed locally. For greater isolation, the `CodePlanExecutorBlock` from the AgenticBlocks library supports execution in a Docker container — edit `make_executor_block` in `opalacoder/agents.py` changing `execution_mode="local"` to `execution_mode="docker"`.
|
|
224
|
+
- Never run the agent in `auto` mode with access to production systems without reviewing the generated subplans.
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
|
|
230
|
+
MIT
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
opalacoder/__init__.py,sha256=8Bawhbei8CD1Y0IEU-BF73c6DZT-3Cxft5qNcaUPeog,106
|
|
2
|
+
opalacoder/agents.py,sha256=F45PyJ0utG3zDoVp_vbdB79gMZCm1aYCWuGQDA5oP8g,10651
|
|
3
|
+
opalacoder/api_keys.py,sha256=O8dXsKPLi-mUGNKkzX2ZuHmepi9Aj8TIROrkp3vN6e4,2526
|
|
4
|
+
opalacoder/cli.py,sha256=wDYeuIwdU9JxanCko9dfjxFJBmgIDBu6FiSXkZJcsjE,13957
|
|
5
|
+
opalacoder/cli_commands.py,sha256=ElOkySzZupYYk5M7VBaAuvhWQ-kSYcZvsbo1xAty0L4,11538
|
|
6
|
+
opalacoder/config.py,sha256=8m8MyB0B3mkYTgEfYuYW7DCmrvu-pl1iBzpJ3kHIxQA,7318
|
|
7
|
+
opalacoder/embeddings.py,sha256=6Z8reaUjFktkp6X80wH5k-vq3h2aBworC6dI-ocHieA,3031
|
|
8
|
+
opalacoder/i18n.py,sha256=pMMd25jDnGW8WW75fzPwJFoTq2Xj87vVEjXnmq7e1mg,15453
|
|
9
|
+
opalacoder/orchestrator.py,sha256=Vpb3AkB0ZmARSHx06RnIAWhhsdbGDmaRkf51CiPmePg,16325
|
|
10
|
+
opalacoder/planner.py,sha256=K8_bdxrMsL_TA-NHW51Dq0AlrspKOamp5SHUQwj2NNc,7839
|
|
11
|
+
opalacoder/project.py,sha256=TFw3cQsQbV7M9_YDy217k7bShnOTZov7yDSlAZ3UJyo,7912
|
|
12
|
+
opalacoder/session.py,sha256=Lxr4vB6-EMeMt_ygk_m_Oaz8AbQneXzdINf-X8nXOrM,215
|
|
13
|
+
opalacoder/skills.py,sha256=KjgpL8oYZKTM6RZCQWlicqzZ-NnzRPTYn8m2iSFTwHk,7740
|
|
14
|
+
opalacoder/structured.py,sha256=DjJvuFoVpc3PJARSwuCgT92E7z19zTsPK_XJ0fuE9Vo,4252
|
|
15
|
+
opalacoder/terminal.py,sha256=VQtBS1o_clS8nQ2rk372TLtTxUUIi-zjD0eNwwRNiCA,6846
|
|
16
|
+
opalacoder/tools.py,sha256=DPaIcUXDi0j83GVyD4niUE25cHgh9HvdcxxODLw6v6Y,13241
|
|
17
|
+
opalacoder/vcs.py,sha256=YhwYRYLqj1QfLJOagHGXRtcWc8RqbJQnhZMufgKH6Lg,9629
|
|
18
|
+
opalacoder/agents.yaml,sha256=8-Bz0FR5ZHtVsWvrA3rK4qbSMStdGxCnsCcwaBsQV44,2086
|
|
19
|
+
opalacoder/skills/generaldeveloper.md,sha256=nQovGfechp7VO2178F_mhFmB_HBBynjPiO3Tk1Ljhao,2895
|
|
20
|
+
opalacoder/skills/html_css_js.md,sha256=_0ofClJ7Wzah44BJKrsIXzHJ1Se56gt9Jt-fhv-oXqc,2703
|
|
21
|
+
opalacoder/skills/opalacoder.md,sha256=izpXE5RDkFYRwajVefoHM-tkPuk88l3_t-QBk_vsRhE,2257
|
|
22
|
+
opalacoder/skills/python_subprocess.md,sha256=g19gZZkczfDjwUD2LFZqQVQXZYKRkE5fVt0y7z5tZ_s,698
|
|
23
|
+
opalacoder/skills/react_vite.md,sha256=asVCnIBZ4HbIj2JLtKTAFaHSa2-44jvISXWjnl3u7WI,456
|
|
24
|
+
opalacoder-0.1.0.dist-info/METADATA,sha256=n-OAqeg1AvREC1_cAJrOk_VBdCrByo2g-zn9e2LDH9o,8660
|
|
25
|
+
opalacoder-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
26
|
+
opalacoder-0.1.0.dist-info/entry_points.txt,sha256=QRzRb2C0E2oetScVmSVhoXUJge_pN3kymfkKiWsxwYs,51
|
|
27
|
+
opalacoder-0.1.0.dist-info/RECORD,,
|