From 60cc73f87ef04f9445f5733ec4aea57db32c4bb3 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Wed, 15 Apr 2026 11:53:05 +0700 Subject: [PATCH] fix: thread allowEmptySubmit through composer submit path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Create button on the new workspace screen was visible but clicking it did nothing — submitAgentInput() still rejected empty payloads as "noop". Thread allowEmptySubmit through Composer into submitAgentInput so the callback fires and workspace creation + redirect completes. Adds regression test for the empty-submit path. --- .../src/components/agent-input-submit.test.ts | 33 +++++++++++++++++++ .../app/src/components/agent-input-submit.ts | 8 ++++- packages/app/src/components/composer.tsx | 1 + 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/app/src/components/agent-input-submit.test.ts b/packages/app/src/components/agent-input-submit.test.ts index 7008f725a..65fa5c30c 100644 --- a/packages/app/src/components/agent-input-submit.test.ts +++ b/packages/app/src/components/agent-input-submit.test.ts @@ -137,4 +137,37 @@ describe("submitAgentInput", () => { expect(setIsProcessing).toHaveBeenNthCalledWith(2, false); expect(clearDraft).not.toHaveBeenCalled(); }); + + it("submits when empty submit is explicitly allowed", async () => { + const queueMessage = vi.fn(); + const submitMessage = vi.fn(async () => {}); + const clearDraft = vi.fn(); + const setUserInput = vi.fn(); + const setSelectedImages = vi.fn(); + const setSendError = vi.fn(); + const setIsProcessing = vi.fn(); + + await expect( + submitAgentInput({ + message: " ", + allowEmptySubmit: true, + isAgentRunning: false, + canSubmit: true, + queueMessage, + submitMessage, + clearDraft, + setUserInput, + setSelectedImages, + setSendError, + setIsProcessing, + }), + ).resolves.toBe("submitted"); + + expect(queueMessage).not.toHaveBeenCalled(); + expect(submitMessage).toHaveBeenCalledWith({ + message: "", + imageAttachments: undefined, + }); + expect(clearDraft).toHaveBeenCalledWith("sent"); + }); }); diff --git a/packages/app/src/components/agent-input-submit.ts b/packages/app/src/components/agent-input-submit.ts index a89df2cfb..73f143cf9 100644 --- a/packages/app/src/components/agent-input-submit.ts +++ b/packages/app/src/components/agent-input-submit.ts @@ -4,6 +4,7 @@ export interface AgentInputSubmitActionInput { message: string; imageAttachments?: TImage[]; hasExternalContent?: boolean; + allowEmptySubmit?: boolean; forceSend?: boolean; isAgentRunning: boolean; canSubmit: boolean; @@ -23,7 +24,12 @@ export async function submitAgentInput( const trimmedMessage = input.message.trim(); const imageAttachments = input.imageAttachments; - if (!trimmedMessage && !imageAttachments?.length && !input.hasExternalContent) { + if ( + !trimmedMessage && + !imageAttachments?.length && + !input.hasExternalContent && + !input.allowEmptySubmit + ) { return "noop"; } diff --git a/packages/app/src/components/composer.tsx b/packages/app/src/components/composer.tsx index 6fabd325b..c2522bbe6 100644 --- a/packages/app/src/components/composer.tsx +++ b/packages/app/src/components/composer.tsx @@ -359,6 +359,7 @@ export function Composer({ message, imageAttachments, hasExternalContent, + allowEmptySubmit, forceSend, isAgentRunning: agentState.status === "running", // Parent-managed submits are still valid submit paths even when the