fix(ui): always show /init command in autocomplete

The /init command was only offered in the autocomplete when the current session had no messages yet, and it was filtered out entirely once any message existed. Since the underlying session.command endpoint works in any session, keep /init available whenever a session exists so AGENTS.md setup stays reachable mid-conversation.
This commit is contained in:
Dawnfz-Lenfeng
2026-08-11 17:45:15 +08:00
parent 99e254acf3
commit 5b8ff22d35
@@ -1,7 +1,6 @@
import React from 'react'; import React from 'react';
import { cn, fuzzyMatch } from '@/lib/utils'; import { cn, fuzzyMatch } from '@/lib/utils';
import { useSessionUIStore } from '@/sync/session-ui-store'; import { useSessionUIStore } from '@/sync/session-ui-store';
import { useSessionMessages } from '@/sync/sync-context';
import { useCommandsStore } from '@/stores/useCommandsStore'; import { useCommandsStore } from '@/stores/useCommandsStore';
import { useSkillsStore } from '@/stores/useSkillsStore'; import { useSkillsStore } from '@/stores/useSkillsStore';
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
@@ -65,8 +64,6 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
}, ref) => { }, ref) => {
const { t } = useI18n(); const { t } = useI18n();
const currentSessionId = useSessionUIStore((state) => state.currentSessionId); const currentSessionId = useSessionUIStore((state) => state.currentSessionId);
const sessionMessages = useSessionMessages(currentSessionId ?? '');
const hasMessagesInCurrentSession = sessionMessages.length > 0;
const hasSession = Boolean(currentSessionId); const hasSession = Boolean(currentSessionId);
const hasNewSessionDraft = useSessionUIStore((state) => Boolean(state.newSessionDraft?.open)); const hasNewSessionDraft = useSessionUIStore((state) => Boolean(state.newSessionDraft?.open));
const canStartSessionCommand = hasSession || hasNewSessionDraft; const canStartSessionCommand = hasSession || hasNewSessionDraft;
@@ -139,7 +136,7 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
})); }));
const builtInCommands: CommandInfo[] = [ const builtInCommands: CommandInfo[] = [
...(hasSession && !hasMessagesInCurrentSession ...(hasSession
? [{ id: 'openchamber:init', name: 'init', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.initDescription'), isBuiltIn: true }] ? [{ id: 'openchamber:init', name: 'init', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.initDescription'), isBuiltIn: true }]
: [] : []
), ),
@@ -195,10 +192,9 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
]; ];
const allCommands = mergeCommandAutocompleteItems(builtInCommands, customCommands, skillCommands); const allCommands = mergeCommandAutocompleteItems(builtInCommands, customCommands, skillCommands);
const allowInitCommand = !hasMessagesInCurrentSession; const filtered = searchQuery
const filtered = (searchQuery
? allCommands.filter(cmd => commandMatchesSearch(cmd, searchQuery)) ? allCommands.filter(cmd => commandMatchesSearch(cmd, searchQuery))
: allCommands).filter(cmd => allowInitCommand || cmd.name !== 'init'); : allCommands;
filtered.sort((a, b) => { filtered.sort((a, b) => {
const aStartsWith = a.name.toLowerCase().startsWith(searchQuery.toLowerCase()); const aStartsWith = a.name.toLowerCase().startsWith(searchQuery.toLowerCase());
@@ -211,9 +207,8 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
setCommands(filtered); setCommands(filtered);
} catch { } catch {
const allowInitCommand = !hasMessagesInCurrentSession;
const builtInCommands: CommandInfo[] = [ const builtInCommands: CommandInfo[] = [
...(hasSession && !hasMessagesInCurrentSession ...(hasSession
? [{ id: 'openchamber:init', name: 'init', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.initDescription'), isBuiltIn: true }] ? [{ id: 'openchamber:init', name: 'init', source: 'openchamber' as const, description: t('chat.commandAutocomplete.command.initDescription'), isBuiltIn: true }]
: [] : []
), ),
@@ -268,12 +263,12 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
), ),
]; ];
const filtered = (searchQuery const filtered = searchQuery
? builtInCommands.filter(cmd => ? builtInCommands.filter(cmd =>
fuzzyMatch(cmd.name, searchQuery) || fuzzyMatch(cmd.name, searchQuery) ||
(cmd.description && fuzzyMatch(cmd.description, searchQuery)) (cmd.description && fuzzyMatch(cmd.description, searchQuery))
) )
: builtInCommands).filter(cmd => allowInitCommand || cmd.name !== 'init'); : builtInCommands;
setCommands(filtered); setCommands(filtered);
} finally { } finally {
@@ -282,7 +277,7 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
}; };
loadCommands(); loadCommands();
}, [searchQuery, hasMessagesInCurrentSession, hasSession, canStartSessionCommand, canUseReviewHandoffFlow, commandsWithMetadata, skills, t]); }, [searchQuery, hasSession, canStartSessionCommand, canUseReviewHandoffFlow, commandsWithMetadata, skills, t]);
React.useEffect(() => { React.useEffect(() => {
setSelectedIndex(0); setSelectedIndex(0);