Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions src/views/agentCombined/handlers/webviewMessageHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,32 +90,30 @@ export class WebviewMessageHandlers {
if (this.state.agentInstance || this.state.isSessionActive) {
this.state.clearSessionState();
await this.state.setSessionActive(false);
await this.state.setSessionStarting(false);
}
await this.state.setSessionStarting(false);

// Check for specific agent deactivation error
if (
originalErrorMessage.includes('404') &&
originalErrorMessage.includes('NOT_FOUND') &&
originalErrorMessage.includes('No valid version available')
) {
await this.messageSender.sendError(
'This agent is currently deactivated, so you can\'t converse with it. Activate the agent using either the "AFDX: Activate Agent" VS Code command or your org\'s Agentforce UI.',
originalErrorMessage
'Agent deactivated',
'This agent is currently deactivated, so you can\'t converse with it. Activate it using the "AFDX: Activate Agent" command or your org\'s Agentforce UI.'
);
} else if (originalErrorMessage.includes('NOT_FOUND') && originalErrorMessage.includes('404')) {
await this.messageSender.sendError(
"The selected agent couldn't be found. Either it's been deleted or you don't have access to it.",
originalErrorMessage
'Agent not found',
"The selected agent couldn't be found. Either it's been deleted or you don't have access to it."
);
} else if (originalErrorMessage.includes('403') || originalErrorMessage.includes('FORBIDDEN')) {
await this.messageSender.sendError(
"You don't have permission to use this agent. Consult your Salesforce administrator.",
originalErrorMessage
'Permission denied',
"You don't have permission to use this agent. Consult your Salesforce administrator."
);
} else {
// For unknown errors, show generic message with technical details
await this.messageSender.sendError('Something went wrong. Please try again.', originalErrorMessage);
await this.messageSender.sendError('Something went wrong', originalErrorMessage);
}

await this.state.setResetAgentViewAvailable(true);
Expand Down
14 changes: 7 additions & 7 deletions test/views/agentCombined/handlers/webviewMessageHandlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ describe('WebviewMessageHandlers', () => {
await handlers.handleError(error);

expect(mockMessageSender.sendError).toHaveBeenCalledWith(
expect.stringContaining('currently deactivated'),
'404 NOT_FOUND: No valid version available for this agent'
'Agent deactivated',
expect.stringContaining('currently deactivated')
);
});

Expand All @@ -176,8 +176,8 @@ describe('WebviewMessageHandlers', () => {
await handlers.handleError(error);

expect(mockMessageSender.sendError).toHaveBeenCalledWith(
expect.stringContaining("couldn't be found"),
'404 NOT_FOUND: Agent does not exist'
'Agent not found',
expect.stringContaining("couldn't be found")
);
});

Expand All @@ -187,8 +187,8 @@ describe('WebviewMessageHandlers', () => {
await handlers.handleError(error);

expect(mockMessageSender.sendError).toHaveBeenCalledWith(
expect.stringContaining("don't have permission"),
'403 FORBIDDEN: Access denied'
'Permission denied',
expect.stringContaining("don't have permission")
);
});

Expand All @@ -198,7 +198,7 @@ describe('WebviewMessageHandlers', () => {
await handlers.handleError(error);

expect(mockMessageSender.sendError).toHaveBeenCalledWith(
'Something went wrong. Please try again.',
'Something went wrong',
'Something unexpected happened'
);
});
Expand Down
6 changes: 4 additions & 2 deletions test/webview/AgentPreview.messages.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,15 @@ describe('AgentPreview - Message Handlers', () => {
it('should handle compilationError with custom message', async () => {
renderComponent();
handlers.get('compilationError')?.({ message: 'Syntax error' });
await waitFor(() => expect(screen.getByText('Syntax error')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('Compilation failed')).toBeInTheDocument());
expect(screen.getByText('Syntax error')).toBeInTheDocument();
});

it('should handle compilationError with default message', async () => {
renderComponent();
handlers.get('compilationError')?.({});
await waitFor(() => expect(screen.getByText('Failed to compile the agent.')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('Compilation failed')).toBeInTheDocument());
expect(screen.getByText('Failed to compile the agent.')).toBeInTheDocument();
});
});

Expand Down
55 changes: 36 additions & 19 deletions webview/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ const App: React.FC = () => {
const disposeRefreshAgents = vscodeApi.onMessage('refreshAgents', () => {
// Switch back to preview tab when refreshing agents
setActiveTab('preview');
sessionActiveRef.current = false;
setIsSessionActive(false);
setIsSessionStarting(false);
});

const disposeSetLiveMode = vscodeApi.onMessage('setLiveMode', (data: { isLiveMode: boolean }) => {
Expand Down Expand Up @@ -251,11 +254,27 @@ const App: React.FC = () => {
}
});

const disposeCompilationError = vscodeApi.onMessage('compilationError', () => {
sessionActiveRef.current = false;
setIsSessionActive(false);
setIsSessionStarting(false);
const startResolver = sessionStartResolversRef.current.shift();
if (startResolver) {
startResolver(false);
}
});

const disposeClearMessages = vscodeApi.onMessage('clearMessages', () => {
setIsSessionStarting(false);
});

return () => {
disposeSessionStarted();
disposeSessionEnded();
disposeSessionStarting();
disposeSessionError();
disposeCompilationError();
disposeClearMessages();
};
}, []);

