OpenClawDashboard/bridge/src/routes/tasks.ts
Manohar 968d6fd178 fix(bridge): tempfile escaping in chat/dispatch/tasks; remove stale K8S refs
Shell escaping fixes (all three routes had the same bug):
- chat.ts: replace escapedMessage + shell-inline with tmpFile docker cp pattern
- dispatch.ts: replace escapedJson + printf with tmpFile docker cp pattern
- tasks.ts: same as dispatch
- inbox path corrected: /sandbox/... → /home/node/.openclaw/workspace/tasks/inbox

Stale reference removals:
- tiger.ts: remove K8S_NAMESPACE + POD_NAME constants (dead since k3s exit)
- index.ts: rewrite header docblock (Caddy→Traefik, k3s→docker exec)
- dispatch.ts: kubectl comment → docker exec comment
- tasks.ts: same kubectl comment fix
2026-05-02 20:10:43 +00:00

144 lines
No EOL
4 KiB
TypeScript

/**
* routes/tasks.ts — Task CRUD routes for Tiger Bridge
*
* Endpoints:
* GET /tiger/tasks — list all tasks (with filters)
* GET /tiger/tasks/:id — get task + executions + outputs
* PUT /tiger/tasks/:id — update task
* DELETE /tiger/tasks/:id — delete task
* POST /tiger/tasks/:id/execute — trigger execution
*/
import { Router } from "express";
import { tasks, executions } from "../db.js";
const router = Router();
// List all tasks (with optional filters)
router.get("/", (req, res) => {
const { status, project, agent } = req.query;
const all = tasks.findAll({
status: status as string,
project: project as string,
agent: agent as string,
});
res.json({ ok: true, tasks: all });
});
// Get task with executions and outputs
router.get("/:id", (req, res) => {
const { id } = req.params;
const task = tasks.getWithExecutions(id);
if (!task) {
return res.status(404).json({ ok: false, error: "Task not found" });
}
res.json({ ok: true, task });
});
// Update task
router.put("/:id", (req, res) => {
const { id } = req.params;
const {
title,
description,
status,
priority,
assigned_agent,
progress,
tags,
notes,
due_date,
} = req.body;
const updated = tasks.update(id, {
title,
description,
status,
priority,
assigned_agent,
progress,
tags: tags ? JSON.stringify(tags) : undefined,
notes,
due_date,
});
if (!updated) {
return res.status(404).json({ ok: false, error: "Task not found" });
}
res.json({ ok: true, task: updated });
});
// Delete task
router.delete("/:id", (req, res) => {
const { id } = req.params;
const deleted = tasks.delete(id);
if (!deleted) {
return res.status(404).json({ ok: false, error: "Task not found" });
}
res.json({ ok: true });
});
// Trigger execution (writes task file to sandbox for Tiger to pick up)
router.post("/:id/execute", async (req, res) => {
const { id } = req.params;
const task = tasks.findById(id) as { id: string; title: string; description: string; assigned_agent: string } | undefined;
if (!task) {
return res.status(404).json({ ok: false, error: "Task not found" });
}
// Prepare task data for dispatch
const taskData = {
id: id,
title: task.title,
description: task.description || "",
assignedAgent: task.assigned_agent || "manual",
context: "",
createdAt: new Date().toISOString(),
status: "pending",
};
// Write task JSON to container's inbox via docker exec
const inboxPath = "/home/node/.openclaw/workspace/tasks/inbox";
const taskFile = `task_${id}.json`;
// Import execInSandbox dynamically to avoid circular deps
const { execInSandbox } = await import("../tiger.js");
try {
// Write task JSON via temp file (avoids ALL shell escaping issues)
const taskJson = JSON.stringify(taskData, null, 2);
const { writeFileSync: wfs, unlinkSync: uls } = await import("fs");
const { execSync: exs } = await import("child_process");
const tmpHost = `/tmp/task_${id}_${Date.now()}.json`;
try {
wfs(tmpHost, taskJson, "utf-8");
exs(`docker cp ${tmpHost} tiger-openclaw:${tmpHost}`, { timeout: 5000 });
uls(tmpHost);
} catch (copyErr: any) {
throw new Error(`Failed to copy task to container: ${copyErr.message}`);
}
await execInSandbox(`mkdir -p ${inboxPath} && mv ${tmpHost} ${inboxPath}/${taskFile}`);
// Create execution record
const execution = executions.create({
task_id: id,
agent: taskData.assignedAgent,
command: `dispatch task ${id} to ${taskData.assignedAgent}`,
});
// Update task status
tasks.update(id, { status: "in-progress" });
res.json({
ok: true,
execution,
message: `Task ${id} dispatched to Tiger inbox`,
});
} catch (err) {
console.error("Execute error:", err);
res.status(500).json({ ok: false, error: "Failed to dispatch task" });
}
});
export default router;