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

@ -146,6 +146,17 @@ def _get_hook(conn: sqlite3.Connection, hook_id: int) -> dict:
return dict(row) if row else {}
def _substitute_vars(command: str, task_id: str | None, conn: sqlite3.Connection) -> str:
"""Substitute {task_id} and {title} in hook command."""
if task_id is None or "{task_id}" not in command and "{title}" not in command:
return command
row = conn.execute("SELECT title FROM tasks WHERE id = ?", (task_id,)).fetchone()
title = row["title"] if row else ""
# Sanitize title for shell safety (strip quotes and newlines)
safe_title = title.replace('"', "'").replace("\n", " ").replace("\r", "")
return command.replace("{task_id}", task_id).replace("{title}", safe_title)
def _execute_hook(
conn: sqlite3.Connection,
hook: dict,
@ -159,9 +170,11 @@ def _execute_hook(
exit_code = -1
success = False
command = _substitute_vars(hook["command"], task_id, conn)
try:
proc = subprocess.run(
hook["command"],
command,
shell=True,
cwd=hook.get("working_dir") or None,
capture_output=True,