From e76d300ca6b086c76da1c9f287d9e0d07491138f Mon Sep 17 00:00:00 2001 From: Dotta Date: Sun, 19 Apr 2026 22:13:07 -0500 Subject: [PATCH] fix: harden runtime stream and approval handling Co-Authored-By: Paperclip --- packages/adapter-utils/src/server-utils.ts | 6 ++++-- .../src/__tests__/agent-permissions-routes.test.ts | 5 ++++- server/src/routes/agents.ts | 9 +++++++-- server/src/services/agents.ts | 13 +++++++------ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/adapter-utils/src/server-utils.ts b/packages/adapter-utils/src/server-utils.ts index 24e5ede5a41..78e740bf5bf 100644 --- a/packages/adapter-utils/src/server-utils.ts +++ b/packages/adapter-utils/src/server-utils.ts @@ -1151,7 +1151,8 @@ export async function runChildProcess( child.stdout?.on("data", (chunk: unknown) => { const readable = child.stdout; - readable?.pause(); + if (!readable) return; + readable.pause(); const text = String(chunk); stdout = appendWithCap(stdout, text); logChain = logChain @@ -1162,7 +1163,8 @@ export async function runChildProcess( child.stderr?.on("data", (chunk: unknown) => { const readable = child.stderr; - readable?.pause(); + if (!readable) return; + readable.pause(); const text = String(chunk); stderr = appendWithCap(stderr, text); logChain = logChain diff --git a/server/src/__tests__/agent-permissions-routes.test.ts b/server/src/__tests__/agent-permissions-routes.test.ts index a3ebea95bc1..978e7c2e244 100644 --- a/server/src/__tests__/agent-permissions-routes.test.ts +++ b/server/src/__tests__/agent-permissions-routes.test.ts @@ -538,7 +538,10 @@ describe("agent permission routes", () => { status: "idle", }; mockAgentService.getById.mockResolvedValue(pendingAgent); - mockAgentService.activatePendingApproval.mockResolvedValue(approvedAgent); + mockAgentService.activatePendingApproval.mockResolvedValue({ + agent: approvedAgent, + activated: true, + }); const app = await createApp({ type: "board", diff --git a/server/src/routes/agents.ts b/server/src/routes/agents.ts index 4a8e70e1e92..e0871c9b8a4 100644 --- a/server/src/routes/agents.ts +++ b/server/src/routes/agents.ts @@ -2130,11 +2130,16 @@ export function agentRoutes(db: Db) { return; } - const agent = await svc.activatePendingApproval(id); - if (!agent) { + const approval = await svc.activatePendingApproval(id); + if (!approval) { res.status(404).json({ error: "Agent not found" }); return; } + if (!approval.activated) { + res.status(409).json({ error: "Only pending approval agents can be approved" }); + return; + } + const { agent } = approval; await logActivity(db, { companyId: agent.companyId, diff --git a/server/src/services/agents.ts b/server/src/services/agents.ts index 925685f56d7..512d0e89cca 100644 --- a/server/src/services/agents.ts +++ b/server/src/services/agents.ts @@ -526,18 +526,19 @@ export function agentService(db: Db) { }, activatePendingApproval: async (id: string) => { - const existing = await getById(id); - if (!existing) return null; - if (existing.status !== "pending_approval") return existing; - const updated = await db .update(agents) .set({ status: "idle", updatedAt: new Date() }) - .where(eq(agents.id, id)) + .where(and(eq(agents.id, id), eq(agents.status, "pending_approval"))) .returning() .then((rows) => rows[0] ?? null); - return updated ? normalizeAgentRow(updated) : null; + if (updated) { + return { agent: normalizeAgentRow(updated), activated: true }; + } + + const existing = await getById(id); + return existing ? { agent: existing, activated: false } : null; }, updatePermissions: async (id: string, permissions: { canCreateAgents: boolean }) => {