fix(FN-2116): show paused agents and cap vitest workers

This commit is contained in:
gsxdsm
2026-04-18 17:34:44 -07:00
parent 5a831a67bc
commit 1d8b7f2cb8
16 changed files with 63 additions and 46 deletions

View File

@@ -0,0 +1,5 @@
---
"@gsxdsm/fusion": patch
---
Cap Vitest worker defaults to one worker across the workspace so engine-triggered test runs cannot saturate CPU.

View File

@@ -0,0 +1,5 @@
---
"@gsxdsm/fusion": patch
---
Show paused and terminated agents in the Agents view default All States filter.

View File

@@ -1,8 +1,8 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import { availableParallelism } from "node:os";
const defaultMaxWorkers = Math.max(1, Math.min(2, Math.ceil(availableParallelism() / 8))); const defaultMaxWorkers = 1;
const maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10); const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : defaultMaxWorkers));
export default defineConfig({ export default defineConfig({
test: { test: {

View File

@@ -1,8 +1,8 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import { availableParallelism } from "node:os";
const defaultMaxWorkers = Math.max(1, Math.min(4, Math.ceil(availableParallelism() / 4))); const defaultMaxWorkers = 1;
const maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10); const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : defaultMaxWorkers));
export default defineConfig({ export default defineConfig({
test: { test: {

View File

@@ -257,23 +257,17 @@ export function AgentsView({ addToast, projectId }: AgentsViewProps) {
const hierarchy = useAgentHierarchy(agents, projectId); const hierarchy = useAgentHierarchy(agents, projectId);
// Filter agents for display: hide terminated agents in default "All States" view // Filter agents for display. "All States" means all non-ephemeral agents,
// but show them when the user explicitly filters to "terminated" // including disabled/terminated agents that still carry configuration.
// Always filter out ephemeral agents (task-workers and spawned children)
const displayAgents = useMemo(() => { const displayAgents = useMemo(() => {
let filtered = agents.filter(a => !isEphemeralAgent(a)); return agents.filter(a => !isEphemeralAgent(a));
if (filterState === "all") { }, [agents]);
filtered = filtered.filter(a => a.state !== "terminated");
}
return filtered;
}, [agents, filterState]);
// Filter org tree to exclude terminated and ephemeral agents in default view // Filter org tree to exclude ephemeral agents in default view.
const displayOrgTree = useMemo(() => { const displayOrgTree = useMemo(() => {
// Recursively filter out terminated and ephemeral agents from the org tree // Recursively filter out ephemeral agents from the org tree.
const filterNode = (node: OrgTreeNode): OrgTreeNode | null => { const filterNode = (node: OrgTreeNode): OrgTreeNode | null => {
if (isEphemeralAgent(node.agent)) return null; if (isEphemeralAgent(node.agent)) return null;
if (filterState === "all" && node.agent.state === "terminated") return null;
return { return {
...node, ...node,
children: node.children children: node.children
@@ -284,7 +278,7 @@ export function AgentsView({ addToast, projectId }: AgentsViewProps) {
return orgTree return orgTree
.map(filterNode) .map(filterNode)
.filter((n): n is OrgTreeNode => n !== null); .filter((n): n is OrgTreeNode => n !== null);
}, [orgTree, filterState]); }, [orgTree]);
const loadAgents = useCallback(async () => { const loadAgents = useCallback(async () => {
setIsLoading(true); setIsLoading(true);

View File

@@ -140,8 +140,7 @@ describe("AgentsView", () => {
expect(screen.getAllByText("idle").length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText("idle").length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText("active").length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText("active").length).toBeGreaterThanOrEqual(1);
expect(screen.getAllByText("paused").length).toBeGreaterThanOrEqual(1); expect(screen.getAllByText("paused").length).toBeGreaterThanOrEqual(1);
// Terminated agents are hidden in default "All States" view expect(screen.getAllByText("terminated").length).toBeGreaterThanOrEqual(1);
expect(screen.queryAllByText("terminated").length).toBe(0);
}); });
}); });
@@ -212,8 +211,7 @@ describe("AgentsView", () => {
await waitFor(() => { await waitFor(() => {
const boardCards = document.querySelectorAll(".agent-board-card"); const boardCards = document.querySelectorAll(".agent-board-card");
// 4 agents total, but terminated (agent-004) is filtered out in default view expect(boardCards.length).toBe(4);
expect(boardCards.length).toBe(3);
}); });
}); });
@@ -782,18 +780,15 @@ describe("AgentsView", () => {
}); });
describe("delete agent", () => { describe("delete agent", () => {
it("shows Delete button for idle agents in default view (terminated filtered out)", async () => { it("shows Delete button for idle and terminated agents in default view", async () => {
render(<AgentsView addToast={mockAddToast} />); render(<AgentsView addToast={mockAddToast} />);
await waitFor(() => { await waitFor(() => {
// In default "All States" view, only idle agent (agent-001) should show Delete button
// Terminated agents (agent-004) are filtered out
const deleteButtons = screen.getAllByTitle("Delete"); const deleteButtons = screen.getAllByTitle("Delete");
expect(deleteButtons.length).toBeGreaterThanOrEqual(1); expect(deleteButtons.length).toBeGreaterThanOrEqual(2);
}); });
// Verify terminated agent is not visible expect(screen.getByText("Test Agent 4")).toBeTruthy();
expect(screen.queryByText("Test Agent 4")).toBeNull();
}); });
it("shows Delete button for terminated agents when explicitly filtered", async () => { it("shows Delete button for terminated agents when explicitly filtered", async () => {
@@ -909,8 +904,6 @@ describe("AgentsView", () => {
render(<AgentsView addToast={mockAddToast} />); render(<AgentsView addToast={mockAddToast} />);
await waitFor(() => { await waitFor(() => {
// Only idle agent (agent-001) should have delete button in default view
// Terminated agent (agent-004) is filtered out
const deleteButtons = screen.getAllByTitle("Delete"); const deleteButtons = screen.getAllByTitle("Delete");
expect(deleteButtons.length).toBeGreaterThanOrEqual(1); expect(deleteButtons.length).toBeGreaterThanOrEqual(1);
}); });

View File

@@ -1,10 +1,10 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import { resolve } from "node:path"; import { resolve } from "node:path";
import { availableParallelism } from "node:os";
const defaultMaxWorkers = Math.max(1, Math.min(4, Math.ceil(availableParallelism() / 4))); const defaultMaxWorkers = 1;
const maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10); const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : defaultMaxWorkers));
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],

View File

@@ -1,8 +1,8 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import { availableParallelism } from "node:os";
const defaultMaxWorkers = Math.max(1, Math.min(2, Math.ceil(availableParallelism() / 8))); const defaultMaxWorkers = 1;
const maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10); const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : defaultMaxWorkers));
export default defineConfig({ export default defineConfig({
test: { test: {

View File

@@ -1,9 +1,9 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import { availableParallelism } from "node:os";
import { resolve } from "node:path"; import { resolve } from "node:path";
const defaultMaxWorkers = Math.max(1, Math.min(2, Math.ceil(availableParallelism() / 8))); const defaultMaxWorkers = 1;
const maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10); const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : defaultMaxWorkers));
export default defineConfig({ export default defineConfig({
resolve: { resolve: {

View File

@@ -1,8 +1,8 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import { availableParallelism } from "node:os";
const defaultMaxWorkers = Math.max(1, Math.min(2, Math.ceil(availableParallelism() / 8))); const defaultMaxWorkers = 1;
const maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10); const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : defaultMaxWorkers));
export default defineConfig({ export default defineConfig({
test: { test: {

View File

@@ -1,8 +1,12 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? "1", 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : 1));
export default defineConfig({ export default defineConfig({
test: { test: {
include: ["src/**/*.test.ts"], include: ["src/**/*.test.ts"],
pool: "threads", pool: "threads",
maxWorkers,
}, },
}); });

View File

@@ -1,9 +1,9 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
import { availableParallelism } from "node:os";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
const defaultMaxWorkers = Math.max(1, Math.min(2, Math.ceil(availableParallelism() / 8))); const defaultMaxWorkers = 1;
const maxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10); const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? String(defaultMaxWorkers), 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : defaultMaxWorkers));
const coreSourceEntry = fileURLToPath(new URL("../core/src/index.ts", import.meta.url)); const coreSourceEntry = fileURLToPath(new URL("../core/src/index.ts", import.meta.url));
export default defineConfig({ export default defineConfig({

View File

@@ -1,8 +1,12 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? "1", 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : 1));
export default defineConfig({ export default defineConfig({
test: { test: {
include: ["src/**/*.test.ts"], include: ["src/**/*.test.ts"],
pool: "threads", pool: "threads",
maxWorkers,
}, },
}); });

View File

@@ -1,8 +1,12 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? "1", 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : 1));
export default defineConfig({ export default defineConfig({
test: { test: {
include: ["src/**/*.test.ts"], include: ["src/**/*.test.ts"],
pool: "threads", pool: "threads",
maxWorkers,
}, },
}); });

View File

@@ -1,8 +1,12 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? "1", 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : 1));
export default defineConfig({ export default defineConfig({
test: { test: {
include: ["src/**/*.test.ts"], include: ["src/**/*.test.ts"],
pool: "threads", pool: "threads",
maxWorkers,
}, },
}); });

View File

@@ -1,8 +1,12 @@
import { defineConfig } from "vitest/config"; import { defineConfig } from "vitest/config";
const requestedMaxWorkers = Number.parseInt(process.env.VITEST_MAX_WORKERS ?? "1", 10);
const maxWorkers = Math.max(1, Math.min(1, Number.isFinite(requestedMaxWorkers) ? requestedMaxWorkers : 1));
export default defineConfig({ export default defineConfig({
test: { test: {
include: ["src/**/*.test.ts"], include: ["src/**/*.test.ts"],
pool: "threads", pool: "threads",
maxWorkers,
}, },
}); });