Skip to content

Commit c4e6a99

Browse files
committed
refactor: centralize error message formatting
Created src/utils/errors/formatSendError.ts as single source of truth for SendMessageError formatting. Both RetryBarrier and ChatInputToasts now use formatSendMessageError() helper, eliminating duplicate logic for provider commands and error messages. - formatSendMessageError() returns message + optional providerCommand - RetryBarrier combines them: "message. Configure with command" - ChatInputToasts uses providerCommand in solution section - All provider-related strings now defined in one place
1 parent fca8976 commit c4e6a99

File tree

3 files changed

+68
-24
lines changed

3 files changed

+68
-24
lines changed

src/components/ChatInputToasts.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { Toast } from "./ChatInputToast";
33
import { SolutionLabel } from "./ChatInputToast";
44
import type { ParsedCommand } from "@/utils/slashCommands/types";
55
import type { SendMessageError as SendMessageErrorType } from "@/types/errors";
6+
import { formatSendMessageError } from "@/utils/errors/formatSendError";
67

78
/**
89
* Creates a toast message for command-related errors and help messages
@@ -146,55 +147,63 @@ export const createCommandToast = (parsed: ParsedCommand): Toast | null => {
146147
*/
147148
export const createErrorToast = (error: SendMessageErrorType): Toast => {
148149
switch (error.type) {
149-
case "api_key_not_found":
150+
case "api_key_not_found": {
151+
const formatted = formatSendMessageError(error);
150152
return {
151153
id: Date.now().toString(),
152154
type: "error",
153155
title: "API Key Not Found",
154156
message: `The ${error.provider} provider requires an API key to function.`,
155-
solution: (
157+
solution: formatted.providerCommand ? (
156158
<>
157159
<SolutionLabel>Quick Fix:</SolutionLabel>
158-
/providers set {error.provider} apiKey YOUR_API_KEY
160+
{formatted.providerCommand}
159161
</>
160-
),
162+
) : undefined,
161163
};
164+
}
162165

163-
case "provider_not_supported":
166+
case "provider_not_supported": {
167+
const formatted = formatSendMessageError(error);
164168
return {
165169
id: Date.now().toString(),
166170
type: "error",
167171
title: "Provider Not Supported",
168-
message: `The ${error.provider} provider is not supported yet.`,
172+
message: formatted.message,
169173
solution: (
170174
<>
171175
<SolutionLabel>Try This:</SolutionLabel>
172176
Use an available provider from /providers list
173177
</>
174178
),
175179
};
180+
}
176181

177-
case "invalid_model_string":
182+
case "invalid_model_string": {
183+
const formatted = formatSendMessageError(error);
178184
return {
179185
id: Date.now().toString(),
180186
type: "error",
181187
title: "Invalid Model Format",
182-
message: error.message,
188+
message: formatted.message,
183189
solution: (
184190
<>
185191
<SolutionLabel>Expected Format:</SolutionLabel>
186192
provider:model-name (e.g., anthropic:claude-opus-4-1)
187193
</>
188194
),
189195
};
196+
}
190197

191198
case "unknown":
192-
default:
199+
default: {
200+
const formatted = formatSendMessageError(error);
193201
return {
194202
id: Date.now().toString(),
195203
type: "error",
196204
title: "Message Send Failed",
197-
message: error.raw || "An unexpected error occurred while sending your message.",
205+
message: formatted.message,
198206
};
207+
}
199208
}
200209
};

src/components/Messages/ChatBarrier/RetryBarrier.tsx

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import { usePersistedState, updatePersistedState } from "@/hooks/usePersistedSta
33
import { getRetryStateKey, getAutoRetryKey } from "@/constants/storage";
44
import { CUSTOM_EVENTS, createCustomEvent } from "@/constants/events";
55
import { cn } from "@/lib/utils";
6-
import type { SendMessageError } from "@/types/errors";
76
import type { RetryState } from "@/hooks/useResumeManager";
87
import { useWorkspaceState } from "@/stores/WorkspaceStore";
98
import { isEligibleForAutoRetry, isNonRetryableSendError } from "@/utils/messages/retryEligibility";
9+
import { formatSendMessageError } from "@/utils/errors/formatSendError";
1010

1111
interface RetryBarrierProps {
1212
workspaceId: string;
@@ -112,19 +112,14 @@ export const RetryBarrier: React.FC<RetryBarrierProps> = ({ workspaceId, classNa
112112
setAutoRetry(false);
113113
};
114114

115-
// Format error message for display
116-
const getErrorMessage = (error: SendMessageError): string => {
117-
switch (error.type) {
118-
case "api_key_not_found":
119-
return `API key not found for ${error.provider}. Configure with /providers set ${error.provider} apiKey YOUR_KEY`;
120-
case "provider_not_supported":
121-
return `Provider ${error.provider} is not supported yet.`;
122-
case "invalid_model_string":
123-
return error.message;
124-
case "unknown":
125-
default:
126-
return error.raw || "Unknown error occurred";
127-
}
115+
// Format error message for display (centralized logic)
116+
const getErrorMessage = (error: typeof lastError): string => {
117+
if (!error) return "";
118+
const formatted = formatSendMessageError(error);
119+
// Combine message with command if available
120+
return formatted.providerCommand
121+
? `${formatted.message} Configure with ${formatted.providerCommand}`
122+
: formatted.message;
128123
};
129124

130125
if (effectiveAutoRetry) {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Centralized error message formatting for SendMessageError types
3+
* Used by both RetryBarrier and ChatInputToasts
4+
*/
5+
6+
import type { SendMessageError } from "@/types/errors";
7+
8+
export interface FormattedError {
9+
message: string;
10+
providerCommand?: string; // e.g., "/providers set anthropic apiKey YOUR_KEY"
11+
}
12+
13+
/**
14+
* Format a SendMessageError into a user-friendly message
15+
* Returns both the message and an optional command suggestion
16+
*/
17+
export function formatSendMessageError(error: SendMessageError): FormattedError {
18+
switch (error.type) {
19+
case "api_key_not_found":
20+
return {
21+
message: `API key not found for ${error.provider}.`,
22+
providerCommand: `/providers set ${error.provider} apiKey YOUR_API_KEY`,
23+
};
24+
25+
case "provider_not_supported":
26+
return {
27+
message: `Provider ${error.provider} is not supported yet.`,
28+
};
29+
30+
case "invalid_model_string":
31+
return {
32+
message: error.message,
33+
};
34+
35+
case "unknown":
36+
return {
37+
message: error.raw || "Unknown error occurred",
38+
};
39+
}
40+
}

0 commit comments

Comments
 (0)