kin: KIN-083 Healthcheck claude CLI auth: перед запуском pipeline проверять что claude залогинен (быстрый claude -p 'ok' --output-format json, проверить is_error и 'Not logged in'). Если не залогинен — не запускать pipeline, а показать ошибку 'Claude CLI requires login' в GUI с инструкцией.

This commit is contained in:
Gros Frumos 2026-03-16 15:48:09 +02:00
parent a80679ae72
commit bfc8f1c0bb
18 changed files with 1390 additions and 57 deletions

View file

@ -426,6 +426,16 @@ def start_project_phase(project_id: str):
in_progress, spawns a background subprocess (same as /api/tasks/{id}/run),
and returns immediately so the HTTP request doesn't block on agent execution.
"""
from agents.runner import check_claude_auth, ClaudeAuthError
try:
check_claude_auth()
except ClaudeAuthError:
raise HTTPException(503, detail={
"error": "claude_auth_required",
"message": "Claude CLI requires login",
"instructions": "Run: claude login",
})
conn = get_conn()
p = models.get_project(conn, project_id)
if not p:
@ -454,8 +464,9 @@ def start_project_phase(project_id: str):
conn.close()
kin_root = Path(__file__).parent.parent
cmd = [sys.executable, "-m", "cli.main", "--db", str(DB_PATH), "run", task_id]
cmd.append("--allow-write")
cmd = [sys.executable, "-m", "cli.main", "--db", str(DB_PATH),
"run", task_id]
cmd.append("--allow-write") # always required: subprocess runs non-interactively (stdin=DEVNULL)
import os
env = os.environ.copy()
@ -776,6 +787,16 @@ def is_task_running(task_id: str):
@app.post("/api/tasks/{task_id}/run")
def run_task(task_id: str):
"""Launch pipeline for a task in background. Returns 202."""
from agents.runner import check_claude_auth, ClaudeAuthError
try:
check_claude_auth()
except ClaudeAuthError:
raise HTTPException(503, detail={
"error": "claude_auth_required",
"message": "Claude CLI requires login",
"instructions": "Run: claude login",
})
conn = get_conn()
t = models.get_task(conn, task_id)
if not t:
@ -965,8 +986,14 @@ def bootstrap(body: BootstrapRequest):
if obs["tasks"] or obs["decisions"]:
obsidian = obs
save_to_db(conn, body.id, body.name, str(project_path),
tech_stack, modules, decisions, obsidian)
try:
save_to_db(conn, body.id, body.name, str(project_path),
tech_stack, modules, decisions, obsidian)
except Exception as e:
if models.get_project(conn, body.id):
models.delete_project(conn, body.id)
conn.close()
raise HTTPException(500, f"Bootstrap failed: {e}")
p = models.get_project(conn, body.id)
conn.close()
return {