File size: 4,450 Bytes
63522a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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,
  };
}