day 1: Kin from zero to production - agents, GUI, autopilot, 352 tests

This commit is contained in:
Gros Frumos 2026-03-15 23:22:49 +02:00
parent 8d9facda4f
commit 8a6f280cbd
22 changed files with 1907 additions and 103 deletions

View file

@ -161,7 +161,7 @@ class TaskPatch(BaseModel):
execution_mode: str | None = None
VALID_STATUSES = {"pending", "in_progress", "review", "done", "blocked", "cancelled"}
VALID_STATUSES = set(models.VALID_TASK_STATUSES)
VALID_EXECUTION_MODES = {"auto", "review"}
@ -248,6 +248,13 @@ def approve_task(task_id: str, body: TaskApprove | None = None):
conn.close()
raise HTTPException(404, f"Task '{task_id}' not found")
models.update_task(conn, task_id, status="done")
try:
from core.hooks import run_hooks as _run_hooks
task_modules = models.get_modules(conn, t["project_id"])
_run_hooks(conn, t["project_id"], task_id,
event="task_done", task_modules=task_modules)
except Exception:
pass
decision = None
if body and body.decision_title:
decision = models.add_decision(
@ -328,12 +335,8 @@ def is_task_running(task_id: str):
return {"running": False}
class TaskRun(BaseModel):
allow_write: bool = False
@app.post("/api/tasks/{task_id}/run")
def run_task(task_id: str, body: TaskRun | None = None):
def run_task(task_id: str):
"""Launch pipeline for a task in background. Returns 202."""
conn = get_conn()
t = models.get_task(conn, task_id)
@ -347,8 +350,7 @@ def run_task(task_id: str, body: TaskRun | None = None):
kin_root = Path(__file__).parent.parent
cmd = [sys.executable, "-m", "cli.main", "--db", str(DB_PATH),
"run", task_id]
if body and body.allow_write:
cmd.append("--allow-write")
cmd.append("--allow-write") # always required: subprocess runs non-interactively (stdin=DEVNULL)
import os
env = os.environ.copy()
@ -413,6 +415,18 @@ def create_decision(body: DecisionCreate):
return d
@app.delete("/api/projects/{project_id}/decisions/{decision_id}")
def delete_decision(project_id: str, decision_id: int):
conn = get_conn()
decision = models.get_decision(conn, decision_id)
if not decision or decision["project_id"] != project_id:
conn.close()
raise HTTPException(404, f"Decision #{decision_id} not found")
models.delete_decision(conn, decision_id)
conn.close()
return {"deleted": decision_id}
# ---------------------------------------------------------------------------
# Cost
# ---------------------------------------------------------------------------