File size: 3,203 Bytes
9b906ea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { CustomChatInput } from "./custom-chat-input";
import { useBtwInterceptor } from "#/hooks/chat/use-btw-interceptor";
import { useGoalInterceptor } from "#/hooks/chat/use-goal-interceptor";
import { useModelInterceptor } from "#/hooks/chat/use-model-interceptor";
import { usePlanModeInterceptor } from "#/hooks/chat/use-plan-mode-interceptor";
import { useChatAttachmentUpload } from "#/hooks/chat/use-chat-attachment-upload";
import { AgentState } from "#/types/agent-state";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
import { useOptionalConversationId } from "#/hooks/use-conversation-id";
import { GitControlBar } from "./git-control-bar";
import { useConversationStore } from "#/stores/conversation-store";
import { useAgentState } from "#/hooks/use-agent-state";
import { useSubConversationTaskPolling } from "#/hooks/query/use-sub-conversation-task-polling";
import { partitionImagesForUpload } from "#/components/features/chat/utils/chat-input.utils";
import { isTaskPolling } from "#/utils/utils";

interface InteractiveChatBoxProps {
  onSubmit: (message: string, images: File[], files: File[]) => void;
  disabled?: boolean;
  hasStartedConversation?: boolean;
}

export function InteractiveChatBox({
  onSubmit,
  disabled = false,
  hasStartedConversation,
}: InteractiveChatBoxProps) {
  const {
    images,
    files,
    imagesMarkedUploadAsFile,
    clearAllFiles,
    subConversationTaskId,
  } = useConversationStore();
  const { curAgentState } = useAgentState();
  const { data: conversation } = useActiveConversation();
  const { conversationId: routeConversationId } = useOptionalConversationId();
  const conversationId = routeConversationId ?? conversation?.id ?? null;

  const { taskStatus: subConversationTaskStatus } =
    useSubConversationTaskPolling(
      subConversationTaskId,
      conversation?.id || null,
    );

  const { handleUpload } = useChatAttachmentUpload();

  const handleAfterGoal = useBtwInterceptor(conversationId, (message) => {
    const { imagesToEmbed, imagesAsFiles } = partitionImagesForUpload(
      images,
      imagesMarkedUploadAsFile,
    );
    onSubmit(message, imagesToEmbed, [...files, ...imagesAsFiles]);
    clearAllFiles();
  });
  const handleAfterPlanMode = usePlanModeInterceptor(
    conversationId,
    curAgentState,
    handleAfterGoal,
  );
  const handleAfterModel = useGoalInterceptor(
    conversationId,
    handleAfterPlanMode,
  );
  const handleSubmit = useModelInterceptor(conversationId, handleAfterModel);

  const handleSuggestionsClick = (suggestion: string) => {
    handleSubmit(suggestion);
  };

  const isDisabled =
    disabled ||
    curAgentState === AgentState.AWAITING_USER_CONFIRMATION ||
    isTaskPolling(subConversationTaskStatus);

  return (
    <div data-testid="interactive-chat-box">
      <CustomChatInput
        disabled={isDisabled}
        isNewConversationPending={disabled}
        hasStartedConversation={hasStartedConversation}
        onSubmit={handleSubmit}
        onFilesPaste={handleUpload}
      />
      <div className="mt-3 pb-3">
        <GitControlBar onSuggestionsClick={handleSuggestionsClick} />
      </div>
    </div>
  );
}