Full pipeline flow through web interface with live updates
API:
POST /api/tasks/{id}/run — sets task to in_progress immediately,
launches subprocess with error handling and logging.
GET /api/tasks/{id}/running — checks pipelines table for active run.
Fixed --db flag position in subprocess command.
TaskDetail (live pipeline):
- Run button starts pipeline, auto-starts 3s polling
- Pipeline cards update in real-time as agent_logs appear
- Pulsing blue dot on header while in_progress
- Spinner on run button during execution
- Auto-stops polling when status changes from in_progress
- Cleanup on component unmount (no leaked timers)
ProjectView (run from list):
- [>] button on each pending task row
- Confirm dialog before starting
- Pulsing blue dot for in_progress tasks
- Click task row → /task/:id with live view
Dashboard (live statuses):
- Pulsing blue dot next to active task count
- Auto-poll every 5s when any project has active tasks
- Stops polling when no active tasks
5 new API tests (running endpoint, run sets status, not found).
141 tests total, all passing. Frontend builds clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ab693d3c4d
commit
db1729730f
5 changed files with 145 additions and 33 deletions
37
web/api.py
37
web/api.py
|
|
@ -257,6 +257,24 @@ def reject_task(task_id: str, body: TaskReject):
|
|||
return {"status": "pending", "reason": body.reason}
|
||||
|
||||
|
||||
@app.get("/api/tasks/{task_id}/running")
|
||||
def is_task_running(task_id: str):
|
||||
"""Check if task has an active (running) pipeline."""
|
||||
conn = get_conn()
|
||||
t = models.get_task(conn, task_id)
|
||||
if not t:
|
||||
conn.close()
|
||||
raise HTTPException(404, f"Task '{task_id}' not found")
|
||||
row = conn.execute(
|
||||
"SELECT id, status FROM pipelines WHERE task_id = ? ORDER BY created_at DESC LIMIT 1",
|
||||
(task_id,),
|
||||
).fetchone()
|
||||
conn.close()
|
||||
if row and row["status"] == "running":
|
||||
return {"running": True, "pipeline_id": row["id"]}
|
||||
return {"running": False}
|
||||
|
||||
|
||||
@app.post("/api/tasks/{task_id}/run")
|
||||
def run_task(task_id: str):
|
||||
"""Launch pipeline for a task in background. Returns 202."""
|
||||
|
|
@ -265,15 +283,22 @@ def run_task(task_id: str):
|
|||
if not t:
|
||||
conn.close()
|
||||
raise HTTPException(404, f"Task '{task_id}' not found")
|
||||
# Set task to in_progress immediately so UI updates
|
||||
models.update_task(conn, task_id, status="in_progress")
|
||||
conn.close()
|
||||
# Launch kin run in background subprocess
|
||||
kin_root = Path(__file__).parent.parent
|
||||
subprocess.Popen(
|
||||
[sys.executable, "-m", "cli.main", "run", task_id, "--db",
|
||||
str(DB_PATH)],
|
||||
cwd=str(kin_root),
|
||||
stdout=subprocess.DEVNULL,
|
||||
)
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, "-m", "cli.main", "--db", str(DB_PATH),
|
||||
"run", task_id],
|
||||
cwd=str(kin_root),
|
||||
stdout=subprocess.DEVNULL,
|
||||
)
|
||||
import logging
|
||||
logging.getLogger("kin").info(f"Pipeline started for {task_id}, pid={proc.pid}")
|
||||
except Exception as e:
|
||||
raise HTTPException(500, f"Failed to start pipeline: {e}")
|
||||
return JSONResponse({"status": "started", "task_id": task_id}, status_code=202)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue