feat(FN-3350): tokenize task detail danger/error styling

Fixes task detail modal danger/error styling by switching to token-based CSS variables for consistent theming across dark and light modes.

Fusion-Task-Id: FN-3350
This commit is contained in:
Fusion
2026-05-04 04:04:13 -07:00
committed by gsxdsm
parent 5be5da1938
commit 6ecfb3c4ec
24 changed files with 487 additions and 53 deletions

View File

@@ -432,6 +432,35 @@ export function registerAgentRuntimeRoutes(ctx: ApiRoutesContext, deps: AgentRun
}
}
if (nextState === "paused") {
const assignedTasks = await scopedStore.getTasksByAssignedAgent(agentId, { excludeArchived: true });
const toPause = assignedTasks.filter((task) => task.paused !== true);
const results = await Promise.allSettled(
toPause.map((task) => scopedStore.pauseTask(task.id, true, undefined, { pausedByAgentId: agentId })),
);
results.forEach((result, index) => {
if (result.status === "rejected") {
console.error(`[agent-state] failed to pause assigned task ${toPause[index]?.id} for ${agentId}:`, result.reason);
}
});
}
if (nextState === "active" || nextState === "terminated") {
const pausedTasks = await scopedStore.getTasksByAssignedAgent(agentId, {
pausedOnly: true,
excludeArchived: true,
});
const toUnpause = pausedTasks.filter((task) => task.pausedByAgentId === agentId);
const results = await Promise.allSettled(
toUnpause.map((task) => scopedStore.pauseTask(task.id, false)),
);
results.forEach((result, index) => {
if (result.status === "rejected") {
console.error(`[agent-state] failed to unpause assigned task ${toUnpause[index]?.id} for ${agentId}:`, result.reason);
}
});
}
const isHeartbeatEnabled = currentAgent.runtimeConfig?.enabled !== false;
if (nextState === "active" && isHeartbeatEnabled && projectHeartbeatMonitor) {
await projectHeartbeatMonitor.executeHeartbeat({

View File

@@ -8,7 +8,7 @@ import {
resolveTitleSummarizerSettingsModel,
validateNodeOverrideChange,
} from "@fusion/core";
import { ApiError, badRequest, notFound } from "../api-error.js";
import { ApiError, badRequest, conflict, notFound } from "../api-error.js";
import type { ApiRoutesContext } from "./types.js";
interface TaskWorkflowRouteDeps {
@@ -824,8 +824,12 @@ export function registerTaskWorkflowRoutes(ctx: ApiRoutesContext, deps: TaskWork
router.post("/tasks/:id/pause", async (req, res) => {
try {
const { store: scopedStore } = await getProjectContext(req);
const task = await scopedStore.pauseTask(req.params.id, true);
res.json(task);
const task = await scopedStore.getTask(req.params.id);
if (task.assignedAgentId) {
throw conflict(`Cannot manually pause/unpause task assigned to agent ${task.assignedAgentId}. Use agent pause controls instead.`);
}
const updated = await scopedStore.pauseTask(req.params.id, true);
res.json(updated);
} catch (err: unknown) {
if (err instanceof ApiError) {
throw err;
@@ -838,8 +842,12 @@ export function registerTaskWorkflowRoutes(ctx: ApiRoutesContext, deps: TaskWork
router.post("/tasks/:id/unpause", async (req, res) => {
try {
const { store: scopedStore } = await getProjectContext(req);
const task = await scopedStore.pauseTask(req.params.id, false);
res.json(task);
const task = await scopedStore.getTask(req.params.id);
if (task.assignedAgentId) {
throw conflict(`Cannot manually pause/unpause task assigned to agent ${task.assignedAgentId}. Use agent pause controls instead.`);
}
const updated = await scopedStore.pauseTask(req.params.id, false);
res.json(updated);
} catch (err: unknown) {
if (err instanceof ApiError) {
throw err;