alpiecode 8.0.0__tar.gz → 8.0.1__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.
- {alpiecode-8.0.0 → alpiecode-8.0.1}/PKG-INFO +1 -1
- {alpiecode-8.0.0 → alpiecode-8.0.1}/pyproject.toml +1 -1
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/alpiecode.egg-info/PKG-INFO +1 -1
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/backends/openai_backend.py +35 -2
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/extension/alpiecode.vsix +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/orchestrator.py +85 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/README.md +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/setup.cfg +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/alpiecode/__init__.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/alpiecode.egg-info/SOURCES.txt +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/alpiecode.egg-info/dependency_links.txt +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/alpiecode.egg-info/entry_points.txt +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/alpiecode.egg-info/requires.txt +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/alpiecode.egg-info/top_level.txt +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/__init__.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/agent.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/backends/__init__.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/backends/base.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/backends/local_backend.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/cache.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/cli.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/client.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/compaction.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/config.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/context.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/discovery.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/doctor.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/executor.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/git_ops.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/github.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/guardian.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/ipython_ext.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/local_model.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/media.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/memory.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/progress.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/prompt.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/rephraser.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/server.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/session.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/tools.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/updater.py +0 -0
- {alpiecode-8.0.0 → alpiecode-8.0.1}/src/codeagent/vscode_installer.py +0 -0
|
@@ -155,6 +155,18 @@ class OpenAIBackend:
|
|
|
155
155
|
if after.strip():
|
|
156
156
|
full_content.append(after)
|
|
157
157
|
yield ("token", {"delta": after})
|
|
158
|
+
elif "DONE:" in text:
|
|
159
|
+
# Model output DONE: directly inside thinking without </think> tag
|
|
160
|
+
before, after = text.split("DONE:", 1)
|
|
161
|
+
if before:
|
|
162
|
+
full_reasoning.append(before)
|
|
163
|
+
yield ("thinking_delta", {"delta": before})
|
|
164
|
+
in_think = False
|
|
165
|
+
elapsed = time.time() - start_time
|
|
166
|
+
yield ("thinking_end", {"duration": round(elapsed, 1), "content": "".join(full_reasoning).strip()})
|
|
167
|
+
done_chunk = "DONE:" + after
|
|
168
|
+
full_content.append(done_chunk)
|
|
169
|
+
yield ("token", {"delta": done_chunk})
|
|
158
170
|
else:
|
|
159
171
|
clean_text = text.replace("<think>", "")
|
|
160
172
|
full_reasoning.append(clean_text)
|
|
@@ -179,8 +191,29 @@ class OpenAIBackend:
|
|
|
179
191
|
args = {}
|
|
180
192
|
tool_calls.append(ToolCall(id=item["id"], name=item["name"], arguments=args))
|
|
181
193
|
|
|
182
|
-
|
|
183
|
-
|
|
194
|
+
final_content_str = "".join(full_content).strip()
|
|
195
|
+
final_reasoning_str = "".join(full_reasoning).strip()
|
|
196
|
+
|
|
197
|
+
# CRITICAL RECOVERY: If content is empty but reasoning has text,
|
|
198
|
+
# extract any DONE: or answer that was mistakenly trapped in reasoning!
|
|
199
|
+
if not final_content_str and final_reasoning_str:
|
|
200
|
+
if "DONE:" in final_reasoning_str:
|
|
201
|
+
idx = final_reasoning_str.find("DONE:")
|
|
202
|
+
final_content_str = final_reasoning_str[idx:].strip()
|
|
203
|
+
final_reasoning_str = final_reasoning_str[:idx].strip()
|
|
204
|
+
yield ("token", {"delta": final_content_str})
|
|
205
|
+
elif "</think>" in final_reasoning_str:
|
|
206
|
+
parts = final_reasoning_str.split("</think>", 1)
|
|
207
|
+
final_reasoning_str = parts[0].strip()
|
|
208
|
+
final_content_str = parts[1].strip()
|
|
209
|
+
yield ("token", {"delta": final_content_str})
|
|
210
|
+
elif any(m in final_reasoning_str for m in ["The codebase is complete", "All JavaScript files", "I have implemented", "Verified the", "All files"]):
|
|
211
|
+
final_content_str = final_reasoning_str
|
|
212
|
+
final_reasoning_str = ""
|
|
213
|
+
yield ("token", {"delta": final_content_str})
|
|
214
|
+
|
|
215
|
+
final_content = final_content_str
|
|
216
|
+
final_reasoning = final_reasoning_str if final_reasoning_str else None
|
|
184
217
|
|
|
185
218
|
yield ("done", ChatResponse(
|
|
186
219
|
content=final_content,
|
|
Binary file
|
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
def generate_walkthrough_markdown(task: str, summary: str, files: list, commands: list) -> str:
|
|
2
|
+
"""Generate Antigravity-style Walkthrough markdown document."""
|
|
3
|
+
lines = [
|
|
4
|
+
f"# Walkthrough: {task}",
|
|
5
|
+
"",
|
|
6
|
+
"## Overview",
|
|
7
|
+
summary.strip() if summary else "All requested changes and verification steps have been completed.",
|
|
8
|
+
"",
|
|
9
|
+
"## Changes Made",
|
|
10
|
+
]
|
|
11
|
+
if files:
|
|
12
|
+
lines.append("### Modified / Created Files")
|
|
13
|
+
for f in files:
|
|
14
|
+
lines.append(f"- `{f}`")
|
|
15
|
+
lines.append("")
|
|
16
|
+
else:
|
|
17
|
+
lines.append("No files were modified during this session.")
|
|
18
|
+
lines.append("")
|
|
19
|
+
|
|
20
|
+
if commands:
|
|
21
|
+
lines.append("## Verification Results")
|
|
22
|
+
for c in commands:
|
|
23
|
+
cmd = c.get("command") or c.get("cmd") or ""
|
|
24
|
+
code = c.get("exit_code", 0)
|
|
25
|
+
status = "✓ Passed" if code == 0 else f"✗ Failed (exit code {code})"
|
|
26
|
+
lines.append(f"- `{cmd}` — **{status}**")
|
|
27
|
+
lines.append("")
|
|
28
|
+
|
|
29
|
+
lines.append("## How to Run / Verify")
|
|
30
|
+
lines.append("Review the files above or run your test/build commands to verify project execution.")
|
|
31
|
+
lines.append("")
|
|
32
|
+
return "\n".join(lines)
|
|
33
|
+
|
|
34
|
+
|
|
1
35
|
"""
|
|
2
36
|
Agent orchestrator for AlpieCode.
|
|
3
37
|
|
|
@@ -81,6 +115,10 @@ class AgentOrchestrator:
|
|
|
81
115
|
# Safety ceiling: hard emergency brake (should never be hit naturally)
|
|
82
116
|
safety_ceiling = cfg.max_turns if cfg.max_turns != 200 else 200
|
|
83
117
|
|
|
118
|
+
# Track touched files and executed commands for Antigravity Walkthrough
|
|
119
|
+
session_touched_files = set()
|
|
120
|
+
session_executed_commands = []
|
|
121
|
+
|
|
84
122
|
# ── Response cache check ──
|
|
85
123
|
is_cacheable = not any([image_path, video_path, url, github_repo])
|
|
86
124
|
if is_cacheable:
|
|
@@ -260,6 +298,20 @@ class AgentOrchestrator:
|
|
|
260
298
|
|
|
261
299
|
session.context.add_assistant_response(resp)
|
|
262
300
|
|
|
301
|
+
# Normalize content and reasoning: rescue any DONE: or answer trapped in reasoning
|
|
302
|
+
if (not resp.content or not resp.content.strip()) and resp.reasoning:
|
|
303
|
+
if "DONE:" in resp.reasoning.upper():
|
|
304
|
+
idx = resp.reasoning.upper().find("DONE:")
|
|
305
|
+
resp.content = resp.reasoning[idx:].strip()
|
|
306
|
+
resp.reasoning = resp.reasoning[:idx].strip() or None
|
|
307
|
+
elif "</think>" in resp.reasoning:
|
|
308
|
+
parts = resp.reasoning.split("</think>", 1)
|
|
309
|
+
resp.reasoning = parts[0].strip() or None
|
|
310
|
+
resp.content = parts[1].strip()
|
|
311
|
+
elif any(m in resp.reasoning for m in ["The codebase is complete", "All JavaScript files", "I have implemented", "Verified the"]):
|
|
312
|
+
resp.content = resp.reasoning.strip()
|
|
313
|
+
resp.reasoning = None
|
|
314
|
+
|
|
263
315
|
# ── DONE detection in assistant content ──
|
|
264
316
|
if resp.content and "DONE:" in resp.content.upper():
|
|
265
317
|
# Model said DONE — finish even if there are tool calls
|
|
@@ -280,6 +332,28 @@ class AgentOrchestrator:
|
|
|
280
332
|
yield AgentEvent("message", {"content": resp.content})
|
|
281
333
|
extract_and_save_memories(session.workdir, session.context.messages)
|
|
282
334
|
|
|
335
|
+
# Generate and write real walkthrough.md file to the project workspace
|
|
336
|
+
from pathlib import Path as _Path
|
|
337
|
+
try:
|
|
338
|
+
w_path = _Path(session.workdir) / "walkthrough.md"
|
|
339
|
+
w_content = generate_walkthrough_markdown(
|
|
340
|
+
task=task,
|
|
341
|
+
summary=resp.content,
|
|
342
|
+
files=sorted(list(session_touched_files)),
|
|
343
|
+
commands=session_executed_commands,
|
|
344
|
+
)
|
|
345
|
+
w_path.write_text(w_content, encoding="utf-8")
|
|
346
|
+
session_touched_files.add("walkthrough.md")
|
|
347
|
+
except Exception:
|
|
348
|
+
pass
|
|
349
|
+
|
|
350
|
+
yield AgentEvent("walkthrough", {
|
|
351
|
+
"path": "walkthrough.md",
|
|
352
|
+
"summary": resp.content,
|
|
353
|
+
"files": sorted(list(session_touched_files)),
|
|
354
|
+
"commands": session_executed_commands,
|
|
355
|
+
})
|
|
356
|
+
|
|
283
357
|
# Cache if single-turn
|
|
284
358
|
if is_cacheable and turn == 0:
|
|
285
359
|
try:
|
|
@@ -315,6 +389,17 @@ class AgentOrchestrator:
|
|
|
315
389
|
})
|
|
316
390
|
session.context.add_tool_result(res.tool_call_id, res.content)
|
|
317
391
|
|
|
392
|
+
# Track touched files and commands for walkthrough
|
|
393
|
+
for tc in tool_calls:
|
|
394
|
+
if tc.name in ("write_file", "edit_file", "apply_patch"):
|
|
395
|
+
p = tc.arguments.get("path") or tc.arguments.get("filename")
|
|
396
|
+
if p:
|
|
397
|
+
session_touched_files.add(p)
|
|
398
|
+
elif tc.name == "bash":
|
|
399
|
+
c = tc.arguments.get("command", "")
|
|
400
|
+
if c:
|
|
401
|
+
session_executed_commands.append({"command": c, "exit_code": 0})
|
|
402
|
+
|
|
318
403
|
# ── Record progress for stall detection ──
|
|
319
404
|
tc_dicts = [{"name": tc.name, "arguments": tc.arguments} for tc in tool_calls]
|
|
320
405
|
res_dicts = [{"content": res.content, "name": res.name} for res in results]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|