From 435be06cdeb56b227ed906c1ddca283fae69fb16 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 26 Apr 2026 00:26:57 +0100 Subject: [PATCH] test(exec): cover control ui approval turn-source resolution --- .../server-methods/server-methods.test.ts | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/gateway/server-methods/server-methods.test.ts b/src/gateway/server-methods/server-methods.test.ts index fb3e146457b..4837706b609 100644 --- a/src/gateway/server-methods/server-methods.test.ts +++ b/src/gateway/server-methods/server-methods.test.ts @@ -1491,6 +1491,74 @@ describe("exec approval handlers", () => { } }); + it("resolves Control UI-style approvals by id while preserving stored turn-source metadata", async () => { + const { handlers, forwarder, respond, context } = createForwardingExecApprovalFixture(); + const broadcasts: Array<{ event: string; payload: unknown }> = []; + const requestContext = { + ...context, + hasExecApprovalClients: () => true, + broadcast: (event: string, payload: unknown) => { + broadcasts.push({ event, payload }); + }, + }; + + const requestPromise = requestExecApproval({ + handlers, + respond, + context: requestContext, + params: { + id: "approval-control-ui-multichannel", + twoPhase: true, + timeoutMs: 60_000, + host: "gateway", + nodeId: undefined, + systemRunPlan: undefined, + sessionKey: "agent:main:feishu:chat-123", + turnSourceChannel: "feishu", + turnSourceTo: "chat-123", + turnSourceAccountId: "work", + turnSourceThreadId: "thread-456", + }, + }); + await drainApprovalRequestTicks(); + + const resolveRespond = vi.fn(); + await resolveExecApproval({ + handlers, + id: "approval-control-ui-multichannel", + respond: resolveRespond, + context: requestContext, + }); + await requestPromise; + + expect(resolveRespond).toHaveBeenCalledWith(true, { ok: true }, undefined); + expect(forwarder.handleResolved).toHaveBeenCalledWith( + expect.objectContaining({ + id: "approval-control-ui-multichannel", + decision: "allow-once", + request: expect.objectContaining({ + sessionKey: "agent:main:feishu:chat-123", + turnSourceChannel: "feishu", + turnSourceTo: "chat-123", + turnSourceAccountId: "work", + turnSourceThreadId: "thread-456", + }), + }), + ); + expect(broadcasts).toContainEqual( + expect.objectContaining({ + event: "exec.approval.resolved", + payload: expect.objectContaining({ + id: "approval-control-ui-multichannel", + request: expect.objectContaining({ + turnSourceChannel: "feishu", + turnSourceTo: "chat-123", + }), + }), + }), + ); + }); + it("fast-fails approvals when no approver clients and no forwarding targets", async () => { const { manager, handlers, forwarder, respond, context } = createForwardingExecApprovalFixture();