diff --git a/web/src/app/home/agents/AgentDetailContent.tsx b/web/src/app/home/agents/AgentDetailContent.tsx index cc64b7ba4..6a3c50951 100644 --- a/web/src/app/home/agents/AgentDetailContent.tsx +++ b/web/src/app/home/agents/AgentDetailContent.tsx @@ -5,7 +5,7 @@ import { toast } from 'sonner'; import { AlertTriangle, Trash2 } from 'lucide-react'; import { httpClient } from '@/app/infra/http/HttpClient'; import { useCurrentWorkspace } from '@/app/infra/http'; -import { Agent } from '@/app/infra/entities/api'; +import { Agent, AgentPlatformTool } from '@/app/infra/entities/api'; import { useSidebarData } from '@/app/home/components/home-sidebar/SidebarDataContext'; import ProcessorDetailWorkbench from '@/app/home/components/processor-detail/ProcessorDetailWorkbench'; import EntityBasicInfoDialog, { @@ -41,6 +41,7 @@ export default function AgentDetailContent({ id }: { id: string }) { currentWorkspace?.permissions.includes('runtime.operate') ?? false; const { refreshPipelines, pipelines, setDetailEntityName } = useSidebarData(); const [agent, setAgent] = useState(null); + const [platformTools, setPlatformTools] = useState([]); const [loading, setLoading] = useState(!isCreateMode); const [formDirty, setFormDirty] = useState(false); const [formSaving, setFormSaving] = useState(false); @@ -224,14 +225,17 @@ export default function AgentDetailContent({ id }: { id: string }) { onSavingChange={setFormSaving} onRunnerStatusChange={setRunnerStatus} onSupportedEventPatternsChange={setSupportedEventPatterns} + onPlatformToolsChange={setPlatformTools} /> } debugTitle={canOperate ? t('agents.debugTab') : undefined} + debugDescription={t('agents.debugPlatformNotice')} debugContent={ canOperate ? ( agentFormRef.current?.save() ?? false} onOpenRunnerConfig={() => diff --git a/web/src/app/home/agents/components/AgentDebugPanel.tsx b/web/src/app/home/agents/components/AgentDebugPanel.tsx index 37539fcaa..bb28e5633 100644 --- a/web/src/app/home/agents/components/AgentDebugPanel.tsx +++ b/web/src/app/home/agents/components/AgentDebugPanel.tsx @@ -10,6 +10,8 @@ import { Play, } from 'lucide-react'; import { httpClient } from '@/app/infra/http/HttpClient'; +import type { AgentPlatformTool } from '@/app/infra/entities/api'; +import { extractI18nObject } from '@/i18n/I18nProvider'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; @@ -43,6 +45,7 @@ import { executionSteps, type DebugExecutionEvent } from './debug-execution'; interface AgentDebugPanelProps { agentId: string; availableEventTypes: string[]; + platformTools?: AgentPlatformTool[]; supportedEventPatterns?: string[]; beforeRun?: () => Promise; hasUnsavedChanges?: boolean; @@ -171,12 +174,16 @@ function matchesEventPattern(pattern: string, eventType: string) { export default function AgentDebugPanel({ agentId, availableEventTypes, + platformTools = [], supportedEventPatterns = ['*'], beforeRun, hasUnsavedChanges = false, onOpenRunnerConfig, }: AgentDebugPanelProps) { const { t } = useTranslation(); + const toolLabels = Object.fromEntries( + platformTools.map((tool) => [tool.name, extractI18nObject(tool.label)]), + ); const [preset, setPreset] = useState('message.received'); const [customEventType, setCustomEventType] = useState('custom.event'); const [inputText, setInputText] = useState(''); @@ -428,9 +435,6 @@ export default function AgentDebugPanel({ return (
-

- {t('agents.debugPlatformNotice')} -

{t('agents.debugTranscript')}

@@ -493,6 +497,7 @@ export default function AgentDebugPanel({ )} {entry.text && ( diff --git a/web/src/app/home/agents/components/AgentExecutionTrace.tsx b/web/src/app/home/agents/components/AgentExecutionTrace.tsx index bd3777d80..662014900 100644 --- a/web/src/app/home/agents/components/AgentExecutionTrace.tsx +++ b/web/src/app/home/agents/components/AgentExecutionTrace.tsx @@ -22,9 +22,11 @@ const textClass = export default function AgentExecutionTrace({ events, finished = false, + toolLabels = {}, }: { events: DebugExecutionEvent[]; finished?: boolean; + toolLabels?: Record; }) { const { t } = useTranslation(); const steps = useMemo(() => executionSteps(events), [events]); @@ -36,9 +38,9 @@ export default function AgentExecutionTrace({ ); return (
- {ended && ( + {ended && toolCount > 0 && (

- {t(toolCount ? 'agents.debugToolCount' : 'agents.debugNoToolCalls', { + {t('agents.debugToolCount', { count: toolCount, })}

@@ -68,15 +70,22 @@ export default function AgentExecutionTrace({ )}
) : ( -
-
+ - {step.name} + {toolLabels[step.name] || step.name} + {toolLabels[step.name] && toolLabels[step.name] !== step.name && ( + + {step.name} + + )} + +
+ {step.parameters !== undefined && ( +
+

+ {t('agents.debugToolArguments')} +

+
+                    {formatValue(step.parameters)}
+                  
+
+ )} + {step.result !== undefined && step.result !== null && ( +
+

+ {t('agents.debugToolResult')} +

+
+                    {formatValue(step.result)}
+                  
+
+ )} + {step.error && ( +
+                  {step.error}
+                
+ )}
- {step.parameters !== undefined && ( -
-

- {t('agents.debugToolArguments')} -

-
-                  {formatValue(step.parameters)}
-                
-
- )} - {step.result !== undefined && step.result !== null && ( -
-

- {t('agents.debugToolResult')} -

-
-                  {formatValue(step.result)}
-                
-
- )} - {step.error && ( -
-                {step.error}
-              
- )} -
+ ), )}
diff --git a/web/src/app/home/agents/components/AgentFormComponent.tsx b/web/src/app/home/agents/components/AgentFormComponent.tsx index 3cdca98be..95af28885 100644 --- a/web/src/app/home/agents/components/AgentFormComponent.tsx +++ b/web/src/app/home/agents/components/AgentFormComponent.tsx @@ -68,6 +68,7 @@ interface AgentFormComponentProps { onSavingChange?: (saving: boolean) => void; onRunnerStatusChange?: (status: AgentRunnerStatus) => void; onSupportedEventPatternsChange?: (patterns: string[]) => void; + onPlatformToolsChange?: (tools: AgentPlatformTool[]) => void; } export type AgentConfigSection = @@ -124,6 +125,7 @@ function AgentFormComponent( onSavingChange, onRunnerStatusChange, onSupportedEventPatternsChange, + onPlatformToolsChange, }: AgentFormComponentProps, ref: ForwardedRef, ) { @@ -131,6 +133,9 @@ function AgentFormComponent( const [runnerConfigSchema, setRunnerConfigSchema] = useState(null); const [platformTools, setPlatformTools] = useState([]); + useEffect(() => { + onPlatformToolsChange?.(platformTools); + }, [onPlatformToolsChange, platformTools]); const [platformToolCatalogAvailable, setPlatformToolCatalogAvailable] = useState(true); const [hostTools, setHostTools] = useState([]); diff --git a/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx b/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx index 1a5d454f8..568927b7d 100644 --- a/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx +++ b/web/src/app/home/components/processor-detail/ProcessorDetailWorkbench.tsx @@ -1,5 +1,5 @@ import { ReactNode, useState } from 'react'; -import { BarChart3, Bug, Settings } from 'lucide-react'; +import { BarChart3, Bug, Info, Settings } from 'lucide-react'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { @@ -36,6 +36,7 @@ interface ProcessorDetailWorkbenchProps { configTitle: string; configContent: ReactNode; debugTitle?: string; + debugDescription?: string; debugContent?: ReactNode; debugConnected?: boolean; debugConnectedLabel?: string; @@ -58,6 +59,7 @@ export default function ProcessorDetailWorkbench({ configTitle, configContent, debugTitle, + debugDescription, debugContent, debugConnected, debugConnectedLabel, @@ -196,6 +198,22 @@ export default function ProcessorDetailWorkbench({
{debugTitle} + {debugDescription && ( + + + + + + {debugDescription} + + + )}
{debugConnected !== undefined && (