From 75aa63ae70567aa02b40352b2d0028efea2401f4 Mon Sep 17 00:00:00 2001 From: qer Date: Thu, 11 Jun 2026 15:29:11 +0800 Subject: [PATCH] feat(kimi-web): defer session creation until first message Clicking '+' now clears activeSessionId instead of eagerly creating a backend session. The onboarding composer is shown immediately. Sending a message without an active session creates it and submits the prompt in one flow via startSessionAndSendPrompt. createSession and createSessionInWorkspace now upsert sessions to avoid duplicates from WebSocket broadcasts. --- apps/kimi-web/src/App.vue | 30 ++- .../src/composables/useKimiWebClient.ts | 49 +++- .../test/start-session-and-send.test.ts | 238 ++++++++++++++++++ 3 files changed, 302 insertions(+), 15 deletions(-) create mode 100644 apps/kimi-web/test/start-session-and-send.test.ts diff --git a/apps/kimi-web/src/App.vue b/apps/kimi-web/src/App.vue index e260af5d3..2c6284eb8 100644 --- a/apps/kimi-web/src/App.vue +++ b/apps/kimi-web/src/App.vue @@ -48,10 +48,6 @@ const activeWorkspaceSessionCount = computed( () => client.visibleWorkspace.value?.sessionCount ?? 0, ); -// True when the active workspace has no sessions — drives the centred input -// placeholder in ChatPane so the user can start typing immediately. -const workspaceEmpty = computed(() => activeWorkspaceSessionCount.value === 0); - // Thinking is on/off (TUI parity — no effort-level cycling). The /thinking // command flips between off and the backend default effort ('high'). function nextThinkingLevel(current: ThinkingLevel): ThinkingLevel { @@ -450,24 +446,32 @@ function handleEditQueued(index: number): void { async function handleSubmit(payload: { text: string; attachments: { fileId: string }[] }): Promise { const wsId = client.activeWorkspaceId.value; - if (wsId && workspaceEmpty.value) { - const session = await client.createSessionInWorkspace(wsId); - if (session === undefined) return; + if (!client.activeSessionId.value && wsId) { + await client.startSessionAndSendPrompt(wsId, payload.text, payload.attachments); + return; } void client.sendPrompt(payload.text, payload.attachments); } -// Primary "+ New": one-click session in the active workspace. If there is no -// active workspace yet (no sessions / no folder added), fall back to the cwd -// dialog so the user can still start somewhere. +// Primary "+ New": clear the active session so the right pane shows the +// onboarding composer. The session is only created when the user sends the +// first message. function handleCreateSession(): void { const wsId = client.activeWorkspaceId.value; if (wsId) { - void client.createSessionInWorkspace(wsId); + client.clearActiveSession(); } else { showNewSession.value = true; } } + +// Workspace-level "+ New" (sidebar group or mobile switcher): switch to the +// workspace and show the onboarding composer. No backend session is created +// until the user actually sends a message. +function handleCreateSessionInWorkspace(workspaceId: string): void { + client.selectWorkspace(workspaceId); + client.clearActiveSession(); +}