diff --git a/frontend/src/lib/components/AIAgentLogViewer.svelte b/frontend/src/lib/components/AIAgentLogViewer.svelte deleted file mode 100644 index 2549fbb29f..0000000000 --- a/frontend/src/lib/components/AIAgentLogViewer.svelte +++ /dev/null @@ -1,281 +0,0 @@ - - -{#if job} -
- {}} - mode="aiagent" - /> -
-{/if} diff --git a/frontend/src/lib/components/FlowJobResult.svelte b/frontend/src/lib/components/FlowJobResult.svelte index eea95a6ecf..3221ee06b5 100644 --- a/frontend/src/lib/components/FlowJobResult.svelte +++ b/frontend/src/lib/components/FlowJobResult.svelte @@ -2,10 +2,9 @@ import { Loader2 } from 'lucide-svelte' import DisplayResult from './DisplayResult.svelte' import LogViewer from './LogViewer.svelte' - import type { CompletedJob, Job } from '$lib/gen' - import AiAgentLogViewer from './AIAgentLogViewer.svelte' import { twMerge } from 'tailwind-merge' - import type { AgentTool } from './flows/agentToolUtils' + import AgentTranscript from './AgentTranscript.svelte' + import { parseAgentResult } from './aiAgentResult' interface Props { waitingForExecutor?: boolean @@ -21,12 +20,6 @@ refreshLog?: boolean downloadLogs?: boolean tagLabel?: string | undefined - aiAgentStatus?: { - tools: AgentTool[] - agentJob: Partial & Pick & { type: 'CompletedJob' } - storedToolCallJobs?: Record - onToolJobLoaded?: (job: Job, idx: number) => void - } } let { @@ -41,9 +34,12 @@ tag = undefined, workspaceId = undefined, downloadLogs = true, - tagLabel = undefined, - aiAgentStatus = undefined + tagLabel = undefined }: Props = $props() + + // An agent step's own logs are worker chatter; what happened is its conversation. + // Derived from the result rather than passed in, so every caller gets it. + let agentResult = $derived(parseAgentResult(result))
- Logs - {#if aiAgentStatus} - + {agentResult ? 'Transcript' : 'Logs'} + {#if agentResult} +
+ +
{:else}
Promise getSelectedIteration: (stepId: string) => number flowSummary?: string - mode?: 'flow' | 'aiagent' currentId?: string | null navigationChain?: NavigationChain select: (id: string) => void @@ -81,7 +80,6 @@ onSelectedIteration, getSelectedIteration, flowSummary, - mode = 'flow', currentId, navigationChain = $bindable(), select, @@ -127,7 +125,7 @@ function getStepProgress(job: RootJobData | undefined, totalSteps: number): string { if (!job || totalSteps === 0) return '' - const stepWord = mode === 'aiagent' ? 'action' : 'step' + const stepWord = 'step' // If flow is completed, show total steps if (job.type === 'CompletedJob') { @@ -558,7 +556,7 @@ {@render flowIcon(getFlowStatus(rootJob), flowInfo?.hasErrors)}
- {mode === 'aiagent' ? 'AI Agent' : level == 0 ? 'Flow' : 'Subflow'} + {level == 0 ? 'Flow' : 'Subflow'} {#if flowInfo?.label} : {flowInfo.label} {/if} @@ -703,32 +701,22 @@
- {#if mode === 'aiagent'} - {#if module.summary} - Tool call: {module.summary} - {:else} - Message - {/if} - {:else} - {module.id} - {/if} + {module.id} - {#if mode === 'flow'} - {#if module.value.type === 'forloopflow'} - For loop - {:else if module.value.type === 'whileloopflow'} - While loop - {:else if module.value.type === 'branchall'} - Branch to all - {:else if module.value.type === 'branchone'} - Branch to one - {:else if module.value.type === 'flow'} - Subflow - {:else} - Step - {/if} + {#if module.value.type === 'forloopflow'} + For loop + {:else if module.value.type === 'whileloopflow'} + While loop + {:else if module.value.type === 'branchall'} + Branch to all + {:else if module.value.type === 'branchone'} + Branch to one + {:else if module.value.type === 'flow'} + Subflow + {:else} + Step {/if} - {#if module.summary && mode !== 'aiagent'} + {#if module.summary} : {module.summary} {/if} {#if hasEmptySubflowValue} diff --git a/frontend/src/lib/components/FlowLogViewerWrapper.svelte b/frontend/src/lib/components/FlowLogViewerWrapper.svelte index 648dbc9f06..3a1c3add1f 100644 --- a/frontend/src/lib/components/FlowLogViewerWrapper.svelte +++ b/frontend/src/lib/components/FlowLogViewerWrapper.svelte @@ -20,7 +20,6 @@ | { id: string; index: number; manuallySet: true; moduleId: string } | { manuallySet: false; moduleId: string } ) => Promise - mode?: 'flow' | 'aiagent' } let { @@ -30,7 +29,6 @@ workspaceId, render, onSelectedIteration, - mode = 'flow' }: Props = $props() // State for tracking expanded rows - using Record to allow explicit control @@ -180,7 +178,6 @@ {render} {getSelectedIteration} flowId="root" - {mode} {currentId} bind:navigationChain {select} diff --git a/frontend/src/lib/components/FlowStatusViewerInner.svelte b/frontend/src/lib/components/FlowStatusViewerInner.svelte index 3b860dc3a1..be99de1798 100644 --- a/frontend/src/lib/components/FlowStatusViewerInner.svelte +++ b/frontend/src/lib/components/FlowStatusViewerInner.svelte @@ -65,7 +65,6 @@ import { getActiveReplay } from './recording/replay.svelte' import { publishLinkedAgentTools } from './flows/flowState' import { - getLinkedAgentTools, linkedToolsScope, releaseLinkedToolsScope, retainLinkedToolsScope @@ -2142,15 +2141,6 @@

No arguments

{/if} {:else if node} - {@const module = - stepDetail && typeof stepDetail !== 'string' ? stepDetail : undefined} - {@const agentTools = - module && module.value.type === 'aiagent' - ? module.value.agent - ? getLinkedAgentTools(linkedToolsViewScope, module.id) - : (module.value.tools ?? []) - : undefined} - {@const parentLoopsPrefix = getParentLoopsPrefix(module?.id ?? '')} {#if node.flow_jobs_results}
{ - if (module) { - const storeKey = parentLoopsPrefix + module.id + '-' + idx - toolCallStore?.setStoredToolCallJob(storeKey, job) - } - } - } - : undefined} />
diff --git a/frontend/src/lib/components/ModulePreviewResultViewer.svelte b/frontend/src/lib/components/ModulePreviewResultViewer.svelte index 3f39531b0a..e1ae3915bb 100644 --- a/frontend/src/lib/components/ModulePreviewResultViewer.svelte +++ b/frontend/src/lib/components/ModulePreviewResultViewer.svelte @@ -8,10 +8,10 @@ import OutputPickerInner from '$lib/components/flows/propPicker/OutputPickerInner.svelte' import { Pane, Splitpanes } from 'svelte-splitpanes' import type { FlowEditorContext, OutputViewerJob } from './flows/types' - import type { AgentTool } from './flows/agentToolUtils' import { getContext } from 'svelte' import { getStringError } from './copilot/chat/utils' - import AiAgentLogViewer from './AIAgentLogViewer.svelte' + import AgentTranscript from './AgentTranscript.svelte' + import { parseAgentResult } from './aiAgentResult' interface Props { lang: Script['language'] @@ -27,9 +27,6 @@ onUpdateMock?: (mock: { enabled: boolean; return_value?: unknown }) => void loadingJob?: boolean tagLabel?: string - // A linked agent persists no tools of its own; its resolved resource tools are passed here so - // the log viewer can label each tool_call with the definition that ran. - linkedAgentTools?: AgentTool[] } let { @@ -45,8 +42,7 @@ disableHistory = false, onUpdateMock, loadingJob = false, - tagLabel = undefined, - linkedAgentTools = undefined + tagLabel = undefined }: Props = $props() const { stepsInputArgs, flowStateStore } = getContext('FlowEditorContext') @@ -61,6 +57,10 @@ ) const logJob = $derived(testJob ?? selectedJob) const preview = $derived.by(() => outputPickerInner?.getPreview?.()) + // The trace of an agent step is its conversation, which its own result carries. + const agentResult = $derived( + logJob?.type === 'CompletedJob' ? parseAgentResult(logJob.result) : undefined + ) @@ -105,15 +105,10 @@ customEmptyMessage="Using pinned data" {tagLabel} /> - {:else if mod.value.type === 'aiagent' && logJob?.type === 'CompletedJob'} - + {:else if agentResult} +
+ +
{:else}