Expand Down Expand Up @@ -364,25 +383,23 @@ const App: React.FC = () => {

return (
<div className="app">
{!hasSessionError && (
<div className="app-menu">
<AgentSelector
selectedAgent={desiredAgentId}
onAgentChange={handleAgentChange}
isSessionActive={isSessionActive}
isSessionStarting={isSessionStarting}
onLiveModeChange={handleLiveModeChange}
initialLiveMode={isLiveMode}
onSelectedAgentInfoChange={setSelectedAgentInfo}
onStopSession={handleStopSession}
onAgentsAvailabilityChange={handleAgentsAvailabilityChange}
/>
<div className="app-menu-divider" />
{previewAgentId !== '' && !isSessionStarting && (
<TabNavigation activeTab={activeTab} onTabChange={handleTabChange} showTracerTab={selectedAgentInfo?.type !== AgentSource.PUBLISHED} />
)}
</div>
)}
<div className="app-menu" style={hasSessionError ? { display: 'none' } : undefined}>
<AgentSelector
selectedAgent={desiredAgentId}
onAgentChange={handleAgentChange}
isSessionActive={isSessionActive}
isSessionStarting={isSessionStarting}
onLiveModeChange={handleLiveModeChange}
initialLiveMode={isLiveMode}
onSelectedAgentInfoChange={setSelectedAgentInfo}
onStopSession={handleStopSession}
onAgentsAvailabilityChange={handleAgentsAvailabilityChange}
/>
<div className="app-menu-divider" />
{previewAgentId !== '' && !isSessionStarting && (
<TabNavigation activeTab={activeTab} onTabChange={handleTabChange} showTracerTab={selectedAgentInfo?.type !== AgentSource.PUBLISHED} />
)}
</div>
<div className="app-content">
<div className={`tab-content ${activeTab === 'preview' ? 'active' : 'hidden'}`}>
<AgentPreview
Expand Down
18 changes: 8 additions & 10 deletions webview/src/components/AgentPreview/AgentPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,15 +268,13 @@ const AgentPreview = forwardRef<AgentPreviewRef, AgentPreviewProps>(
const disposeCompilationError = vscodeApi.onMessage('compilationError', data => {
setIsLoading(false);
setAgentConnected(false);

const errorMessage: Message = {
id: Date.now().toString(),
type: 'system',
content: data?.message || 'Failed to compile the agent.',
systemType: 'error',
timestamp: new Date().toISOString()
};
setMessages(prev => [...prev, errorMessage]);
sessionActiveStateRef.current = false;
sessionErrorTimestampRef.current = Date.now();
setHasSessionError(true);
setErrorMessage('Compilation failed');
setErrorDetails(data?.message || 'Failed to compile the agent.');
setMessages(prev => pruneStartingSessionMessages(prev));
onSessionTransitionSettled();
});
disposers.push(disposeCompilationError);

Expand Down Expand Up @@ -312,7 +310,7 @@ const AgentPreview = forwardRef<AgentPreviewRef, AgentPreviewProps>(
sessionActiveStateRef.current = false;
sessionErrorTimestampRef.current = Date.now();
setHasSessionError(true);
setErrorMessage(data?.message || 'Something went wrong. Please try again.');
setErrorMessage(data?.message || 'Something went wrong');
setErrorDetails(data?.details);
setMessages(prev => pruneStartingSessionMessages(prev));
setIsLoading(false);
Expand Down
Loading