Files
openclaw-taskboard/lib/openclaw-sync.ts

118 lines
3.1 KiB
TypeScript

import fs from "node:fs";
import { SWARM_TASKS_FILE } from "@/lib/fleet-config";
import { appendTaskEvent, applyTaskCallback, findTask } from "@/lib/tasks";
type SwarmRegistryTask = {
id: string;
taskboardTaskId?: number | null;
status?: string;
tmuxSession?: string;
worktree?: string;
pr?: number | null;
note?: string | null;
failedAt?: number | null;
completedAt?: number | null;
startedAt?: number | null;
agent?: string | null;
};
function readRegistry() {
if (!fs.existsSync(SWARM_TASKS_FILE)) {
return [] as SwarmRegistryTask[];
}
const parsed = JSON.parse(fs.readFileSync(SWARM_TASKS_FILE, "utf8")) as { tasks?: SwarmRegistryTask[] };
return Array.isArray(parsed.tasks) ? parsed.tasks : [];
}
function statusToDispatchState(status: string | undefined) {
switch (status) {
case "running":
return "acknowledged" as const;
case "done":
return "completed" as const;
case "failed":
return "failed" as const;
case "queued":
case "retrying":
return "dispatched" as const;
default:
return null;
}
}
function statusToTaskStatus(status: string | undefined) {
switch (status) {
case "running":
return "In Progress" as const;
case "done":
return "Done" as const;
case "failed":
return "Backlog" as const;
case "queued":
case "retrying":
return "Todo" as const;
default:
return undefined;
}
}
export async function syncOpenClawTasks() {
const registryTasks = readRegistry();
const results: Array<{ taskId: number; registryStatus: string; synced: boolean }> = [];
for (const registryTask of registryTasks) {
if (!registryTask.taskboardTaskId) {
continue;
}
const task = await findTask(registryTask.taskboardTaskId);
if (!task) {
continue;
}
const dispatchState = statusToDispatchState(registryTask.status);
const taskStatus = statusToTaskStatus(registryTask.status);
if (!dispatchState) {
continue;
}
await applyTaskCallback(task.id, {
status: taskStatus,
dispatch_state: dispatchState,
summary:
registryTask.status === "done"
? `OpenClaw task ${registryTask.id} completed`
: registryTask.status === "failed"
? `OpenClaw task ${registryTask.id} failed`
: `OpenClaw task ${registryTask.id} ${registryTask.status}`,
detail:
registryTask.pr
? `PR #${registryTask.pr} from ${registryTask.id}`
: registryTask.note || registryTask.worktree || "",
completed_by: registryTask.agent || "openclaw-swarm",
last_error: registryTask.status === "failed" ? registryTask.note || "Swarm task failed" : null,
});
await appendTaskEvent({
taskId: task.id,
assignee: task.assignee,
family: task.family,
host: task.target_host,
eventType: "updated",
state: dispatchState,
summary: `OpenClaw sync: ${registryTask.status}`,
detail: registryTask.worktree || "",
});
results.push({
taskId: task.id,
registryStatus: registryTask.status || "unknown",
synced: true,
});
}
return results;
}