From 054c08ea75cc33e11c643588141bdd2e40acc8ee Mon Sep 17 00:00:00 2001 From: qer Date: Wed, 10 Jun 2026 21:20:08 +0800 Subject: [PATCH] feat(kimi-web): show empty-workspace hint in sidebar and centred quick-start input in chat --- apps/kimi-web/src/App.vue | 11 +- apps/kimi-web/src/components/ChatPane.vue | 126 ++++++++++++++++-- .../src/components/ConversationPane.vue | 5 + apps/kimi-web/src/components/Sidebar.vue | 8 ++ apps/kimi-web/src/i18n/locales/en/composer.ts | 1 + apps/kimi-web/src/i18n/locales/en/sidebar.ts | 1 + apps/kimi-web/src/i18n/locales/zh/composer.ts | 1 + apps/kimi-web/src/i18n/locales/zh/sidebar.ts | 1 + 8 files changed, 144 insertions(+), 10 deletions(-) diff --git a/apps/kimi-web/src/App.vue b/apps/kimi-web/src/App.vue index 09481a9d1..29511b809 100644 --- a/apps/kimi-web/src/App.vue +++ b/apps/kimi-web/src/App.vue @@ -45,6 +45,10 @@ const activeWorkspaceSessionCount = computed( () => client.sessionsForView.value.length, ); +// 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 { @@ -250,7 +254,11 @@ function handleEditQueued(index: number): void { client.unqueue(index); } -function handleSubmit(payload: { text: string; attachments: { fileId: string }[] }): void { +async function handleSubmit(payload: { text: string; attachments: { fileId: string }[] }): Promise { + const wsId = client.activeWorkspaceId.value; + if (wsId && workspaceEmpty.value) { + await client.createSessionInWorkspace(wsId); + } void client.sendPrompt(payload.text, payload.attachments); } @@ -354,6 +362,7 @@ function handleCreateSession(): void { :changes-by-path="client.changesByPath.value" :file-reload-key="client.activeSessionId.value" :session-loading="client.sessionLoading.value" + :workspace-empty="workspaceEmpty" @submit="handleSubmit($event)" @approval="(approvalId, response) => client.respondApproval(approvalId, response)" @cancel-task="client.cancelTask($event)" diff --git a/apps/kimi-web/src/components/ChatPane.vue b/apps/kimi-web/src/components/ChatPane.vue index b4d13a143..4746c5b00 100644 --- a/apps/kimi-web/src/components/ChatPane.vue +++ b/apps/kimi-web/src/components/ChatPane.vue @@ -65,8 +65,13 @@ const props = withDefaults( * the empty-conversation state. */ sessionLoading?: boolean; + /** + * True when the active workspace has no sessions — shows a centred input + * placeholder so the user can start typing immediately. + */ + workspaceEmpty?: boolean; }>(), - { approvals: () => [], bubble: false, mobile: false, running: false, sending: false }, + { approvals: () => [], bubble: false, mobile: false, running: false, sending: false, workspaceEmpty: false }, ); // Bubble layout is active on phones AND on the Modern desktop theme. ThinkingBlock @@ -87,11 +92,30 @@ const emit = defineEmits<{ /** The user toggled a process fold — the scroller must NOT auto-follow to the bottom, or the fold visually expands upward from a pinned bottom. */ foldToggle: []; + /** Centred quick-start submit (workspace has no sessions yet). */ + submit: [payload: { text: string; attachments: { fileId: string }[] }]; }>(); // Per-turn copy button state (keyed by turn id) const copiedTurn = ref(null); +// Centred quick-start textarea for empty workspaces +const quickText = ref(''); + +function handleQuickSubmit(): void { + const text = quickText.value.trim(); + if (!text) return; + quickText.value = ''; + emit('submit', { text, attachments: [] }); +} + +function onQuickKeydown(e: KeyboardEvent): void { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + handleQuickSubmit(); + } +} + /** Assemble the full content of a turn for copying — follows the ordered blocks so thinking/text/tool output copy in the order they happened. */ function turnPlainText(turn: ChatTurn): string { @@ -226,10 +250,28 @@ function processSummary(turn: ChatTurn): string { {{ t('conversation.loading') }}
- -
{{ t('composer.emptyConversation') }}
+