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