mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-12 20:57:42 +02:00
[Haik]: refactor: restructure frontend component hierarchy — move OnboardingModal into OnboardingModal/ with ProviderStep, ToolsStep, and useOnboarding submodules; move OpenSwarmThread from thread/ into OpenSwarmThread/ with AssistantMessage, BranchPicker, MessageActions, UserMessage components and utils; split AgentCardCollapsed into AgentCardCollapsed/ extracting GoogleServiceIcon, getToolDisplayName, and summarizeToolInput into components/; move approval-card to ApprovalCard (PascalCase) with ApprovalCard.tsx, schema.ts, _adapter.tsx, and README.md; update import paths in AgentChat.tsx, CompactActionablePill, ExpandedCard, BrowserCard, AgentCard, and approval-utils; remove re-exports from approval-tools.tsx in favor of direct imports; replace aliased component names (ApprovalBar → ApprovalRouter, BatchApprovalBar → BatchApprovalWrapper)
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -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<{
|
||||
</Typography>
|
||||
)}
|
||||
{group.approvals.length > 1 ? (
|
||||
<BatchApprovalBar
|
||||
<BatchApprovalWrapper
|
||||
requests={group.approvals}
|
||||
onApprove={onApprove}
|
||||
onDeny={onDeny}
|
||||
/>
|
||||
) : (
|
||||
group.approvals.map((req) => (
|
||||
<ApprovalBar
|
||||
<ApprovalRouter
|
||||
key={req.id}
|
||||
request={req}
|
||||
onApprove={onApprove}
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Box, Modal } from '@mui/material';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { useOnboarding } from './useOnboarding';
|
||||
import ProviderStep from './ProviderStep';
|
||||
import ToolsStep from './ToolsStep';
|
||||
import { useOnboarding } from './components/useOnboarding';
|
||||
import ProviderStep from './components/ProviderStep';
|
||||
import ToolsStep from './components/ToolsStep';
|
||||
|
||||
const OnboardingModal: React.FC = () => {
|
||||
const c = useClaudeTokens();
|
||||
@@ -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';
|
||||
|
||||
+4
-11
@@ -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<string | undefined>(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;
|
||||
+1
-1
@@ -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 = () => (
|
||||
<ActionBarPrimitive.Root
|
||||
+1
-1
@@ -7,7 +7,7 @@ import {
|
||||
import { UserMessageAttachments } from '@/components/assistant-ui/attachment';
|
||||
import { useAppSelector } from '@/shared/hooks';
|
||||
import type { AgentMessage } from '@/shared/state/agentsSlice';
|
||||
import { useSessionId } from './OpenSwarmThread';
|
||||
import { useSessionId } from '../utils';
|
||||
import { UserActionBar } from './MessageActions';
|
||||
import { BranchPicker } from './BranchPicker';
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
export const SessionIdContext = createContext<string | undefined>(undefined);
|
||||
export const useSessionId = () => useContext(SessionIdContext);
|
||||
|
||||
export const BranchChatContext = createContext<
|
||||
((newSessionId: string) => void) | undefined
|
||||
>(undefined);
|
||||
export const useBranchChatCallback = () => useContext(BranchChatContext);
|
||||
@@ -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)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+5
-4
@@ -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<AgentCardCollapsedProps> = ({
|
||||
|
||||
{hasPending && pendingReq && pendingReq.tool_name === 'AskUserQuestion' ? (
|
||||
<Box onClick={(e) => e.stopPropagation()}>
|
||||
<QuestionForm
|
||||
<ToolQuestion
|
||||
compact
|
||||
request={pendingReq}
|
||||
onApprove={(requestId, updatedInput) =>
|
||||
+7
@@ -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;
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
import { parseMcpToolName } from '@/app/pages/AgentChat/toolkit/approval-utils';
|
||||
|
||||
export function summarizeToolInput(toolName: string, toolInput: Record<string, any>): 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user