Canvas: Add worker kill action to monitoring tab

Change-Id: I8387dcf2320f9eccdb2e443fd4039e91ff35ed31
diff --git a/apps/canvas/back/src/index.ts b/apps/canvas/back/src/index.ts
index b33cbbc..cc8d9ef 100644
--- a/apps/canvas/back/src/index.ts
+++ b/apps/canvas/back/src/index.ts
@@ -902,6 +902,30 @@
 	}
 };
 
+const handleQuitWorker: express.Handler = async (req, resp) => {
+	const projectId = Number(req.params["projectId"]);
+	const serviceName = req.params["serviceName"];
+	const workerId = req.params["workerId"];
+
+	const projectMonitor = projectMonitors.get(projectId);
+	if (!projectMonitor) {
+		resp.status(404).send({ error: "Project monitor not found" });
+		return;
+	}
+
+	try {
+		await projectMonitor.terminateWorker(serviceName, workerId);
+		resp.status(200).send({ message: "Worker termination initiated" });
+	} catch (error) {
+		console.error(
+			`Failed to terminate worker ${workerId} in service ${serviceName} for project ${projectId}:`,
+			error,
+		);
+		const errorMessage = error instanceof Error ? error.message : "Unknown error";
+		resp.status(500).send({ error: `Failed to terminate worker: ${errorMessage}` });
+	}
+};
+
 const handleReloadWorker: express.Handler = async (req, resp) => {
 	const projectId = Number(req.params["projectId"]);
 	const serviceName = req.params["serviceName"];
@@ -1101,6 +1125,7 @@
 	projectRouter.post("/:projectId/anthropic-token", handleUpdateAnthropicToken);
 	projectRouter.get("/:projectId/env", handleEnv);
 	projectRouter.post("/:projectId/reload/:serviceName/:workerId", handleReloadWorker);
+	projectRouter.post("/:projectId/quitquitquit/:serviceName/:workerId", handleQuitWorker);
 	projectRouter.post("/:projectId/reload", handleReload);
 	projectRouter.get("/:projectId/logs/:service/:workerId", handleServiceLogs);
 	projectRouter.post("/:projectId/remove-deployment", handleRemoveDeployment);