From 1c0b886052c51c7906add867e39b9521dfbc27ae Mon Sep 17 00:00:00 2001 From: haikdc Date: Sat, 18 Apr 2026 14:42:41 -0700 Subject: [PATCH] =?UTF-8?q?[Haik]:=20refactor:=20restructure=20frontend=20?= =?UTF-8?q?component=20hierarchy=20=E2=80=94=20move=20OnboardingModal=20in?= =?UTF-8?q?to=20OnboardingModal/=20with=20ProviderStep,=20ToolsStep,=20and?= =?UTF-8?q?=20useOnboarding=20submodules;=20move=20OpenSwarmThread=20from?= =?UTF-8?q?=20thread/=20into=20OpenSwarmThread/=20with=20AssistantMessage,?= =?UTF-8?q?=20BranchPicker,=20MessageActions,=20UserMessage=20components?= =?UTF-8?q?=20and=20utils;=20split=20AgentCardCollapsed=20into=20AgentCard?= =?UTF-8?q?Collapsed/=20extracting=20GoogleServiceIcon,=20getToolDisplayNa?= =?UTF-8?q?me,=20and=20summarizeToolInput=20into=20components/;=20move=20a?= =?UTF-8?q?pproval-card=20to=20ApprovalCard=20(PascalCase)=20with=20Approv?= =?UTF-8?q?alCard.tsx,=20schema.ts,=20=5Fadapter.tsx,=20and=20README.md;?= =?UTF-8?q?=20update=20import=20paths=20in=20AgentChat.tsx,=20CompactActio?= =?UTF-8?q?nablePill,=20ExpandedCard,=20BrowserCard,=20AgentCard,=20and=20?= =?UTF-8?q?approval-utils;=20remove=20re-exports=20from=20approval-tools.t?= =?UTF-8?q?sx=20in=20favor=20of=20direct=20imports;=20replace=20aliased=20?= =?UTF-8?q?component=20names=20(ApprovalBar=20=E2=86=92=20ApprovalRouter,?= =?UTF-8?q?=20BatchApprovalBar=20=E2=86=92=20BatchApprovalWrapper)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DynamicIsland/CompactActionablePill.tsx | 3 +- .../components/DynamicIsland/ExpandedCard.tsx | 6 +-- .../{ => OnboardingModal}/OnboardingModal.tsx | 6 +-- .../components}/ProviderStep.tsx | 0 .../components}/ToolsStep.tsx | 0 .../components}/useOnboarding.ts | 0 .../src/app/pages/AgentChat/AgentChat.tsx | 2 +- .../OpenSwarmThread.tsx | 15 ++----- .../components}/AssistantMessage.tsx | 0 .../components}/BranchPicker.tsx | 0 .../components}/MessageActions.tsx | 2 +- .../components}/UserMessage.tsx | 2 +- .../pages/AgentChat/OpenSwarmThread/utils.ts | 9 ++++ .../AgentChat/toolkit/approval-tools.tsx | 9 +--- .../AgentChat/toolkit/approval-utils.tsx | 3 +- .../cards/AgentCard/AgentCard.tsx | 2 +- .../AgentCardCollapsed.tsx | 9 ++-- .../components/GoogleServiceIcon.tsx | 0 .../components/getToolDisplayName.ts | 7 +++ .../components/summarizeToolInput.ts | 43 +++++++++++++++++++ .../cards/BrowserCard/BrowserCard.tsx | 2 +- .../ApprovalCard.tsx} | 0 .../{approval-card => ApprovalCard}/README.md | 0 .../_adapter.tsx | 0 .../{approval-card => ApprovalCard}/schema.ts | 0 25 files changed, 84 insertions(+), 36 deletions(-) rename frontend/src/app/components/{ => OnboardingModal}/OnboardingModal.tsx (89%) rename frontend/src/app/components/{ => OnboardingModal/components}/ProviderStep.tsx (100%) rename frontend/src/app/components/{ => OnboardingModal/components}/ToolsStep.tsx (100%) rename frontend/src/app/components/{ => OnboardingModal/components}/useOnboarding.ts (100%) rename frontend/src/app/pages/AgentChat/{thread => OpenSwarmThread}/OpenSwarmThread.tsx (87%) rename frontend/src/app/pages/AgentChat/{thread => OpenSwarmThread/components}/AssistantMessage.tsx (100%) rename frontend/src/app/pages/AgentChat/{thread => OpenSwarmThread/components}/BranchPicker.tsx (100%) rename frontend/src/app/pages/AgentChat/{thread => OpenSwarmThread/components}/MessageActions.tsx (97%) rename frontend/src/app/pages/AgentChat/{thread => OpenSwarmThread/components}/UserMessage.tsx (99%) create mode 100644 frontend/src/app/pages/AgentChat/OpenSwarmThread/utils.ts rename frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/{ => AgentCardCollapsed}/AgentCardCollapsed.tsx (96%) rename frontend/src/app/{ => pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed}/components/GoogleServiceIcon.tsx (100%) create mode 100644 frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/getToolDisplayName.ts create mode 100644 frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/summarizeToolInput.ts rename frontend/src/components/tool-ui/{approval-card/approval-card.tsx => ApprovalCard/ApprovalCard.tsx} (100%) rename frontend/src/components/tool-ui/{approval-card => ApprovalCard}/README.md (100%) rename frontend/src/components/tool-ui/{approval-card => ApprovalCard}/_adapter.tsx (100%) rename frontend/src/components/tool-ui/{approval-card => ApprovalCard}/schema.ts (100%) diff --git a/frontend/src/app/components/DynamicIsland/CompactActionablePill.tsx b/frontend/src/app/components/DynamicIsland/CompactActionablePill.tsx index 97a84d82..8d6cca25 100644 --- a/frontend/src/app/components/DynamicIsland/CompactActionablePill.tsx +++ b/frontend/src/app/components/DynamicIsland/CompactActionablePill.tsx @@ -7,7 +7,8 @@ import CloseIcon from '@mui/icons-material/Close'; import CheckIcon from '@mui/icons-material/Check'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { motion } from 'framer-motion'; -import { parseMcpToolName, useMcpToolMeta, getToolIcon } from '@/app/pages/AgentChat/toolkit/approval-tools'; +import { parseMcpToolName, getToolIcon } from '@/app/pages/AgentChat/toolkit/approval-utils'; +import { useMcpToolMeta } from '@/app/pages/AgentChat/toolkit/approval-tools'; import { SPRING_BOUNCE } from './islandTypes'; import type { ClaudeTokens } from './islandTypes'; import type { ApprovalRequest } from '@/shared/state/agentsSlice'; diff --git a/frontend/src/app/components/DynamicIsland/ExpandedCard.tsx b/frontend/src/app/components/DynamicIsland/ExpandedCard.tsx index bda2cfb0..b35ba4b9 100644 --- a/frontend/src/app/components/DynamicIsland/ExpandedCard.tsx +++ b/frontend/src/app/components/DynamicIsland/ExpandedCard.tsx @@ -4,7 +4,7 @@ import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; import CloseIcon from '@mui/icons-material/Close'; import { motion } from 'framer-motion'; -import { ApprovalRouter as ApprovalBar, BatchApprovalWrapper as BatchApprovalBar } from '@/app/pages/AgentChat/toolkit/approval-tools'; +import { ApprovalRouter, BatchApprovalWrapper } from '@/app/pages/AgentChat/toolkit/approval-tools'; import { AgentStatusRow } from './AgentStatusRow'; import { CompletedAgentsList } from './CompletedAgentsList'; import type { ClaudeTokens, SessionApprovalGroup, TrackedAgent } from './islandTypes'; @@ -144,14 +144,14 @@ export const ExpandedCard: React.FC<{ )} {group.approvals.length > 1 ? ( - ) : ( group.approvals.map((req) => ( - { const c = useClaudeTokens(); diff --git a/frontend/src/app/components/ProviderStep.tsx b/frontend/src/app/components/OnboardingModal/components/ProviderStep.tsx similarity index 100% rename from frontend/src/app/components/ProviderStep.tsx rename to frontend/src/app/components/OnboardingModal/components/ProviderStep.tsx diff --git a/frontend/src/app/components/ToolsStep.tsx b/frontend/src/app/components/OnboardingModal/components/ToolsStep.tsx similarity index 100% rename from frontend/src/app/components/ToolsStep.tsx rename to frontend/src/app/components/OnboardingModal/components/ToolsStep.tsx diff --git a/frontend/src/app/components/useOnboarding.ts b/frontend/src/app/components/OnboardingModal/components/useOnboarding.ts similarity index 100% rename from frontend/src/app/components/useOnboarding.ts rename to frontend/src/app/components/OnboardingModal/components/useOnboarding.ts diff --git a/frontend/src/app/pages/AgentChat/AgentChat.tsx b/frontend/src/app/pages/AgentChat/AgentChat.tsx index 0a64e154..1386c127 100644 --- a/frontend/src/app/pages/AgentChat/AgentChat.tsx +++ b/frontend/src/app/pages/AgentChat/AgentChat.tsx @@ -5,7 +5,7 @@ import { AssistantRuntimeProvider, useAui, Tools } from '@assistant-ui/react'; import { ApprovalRouter, BatchApprovalWrapper } from './toolkit/approval-tools'; import ChatHeader from './ChatHeader'; import MessageQueue from './MessageQueue'; -import OpenSwarmThread from './thread/OpenSwarmThread'; +import OpenSwarmThread from './OpenSwarmThread/OpenSwarmThread'; import ChatInput from './ChatInput/ChatInput'; import { useAgentChat } from './hooks/useAgentChat'; import { useOpenSwarmRuntime, type ComposerExtras, type DispatchableMessage } from './runtime/useOpenSwarmRuntime'; diff --git a/frontend/src/app/pages/AgentChat/thread/OpenSwarmThread.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/OpenSwarmThread.tsx similarity index 87% rename from frontend/src/app/pages/AgentChat/thread/OpenSwarmThread.tsx rename to frontend/src/app/pages/AgentChat/OpenSwarmThread/OpenSwarmThread.tsx index bdaba868..3faf14bc 100644 --- a/frontend/src/app/pages/AgentChat/thread/OpenSwarmThread.tsx +++ b/frontend/src/app/pages/AgentChat/OpenSwarmThread/OpenSwarmThread.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, type FC, type ReactNode } from 'react'; +import { type FC, type ReactNode } from 'react'; import { ThreadPrimitive, MessagePrimitive, @@ -9,16 +9,9 @@ import { ArrowDownIcon } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { TooltipProvider } from '@/components/ui/tooltip'; import { TooltipIconButton } from '@/components/assistant-ui/tooltip-icon-button'; -import { UserMessage } from './UserMessage'; -import { AssistantMessage } from './AssistantMessage'; - -const SessionIdContext = createContext(undefined); -export const useSessionId = () => useContext(SessionIdContext); - -const BranchChatContext = createContext< - ((newSessionId: string) => void) | undefined ->(undefined); -export const useBranchChatCallback = () => useContext(BranchChatContext); +import { UserMessage } from './components/UserMessage'; +import { AssistantMessage } from './components/AssistantMessage'; +import { SessionIdContext, BranchChatContext } from './utils'; interface OpenSwarmThreadProps { sessionId?: string; diff --git a/frontend/src/app/pages/AgentChat/thread/AssistantMessage.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/AssistantMessage.tsx similarity index 100% rename from frontend/src/app/pages/AgentChat/thread/AssistantMessage.tsx rename to frontend/src/app/pages/AgentChat/OpenSwarmThread/components/AssistantMessage.tsx diff --git a/frontend/src/app/pages/AgentChat/thread/BranchPicker.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/BranchPicker.tsx similarity index 100% rename from frontend/src/app/pages/AgentChat/thread/BranchPicker.tsx rename to frontend/src/app/pages/AgentChat/OpenSwarmThread/components/BranchPicker.tsx diff --git a/frontend/src/app/pages/AgentChat/thread/MessageActions.tsx b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/MessageActions.tsx similarity index 97% rename from frontend/src/app/pages/AgentChat/thread/MessageActions.tsx rename to frontend/src/app/pages/AgentChat/OpenSwarmThread/components/MessageActions.tsx index 305d8100..56231b0e 100644 --- a/frontend/src/app/pages/AgentChat/thread/MessageActions.tsx +++ b/frontend/src/app/pages/AgentChat/OpenSwarmThread/components/MessageActions.tsx @@ -17,7 +17,7 @@ import { setActiveSession, } from '@/shared/state/agentsSlice'; import { DUPLICATE_SESSION } from '@/shared/backend-bridge/apps/agents'; -import { useSessionId, useBranchChatCallback } from './OpenSwarmThread'; +import { useSessionId, useBranchChatCallback } from '../utils'; export const UserActionBar: FC = () => ( (undefined); +export const useSessionId = () => useContext(SessionIdContext); + +export const BranchChatContext = createContext< + ((newSessionId: string) => void) | undefined +>(undefined); +export const useBranchChatCallback = () => useContext(BranchChatContext); \ No newline at end of file diff --git a/frontend/src/app/pages/AgentChat/toolkit/approval-tools.tsx b/frontend/src/app/pages/AgentChat/toolkit/approval-tools.tsx index 37593260..46fbe4f9 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/approval-tools.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/approval-tools.tsx @@ -1,6 +1,6 @@ import React, { useMemo, useCallback } from 'react'; import type { Toolkit } from '@assistant-ui/react'; -import { ApprovalCard } from '@/components/tool-ui/approval-card/approval-card'; +import { ApprovalCard } from '@/components/tool-ui/ApprovalCard/ApprovalCard'; import type { ApprovalRequest } from '@/shared/state/agentsSlice'; import { useAppSelector } from '@/shared/hooks'; import type { ToolDefinition } from '@/shared/state/toolsSlice'; @@ -12,13 +12,6 @@ import { } from './approval-utils'; import { ToolQuestion } from './approval-question'; -// Re-exports so external consumers can import everything from this file -export { - parseMcpToolName, - getToolIcon, -} from './approval-utils'; -export { ToolQuestion } from './approval-question'; - // --------------------------------------------------------------------------- // useMcpToolMeta (React hook — lives here alongside other component code) // --------------------------------------------------------------------------- diff --git a/frontend/src/app/pages/AgentChat/toolkit/approval-utils.tsx b/frontend/src/app/pages/AgentChat/toolkit/approval-utils.tsx index 394530f4..bbf62ed8 100644 --- a/frontend/src/app/pages/AgentChat/toolkit/approval-utils.tsx +++ b/frontend/src/app/pages/AgentChat/toolkit/approval-utils.tsx @@ -1,6 +1,7 @@ import React from 'react'; import type { ReactNode } from 'react'; -import type { MetadataItem } from '@/components/tool-ui/approval-card'; +// TODO: what is this even supposed to try and import/use ??? +import type { MetadataItem } from '@/components/tool-ui/ApprovalCard/schema'; import { Terminal, FileText, FilePen, Search, MessageCircleQuestion, Wrench, diff --git a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/AgentCard.tsx b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/AgentCard.tsx index 253f0049..47989b6b 100644 --- a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/AgentCard.tsx +++ b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/AgentCard.tsx @@ -16,7 +16,7 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext'; import { useOverlayScrollPassthrough } from '../shared/useOverlayScrollPassthrough'; import { type ResizeDir, DRAG_THRESHOLD, CURSOR_MAP, HANDLE_DEFS } from '../shared/cardLayoutConstants'; import CardGlowOverlay from './components/CardGlowOverlay'; -import AgentCardCollapsed from './components/AgentCardCollapsed'; +import AgentCardCollapsed from './components/AgentCardCollapsed/AgentCardCollapsed'; import { formatDuration, getStatusColors, getPreviewContent } from './components/agentCardUtils'; interface Props { diff --git a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed.tsx b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/AgentCardCollapsed.tsx similarity index 96% rename from frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed.tsx rename to frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/AgentCardCollapsed.tsx index 90c5316b..619c22e1 100644 --- a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed.tsx +++ b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/AgentCardCollapsed.tsx @@ -12,10 +12,11 @@ import TerminalIcon from '@mui/icons-material/Terminal'; import { AgentSession } from '@/shared/state/agentsSlice'; import { HANDLE_APPROVAL } from '@/shared/backend-bridge/apps/agents'; import { useAppDispatch } from '@/shared/hooks'; -import { ToolQuestion as QuestionForm } from '@/app/pages/AgentChat/toolkit/approval-tools'; +import { ToolQuestion } from '@/app/pages/AgentChat/toolkit/approval-question'; import { parseMcpToolName } from '@/app/pages/AgentChat/toolkit/approval-utils'; -import GoogleServiceIcon from '@/app/components/GoogleServiceIcon'; -import { summarizeToolInput, getToolDisplayName } from './agentCardUtils'; +import GoogleServiceIcon from './components/GoogleServiceIcon'; +import { summarizeToolInput } from './components/summarizeToolInput'; +import { getToolDisplayName } from './components/getToolDisplayName'; interface AgentCardCollapsedProps { session: AgentSession; @@ -75,7 +76,7 @@ const AgentCardCollapsed: React.FC = ({ {hasPending && pendingReq && pendingReq.tool_name === 'AskUserQuestion' ? ( e.stopPropagation()}> - diff --git a/frontend/src/app/components/GoogleServiceIcon.tsx b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/GoogleServiceIcon.tsx similarity index 100% rename from frontend/src/app/components/GoogleServiceIcon.tsx rename to frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/GoogleServiceIcon.tsx diff --git a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/getToolDisplayName.ts b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/getToolDisplayName.ts new file mode 100644 index 00000000..30a17800 --- /dev/null +++ b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/getToolDisplayName.ts @@ -0,0 +1,7 @@ +import { parseMcpToolName } from '@/app/pages/AgentChat/toolkit/approval-utils'; + +export function getToolDisplayName(toolName: string): string { + const mcp = parseMcpToolName(toolName); + if (mcp.isMcp) return mcp.displayName; + return toolName; +} \ No newline at end of file diff --git a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/summarizeToolInput.ts b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/summarizeToolInput.ts new file mode 100644 index 00000000..bd4872a3 --- /dev/null +++ b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/AgentCard/components/AgentCardCollapsed/components/summarizeToolInput.ts @@ -0,0 +1,43 @@ +import { parseMcpToolName } from '@/app/pages/AgentChat/toolkit/approval-utils'; + +export function summarizeToolInput(toolName: string, toolInput: Record): string { + const mcp = parseMcpToolName(toolName); + if (mcp.isMcp) { + const keys = Object.keys(toolInput || {}); + if (keys.length === 0) return ''; + if (keys.length === 1) { + const v = toolInput[keys[0]]; + const s = typeof v === 'string' ? v : JSON.stringify(v); + return s.length > 60 ? s.slice(0, 60) + '…' : s; + } + return keys.slice(0, 3).map((k) => { + const v = toolInput[k]; + const s = typeof v === 'string' ? v : JSON.stringify(v); + return `${k}: ${s.length > 30 ? s.slice(0, 30) + '…' : s}`; + }).join(' '); + } + switch (toolName) { + case 'Bash': + return toolInput.command || '(command)'; + case 'Read': + return toolInput.file_path || toolInput.path || '(file)'; + case 'Write': + case 'Edit': + return toolInput.file_path || toolInput.path || '(file)'; + case 'Grep': + return `/${toolInput.pattern || ''}/${toolInput.path ? ` in ${toolInput.path}` : ''}`; + case 'Glob': + return toolInput.glob_pattern || toolInput.pattern || '(pattern)'; + case 'AskUserQuestion': { + const questions = toolInput.questions; + if (Array.isArray(questions) && questions.length > 0) { + return questions[0].question || questions[0].prompt || questions[0].text || 'Question pending'; + } + return 'Question pending'; + } + default: { + return toolInput.command || toolInput.file_path || toolInput.path || toolInput.query + || JSON.stringify(toolInput).slice(0, 60); + } + } +} \ No newline at end of file diff --git a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/BrowserCard/BrowserCard.tsx b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/BrowserCard/BrowserCard.tsx index c14552aa..3068bb65 100644 --- a/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/BrowserCard/BrowserCard.tsx +++ b/frontend/src/app/pages/Dashboard/DashboardCanvas/cards/BrowserCard/BrowserCard.tsx @@ -8,7 +8,7 @@ import { useBrowserActivity } from '@/shared/useBrowserActivity'; import { resolveInput, isGoogleSearch } from '@/shared/resolveUrl'; import BrowserAgentOverlay from './components/BrowserAgentOverlay/BrowserAgentOverlay'; import { useOverlayScrollPassthrough } from '../shared/useOverlayScrollPassthrough'; -import { useElementSelection } from '@/app/components/ElementSelectionContext'; +import { useElementSelection } from '@/app/pages/Dashboard/_shared/element_selection/useElementSelection'; import { type ResizeDir, CURSOR_MAP, HANDLE_DEFS, DRAG_THRESHOLD } from '../shared/cardLayoutConstants'; import { useWebviewLifecycle, isElectron, chromeUserAgent, webviewPreloadPath, type WebviewElement } from './hooks/useWebviewLifecycle'; import type { TabLocalState } from './TabLocalState'; diff --git a/frontend/src/components/tool-ui/approval-card/approval-card.tsx b/frontend/src/components/tool-ui/ApprovalCard/ApprovalCard.tsx similarity index 100% rename from frontend/src/components/tool-ui/approval-card/approval-card.tsx rename to frontend/src/components/tool-ui/ApprovalCard/ApprovalCard.tsx diff --git a/frontend/src/components/tool-ui/approval-card/README.md b/frontend/src/components/tool-ui/ApprovalCard/README.md similarity index 100% rename from frontend/src/components/tool-ui/approval-card/README.md rename to frontend/src/components/tool-ui/ApprovalCard/README.md diff --git a/frontend/src/components/tool-ui/approval-card/_adapter.tsx b/frontend/src/components/tool-ui/ApprovalCard/_adapter.tsx similarity index 100% rename from frontend/src/components/tool-ui/approval-card/_adapter.tsx rename to frontend/src/components/tool-ui/ApprovalCard/_adapter.tsx diff --git a/frontend/src/components/tool-ui/approval-card/schema.ts b/frontend/src/components/tool-ui/ApprovalCard/schema.ts similarity index 100% rename from frontend/src/components/tool-ui/approval-card/schema.ts rename to frontend/src/components/tool-ui/ApprovalCard/schema.ts