mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[Haik]: cleanup: remove dead code and tighten TypeScript types across frontend — delete unused AutoRunLog.tsx, LogEntry.tsx, and clearClipboard(); remove SendMessagePayload, GenerateGroupMetaPayload, SearchHistoryParams, and summarizeToolInput from shared types and agentCardUtils; replace Record<string, any> with Record<string, unknown> in agentsTypes.ts and dashboardClipboard.ts; type getStatusColors param as ClaudeTokens; relocate richEditorUtils.ts from app/components to RichPromptEditor and update imports; narrow summarizeMessage export to module-private in BrowserAgentOverlay; wrap session-change state resets in queueMicrotask to avoid render-during-render warnings
This commit is contained in:
+3
-50
@@ -1,5 +1,6 @@
|
||||
import { AgentSession } from '@/shared/state/agentsSlice';
|
||||
import { parseMcpToolName } from '@/app/pages/AgentChat/toolkit/approvalToolkit/utils';
|
||||
import { ClaudeTokens } from '@/shared/styles/claudeTokens';
|
||||
import { getToolDisplayName } from './AgentCardCollapsed/components/getToolDisplayName';
|
||||
|
||||
export function formatDuration(createdAt: string, closedAt?: string | null, status?: string): string {
|
||||
const start = new Date(createdAt).getTime();
|
||||
@@ -13,55 +14,7 @@ export function formatDuration(createdAt: string, closedAt?: string | null, stat
|
||||
return `${hours}h ${minutes % 60}m`;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getToolDisplayName(toolName: string): string {
|
||||
const mcp = parseMcpToolName(toolName);
|
||||
if (mcp.isMcp) return mcp.displayName;
|
||||
return toolName;
|
||||
}
|
||||
|
||||
export function getStatusColors(c: Record<string, any>): Record<string, { color: string; bg: string }> {
|
||||
export function getStatusColors(c: ClaudeTokens): Record<string, { color: string; bg: string }> {
|
||||
return {
|
||||
running: { color: c.status.success, bg: c.status.successBg },
|
||||
waiting_approval: { color: c.status.warning, bg: c.status.warningBg },
|
||||
|
||||
+6
-4
@@ -17,7 +17,7 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { OverlayEntry } from './OverlayEntry';
|
||||
import OverlayActionLog from './OverlayActionLog';
|
||||
|
||||
export function summarizeMessage(msg: AgentMessage): OverlayEntry {
|
||||
function summarizeMessage(msg: AgentMessage): OverlayEntry {
|
||||
if (msg.role === 'assistant' && typeof msg.content === 'string') {
|
||||
const trimmed = msg.content.trim();
|
||||
if (!trimmed) return { type: 'skip', text: '' };
|
||||
@@ -80,9 +80,11 @@ const BrowserAgentOverlay: React.FC<Props> = ({ session, browserWidth, browserHe
|
||||
useEffect(() => {
|
||||
if (session.session_id !== prevSessionId.current) {
|
||||
prevSessionId.current = session.session_id;
|
||||
setFadeOut(false);
|
||||
setHidden(false);
|
||||
setConfirmStop(false);
|
||||
queueMicrotask(() => {
|
||||
setFadeOut(false);
|
||||
setHidden(false);
|
||||
setConfirmStop(false);
|
||||
});
|
||||
}
|
||||
}, [session.session_id]);
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
||||
import { CommandPickerItem } from '@/app/components/CommandPicker';
|
||||
import { CommandPickerItem } from './CommandPicker/components/commandPickerTypes';
|
||||
import {
|
||||
SKILL_PILL_ATTR,
|
||||
AttachedSkill,
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
detectEditorTrigger,
|
||||
TriggerState,
|
||||
EMPTY_TRIGGER,
|
||||
} from '@/app/components/richEditorUtils';
|
||||
} from './richEditorUtils';
|
||||
import { useAppSelector } from '@/shared/hooks';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { RichPromptEditorProps, LINE_HEIGHT, FONT_SIZE } from './richPromptEditorTypes';
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
|
||||
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
|
||||
import { AgentMessage } from '@/shared/state/agentsSlice';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { LogEntry } from './LogEntry';
|
||||
|
||||
interface AutoRunLogProps {
|
||||
messages: AgentMessage[];
|
||||
status: string | null;
|
||||
logEndRef: React.RefObject<HTMLDivElement | null>;
|
||||
c: ReturnType<typeof useClaudeTokens>;
|
||||
}
|
||||
|
||||
export const AutoRunLog: React.FC<AutoRunLogProps> = ({ messages, status, logEndRef, c }) => {
|
||||
const isRunning = status === 'running' || status === 'waiting_approval';
|
||||
const isDone = status === 'completed' || status === 'stopped';
|
||||
const isError = status === 'error';
|
||||
|
||||
return (
|
||||
<Box sx={{
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
border: `1px solid ${c.border.subtle}`,
|
||||
borderRadius: 1,
|
||||
overflow: 'hidden',
|
||||
}}>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
px: 1.5,
|
||||
py: 0.75,
|
||||
bgcolor: c.bg.secondary,
|
||||
borderBottom: `1px solid ${c.border.subtle}`,
|
||||
flexShrink: 0,
|
||||
}}>
|
||||
{isRunning && <CircularProgress size={12} sx={{ color: '#f59e0b' }} />}
|
||||
{isDone && <CheckCircleOutlineIcon sx={{ fontSize: 14, color: c.accent.primary }} />}
|
||||
{isError && <ErrorOutlineIcon sx={{ fontSize: 14, color: '#ef4444' }} />}
|
||||
<Typography sx={{ fontSize: '0.72rem', fontWeight: 600, color: c.text.muted }}>
|
||||
{isRunning ? 'Agent running…' : isDone ? 'Agent completed' : isError ? 'Agent error' : 'Execution log'}
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: '0.68rem', color: c.text.ghost, ml: 'auto' }}>
|
||||
{messages.length} messages
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, overflow: 'auto', px: 1.5, py: 1 }}>
|
||||
{messages.map((msg) => (
|
||||
<LogEntry key={msg.id} msg={msg} c={c} />
|
||||
))}
|
||||
<div ref={logEndRef} />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -1,110 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Collapse from '@mui/material/Collapse';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import { AgentMessage } from '@/shared/state/agentsSlice';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
|
||||
interface LogEntryProps {
|
||||
msg: AgentMessage;
|
||||
c: ReturnType<typeof useClaudeTokens>;
|
||||
}
|
||||
|
||||
export const LogEntry: React.FC<LogEntryProps> = ({ msg, c }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
if (msg.role === 'user') return null;
|
||||
|
||||
if (msg.role === 'assistant') {
|
||||
const text = typeof msg.content === 'string'
|
||||
? msg.content
|
||||
: Array.isArray(msg.content)
|
||||
? msg.content.filter((b: any) => b.type === 'text').map((b: any) => b.text).join('')
|
||||
: JSON.stringify(msg.content);
|
||||
if (!text.trim()) return null;
|
||||
return (
|
||||
<Box sx={{ mb: 0.5 }}>
|
||||
<Box
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{ display: 'flex', alignItems: 'center', gap: 0.5, cursor: 'pointer', '&:hover': { opacity: 0.8 } }}
|
||||
>
|
||||
<ExpandMoreIcon sx={{ fontSize: 14, color: c.text.ghost, transform: open ? 'rotate(0deg)' : 'rotate(-90deg)', transition: '0.15s' }} />
|
||||
<Typography sx={{ fontSize: '0.72rem', color: c.text.muted, fontStyle: 'italic', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{text.slice(0, 120)}{text.length > 120 ? '…' : ''}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Collapse in={open}>
|
||||
<Typography sx={{ fontSize: '0.72rem', color: c.text.secondary, whiteSpace: 'pre-wrap', pl: 2.5, pt: 0.5, fontFamily: c.font.mono, lineHeight: 1.5 }}>
|
||||
{text}
|
||||
</Typography>
|
||||
</Collapse>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
if (msg.role === 'tool_call') {
|
||||
const tc = typeof msg.content === 'object' ? msg.content as Record<string, any> : {};
|
||||
return (
|
||||
<Box sx={{ mb: 0.5 }}>
|
||||
<Box
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{ display: 'flex', alignItems: 'center', gap: 0.5, cursor: 'pointer', '&:hover': { opacity: 0.8 } }}
|
||||
>
|
||||
<ExpandMoreIcon sx={{ fontSize: 14, color: c.text.ghost, transform: open ? 'rotate(0deg)' : 'rotate(-90deg)', transition: '0.15s' }} />
|
||||
<Chip
|
||||
label={tc.tool || 'tool'}
|
||||
size="small"
|
||||
sx={{ height: 18, fontSize: '0.68rem', fontWeight: 600, fontFamily: c.font.mono, bgcolor: c.accent.primary + '20', color: c.accent.primary }}
|
||||
/>
|
||||
{tc.input && (
|
||||
<Typography sx={{ fontSize: '0.68rem', color: c.text.ghost, ml: 0.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{JSON.stringify(tc.input).slice(0, 80)}…
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
<Collapse in={open}>
|
||||
<Box sx={{ pl: 2.5, pt: 0.5 }}>
|
||||
<Typography component="pre" sx={{ fontSize: '0.68rem', color: c.text.secondary, fontFamily: c.font.mono, whiteSpace: 'pre-wrap', maxHeight: 200, overflow: 'auto' }}>
|
||||
{JSON.stringify(tc.input, null, 2)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
if (msg.role === 'tool_result') {
|
||||
const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
|
||||
return (
|
||||
<Box sx={{ mb: 0.5 }}>
|
||||
<Box
|
||||
onClick={() => setOpen(!open)}
|
||||
sx={{ display: 'flex', alignItems: 'center', gap: 0.5, cursor: 'pointer', '&:hover': { opacity: 0.8 } }}
|
||||
>
|
||||
<ExpandMoreIcon sx={{ fontSize: 14, color: c.text.ghost, transform: open ? 'rotate(0deg)' : 'rotate(-90deg)', transition: '0.15s' }} />
|
||||
<Typography sx={{ fontSize: '0.68rem', color: c.text.ghost }}>
|
||||
result ({content.length > 60 ? `${content.length} chars` : content.slice(0, 60)})
|
||||
</Typography>
|
||||
</Box>
|
||||
<Collapse in={open}>
|
||||
<Typography component="pre" sx={{ fontSize: '0.68rem', color: c.text.secondary, fontFamily: c.font.mono, whiteSpace: 'pre-wrap', pl: 2.5, pt: 0.5, maxHeight: 200, overflow: 'auto' }}>
|
||||
{content}
|
||||
</Typography>
|
||||
</Collapse>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
if (msg.role === 'system') {
|
||||
const text = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
|
||||
return (
|
||||
<Typography sx={{ fontSize: '0.68rem', color: c.text.ghost, fontStyle: 'italic', mb: 0.5 }}>
|
||||
{text}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -4,7 +4,7 @@ export interface ClipboardCard {
|
||||
type: CardType;
|
||||
id: string;
|
||||
name: string;
|
||||
meta: Record<string, any>;
|
||||
meta: Record<string, unknown>;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
@@ -20,8 +20,4 @@ export function setClipboardCards(cards: ClipboardCard[]): void {
|
||||
|
||||
export function getClipboardCards(): ClipboardCard[] {
|
||||
return clipboardCards;
|
||||
}
|
||||
|
||||
export function clearClipboard(): void {
|
||||
clipboardCards = [];
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
export interface AgentMessage {
|
||||
id: string;
|
||||
role: 'user' | 'assistant' | 'tool_call' | 'tool_result' | 'system';
|
||||
content: any;
|
||||
content: string | Record<string, unknown>;
|
||||
timestamp: string;
|
||||
branch_id: string;
|
||||
parent_id: string | null;
|
||||
@@ -16,7 +16,7 @@ export interface ApprovalRequest {
|
||||
id: string;
|
||||
session_id: string;
|
||||
tool_name: string;
|
||||
tool_input: Record<string, any>;
|
||||
tool_input: Record<string, unknown>;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
@@ -86,20 +86,6 @@ export interface ContextPath {
|
||||
type: 'file' | 'directory';
|
||||
}
|
||||
|
||||
export interface SendMessagePayload {
|
||||
sessionId: string;
|
||||
prompt: string;
|
||||
mode?: string;
|
||||
model?: string;
|
||||
provider?: string;
|
||||
images?: Array<{ data: string; media_type: string }>;
|
||||
contextPaths?: Array<ContextPath>;
|
||||
forcedTools?: string[];
|
||||
attachedSkills?: Array<{ id: string; name: string; content: string }>;
|
||||
hidden?: boolean;
|
||||
selectedBrowserIds?: string[];
|
||||
}
|
||||
|
||||
export interface LaunchAndSendPayload {
|
||||
draftId: string;
|
||||
config: AgentConfig;
|
||||
@@ -115,21 +101,6 @@ export interface LaunchAndSendPayload {
|
||||
selectedBrowserIds?: string[];
|
||||
}
|
||||
|
||||
export interface GenerateGroupMetaPayload {
|
||||
sessionId: string;
|
||||
groupId: string;
|
||||
toolCalls: Array<{ tool: string; input_summary: string }>;
|
||||
resultsSummary?: string[];
|
||||
isRefinement?: boolean;
|
||||
}
|
||||
|
||||
export interface SearchHistoryParams {
|
||||
q?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
dashboardId?: string;
|
||||
}
|
||||
|
||||
export interface HistorySession {
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user