openhands / src /hooks /use-chat-input-profile-state.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
63522a5 verified
Raw History Blame Contribute Delete
4.45 kB
import { useCallback } from "react";
import { useIsMutating } from "@tanstack/react-query";
import type { AgentProfileSummary } from "#/api/agent-profiles-service/agent-profiles-service.api";
import { getStoredConversationMetadata } from "#/api/conversation-metadata-store";
import { useNavigation } from "#/context/navigation-context";
import { useAgentProfiles } from "#/hooks/query/use-agent-profiles";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
import {
CREATE_CONVERSATION_MUTATION_KEY,
useCreateConversation,
type CreateConversationVariables,
} from "#/hooks/mutation/use-create-conversation";
import {
useActivateAgentProfile,
ACTIVATE_AGENT_PROFILE_MUTATION_KEY,
} from "#/hooks/mutation/use-activate-agent-profile";
export interface ChatInputProfileState {
profiles: AgentProfileSummary[];
currentProfileId: string | null;
currentProfileName: string | null;
isInConversation: boolean;
isLoading: boolean;
isSwitching: boolean;
selectProfile: (profile: AgentProfileSummary) => void;
}
export function useChatInputProfileState(): ChatInputProfileState {
const { conversationId, navigate } = useNavigation();
const { data: conversation, isLoading: isLoadingConversation } =
useActiveConversation();
const { data: agentProfiles, isLoading: isLoadingProfiles } =
useAgentProfiles();
const createConversation = useCreateConversation();
const activateProfile = useActivateAgentProfile();
const activatingProfiles = useIsMutating({
mutationKey: ACTIVATE_AGENT_PROFILE_MUTATION_KEY,
});
const creatingConversations = useIsMutating({
mutationKey: CREATE_CONVERSATION_MUTATION_KEY,
});
const isTaskRoute = conversationId?.startsWith("task-") ?? false;
const isSwitching =
isTaskRoute || activatingProfiles > 0 || creatingConversations > 0;
const profiles = agentProfiles?.profiles ?? [];
const isInConversation = Boolean(conversationId);
const currentProfileId = isInConversation
? (conversation?.launched_agent_profile?.agent_profile_id ??
agentProfiles?.active_agent_profile_id ??
null)
: (agentProfiles?.active_agent_profile_id ?? null);
const currentProfileName =
profiles.find((p) => p.id != null && p.id === currentProfileId)?.name ??
null;
const selectProfile = useCallback(
(profile: AgentProfileSummary) => {
if (isTaskRoute || !profile.id || profile.id === currentProfileId) return;
if (!isInConversation) {
activateProfile.mutate(profile.id);
return;
}
const metadata = conversationId
? getStoredConversationMetadata(conversationId)
: null;
const variables: CreateConversationVariables = {
agentProfileId: profile.id,
entryPoint: "blank_conversation_profile_picker",
};
if (conversation?.selected_repository) {
variables.repository = {
name: conversation.selected_repository,
gitProvider: conversation.git_provider ?? "github",
branch: conversation.selected_branch ?? undefined,
};
}
if (conversation?.selected_workspace) {
variables.workingDir = conversation.selected_workspace;
variables.workspaceMode = metadata?.workspace_mode ?? "local_repo";
}
if (metadata?.plugins?.length) {
variables.plugins = metadata.plugins;
}
// mutateAsync, not mutate-scoped callbacks: this hook lives inside the
// tools-menu content, which unmounts as soon as a profile is picked, and
// React Query drops mutate-scoped callbacks on unmount — the replacement
// conversation would be created without ever navigating to it. The
// promise (and the navigate closure) survive the unmount. Errors are
// already surfaced by the global mutation toast; swallow the rejection.
createConversation
.mutateAsync(variables)
.then((data) => navigate(`/conversations/${data.conversation_id}`))
.catch(() => {});
},
[
activateProfile,
conversation,
conversationId,
createConversation,
currentProfileId,
isInConversation,
isTaskRoute,
navigate,
],
);
return {
profiles,
currentProfileId,
currentProfileName,
isInConversation,
isLoading:
isLoadingProfiles ||
isTaskRoute ||
(isInConversation && isLoadingConversation),
isSwitching,
selectProfile,
};
}