diff --git a/ui/desktop/src/components/ToolCallConfirmation.test.tsx b/ui/desktop/src/components/ToolCallConfirmation.test.tsx new file mode 100644 index 000000000..0579fdb2d --- /dev/null +++ b/ui/desktop/src/components/ToolCallConfirmation.test.tsx @@ -0,0 +1,55 @@ +import { render, screen } from '@testing-library/react'; +import { describe, expect, it, vi } from 'vitest'; +import { IntlTestWrapper } from '../i18n/test-utils'; +import type { ActionRequired } from '../types/message'; +import ToolCallConfirmation from './ToolCallConfirmation'; + +vi.mock('./ToolApprovalButtons', () => ({ + default: () =>
, +})); + +const securityPrompt = 'This command sends a local file to a remote service.'; + +const actionRequiredContent = { + type: 'actionRequired', + data: { + actionType: 'toolConfirmation', + id: 'request-1', + toolName: 'developer__shell', + arguments: { + command: 'upload /home/alice/private.txt to files.example.test', + }, + prompt: securityPrompt, + }, +} as ActionRequired & { type: 'actionRequired' }; + +describe('ToolCallConfirmation', () => { + it('shows the concrete tool arguments before approval', () => { + render( + , + { wrapper: IntlTestWrapper } + ); + + expect(screen.getByText('command')).toBeInTheDocument(); + expect(screen.getByText(/upload \/home\/alice\/private\.txt/)).toBeInTheDocument(); + expect(screen.getByTestId('approval-buttons')).toBeInTheDocument(); + }); + + it('shows the security prompt before approval', () => { + render( + , + { wrapper: IntlTestWrapper } + ); + + expect(screen.getByText(securityPrompt)).toBeInTheDocument(); + expect(screen.getByTestId('approval-buttons')).toBeInTheDocument(); + }); +}); diff --git a/ui/desktop/src/components/ToolCallConfirmation.tsx b/ui/desktop/src/components/ToolCallConfirmation.tsx index 97d95ef2d..bd50f76e5 100644 --- a/ui/desktop/src/components/ToolCallConfirmation.tsx +++ b/ui/desktop/src/components/ToolCallConfirmation.tsx @@ -2,6 +2,7 @@ import type { ActionRequired } from '../types/message'; import { defineMessages, useIntl } from '../i18n'; import { snakeToTitleCase } from '../utils'; import ToolApprovalButtons from './ToolApprovalButtons'; +import { ToolCallArguments, type ToolCallArgumentValue } from './ToolCallArguments'; const i18n = defineMessages({ allowToolCallWithName: { @@ -35,7 +36,7 @@ export default function ToolConfirmation({ }: ToolConfirmationProps) { const intl = useIntl(); const data = actionRequiredContent.data as ToolConfirmationData; - const { id, toolName, prompt } = data; + const { id, toolName, arguments: toolArguments, prompt } = data; const displayName = formatToolName(toolName); return ( @@ -45,9 +46,13 @@ export default function ToolConfirmation({ ? intl.formatMessage(i18n.allowToolCallWithName, { toolName: displayName }) : intl.formatMessage(i18n.gooseWouldLikeToCallWithName, { toolName: displayName })}
- +
+ {prompt &&
{prompt}
} + } /> + +
); }