fix(chat): scope command, skill, and file autocomplete to the chat's own directory
Commands and skills for the composer were read from the ambient store, which follows the project selected in the sidebar; opening a managed chat or a chat draft never changes that selection, so the previous project's commands, skills, and (for drafts) files leaked into chats. The autocompletes now load and read commands and skills for the effective directory, and a chat draft resolves its effective directory to the prepared chat directory or the Chats root instead of the last project. Claude-Session: https://claude.ai/code/session_017TK5JAYDfT3Fotc23UEg98
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import { cn, fuzzyMatch } from '@/lib/utils';
|
||||
import { useSessionUIStore } from '@/sync/session-ui-store';
|
||||
import { useCommandsStore } from '@/stores/useCommandsStore';
|
||||
import { useSkillsStore } from '@/stores/useSkillsStore';
|
||||
import { selectCommandsForDirectory, useCommandsStore } from '@/stores/useCommandsStore';
|
||||
import { selectSkillsForDirectory, useSkillsStore } from '@/stores/useSkillsStore';
|
||||
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { Icon } from "@/components/icon/Icon";
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
@@ -73,10 +74,16 @@ export const CommandAutocomplete = React.forwardRef<CommandAutocompleteHandle, C
|
||||
|
||||
const [commands, setCommands] = React.useState<CommandInfo[]>([]);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const commandsWithMetadata = useCommandsStore((s) => s.commands);
|
||||
const refreshCommands = useCommandsStore((s) => s.loadCommands);
|
||||
const skills = useSkillsStore((s) => s.skills);
|
||||
const refreshSkills = useSkillsStore((s) => s.loadSkills);
|
||||
// Commands and skills belong to the directory the composer sends to — the
|
||||
// session's own directory, or the Chats root for a chat draft — not to the
|
||||
// project the app was on last.
|
||||
const effectiveDirectory = useEffectiveDirectory();
|
||||
const commandsWithMetadata = useCommandsStore((s) => selectCommandsForDirectory(s, effectiveDirectory));
|
||||
const loadCommandsForDirectory = useCommandsStore((s) => s.loadCommands);
|
||||
const skills = useSkillsStore((s) => selectSkillsForDirectory(s, effectiveDirectory));
|
||||
const loadSkillsForDirectory = useSkillsStore((s) => s.loadSkills);
|
||||
const refreshCommands = React.useCallback(() => loadCommandsForDirectory(effectiveDirectory), [effectiveDirectory, loadCommandsForDirectory]);
|
||||
const refreshSkills = React.useCallback(() => loadSkillsForDirectory(effectiveDirectory), [effectiveDirectory, loadSkillsForDirectory]);
|
||||
const [selectedIndex, setSelectedIndex] = React.useState(0);
|
||||
const selectedIndexRef = React.useRef(0);
|
||||
const keyboardNavigationRef = React.useRef(false);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { cn, fuzzyMatch } from '@/lib/utils';
|
||||
import { useSkillsStore } from '@/stores/useSkillsStore';
|
||||
import { selectSkillsForDirectory, useSkillsStore } from '@/stores/useSkillsStore';
|
||||
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
||||
import { useUIStore } from '@/stores/useUIStore';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { useMobileAutocompleteMaxHeight } from './useMobileAutocompleteMaxHeight';
|
||||
@@ -38,13 +39,16 @@ export const SkillAutocomplete = React.forwardRef<SkillAutocompleteHandle, Skill
|
||||
const keyboardNavigationRef = React.useRef(false);
|
||||
const [filteredSkills, setFilteredSkills] = React.useState<SkillInfo[]>([]);
|
||||
const itemRefs = React.useRef<(HTMLDivElement | null)[]>([]);
|
||||
const skills = useSkillsStore((s) => s.skills);
|
||||
// Skills of the directory the composer sends to (session directory, or the
|
||||
// Chats root for a chat draft), not of the project the app was on last.
|
||||
const effectiveDirectory = useEffectiveDirectory();
|
||||
const skills = useSkillsStore((s) => selectSkillsForDirectory(s, effectiveDirectory));
|
||||
const loadSkills = useSkillsStore((s) => s.loadSkills);
|
||||
|
||||
React.useEffect(() => {
|
||||
// Always trigger loadSkills when autocomplete opens to ensure project context is fresh
|
||||
void loadSkills();
|
||||
}, [loadSkills]);
|
||||
// Always trigger loadSkills when autocomplete opens to ensure the directory's skills are fresh
|
||||
void loadSkills(effectiveDirectory);
|
||||
}, [effectiveDirectory, loadSkills]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const normalizedQuery = searchQuery.trim();
|
||||
|
||||
Reference in New Issue
Block a user