acra-cli 0.1.1__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.
- acra/__init__.py +7 -0
- acra/__main__.py +4 -0
- acra/agents/__init__.py +0 -0
- acra/agents/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/__pycache__/llm.cpython-312.pyc +0 -0
- acra/agents/__pycache__/llm_utils.cpython-312.pyc +0 -0
- acra/agents/coder/__init__.py +0 -0
- acra/agents/coder/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/coder/__pycache__/coder_agent.cpython-312.pyc +0 -0
- acra/agents/coder/__pycache__/coder_chain.cpython-312.pyc +0 -0
- acra/agents/coder/coder_agent.py +235 -0
- acra/agents/coder/coder_chain.py +204 -0
- acra/agents/critic/__init__.py +0 -0
- acra/agents/critic/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/critic/__pycache__/critic_agent.cpython-312.pyc +0 -0
- acra/agents/critic/__pycache__/critic_chain.cpython-312.pyc +0 -0
- acra/agents/critic/critic_agent.py +199 -0
- acra/agents/critic/critic_chain.py +268 -0
- acra/agents/executor/__init__.py +0 -0
- acra/agents/executor/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/executor/__pycache__/docker_runner.cpython-312.pyc +0 -0
- acra/agents/executor/__pycache__/executor_agent.cpython-312.pyc +0 -0
- acra/agents/executor/__pycache__/sandbox_runner.cpython-312.pyc +0 -0
- acra/agents/executor/docker_runner.py +114 -0
- acra/agents/executor/executor_agent.py +142 -0
- acra/agents/executor/sandbox_runner.py +144 -0
- acra/agents/human/__init__.py +0 -0
- acra/agents/human/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/human/__pycache__/human_node.cpython-312.pyc +0 -0
- acra/agents/human/human_node.py +37 -0
- acra/agents/llm.py +263 -0
- acra/agents/llm_utils.py +161 -0
- acra/agents/memory/__init__.py +0 -0
- acra/agents/memory/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/memory/__pycache__/memory_agent.cpython-312.pyc +0 -0
- acra/agents/memory/__pycache__/memory_manager.cpython-312.pyc +0 -0
- acra/agents/memory/__pycache__/retrieval.cpython-312.pyc +0 -0
- acra/agents/memory/memory_agent.py +239 -0
- acra/agents/memory/memory_manager.py +273 -0
- acra/agents/memory/retrieval.py +355 -0
- acra/agents/planner/__init__.py +0 -0
- acra/agents/planner/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/planner/__pycache__/planner_agent.cpython-312.pyc +0 -0
- acra/agents/planner/__pycache__/planner_chain.cpython-312.pyc +0 -0
- acra/agents/planner/planner_agent.py +97 -0
- acra/agents/planner/planner_chain.py +160 -0
- acra/agents/researcher/__init__.py +1 -0
- acra/agents/researcher/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/agents/researcher/__pycache__/researcher_agent.cpython-312.pyc +0 -0
- acra/agents/researcher/__pycache__/researcher_chain.cpython-312.pyc +0 -0
- acra/agents/researcher/researcher_agent.py +231 -0
- acra/agents/researcher/researcher_chain.py +193 -0
- acra/brain/__init__.py +6 -0
- acra/brain/model_registry.py +19 -0
- acra/brain/provider_manager.py +21 -0
- acra/cli.py +52 -0
- acra/commands/__init__.py +29 -0
- acra/commands/ask.py +49 -0
- acra/commands/brain.py +58 -0
- acra/commands/config.py +25 -0
- acra/commands/context.py +30 -0
- acra/commands/graph.py +18 -0
- acra/commands/keys.py +40 -0
- acra/commands/logs.py +13 -0
- acra/commands/memory.py +27 -0
- acra/commands/plugin.py +18 -0
- acra/commands/research.py +65 -0
- acra/commands/serve.py +13 -0
- acra/commands/session.py +20 -0
- acra/commands/utils.py +12 -0
- acra/config/__init__.py +36 -0
- acra/config/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/config/__pycache__/defaults.cpython-312.pyc +0 -0
- acra/config/__pycache__/profile_manager.cpython-312.pyc +0 -0
- acra/config/defaults.py +88 -0
- acra/config/profile_manager.py +87 -0
- acra/execution/__init__.py +1 -0
- acra/execution/logs/__init__.py +1 -0
- acra/execution/logs/error_logs/__init__.py +1 -0
- acra/execution/logs/execution_logs/__init__.py +1 -0
- acra/execution/sandbox/__init__.py +1 -0
- acra/execution/sandbox/docker_executor.py +209 -0
- acra/execution/sandbox/isolated_runner.py +148 -0
- acra/execution/sandbox/sandbox_manager.py +178 -0
- acra/graph/__init__.py +0 -0
- acra/graph/checkpoint.py +85 -0
- acra/graph/conditional_edges.py +103 -0
- acra/graph/edges.py +85 -0
- acra/graph/graph_visualizer.py +175 -0
- acra/graph/nodes.py +68 -0
- acra/graph/router.py +69 -0
- acra/graph/state.py +93 -0
- acra/graph/workflow.py +117 -0
- acra/memory/__init__.py +1 -0
- acra/memory/checkpoints/__init__.py +1 -0
- acra/memory/checkpoints/data/__init__.py +1 -0
- acra/memory/checkpoints/postgres_checkpoint.py +247 -0
- acra/memory/checkpoints/sqlite_checkpoint.py +309 -0
- acra/memory/chroma_db/__init__.py +1 -0
- acra/memory/conversation_memory/__init__.py +1 -0
- acra/memory/conversation_memory/long_term.py +229 -0
- acra/memory/conversation_memory/short_term.py +158 -0
- acra/memory/storage/__init__.py +1 -0
- acra/memory/vector_store/__init__.py +0 -0
- acra/memory/vector_store/chroma_store.py +260 -0
- acra/memory/vector_store/embeddings.py +43 -0
- acra/observability/__init__.py +1 -0
- acra/observability/langsmith_tracing.py +91 -0
- acra/observability/metrics.py +189 -0
- acra/observability/monitoring.py +162 -0
- acra/observability/token_tracking.py +131 -0
- acra/prompts/__init__.py +1 -0
- acra/schemas/__init__.py +0 -0
- acra/schemas/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/coder_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/critic_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/execution_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/planner_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/researcher_schema.cpython-312.pyc +0 -0
- acra/schemas/__pycache__/shared_schema.cpython-312.pyc +0 -0
- acra/schemas/coder_schema.py +257 -0
- acra/schemas/critic_schema.py +177 -0
- acra/schemas/execution_schema.py +74 -0
- acra/schemas/planner_schema.py +129 -0
- acra/schemas/researcher_schema.py +220 -0
- acra/schemas/shared_schema.py +329 -0
- acra/tools/__init__.py +1 -0
- acra/tools/code_tools/__init__.py +1 -0
- acra/tools/code_tools/file_reader.py +156 -0
- acra/tools/code_tools/file_writer.py +108 -0
- acra/tools/code_tools/python_repl.py +72 -0
- acra/tools/code_tools/terminal_runner.py +98 -0
- acra/tools/github_tools/__init__.py +1 -0
- acra/tools/github_tools/commit_generator.py +91 -0
- acra/tools/github_tools/github_search.py +113 -0
- acra/tools/github_tools/repo_analyzer.py +138 -0
- acra/tools/integration_test_helper.py +370 -0
- acra/tools/validation_tools/__init__.py +1 -0
- acra/tools/validation_tools/dependency_checker.py +101 -0
- acra/tools/validation_tools/environment_config_validator.py +353 -0
- acra/tools/validation_tools/http_validator.py +336 -0
- acra/tools/validation_tools/response_validator.py +407 -0
- acra/tools/validation_tools/security_checker.py +93 -0
- acra/tools/validation_tools/syntax_checker.py +75 -0
- acra/tools/validation_tools/web_framework_validator.py +382 -0
- acra/tools/web_tools/__init__.py +1 -0
- acra/tools/web_tools/arxiv_search.py +110 -0
- acra/tools/web_tools/serpapi_search.py +106 -0
- acra/tools/web_tools/tavily_search.py +96 -0
- acra/ui/__init__.py +8 -0
- acra/ui/__pycache__/__init__.cpython-312.pyc +0 -0
- acra/ui/__pycache__/banner.cpython-312.pyc +0 -0
- acra/ui/__pycache__/components.cpython-312.pyc +0 -0
- acra/ui/__pycache__/shell.cpython-312.pyc +0 -0
- acra/ui/__pycache__/theme.cpython-312.pyc +0 -0
- acra/ui/banner.py +40 -0
- acra/ui/components.py +32 -0
- acra/ui/shell.py +91 -0
- acra/ui/theme.py +28 -0
- acra/utils/__init__.py +21 -0
- acra/utils/context_manager.py +20 -0
- acra/utils/keyring_manager.py +83 -0
- acra/utils/output_formatter.py +18 -0
- acra/utils/session_manager.py +59 -0
- acra_cli-0.1.1.dist-info/METADATA +616 -0
- acra_cli-0.1.1.dist-info/RECORD +169 -0
- acra_cli-0.1.1.dist-info/WHEEL +5 -0
- acra_cli-0.1.1.dist-info/licenses/LICENSE +661 -0
- acra_cli-0.1.1.dist-info/top_level.txt +1 -0
acra/__init__.py
ADDED
acra/__main__.py
ADDED
acra/agents/__init__.py
ADDED
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
from typing import Dict, Optional
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
from langchain_core.exceptions import OutputParserException
|
|
5
|
+
from langchain_core.messages import AIMessage
|
|
6
|
+
|
|
7
|
+
from acra.graph.state import AgentState
|
|
8
|
+
from acra.agents.coder.coder_chain import create_coder_chain
|
|
9
|
+
from acra.schemas.coder_schema import CoderOutput
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _build_fallback_response(project_name: str, entry_point: str, generated_files: Dict) -> CoderOutput:
|
|
13
|
+
"""Create a safe fallback coder response when structured output parsing fails."""
|
|
14
|
+
return CoderOutput(
|
|
15
|
+
generated_files=generated_files or {},
|
|
16
|
+
explanation="Generated project files from the latest workflow state.",
|
|
17
|
+
coding_status="completed",
|
|
18
|
+
next_agent="executor",
|
|
19
|
+
project_name=project_name or "current_project",
|
|
20
|
+
entry_point=entry_point or "app.py",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _extract_project_name(user_request: str) -> str:
|
|
25
|
+
"""
|
|
26
|
+
Extract project name from user request.
|
|
27
|
+
|
|
28
|
+
Tries to extract from:
|
|
29
|
+
1. Quoted names: "project 'name'" or "create 'name'"
|
|
30
|
+
2. Filenames: "calculator.html" -> "calculator"
|
|
31
|
+
3. First few words of request
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
# Try quoted names: 'project_name' or "project_name"
|
|
35
|
+
quoted_match = re.search(r"['\"]([^'\"]+)['\"]", user_request)
|
|
36
|
+
if quoted_match:
|
|
37
|
+
name = quoted_match.group(1)
|
|
38
|
+
# Remove file extension if present
|
|
39
|
+
name = name.rsplit('.', 1)[0]
|
|
40
|
+
# Sanitize name (remove spaces, special chars)
|
|
41
|
+
name = re.sub(r'[^\w-]', '_', name)
|
|
42
|
+
if name:
|
|
43
|
+
return name
|
|
44
|
+
|
|
45
|
+
# Fallback: use first few words (max 2)
|
|
46
|
+
words = user_request.split()[:2]
|
|
47
|
+
project_name = '_'.join(words).lower()
|
|
48
|
+
project_name = re.sub(r'[^\w-]', '_', project_name)
|
|
49
|
+
|
|
50
|
+
return project_name or "generated_project"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def coder_agent(state: AgentState) -> Dict:
|
|
54
|
+
"""
|
|
55
|
+
Coding Agent
|
|
56
|
+
|
|
57
|
+
Responsibilities:
|
|
58
|
+
- Generate source code
|
|
59
|
+
- Create project files
|
|
60
|
+
- Fix execution errors
|
|
61
|
+
- Update generated codebase
|
|
62
|
+
- Prepare output for execution
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
#extract state
|
|
66
|
+
|
|
67
|
+
user_request = state.get("user_request", "")
|
|
68
|
+
|
|
69
|
+
# Extract or preserve project name
|
|
70
|
+
project_name = state.get("project_name", "")
|
|
71
|
+
if not project_name:
|
|
72
|
+
project_name = _extract_project_name(user_request)
|
|
73
|
+
|
|
74
|
+
current_step = state.get("current_step", "")
|
|
75
|
+
|
|
76
|
+
plan = state.get("plan", [])
|
|
77
|
+
|
|
78
|
+
generated_files = state.get(
|
|
79
|
+
"generated_files",
|
|
80
|
+
{}
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
interactive = state.get("interactive", False)
|
|
84
|
+
|
|
85
|
+
error_message = state.get(
|
|
86
|
+
"error_message",
|
|
87
|
+
""
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
entry_point = state.get("entry_point", "app.py") or "app.py"
|
|
91
|
+
|
|
92
|
+
retry_count = state.get(
|
|
93
|
+
"retry_count",
|
|
94
|
+
0
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
critic_feedback = state.get(
|
|
98
|
+
"critic_feedback",
|
|
99
|
+
""
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
research_data = state.get(
|
|
103
|
+
"research_data",
|
|
104
|
+
[]
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
#create coder chain
|
|
109
|
+
|
|
110
|
+
coder_chain = create_coder_chain()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
#invoke coder chain
|
|
114
|
+
|
|
115
|
+
used_fallback = False
|
|
116
|
+
try:
|
|
117
|
+
response = coder_chain.invoke({
|
|
118
|
+
|
|
119
|
+
"user_request": user_request,
|
|
120
|
+
|
|
121
|
+
"current_step": current_step,
|
|
122
|
+
|
|
123
|
+
"plan": plan,
|
|
124
|
+
|
|
125
|
+
"generated_files": generated_files,
|
|
126
|
+
|
|
127
|
+
"error_message": error_message,
|
|
128
|
+
|
|
129
|
+
"retry_count": retry_count,
|
|
130
|
+
|
|
131
|
+
"critic_feedback": critic_feedback,
|
|
132
|
+
|
|
133
|
+
"research_data": research_data,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
#extract structured output
|
|
137
|
+
|
|
138
|
+
updated_files = response.generated_files
|
|
139
|
+
explanation = response.explanation
|
|
140
|
+
coding_status = response.coding_status
|
|
141
|
+
entry_point = getattr(response, "entry_point", entry_point) or entry_point
|
|
142
|
+
next_agent = response.next_agent
|
|
143
|
+
|
|
144
|
+
except (OutputParserException, AttributeError, TypeError, ValueError) as exc:
|
|
145
|
+
response = _build_fallback_response(
|
|
146
|
+
project_name=project_name,
|
|
147
|
+
entry_point=entry_point,
|
|
148
|
+
generated_files=generated_files,
|
|
149
|
+
)
|
|
150
|
+
updated_files = response.generated_files
|
|
151
|
+
explanation = response.explanation
|
|
152
|
+
coding_status = response.coding_status
|
|
153
|
+
entry_point = response.entry_point
|
|
154
|
+
next_agent = response.next_agent
|
|
155
|
+
used_fallback = True
|
|
156
|
+
if error_message:
|
|
157
|
+
explanation = f"{explanation} Fallback due to parser error: {exc}"
|
|
158
|
+
|
|
159
|
+
if interactive and getattr(response, "requires_human_approval", False):
|
|
160
|
+
next_agent = "human"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
#coder workflow logic
|
|
164
|
+
|
|
165
|
+
# first genration
|
|
166
|
+
if used_fallback:
|
|
167
|
+
coder_message = (
|
|
168
|
+
"⚠️ Coding Agent: "
|
|
169
|
+
"The model returned an incomplete structured response. "
|
|
170
|
+
"Using a safe fallback structure to continue the workflow."
|
|
171
|
+
)
|
|
172
|
+
elif retry_count == 0 and not error_message:
|
|
173
|
+
|
|
174
|
+
coder_message = (
|
|
175
|
+
"💻 Coding Agent: "
|
|
176
|
+
"Generating project files and implementation..."
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# error fioxing mode
|
|
180
|
+
elif error_message:
|
|
181
|
+
|
|
182
|
+
coder_message = (
|
|
183
|
+
"🛠️ Coding Agent: "
|
|
184
|
+
"Execution failure detected.\n\n"
|
|
185
|
+
f"Error:\n{error_message}\n\n"
|
|
186
|
+
"Attempting autonomous repair..."
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# critic revision mode
|
|
190
|
+
elif critic_feedback:
|
|
191
|
+
|
|
192
|
+
coder_message = (
|
|
193
|
+
"🧪 Coding Agent: "
|
|
194
|
+
"Critic feedback received.\n\n"
|
|
195
|
+
"Improving implementation quality..."
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# general update
|
|
199
|
+
else:
|
|
200
|
+
|
|
201
|
+
coder_message = (
|
|
202
|
+
"⚡ Coding Agent: "
|
|
203
|
+
"Updating implementation..."
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
#return update state
|
|
208
|
+
|
|
209
|
+
return {
|
|
210
|
+
|
|
211
|
+
# convarsation update
|
|
212
|
+
"messages": [
|
|
213
|
+
AIMessage(content=coder_message)
|
|
214
|
+
],
|
|
215
|
+
|
|
216
|
+
# generate codebase
|
|
217
|
+
"generated_files": updated_files,
|
|
218
|
+
"project_name": project_name,
|
|
219
|
+
"entry_point": entry_point,
|
|
220
|
+
|
|
221
|
+
# coding metadata
|
|
222
|
+
"coding_status": coding_status,
|
|
223
|
+
"coding_explanation": explanation,
|
|
224
|
+
|
|
225
|
+
# workflow
|
|
226
|
+
"next_agent": next_agent,
|
|
227
|
+
"current_agent": "coder",
|
|
228
|
+
|
|
229
|
+
# reset execution state before rerun
|
|
230
|
+
"execution_success": False,
|
|
231
|
+
"execution_output": "",
|
|
232
|
+
|
|
233
|
+
# clear previous errors after regeneration
|
|
234
|
+
"error_message": "",
|
|
235
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
2
|
+
from acra.agents.llm import llm
|
|
3
|
+
from acra.schemas.coder_schema import CoderOutput
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# create coder chain
|
|
7
|
+
|
|
8
|
+
def create_coder_chain():
|
|
9
|
+
"""
|
|
10
|
+
Creates the Coding Agent chain.
|
|
11
|
+
|
|
12
|
+
Responsibilities:
|
|
13
|
+
- Generate source code
|
|
14
|
+
- Create project files
|
|
15
|
+
- Fix runtime errors
|
|
16
|
+
- Improve existing code
|
|
17
|
+
- Respond to critic feedback
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
model = llm()
|
|
21
|
+
|
|
22
|
+
coder_prompt = ChatPromptTemplate.from_messages([
|
|
23
|
+
|
|
24
|
+
(
|
|
25
|
+
"system",
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
You are the Coding Agent inside an autonomous AI platform called AgentForge.
|
|
29
|
+
|
|
30
|
+
You are an expert AI software engineer.
|
|
31
|
+
|
|
32
|
+
Your responsibilities:
|
|
33
|
+
- Generate production-quality code
|
|
34
|
+
- Create complete project files
|
|
35
|
+
- Fix runtime errors
|
|
36
|
+
- Improve architecture
|
|
37
|
+
- Modify existing implementations
|
|
38
|
+
- Respond to critic feedback
|
|
39
|
+
- Ensure clean and executable code
|
|
40
|
+
|
|
41
|
+
==================================================
|
|
42
|
+
YOUR CAPABILITIES
|
|
43
|
+
==================================================
|
|
44
|
+
|
|
45
|
+
You can:
|
|
46
|
+
- generate Python applications
|
|
47
|
+
- create APIs
|
|
48
|
+
- write backend systems
|
|
49
|
+
- implement ML pipelines
|
|
50
|
+
- create tests
|
|
51
|
+
- generate configuration files
|
|
52
|
+
- fix broken code
|
|
53
|
+
- improve code quality
|
|
54
|
+
|
|
55
|
+
==================================================
|
|
56
|
+
IMPORTANT RULES
|
|
57
|
+
==================================================
|
|
58
|
+
|
|
59
|
+
1. ALWAYS generate executable code
|
|
60
|
+
2. NEVER generate incomplete placeholders
|
|
61
|
+
3. NEVER leave TODO comments
|
|
62
|
+
4. ALWAYS return complete file contents
|
|
63
|
+
5. ALWAYS preserve working code unless fixing issues
|
|
64
|
+
6. Keep architecture modular and clean
|
|
65
|
+
7. Prefer readability and maintainability
|
|
66
|
+
8. Handle runtime errors carefully
|
|
67
|
+
9. Generate minimal but functional implementations
|
|
68
|
+
10. Return ONLY structured output
|
|
69
|
+
11. YOU MUST INCLUDE EVERY REQUIRED FIELD IN THE RESPONSE
|
|
70
|
+
12. DO NOT OMIT explanation, coding_status, next_agent, entry_point, or generated_files
|
|
71
|
+
13. If a field is not applicable, still provide a safe default value rather than omitting it
|
|
72
|
+
14. generated_files must be a dictionary mapping filenames to full file contents
|
|
73
|
+
15. If you are unsure, return a conservative working implementation instead of an empty response
|
|
74
|
+
|
|
75
|
+
==================================================
|
|
76
|
+
CURRENT WORKFLOW STATE
|
|
77
|
+
==================================================
|
|
78
|
+
|
|
79
|
+
USER REQUEST:
|
|
80
|
+
{user_request}
|
|
81
|
+
|
|
82
|
+
CURRENT TASK:
|
|
83
|
+
{current_step}
|
|
84
|
+
|
|
85
|
+
FULL EXECUTION PLAN:
|
|
86
|
+
{plan}
|
|
87
|
+
|
|
88
|
+
PREVIOUSLY GENERATED FILES:
|
|
89
|
+
{generated_files}
|
|
90
|
+
|
|
91
|
+
EXECUTION ERROR:
|
|
92
|
+
{error_message}
|
|
93
|
+
|
|
94
|
+
RETRY COUNT:
|
|
95
|
+
{retry_count}
|
|
96
|
+
|
|
97
|
+
CRITIC FEEDBACK:
|
|
98
|
+
{critic_feedback}
|
|
99
|
+
|
|
100
|
+
RESEARCH DATA:
|
|
101
|
+
{research_data}
|
|
102
|
+
|
|
103
|
+
==================================================
|
|
104
|
+
YOUR TASK
|
|
105
|
+
==================================================
|
|
106
|
+
|
|
107
|
+
Analyze the workflow state carefully.
|
|
108
|
+
|
|
109
|
+
Then:
|
|
110
|
+
|
|
111
|
+
1. Generate or update project files
|
|
112
|
+
2. Fix runtime issues if errors exist
|
|
113
|
+
3. Improve implementation if critic feedback exists
|
|
114
|
+
4. Maintain consistency across all files
|
|
115
|
+
5. Prepare project for execution
|
|
116
|
+
|
|
117
|
+
==================================================
|
|
118
|
+
OUTPUT REQUIREMENTS
|
|
119
|
+
==================================================
|
|
120
|
+
|
|
121
|
+
You MUST return ALL of the following fields and they must be present in every response:
|
|
122
|
+
|
|
123
|
+
1. generated_files
|
|
124
|
+
- dictionary of filename → file content
|
|
125
|
+
- must not be empty unless the task is impossible
|
|
126
|
+
|
|
127
|
+
2. explanation
|
|
128
|
+
- short explanation of changes
|
|
129
|
+
- never omit this field
|
|
130
|
+
|
|
131
|
+
3. coding_status
|
|
132
|
+
- one of: generating, updating, fixing, improving, completed, failed
|
|
133
|
+
- never omit this field
|
|
134
|
+
|
|
135
|
+
4. next_agent
|
|
136
|
+
- one of: executor, critic, human
|
|
137
|
+
- never omit this field
|
|
138
|
+
|
|
139
|
+
5. entry_point
|
|
140
|
+
- the file that should be executed to start the project, for example "app.py" or "main.py"
|
|
141
|
+
- never omit this field
|
|
142
|
+
|
|
143
|
+
6. project_name
|
|
144
|
+
- a valid project name string
|
|
145
|
+
- never omit this field
|
|
146
|
+
|
|
147
|
+
Before responding, verify that every required field exists and is non-empty.
|
|
148
|
+
If any field is missing in your draft, fill it with a safe default before finalizing.
|
|
149
|
+
|
|
150
|
+
==================================================
|
|
151
|
+
CODING STATUS OPTIONS
|
|
152
|
+
==================================================
|
|
153
|
+
|
|
154
|
+
- generating
|
|
155
|
+
- updating
|
|
156
|
+
- fixing
|
|
157
|
+
- improving
|
|
158
|
+
- completed
|
|
159
|
+
|
|
160
|
+
==================================================
|
|
161
|
+
NEXT AGENT OPTIONS
|
|
162
|
+
==================================================
|
|
163
|
+
|
|
164
|
+
- executor
|
|
165
|
+
- critic
|
|
166
|
+
|
|
167
|
+
==================================================
|
|
168
|
+
IMPORTANT
|
|
169
|
+
==================================================
|
|
170
|
+
|
|
171
|
+
- If execution errors exist:
|
|
172
|
+
focus on fixing the errors.
|
|
173
|
+
|
|
174
|
+
- If critic feedback exists:
|
|
175
|
+
improve code quality and architecture.
|
|
176
|
+
|
|
177
|
+
- If no files exist:
|
|
178
|
+
generate the initial implementation.
|
|
179
|
+
|
|
180
|
+
- Always return FULL updated file contents.
|
|
181
|
+
"""
|
|
182
|
+
),
|
|
183
|
+
|
|
184
|
+
(
|
|
185
|
+
"human",
|
|
186
|
+
|
|
187
|
+
"""
|
|
188
|
+
Generate or update the project implementation based on the workflow state.
|
|
189
|
+
"""
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
])
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# structured output
|
|
196
|
+
|
|
197
|
+
structured_llm = model.with_structured_output(
|
|
198
|
+
CoderOutput
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
#return chain
|
|
203
|
+
|
|
204
|
+
return coder_prompt | structured_llm
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
from langchain_core.messages import AIMessage
|
|
4
|
+
|
|
5
|
+
from acra.graph.state import AgentState
|
|
6
|
+
|
|
7
|
+
from acra.agents.critic.critic_chain import (
|
|
8
|
+
create_critic_chain
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def critic_agent(state: AgentState) -> Dict:
|
|
13
|
+
"""
|
|
14
|
+
Critic Agent
|
|
15
|
+
|
|
16
|
+
Responsibilities:
|
|
17
|
+
- Evaluate generated code
|
|
18
|
+
- Review execution results
|
|
19
|
+
- Detect vulnerabilities
|
|
20
|
+
- Analyze architecture quality
|
|
21
|
+
- Decide whether code is acceptable
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
#extract state
|
|
25
|
+
|
|
26
|
+
user_request = state.get(
|
|
27
|
+
"user_request",
|
|
28
|
+
""
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
current_step = state.get(
|
|
32
|
+
"current_step",
|
|
33
|
+
""
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
generated_files = state.get(
|
|
37
|
+
"generated_files",
|
|
38
|
+
{}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
interactive = state.get("interactive", False)
|
|
42
|
+
|
|
43
|
+
execution_success = state.get(
|
|
44
|
+
"execution_success",
|
|
45
|
+
False
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
execution_logs = state.get(
|
|
49
|
+
"execution_logs",
|
|
50
|
+
""
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
execution_output = state.get(
|
|
54
|
+
"execution_output",
|
|
55
|
+
""
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
error_message = state.get(
|
|
59
|
+
"error_message",
|
|
60
|
+
""
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
retry_count = state.get(
|
|
64
|
+
"retry_count",
|
|
65
|
+
0
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
#create chain
|
|
70
|
+
|
|
71
|
+
critic_chain = create_critic_chain()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
#invoke critic agent chain
|
|
75
|
+
|
|
76
|
+
response = critic_chain.invoke({
|
|
77
|
+
|
|
78
|
+
"user_request": user_request,
|
|
79
|
+
|
|
80
|
+
"current_step": current_step,
|
|
81
|
+
|
|
82
|
+
"generated_files": generated_files,
|
|
83
|
+
|
|
84
|
+
"execution_success": execution_success,
|
|
85
|
+
|
|
86
|
+
"execution_logs": execution_logs,
|
|
87
|
+
|
|
88
|
+
"execution_output": execution_output,
|
|
89
|
+
|
|
90
|
+
"error_message": error_message,
|
|
91
|
+
|
|
92
|
+
"retry_count": retry_count,
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
#extract structured response
|
|
97
|
+
|
|
98
|
+
review_status = response.review_status
|
|
99
|
+
|
|
100
|
+
quality_score = response.quality_score
|
|
101
|
+
|
|
102
|
+
summary = response.summary
|
|
103
|
+
|
|
104
|
+
feedback = response.feedback
|
|
105
|
+
|
|
106
|
+
next_agent = response.next_agent
|
|
107
|
+
|
|
108
|
+
if interactive and getattr(response, "requires_human_approval", False):
|
|
109
|
+
next_agent = "human"
|
|
110
|
+
|
|
111
|
+
issues = response.issues or []
|
|
112
|
+
|
|
113
|
+
security_issues = (
|
|
114
|
+
response.security_issues or []
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
improvement_suggestions = (
|
|
118
|
+
response.improvement_suggestions or []
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
#review success
|
|
123
|
+
|
|
124
|
+
if review_status == "approved":
|
|
125
|
+
|
|
126
|
+
critic_message = (
|
|
127
|
+
"Critic Agent: "
|
|
128
|
+
"Implementation approved.\n\n"
|
|
129
|
+
f"Quality Score: {quality_score}/10\n\n"
|
|
130
|
+
f"Summary:\n{summary}"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
#review failed
|
|
134
|
+
|
|
135
|
+
elif review_status in [
|
|
136
|
+
"needs_improvement",
|
|
137
|
+
"failed"
|
|
138
|
+
]:
|
|
139
|
+
|
|
140
|
+
critic_message = (
|
|
141
|
+
"Critic Agent: "
|
|
142
|
+
"Issues detected in implementation.\n\n"
|
|
143
|
+
f"Quality Score: {quality_score}/10\n\n"
|
|
144
|
+
f"Feedback:\n{feedback}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
#security failure
|
|
148
|
+
|
|
149
|
+
elif review_status == "unsafe":
|
|
150
|
+
|
|
151
|
+
critic_message = (
|
|
152
|
+
"Critic Agent: "
|
|
153
|
+
"Security risks detected.\n\n"
|
|
154
|
+
f"Security Issues:\n"
|
|
155
|
+
f"{security_issues}"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
#feedback
|
|
159
|
+
|
|
160
|
+
else:
|
|
161
|
+
|
|
162
|
+
critic_message = (
|
|
163
|
+
"Critic Agent: "
|
|
164
|
+
"Unexpected review state encountered."
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
#return update state
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
|
|
172
|
+
"messages": [
|
|
173
|
+
AIMessage(content=critic_message)
|
|
174
|
+
],
|
|
175
|
+
|
|
176
|
+
# Review Results
|
|
177
|
+
"review_status": review_status,
|
|
178
|
+
|
|
179
|
+
"quality_score": quality_score,
|
|
180
|
+
|
|
181
|
+
"critic_feedback": feedback,
|
|
182
|
+
|
|
183
|
+
"critic_summary": summary,
|
|
184
|
+
|
|
185
|
+
"review_issues": issues,
|
|
186
|
+
|
|
187
|
+
"security_issues": security_issues,
|
|
188
|
+
|
|
189
|
+
"improvement_suggestions": (
|
|
190
|
+
improvement_suggestions
|
|
191
|
+
),
|
|
192
|
+
|
|
193
|
+
# Workflow
|
|
194
|
+
"next_agent": next_agent,
|
|
195
|
+
"current_agent": "critic",
|
|
196
|
+
|
|
197
|
+
# Reset retry count on approval so future workflow phases start fresh
|
|
198
|
+
"retry_count": 0 if review_status == "approved" else state.get("retry_count", 0),
|
|
199
|
+
}
|