summaryrefslogtreecommitdiff
path: root/makima/frontend/src/lib/api.ts
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-16 19:50:27 +0000
committersoryu <soryu@soryu.co>2026-01-17 05:38:07 +0000
commit75d9644d44ba998a32ed14c072e883a75145ab72 (patch)
treeb82dee94632fd40764a92a9b11da24ef21600ed5 /makima/frontend/src/lib/api.ts
parent6b94b5895ed27e3aef052a1843fb3f334397d1b4 (diff)
downloadsoryu-75d9644d44ba998a32ed14c072e883a75145ab72.tar.gz
soryu-75d9644d44ba998a32ed14c072e883a75145ab72.zip
Add autopilot panel and retry system
Diffstat (limited to 'makima/frontend/src/lib/api.ts')
-rw-r--r--makima/frontend/src/lib/api.ts114
1 files changed, 114 insertions, 0 deletions
diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts
index 9c56f6b..ee04935 100644
--- a/makima/frontend/src/lib/api.ts
+++ b/makima/frontend/src/lib/api.ts
@@ -2492,3 +2492,117 @@ export async function resumeFromCheckpoint(
}
return res.json();
}
+
+// =============================================================================
+// Supervisor/Autopilot Control Functions
+// =============================================================================
+
+/**
+ * Start a contract's supervisor task (enable autopilot mode).
+ * This is a convenience wrapper around startTask.
+ */
+export async function startSupervisor(supervisorTaskId: string): Promise<Task> {
+ return startTask(supervisorTaskId);
+}
+
+/**
+ * Stop a contract's supervisor task (pause autopilot mode).
+ * This is a convenience wrapper around stopTask.
+ */
+export async function stopSupervisor(supervisorTaskId: string): Promise<Task> {
+ return stopTask(supervisorTaskId);
+}
+
+/** Status of the supervisor/autopilot for a contract */
+export interface SupervisorStatus {
+ supervisorTaskId: string | null;
+ status: "not_configured" | "pending" | "starting" | "running" | "paused" | "done" | "failed";
+ daemonId: string | null;
+ canStart: boolean;
+ canStop: boolean;
+ canResume: boolean;
+}
+
+/**
+ * Get the supervisor status for a contract.
+ */
+export function getSupervisorStatus(
+ contract: ContractWithRelations
+): SupervisorStatus {
+ const supervisorTaskId = contract.supervisorTaskId;
+
+ if (!supervisorTaskId) {
+ return {
+ supervisorTaskId: null,
+ status: "not_configured",
+ daemonId: null,
+ canStart: false,
+ canStop: false,
+ canResume: false,
+ };
+ }
+
+ // Find the supervisor task in the contract's tasks
+ const supervisorTask = contract.tasks.find(
+ (t) => t.id === supervisorTaskId && t.isSupervisor
+ );
+
+ if (!supervisorTask) {
+ return {
+ supervisorTaskId,
+ status: "pending",
+ daemonId: null,
+ canStart: true,
+ canStop: false,
+ canResume: false,
+ };
+ }
+
+ // Map task status to supervisor status
+ let status: SupervisorStatus["status"];
+ let canStart = false;
+ let canStop = false;
+ let canResume = false;
+
+ switch (supervisorTask.status) {
+ case "pending":
+ status = "pending";
+ canStart = true;
+ break;
+ case "initializing":
+ case "starting":
+ status = "starting";
+ canStop = true;
+ break;
+ case "running":
+ status = "running";
+ canStop = true;
+ break;
+ case "paused":
+ case "blocked":
+ status = "paused";
+ canResume = true;
+ canStop = true;
+ break;
+ case "done":
+ case "merged":
+ status = "done";
+ break;
+ case "failed":
+ status = "failed";
+ canResume = true;
+ break;
+ default:
+ status = "pending";
+ canStart = true;
+ }
+
+ return {
+ supervisorTaskId,
+ status,
+ daemonId: null, // Task summary doesn't have daemon_id, would need full task
+ canStart,
+ canStop,
+ canResume,
+ };
+}