diff --git a/frontend/src/lib/components/copilot/chat/ToolExecutionDisplay.svelte b/frontend/src/lib/components/copilot/chat/ToolExecutionDisplay.svelte index 2c09b1cacd..f6e5950ac6 100644 --- a/frontend/src/lib/components/copilot/chat/ToolExecutionDisplay.svelte +++ b/frontend/src/lib/components/copilot/chat/ToolExecutionDisplay.svelte @@ -18,8 +18,16 @@ message.parameters !== undefined && Object.keys(message.parameters).length > 0 ) + const isSuccessful = $derived( + !message.isLoading && + !message.error && + !message.needsConfirmation && + !message.isStreamingArguments + ) + const autoCollapseDetails = $derived(message.autoCollapseDetails !== false) + let isExpanded = $derived( - message.showDetails || + (message.showDetails && (!isSuccessful || !autoCollapseDetails)) || (message.isStreamingArguments && hasParameters) || (message.isLoading && message.needsConfirmation) ) diff --git a/frontend/src/lib/components/copilot/chat/anthropic.ts b/frontend/src/lib/components/copilot/chat/anthropic.ts index 4bc581db88..489d700ace 100644 --- a/frontend/src/lib/components/copilot/chat/anthropic.ts +++ b/frontend/src/lib/components/copilot/chat/anthropic.ts @@ -107,7 +107,8 @@ export async function parseAnthropicCompletion( toolName, isStreamingArguments: shouldStream, showFade: tool?.showFade, - showDetails: tool?.showDetails + showDetails: tool?.showDetails, + autoCollapseDetails: tool?.autoCollapseDetails }) } } diff --git a/frontend/src/lib/components/copilot/chat/flow/core.ts b/frontend/src/lib/components/copilot/chat/flow/core.ts index c54c652247..9de82b4132 100644 --- a/frontend/src/lib/components/copilot/chat/flow/core.ts +++ b/frontend/src/lib/components/copilot/chat/flow/core.ts @@ -420,7 +420,8 @@ export const flowTools: Tool[] = [ }, requiresConfirmation: true, confirmationMessage: 'Run flow test', - showDetails: true + showDetails: true, + autoCollapseDetails: false }, { // set strict to false to avoid issues with open ai models @@ -537,7 +538,8 @@ export const flowTools: Tool[] = [ }, requiresConfirmation: true, confirmationMessage: 'Run flow step test', - showDetails: true + showDetails: true, + autoCollapseDetails: false }, { def: inspectInlineScriptToolDef, diff --git a/frontend/src/lib/components/copilot/chat/openai-responses.ts b/frontend/src/lib/components/copilot/chat/openai-responses.ts index c557132417..378e1073f7 100644 --- a/frontend/src/lib/components/copilot/chat/openai-responses.ts +++ b/frontend/src/lib/components/copilot/chat/openai-responses.ts @@ -270,7 +270,8 @@ export async function parseOpenAIResponsesCompletion( toolName: item.name, isStreamingArguments: shouldStream, showFade: tool?.showFade, - showDetails: tool?.showDetails + showDetails: tool?.showDetails, + autoCollapseDetails: tool?.autoCollapseDetails }) } }) diff --git a/frontend/src/lib/components/copilot/chat/script/core.ts b/frontend/src/lib/components/copilot/chat/script/core.ts index b236235527..1e30bf50d9 100644 --- a/frontend/src/lib/components/copilot/chat/script/core.ts +++ b/frontend/src/lib/components/copilot/chat/script/core.ts @@ -905,7 +905,8 @@ export const testRunScriptTool: Tool = { }, requiresConfirmation: true, confirmationMessage: 'Run script test', - showDetails: true + showDetails: true, + autoCollapseDetails: false } export const getLintErrorsTool: Tool = { diff --git a/frontend/src/lib/components/copilot/chat/shared.test.ts b/frontend/src/lib/components/copilot/chat/shared.test.ts index b15fddcb94..d26f5cbb54 100644 --- a/frontend/src/lib/components/copilot/chat/shared.test.ts +++ b/frontend/src/lib/components/copilot/chat/shared.test.ts @@ -188,6 +188,7 @@ describe('processToolCall', () => { content: error, error, isLoading: false, + isStreamingArguments: false, needsConfirmation: false, showDetails: true }) @@ -207,6 +208,8 @@ describe('processToolCall', () => { def: createToolDef(z.object({}), 'create_schedule', 'Create schedule'), requiresConfirmation: true, confirmationMessage: 'Create schedule', + showDetails: true, + autoCollapseDetails: false, validateBeforeConfirmation: () => undefined, fn } @@ -227,6 +230,20 @@ describe('processToolCall', () => { expect(requestConfirmation).toHaveBeenCalledWith('call_2') expect(fn).toHaveBeenCalled() + expect(setToolStatus).toHaveBeenCalledWith( + 'call_2', + expect.objectContaining({ + autoCollapseDetails: false, + showDetails: true + }) + ) + expect(setToolStatus).toHaveBeenLastCalledWith( + 'call_2', + expect.objectContaining({ + isLoading: false, + isStreamingArguments: false + }) + ) expect(result.content).toBe('ok') }) diff --git a/frontend/src/lib/components/copilot/chat/shared.ts b/frontend/src/lib/components/copilot/chat/shared.ts index 1836267cd3..0723cc3eb3 100644 --- a/frontend/src/lib/components/copilot/chat/shared.ts +++ b/frontend/src/lib/components/copilot/chat/shared.ts @@ -498,6 +498,7 @@ export type ToolDisplayMessage = { error?: string needsConfirmation?: boolean showDetails?: boolean + autoCollapseDetails?: boolean isStreamingArguments?: boolean toolName?: string showFade?: boolean @@ -567,9 +568,11 @@ export async function processToolCall({ content: validationError, parameters: args, isLoading: false, + isStreamingArguments: false, error: validationError, needsConfirmation: false, - showDetails: tool?.showDetails + showDetails: tool?.showDetails, + autoCollapseDetails: tool?.autoCollapseDetails }) return { role: 'tool' as const, @@ -588,7 +591,8 @@ export async function processToolCall({ parameters: args, isLoading: true, needsConfirmation: needsConfirmation, - showDetails: tool?.showDetails + showDetails: tool?.showDetails, + autoCollapseDetails: tool?.autoCollapseDetails }) // If confirmation is needed and we have the callback, wait for it @@ -599,6 +603,7 @@ export async function processToolCall({ toolCallbacks.setToolStatus(toolCall.id, { content: 'Cancelled by user', isLoading: false, + isStreamingArguments: false, error: 'Tool execution was cancelled by user', needsConfirmation: false }) @@ -628,12 +633,14 @@ export async function processToolCall({ toolId: toolCall.id }) toolCallbacks.setToolStatus(toolCall.id, { - isLoading: false + isLoading: false, + isStreamingArguments: false }) } catch (err) { console.error(err) toolCallbacks.setToolStatus(toolCall.id, { isLoading: false, + isStreamingArguments: false, error: 'An error occurred while calling the tool' }) const errorMessage = @@ -679,6 +686,7 @@ export interface Tool { requiresConfirmation?: boolean confirmationMessage?: string showDetails?: boolean + autoCollapseDetails?: boolean streamArguments?: boolean showFade?: boolean } diff --git a/frontend/src/lib/components/copilot/lib.ts b/frontend/src/lib/components/copilot/lib.ts index f919103400..de87579a23 100644 --- a/frontend/src/lib/components/copilot/lib.ts +++ b/frontend/src/lib/components/copilot/lib.ts @@ -1069,6 +1069,7 @@ export async function parseOpenAICompletion( isStreamingArguments: shouldStream, showFade: tool?.showFade, showDetails: tool?.showDetails, + autoCollapseDetails: tool?.autoCollapseDetails, parameters: parameters }) }