day 1: Kin from zero to production - agents, GUI, autopilot, 352 tests
This commit is contained in:
parent
8d9facda4f
commit
8a6f280cbd
22 changed files with 1907 additions and 103 deletions
|
|
@ -99,6 +99,7 @@ def run_agent(
|
|||
|
||||
return {
|
||||
"success": success,
|
||||
"error": result.get("error") if not success else None,
|
||||
"output": parsed_output if parsed_output else output_text,
|
||||
"raw_output": output_text,
|
||||
"role": role,
|
||||
|
|
@ -155,7 +156,8 @@ def _run_claude(
|
|||
raw_stdout = proc.stdout or ""
|
||||
result: dict[str, Any] = {
|
||||
"output": raw_stdout,
|
||||
"error": proc.stderr if proc.returncode != 0 else None,
|
||||
"error": proc.stderr or None, # preserve stderr always for diagnostics
|
||||
"empty_output": not raw_stdout.strip(),
|
||||
"returncode": proc.returncode,
|
||||
}
|
||||
|
||||
|
|
@ -370,7 +372,7 @@ def _is_permission_error(result: dict) -> bool:
|
|||
output = (result.get("raw_output") or result.get("output") or "")
|
||||
if not isinstance(output, str):
|
||||
output = json.dumps(output, ensure_ascii=False)
|
||||
error = result.get("error_message") or ""
|
||||
error = result.get("error") or ""
|
||||
text = output + " " + error
|
||||
return any(re.search(p, text) for p in PERMISSION_PATTERNS)
|
||||
|
||||
|
|
@ -429,15 +431,48 @@ def run_pipeline(
|
|||
model = step.get("model", "sonnet")
|
||||
brief = step.get("brief")
|
||||
|
||||
result = run_agent(
|
||||
conn, role, task_id, project_id,
|
||||
model=model,
|
||||
previous_output=previous_output,
|
||||
brief_override=brief,
|
||||
dry_run=dry_run,
|
||||
allow_write=allow_write,
|
||||
noninteractive=noninteractive,
|
||||
)
|
||||
try:
|
||||
result = run_agent(
|
||||
conn, role, task_id, project_id,
|
||||
model=model,
|
||||
previous_output=previous_output,
|
||||
brief_override=brief,
|
||||
dry_run=dry_run,
|
||||
allow_write=allow_write,
|
||||
noninteractive=noninteractive,
|
||||
)
|
||||
except Exception as exc:
|
||||
exc_msg = f"Step {i+1}/{len(steps)} ({role}) raised exception: {exc}"
|
||||
if pipeline:
|
||||
models.update_pipeline(
|
||||
conn, pipeline["id"],
|
||||
status="failed",
|
||||
total_cost_usd=total_cost,
|
||||
total_tokens=total_tokens,
|
||||
total_duration_seconds=total_duration,
|
||||
)
|
||||
models.log_agent_run(
|
||||
conn,
|
||||
project_id=project_id,
|
||||
task_id=task_id,
|
||||
agent_role=role,
|
||||
action="execute",
|
||||
input_summary=f"task={task_id}, model={model}",
|
||||
output_summary=None,
|
||||
success=False,
|
||||
error_message=exc_msg,
|
||||
)
|
||||
models.update_task(conn, task_id, status="blocked", blocked_reason=exc_msg)
|
||||
return {
|
||||
"success": False,
|
||||
"error": exc_msg,
|
||||
"steps_completed": i,
|
||||
"results": results,
|
||||
"total_cost_usd": total_cost,
|
||||
"total_tokens": total_tokens,
|
||||
"total_duration_seconds": total_duration,
|
||||
"pipeline_id": pipeline["id"] if pipeline else None,
|
||||
}
|
||||
|
||||
if dry_run:
|
||||
results.append(result)
|
||||
|
|
@ -485,10 +520,14 @@ def run_pipeline(
|
|||
total_tokens=total_tokens,
|
||||
total_duration_seconds=total_duration,
|
||||
)
|
||||
models.update_task(conn, task_id, status="blocked")
|
||||
agent_error = result.get("error") or ""
|
||||
error_msg = f"Step {i+1}/{len(steps)} ({role}) failed"
|
||||
if agent_error:
|
||||
error_msg += f": {agent_error}"
|
||||
models.update_task(conn, task_id, status="blocked", blocked_reason=error_msg)
|
||||
return {
|
||||
"success": False,
|
||||
"error": f"Step {i+1}/{len(steps)} ({role}) failed",
|
||||
"error": error_msg,
|
||||
"steps_completed": i,
|
||||
"results": results,
|
||||
"total_cost_usd": total_cost,
|
||||
|
|
@ -524,6 +563,11 @@ def run_pipeline(
|
|||
event="task_auto_approved", task_modules=task_modules)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
run_hooks(conn, project_id, task_id,
|
||||
event="task_done", task_modules=task_modules)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Auto followup: generate tasks, auto-resolve permission issues.
|
||||
# Guard: skip for followup-sourced tasks to prevent infinite recursion.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue