feat(app): create empty workspace without a prompt (#834)
* feat(app): create empty workspace from new-workspace composer Pressing Create with an empty composer (no text, no attachments) on the new-workspace screen now creates the workspace without an agent and lands the user on the empty-state, where they can open a terminal or start an agent on their own. Dispatching submit handler routes to a named runCreateEmptyWorkspace sibling of runCreateChatAgent so empty creation is a first-class action, not a hidden branch in the chat path. * refactor(app): extract empty-workspace helpers into own module Gives the empty-workspace dispatch a real home, shrinks the test mock graph from ~20 modules to one. * test(app): type prompt in new-workspace e2e to exercise chat path Empty-submission now creates a bare workspace (no agent), so tests that assert agent-tab/optimistic-draft behavior must type a prompt to take the chat path.
This commit is contained in:
@@ -30,6 +30,7 @@ import type { ComposerAttachment, UserComposerAttachment } from "@/attachments/t
|
||||
import type { ImageAttachment, MessagePayload } from "@/components/message-input";
|
||||
import type { AgentAttachment, GitHubSearchItem } from "@server/shared/messages";
|
||||
import type { AgentProvider } from "@server/server/agent/agent-sdk-types";
|
||||
import { isEmptyWorkspaceSubmission, runCreateEmptyWorkspace } from "./new-workspace-empty";
|
||||
import { pickerItemToCheckoutRequest, type PickerItem } from "./new-workspace-picker-item";
|
||||
import { syncPickerPrAttachment } from "./new-workspace-picker-state";
|
||||
|
||||
@@ -398,7 +399,7 @@ export function NewWorkspaceScreen({
|
||||
const [createdWorkspace, setCreatedWorkspace] = useState<ReturnType<
|
||||
typeof normalizeWorkspaceDescriptor
|
||||
> | null>(null);
|
||||
const [pendingAction, setPendingAction] = useState<"chat" | null>(null);
|
||||
const [pendingAction, setPendingAction] = useState<"chat" | "empty" | null>(null);
|
||||
const [pickerSelection, setPickerSelection] = useState<PickerSelection | null>(null);
|
||||
const [pickerOpen, setPickerOpen] = useState(false);
|
||||
const [pickerSearchQuery, setPickerSearchQuery] = useState("");
|
||||
@@ -602,11 +603,21 @@ export function NewWorkspaceScreen({
|
||||
[buildCreateWorktreeInput, createdWorkspace, mergeWorkspaces, serverId, withConnectedClient],
|
||||
);
|
||||
|
||||
const handleCreateChatAgent = useCallback(
|
||||
const handleSubmitNewWorkspace = useCallback(
|
||||
async (payload: MessagePayload) => {
|
||||
try {
|
||||
setPendingAction("chat");
|
||||
setErrorMessage(null);
|
||||
if (isEmptyWorkspaceSubmission(payload)) {
|
||||
setPendingAction("empty");
|
||||
await runCreateEmptyWorkspace({
|
||||
payload,
|
||||
ensureWorkspace,
|
||||
serverId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setPendingAction("chat");
|
||||
await runCreateChatAgent({
|
||||
payload,
|
||||
composerState,
|
||||
@@ -729,11 +740,11 @@ export function NewWorkspaceScreen({
|
||||
agentId={`new-workspace:${serverId}:${sourceDirectory}`}
|
||||
serverId={serverId}
|
||||
isPaneFocused={true}
|
||||
onSubmitMessage={handleCreateChatAgent}
|
||||
onSubmitMessage={handleSubmitNewWorkspace}
|
||||
allowEmptySubmit={true}
|
||||
submitButtonAccessibilityLabel="Create"
|
||||
submitIcon="return"
|
||||
isSubmitLoading={pendingAction === "chat"}
|
||||
isSubmitLoading={pendingAction !== null}
|
||||
submitBehavior="preserve-and-lock"
|
||||
blurOnSubmit={true}
|
||||
value={chatDraft.text}
|
||||
|
||||
Reference in New Issue
Block a user