refactor(ui): unify primary agent filtering for mentions and UI (#339)
This commit is contained in:
committed by
GitHub
parent
0503f51357
commit
b166d831ce
@@ -18,6 +18,11 @@ export interface AgentMentionAutocompleteHandle {
|
|||||||
|
|
||||||
type AutocompleteTab = 'commands' | 'agents' | 'files';
|
type AutocompleteTab = 'commands' | 'agents' | 'files';
|
||||||
|
|
||||||
|
const isMentionableAgentMode = (mode?: string | null): boolean => {
|
||||||
|
if (!mode) return false;
|
||||||
|
return mode !== 'primary';
|
||||||
|
};
|
||||||
|
|
||||||
interface AgentMentionAutocompleteProps {
|
interface AgentMentionAutocompleteProps {
|
||||||
searchQuery: string;
|
searchQuery: string;
|
||||||
onAgentSelect: (agentName: string) => void;
|
onAgentSelect: (agentName: string) => void;
|
||||||
@@ -27,14 +32,7 @@ interface AgentMentionAutocompleteProps {
|
|||||||
onTabSelect?: (tab: AutocompleteTab) => void;
|
onTabSelect?: (tab: AutocompleteTab) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isMentionable = (mode?: string | null): boolean => {
|
export const AgentMentionAutocomplete = React.forwardRef<AgentMentionAutocompleteHandle, AgentMentionAutocompleteProps>(({
|
||||||
if (!mode) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return mode !== 'primary';
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AgentMentionAutocomplete = React.forwardRef<AgentMentionAutocompleteHandle, AgentMentionAutocompleteProps>(({
|
|
||||||
searchQuery,
|
searchQuery,
|
||||||
onAgentSelect,
|
onAgentSelect,
|
||||||
onClose,
|
onClose,
|
||||||
@@ -59,7 +57,7 @@ export const AgentMentionAutocomplete = React.forwardRef<AgentMentionAutocomplet
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const visibleAgents = getVisibleAgents();
|
const visibleAgents = getVisibleAgents();
|
||||||
const filtered = visibleAgents
|
const filtered = visibleAgents
|
||||||
.filter((agent) => isMentionable(agent.mode))
|
.filter((agent) => isMentionableAgentMode(agent.mode))
|
||||||
.map((agent) => {
|
.map((agent) => {
|
||||||
const metadata = agentsWithMetadata.find(a => a.name === agent.name) as (AgentWithExtras & { scope?: string }) | undefined;
|
const metadata = agentsWithMetadata.find(a => a.name === agent.name) as (AgentWithExtras & { scope?: string }) | undefined;
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ interface ChatInputProps {
|
|||||||
scrollToBottom?: (options?: { instant?: boolean; force?: boolean; clearAnchor?: boolean }) => void;
|
scrollToBottom?: (options?: { instant?: boolean; force?: boolean; clearAnchor?: boolean }) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isPrimaryMode = (mode?: string) => mode === 'primary' || mode === 'all' || mode === undefined || mode === null;
|
|
||||||
|
|
||||||
const CHAT_INPUT_DRAFT_KEY = 'openchamber_chat_input_draft';
|
const CHAT_INPUT_DRAFT_KEY = 'openchamber_chat_input_draft';
|
||||||
|
|
||||||
// Helper to safely read from localStorage
|
// Helper to safely read from localStorage
|
||||||
@@ -118,6 +116,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
|
|
||||||
const { currentProviderId, currentModelId, currentVariant, currentAgentName, setAgent, getVisibleAgents } = useConfigStore();
|
const { currentProviderId, currentModelId, currentVariant, currentAgentName, setAgent, getVisibleAgents } = useConfigStore();
|
||||||
const agents = getVisibleAgents();
|
const agents = getVisibleAgents();
|
||||||
|
const primaryAgents = React.useMemo(() => agents.filter((agent) => agent.mode === 'primary'), [agents]);
|
||||||
const { isMobile, inputBarOffset, isKeyboardOpen, setTimelineDialogOpen, cornerRadius, persistChatDraft } = useUIStore();
|
const { isMobile, inputBarOffset, isKeyboardOpen, setTimelineDialogOpen, cornerRadius, persistChatDraft } = useUIStore();
|
||||||
const { working } = useAssistantStatus();
|
const { working } = useAssistantStatus();
|
||||||
const { currentTheme } = useThemeSystem();
|
const { currentTheme } = useThemeSystem();
|
||||||
@@ -799,7 +798,6 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
}, [abortCurrentOperation, clearAbortPrompt, startAbortIndicator]);
|
}, [abortCurrentOperation, clearAbortPrompt, startAbortIndicator]);
|
||||||
|
|
||||||
const handleCycleAgent = React.useCallback(() => {
|
const handleCycleAgent = React.useCallback(() => {
|
||||||
const primaryAgents = agents.filter(agent => isPrimaryMode(agent.mode));
|
|
||||||
if (primaryAgents.length <= 1) return;
|
if (primaryAgents.length <= 1) return;
|
||||||
|
|
||||||
const currentIndex = primaryAgents.findIndex(agent => agent.name === currentAgentName);
|
const currentIndex = primaryAgents.findIndex(agent => agent.name === currentAgentName);
|
||||||
@@ -811,7 +809,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
|||||||
if (currentSessionId) {
|
if (currentSessionId) {
|
||||||
saveSessionAgentSelection(currentSessionId, nextAgent.name);
|
saveSessionAgentSelection(currentSessionId, nextAgent.name);
|
||||||
}
|
}
|
||||||
}, [agents, currentAgentName, currentSessionId, setAgent, saveSessionAgentSelection]);
|
}, [primaryAgents, currentAgentName, currentSessionId, setAgent, saveSessionAgentSelection]);
|
||||||
|
|
||||||
const adjustTextareaHeight = React.useCallback(() => {
|
const adjustTextareaHeight = React.useCallback(() => {
|
||||||
const textarea = textareaRef.current;
|
const textarea = textareaRef.current;
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ type IconComponent = ComponentType<any>;
|
|||||||
|
|
||||||
type ProviderModel = Record<string, unknown> & { id?: string; name?: string };
|
type ProviderModel = Record<string, unknown> & { id?: string; name?: string };
|
||||||
|
|
||||||
const isPrimaryMode = (mode?: string) => mode === 'primary' || mode === 'all' || mode === undefined || mode === null;
|
|
||||||
|
|
||||||
type PermissionAction = 'allow' | 'ask' | 'deny';
|
type PermissionAction = 'allow' | 'ask' | 'deny';
|
||||||
type PermissionRule = { permission: string; pattern: string; action: PermissionAction };
|
type PermissionRule = { permission: string; pattern: string; action: PermissionAction };
|
||||||
|
|
||||||
@@ -288,6 +286,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
|
|||||||
|
|
||||||
// Use visible agents (excludes hidden internal agents)
|
// Use visible agents (excludes hidden internal agents)
|
||||||
const agents = getVisibleAgents();
|
const agents = getVisibleAgents();
|
||||||
|
const primaryAgents = React.useMemo(() => agents.filter((agent) => agent.mode === 'primary'), [agents]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
currentSessionId,
|
currentSessionId,
|
||||||
@@ -432,8 +431,12 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
|
|||||||
setModelSelectedIndex(0);
|
setModelSelectedIndex(0);
|
||||||
}, [desktopModelQuery]);
|
}, [desktopModelQuery]);
|
||||||
|
|
||||||
|
const selectableDesktopAgents = React.useMemo(() => {
|
||||||
|
return agents.filter((agent) => agent.mode !== 'subagent');
|
||||||
|
}, [agents]);
|
||||||
|
|
||||||
const sortedAndFilteredAgents = React.useMemo(() => {
|
const sortedAndFilteredAgents = React.useMemo(() => {
|
||||||
const sorted = [...agents].sort((a, b) => a.name.localeCompare(b.name));
|
const sorted = [...selectableDesktopAgents].sort((a, b) => a.name.localeCompare(b.name));
|
||||||
if (!agentSearchQuery.trim()) {
|
if (!agentSearchQuery.trim()) {
|
||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
@@ -441,17 +444,17 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
|
|||||||
fuzzyMatch(agentSearchQuery, agent.name) ||
|
fuzzyMatch(agentSearchQuery, agent.name) ||
|
||||||
(agent.description && fuzzyMatch(agentSearchQuery, agent.description))
|
(agent.description && fuzzyMatch(agentSearchQuery, agent.description))
|
||||||
);
|
);
|
||||||
}, [agents, agentSearchQuery]);
|
}, [selectableDesktopAgents, agentSearchQuery]);
|
||||||
|
|
||||||
const defaultAgentName = React.useMemo(() => {
|
const defaultAgentName = React.useMemo(() => {
|
||||||
if (settingsDefaultAgent) {
|
if (settingsDefaultAgent) {
|
||||||
const found = agents.find(a => a.name === settingsDefaultAgent);
|
const found = selectableDesktopAgents.find(a => a.name === settingsDefaultAgent);
|
||||||
if (found) return found.name;
|
if (found) return found.name;
|
||||||
}
|
}
|
||||||
const buildAgent = agents.find(a => a.name === 'build');
|
const buildAgent = selectableDesktopAgents.find(a => a.name === 'build');
|
||||||
if (buildAgent) return buildAgent.name;
|
if (buildAgent) return buildAgent.name;
|
||||||
return agents[0]?.name;
|
return selectableDesktopAgents[0]?.name;
|
||||||
}, [settingsDefaultAgent, agents]);
|
}, [settingsDefaultAgent, selectableDesktopAgents]);
|
||||||
|
|
||||||
const currentAgent = React.useMemo(() => {
|
const currentAgent = React.useMemo(() => {
|
||||||
if (uiAgentName) {
|
if (uiAgentName) {
|
||||||
@@ -696,7 +699,6 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const primaryAgents = agents.filter(agent => isPrimaryMode(agent.mode));
|
|
||||||
const fallbackAgent = agents.find(agent => agent.name === 'build') || primaryAgents[0] || agents[0];
|
const fallbackAgent = agents.find(agent => agent.name === 'build') || primaryAgents[0] || agents[0];
|
||||||
if (!fallbackAgent) {
|
if (!fallbackAgent) {
|
||||||
return;
|
return;
|
||||||
@@ -821,6 +823,7 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
|
|||||||
currentSessionId,
|
currentSessionId,
|
||||||
currentSessionMessageCount,
|
currentSessionMessageCount,
|
||||||
agents,
|
agents,
|
||||||
|
primaryAgents,
|
||||||
currentAgentName,
|
currentAgentName,
|
||||||
getAgentModelForSession,
|
getAgentModelForSession,
|
||||||
setAgent,
|
setAgent,
|
||||||
@@ -1107,7 +1110,6 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
|
|||||||
|
|
||||||
const getAgentDisplayName = () => {
|
const getAgentDisplayName = () => {
|
||||||
if (!uiAgentName) {
|
if (!uiAgentName) {
|
||||||
const primaryAgents = agents.filter(agent => isPrimaryMode(agent.mode));
|
|
||||||
const buildAgent = primaryAgents.find(agent => agent.name === 'build');
|
const buildAgent = primaryAgents.find(agent => agent.name === 'build');
|
||||||
const defaultAgent = buildAgent || primaryAgents[0];
|
const defaultAgent = buildAgent || primaryAgents[0];
|
||||||
return defaultAgent ? capitalizeAgentName(defaultAgent.name) : 'Select Agent';
|
return defaultAgent ? capitalizeAgentName(defaultAgent.name) : 'Select Agent';
|
||||||
@@ -1724,8 +1726,6 @@ export const ModelControls: React.FC<ModelControlsProps> = ({
|
|||||||
const renderMobileAgentPanel = () => {
|
const renderMobileAgentPanel = () => {
|
||||||
if (!isCompact) return null;
|
if (!isCompact) return null;
|
||||||
|
|
||||||
const primaryAgents = agents.filter(agent => isPrimaryMode(agent.mode));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MobileOverlayPanel
|
<MobileOverlayPanel
|
||||||
open={activeMobilePanel === 'agent'}
|
open={activeMobilePanel === 'agent'}
|
||||||
|
|||||||
Reference in New Issue
Block a user