refactor(frontend): disable some agent server API until implemented in the server source code (#11476)

This commit is contained in:
Hiep Le 2025-10-23 22:38:18 +07:00 committed by GitHub
parent f3d9faef34
commit dd2a62c992
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 156 additions and 77 deletions

View File

@ -249,7 +249,7 @@ export function ChatInterface() {
<div className="flex justify-between relative">
<div className="flex items-center gap-1">
<ConfirmationModeEnabled />
{totalEvents > 0 && (
{totalEvents > 0 && !isV1Conversation && (
<TrajectoryActions
onPositiveFeedback={() =>
onClickShareFeedbackActionButton("positive")
@ -274,7 +274,7 @@ export function ChatInterface() {
<InteractiveChatBox onSubmit={handleSendMessage} />
</div>
{config?.APP_MODE !== "saas" && (
{config?.APP_MODE !== "saas" && !isV1Conversation && (
<FeedbackModal
isOpen={feedbackModalIsOpen}
onClose={() => setFeedbackModalIsOpen(false)}

View File

@ -24,6 +24,7 @@ import {
import { AgentState } from "#/types/agent-state";
import { getFirstPRUrl } from "#/utils/parse-pr-url";
import MemoryIcon from "#/icons/memory_icon.svg?react";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
const isErrorEvent = (evt: unknown): evt is { error: true; message: string } =>
typeof evt === "object" &&
@ -51,6 +52,11 @@ export const Messages: React.FC<MessagesProps> = React.memo(
const { getOptimisticUserMessage } = useOptimisticUserMessageStore();
const { conversationId } = useConversationId();
const { data: conversation } = useUserConversation(conversationId);
const { data: activeConversation } = useActiveConversation();
// TODO: Hide microagent actions for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = activeConversation?.conversation_version === "V1";
const optimisticUserMessage = getOptimisticUserMessage();
@ -236,7 +242,7 @@ export const Messages: React.FC<MessagesProps> = React.memo(
)}
microagentPRUrl={getMicroagentPRUrlForEvent(message.id)}
actions={
conversation?.selected_repository
conversation?.selected_repository && !isV1Conversation
? [
{
icon: (
@ -259,6 +265,7 @@ export const Messages: React.FC<MessagesProps> = React.memo(
<ChatMessage type="user" message={optimisticUserMessage} />
)}
{conversation?.selected_repository &&
!isV1Conversation &&
showLaunchMicroagentModal &&
selectedEventId &&
createPortal(

View File

@ -14,6 +14,7 @@ import { LoadingMicroagentBody } from "./loading-microagent-body";
import { LoadingMicroagentTextarea } from "./loading-microagent-textarea";
import { useGetMicroagents } from "#/hooks/query/use-get-microagents";
import { Typography } from "#/ui/typography";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
interface LaunchMicroagentModalProps {
onClose: () => void;
@ -32,6 +33,7 @@ export function LaunchMicroagentModal({
}: LaunchMicroagentModalProps) {
const { t } = useTranslation();
const { runtimeActive } = useHandleRuntimeActive();
const { data: conversation } = useActiveConversation();
const { data: prompt, isLoading: promptIsLoading } =
useMicroagentPrompt(eventId);
@ -40,6 +42,15 @@ export function LaunchMicroagentModal({
const [triggers, setTriggers] = React.useState<string[]>([]);
// TODO: Hide LaunchMicroagentModal for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = conversation?.conversation_version === "V1";
// Don't render anything for V1 conversations
if (isV1Conversation) {
return null;
}
const formAction = (formData: FormData) => {
const query = formData.get("query-input")?.toString();
const target = formData.get("target-input")?.toString();

View File

@ -28,17 +28,23 @@ interface ToolsContextMenuProps {
onClose: () => void;
onShowMicroagents: (event: React.MouseEvent<HTMLButtonElement>) => void;
onShowAgentTools: (event: React.MouseEvent<HTMLButtonElement>) => void;
shouldShowAgentTools?: boolean;
}
export function ToolsContextMenu({
onClose,
onShowMicroagents,
onShowAgentTools,
shouldShowAgentTools = true,
}: ToolsContextMenuProps) {
const { t } = useTranslation();
const { data: conversation } = useActiveConversation();
const { providers } = useUserProviders();
// TODO: Hide microagent menu items for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = conversation?.conversation_version === "V1";
const [activeSubmenu, setActiveSubmenu] = useState<"git" | "macros" | null>(
null,
);
@ -64,7 +70,7 @@ export function ToolsContextMenu({
testId="tools-context-menu"
position="top"
alignment="left"
className="left-[-16px] mb-2 bottom-full overflow-visible"
className="left-[-16px] mb-2 bottom-full overflow-visible min-w-[200px]"
>
{/* Git Tools */}
{showGitTools && (
@ -122,33 +128,37 @@ export function ToolsContextMenu({
</div>
</div>
<Divider />
{(!isV1Conversation || shouldShowAgentTools) && <Divider />}
{/* Show Available Microagents */}
<ContextMenuListItem
testId="show-microagents-button"
onClick={onShowMicroagents}
className={contextMenuListItemClassName}
>
<ToolsContextMenuIconText
icon={<RobotIcon width={16} height={16} />}
text={t(I18nKey.CONVERSATION$SHOW_MICROAGENTS)}
className={CONTEXT_MENU_ICON_TEXT_CLASSNAME}
/>
</ContextMenuListItem>
{/* Show Available Microagents - Hidden for V1 conversations */}
{!isV1Conversation && (
<ContextMenuListItem
testId="show-microagents-button"
onClick={onShowMicroagents}
className={contextMenuListItemClassName}
>
<ToolsContextMenuIconText
icon={<RobotIcon width={16} height={16} />}
text={t(I18nKey.CONVERSATION$SHOW_MICROAGENTS)}
className={CONTEXT_MENU_ICON_TEXT_CLASSNAME}
/>
</ContextMenuListItem>
)}
{/* Show Agent Tools and Metadata */}
<ContextMenuListItem
testId="show-agent-tools-button"
onClick={onShowAgentTools}
className={contextMenuListItemClassName}
>
<ToolsContextMenuIconText
icon={<ToolsIcon width={16} height={16} />}
text={t(I18nKey.BUTTON$SHOW_AGENT_TOOLS_AND_METADATA)}
className={CONTEXT_MENU_ICON_TEXT_CLASSNAME}
/>
</ContextMenuListItem>
{/* Show Agent Tools and Metadata - Only show if system message is available */}
{shouldShowAgentTools && (
<ContextMenuListItem
testId="show-agent-tools-button"
onClick={onShowAgentTools}
className={contextMenuListItemClassName}
>
<ToolsContextMenuIconText
icon={<ToolsIcon width={16} height={16} />}
text={t(I18nKey.BUTTON$SHOW_AGENT_TOOLS_AND_METADATA)}
className={CONTEXT_MENU_ICON_TEXT_CLASSNAME}
/>
</ContextMenuListItem>
)}
</ContextMenu>
);
}

View File

@ -23,6 +23,7 @@ export function Tools() {
microagentsModalVisible,
setMicroagentsModalVisible,
systemMessage,
shouldShowAgentTools,
} = useConversationNameContextMenu({
conversationId,
conversationStatus: conversation?.status,
@ -52,6 +53,7 @@ export function Tools() {
onClose={() => setContextMenuOpen(false)}
onShowMicroagents={handleShowMicroagents}
onShowAgentTools={handleShowAgentTools}
shouldShowAgentTools={shouldShowAgentTools}
/>
)}

View File

@ -15,6 +15,7 @@ import { ContextMenuListItem } from "../context-menu/context-menu-list-item";
import { Divider } from "#/ui/divider";
import { I18nKey } from "#/i18n/declaration";
import { ContextMenuIconText } from "../context-menu/context-menu-icon-text";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
interface ConversationCardContextMenuProps {
onClose: () => void;
@ -41,6 +42,11 @@ export function ConversationCardContextMenu({
}: ConversationCardContextMenuProps) {
const { t } = useTranslation();
const ref = useClickOutsideElement<HTMLUListElement>(onClose);
const { data: conversation } = useActiveConversation();
// TODO: Hide microagent menu items for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = conversation?.conversation_version === "V1";
const hasEdit = Boolean(onEdit);
const hasDownload = Boolean(onDownloadViaVSCode);
@ -97,7 +103,7 @@ export function ConversationCardContextMenu({
</ContextMenuListItem>
)}
{onShowMicroagents && (
{onShowMicroagents && !isV1Conversation && (
<ContextMenuListItem
testId="show-microagents-button"
onClick={onShowMicroagents}

View File

@ -11,6 +11,7 @@ import { MicroagentsLoadingState } from "./microagents-loading-state";
import { MicroagentsEmptyState } from "./microagents-empty-state";
import { MicroagentItem } from "./microagent-item";
import { useAgentState } from "#/hooks/use-agent-state";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
interface MicroagentsModalProps {
onClose: () => void;
@ -19,6 +20,7 @@ interface MicroagentsModalProps {
export function MicroagentsModal({ onClose }: MicroagentsModalProps) {
const { t } = useTranslation();
const { curAgentState } = useAgentState();
const { data: conversation } = useActiveConversation();
const [expandedAgents, setExpandedAgents] = useState<Record<string, boolean>>(
{},
);
@ -30,6 +32,15 @@ export function MicroagentsModal({ onClose }: MicroagentsModalProps) {
isRefetching,
} = useConversationMicroagents();
// TODO: Hide MicroagentsModal for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = conversation?.conversation_version === "V1";
// Don't render anything for V1 conversations
if (isV1Conversation) {
return null;
}
const toggleAgent = (agentName: string) => {
setExpandedAgents((prev) => ({
...prev,

View File

@ -6,6 +6,7 @@ import { ContextMenu } from "#/ui/context-menu";
import { ContextMenuListItem } from "../context-menu/context-menu-list-item";
import { Divider } from "#/ui/divider";
import { I18nKey } from "#/i18n/declaration";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
import EditIcon from "#/icons/u-edit.svg?react";
import RobotIcon from "#/icons/u-robot.svg?react";
@ -52,6 +53,11 @@ export function ConversationNameContextMenu({
const { t } = useTranslation();
const ref = useClickOutsideElement<HTMLUListElement>(onClose);
const { data: conversation } = useActiveConversation();
// TODO: Hide microagent menu items for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = conversation?.conversation_version === "V1";
const hasDownload = Boolean(onDownloadViaVSCode);
const hasExport = Boolean(onExportConversation);
@ -85,7 +91,7 @@ export function ConversationNameContextMenu({
{hasTools && <Divider testId="separator-tools" />}
{onShowMicroagents && (
{onShowMicroagents && !isV1Conversation && (
<ContextMenuListItem
testId="show-microagents-button"
onClick={onShowMicroagents}
@ -113,9 +119,11 @@ export function ConversationNameContextMenu({
</ContextMenuListItem>
)}
{(hasExport || hasDownload) && <Divider testId="separator-export" />}
{(hasExport || hasDownload) && !isV1Conversation && (
<Divider testId="separator-export" />
)}
{onExportConversation && (
{onExportConversation && !isV1Conversation && (
<ContextMenuListItem
testId="export-conversation-button"
onClick={onExportConversation}
@ -129,7 +137,7 @@ export function ConversationNameContextMenu({
</ContextMenuListItem>
)}
{onDownloadViaVSCode && (
{onDownloadViaVSCode && !isV1Conversation && (
<ContextMenuListItem
testId="download-vscode-button"
onClick={onDownloadViaVSCode}
@ -143,7 +151,9 @@ export function ConversationNameContextMenu({
</ContextMenuListItem>
)}
{(hasInfo || hasControl) && <Divider testId="separator-info-control" />}
{(hasInfo || hasControl) && !isV1Conversation && (
<Divider testId="separator-info-control" />
)}
{onDisplayCost && (
<ContextMenuListItem

View File

@ -5,6 +5,7 @@ import { I18nKey } from "#/i18n/declaration";
import { Feedback } from "#/api/open-hands.types";
import { useSubmitFeedback } from "#/hooks/mutation/use-submit-feedback";
import { BrandButton } from "../settings/brand-button";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
const FEEDBACK_VERSION = "1.0";
const VIEWER_PAGE = "https://www.all-hands.dev/share";
@ -16,6 +17,7 @@ interface FeedbackFormProps {
export function FeedbackForm({ onClose, polarity }: FeedbackFormProps) {
const { t } = useTranslation();
const { data: conversation } = useActiveConversation();
const copiedToClipboardToast = () => {
hotToast(t(I18nKey.FEEDBACK$PASSWORD_COPIED_MESSAGE), {
@ -60,6 +62,15 @@ export function FeedbackForm({ onClose, polarity }: FeedbackFormProps) {
const { mutate: submitFeedback, isPending } = useSubmitFeedback();
// TODO: Hide FeedbackForm for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = conversation?.conversation_version === "V1";
// Don't render anything for V1 conversations
if (isV1Conversation) {
return null;
}
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event?.preventDefault();
const formData = new FormData(event.currentTarget);

View File

@ -5,6 +5,7 @@ import { cn } from "#/utils/utils";
import { I18nKey } from "#/i18n/declaration";
import { useSubmitConversationFeedback } from "#/hooks/mutation/use-submit-conversation-feedback";
import { ScrollContext } from "#/context/scroll-context";
import { useActiveConversation } from "#/hooks/query/use-active-conversation";
// Global timeout duration in milliseconds
const AUTO_SUBMIT_TIMEOUT = 10000;
@ -23,6 +24,7 @@ export function LikertScale({
initialReason,
}: LikertScaleProps) {
const { t } = useTranslation();
const { data: conversation } = useActiveConversation();
const [selectedRating, setSelectedRating] = useState<number | null>(
initialRating || null,
@ -77,6 +79,56 @@ export function LikertScale({
}
}, [initialReason]);
// Countdown effect
useEffect(() => {
if (countdown > 0 && showReasons && !isSubmitted) {
const timer = setTimeout(() => {
setCountdown(countdown - 1);
}, 1000);
return () => clearTimeout(timer);
}
return () => {};
}, [countdown, showReasons, isSubmitted]);
// Clean up timeout on unmount
useEffect(
() => () => {
if (reasonTimeout) {
clearTimeout(reasonTimeout);
}
},
[reasonTimeout],
);
// Scroll to bottom when component mounts, but only if user is already at the bottom
useEffect(() => {
if (scrollToBottom && autoScroll && !isSubmitted) {
// Small delay to ensure the component is fully rendered
setTimeout(() => {
scrollToBottom();
}, 100);
}
}, [scrollToBottom, autoScroll, isSubmitted]);
// Scroll to bottom when reasons are shown, but only if user is already at the bottom
useEffect(() => {
if (scrollToBottom && autoScroll && showReasons) {
// Small delay to ensure the reasons are fully rendered
setTimeout(() => {
scrollToBottom();
}, 100);
}
}, [scrollToBottom, autoScroll, showReasons]);
// TODO: Hide LikertScale for V1 conversations
// This is a temporary measure and may be re-enabled in the future
const isV1Conversation = conversation?.conversation_version === "V1";
// Don't render anything for V1 conversations
if (isV1Conversation) {
return null;
}
// Submit feedback and disable the component
const submitFeedback = (rating: number, reason?: string) => {
submitConversationFeedback(
@ -137,47 +189,6 @@ export function LikertScale({
}
};
// Countdown effect
useEffect(() => {
if (countdown > 0 && showReasons && !isSubmitted) {
const timer = setTimeout(() => {
setCountdown(countdown - 1);
}, 1000);
return () => clearTimeout(timer);
}
return () => {};
}, [countdown, showReasons, isSubmitted]);
// Clean up timeout on unmount
useEffect(
() => () => {
if (reasonTimeout) {
clearTimeout(reasonTimeout);
}
},
[reasonTimeout],
);
// Scroll to bottom when component mounts, but only if user is already at the bottom
useEffect(() => {
if (scrollToBottom && autoScroll && !isSubmitted) {
// Small delay to ensure the component is fully rendered
setTimeout(() => {
scrollToBottom();
}, 100);
}
}, [scrollToBottom, autoScroll, isSubmitted]);
// Scroll to bottom when reasons are shown, but only if user is already at the bottom
useEffect(() => {
if (scrollToBottom && autoScroll && showReasons) {
// Small delay to ensure the reasons are fully rendered
setTimeout(() => {
scrollToBottom();
}, 100);
}
}, [scrollToBottom, autoScroll, showReasons]);
// Helper function to get button class based on state
const getButtonClass = (rating: number) => {
if (isSubmitted) {

View File

@ -10,6 +10,7 @@ type SubmitFeedbackArgs = {
export const useSubmitFeedback = () => {
const { conversationId } = useConversationId();
return useMutation({
mutationFn: ({ feedback }: SubmitFeedbackArgs) =>
ConversationService.submitFeedback(conversationId, feedback),

View File

@ -4,7 +4,6 @@ import { useConversationId } from "../use-conversation-id";
export const useMicroagentPrompt = (eventId: number) => {
const { conversationId } = useConversationId();
return useQuery({
queryKey: ["memory", "prompt", conversationId, eventId],
queryFn: () =>