feat(error-handling): Implement comprehensive gateway error handling with user-friendly messages

- Add comprehensive gateway error handler with friendly user messages
- Handle subscription status errors (inactive BYOK, subscription required)
- Handle authentication errors (invalid API keys, missing tokens)
- Handle rate limiting with retry suggestions
- Handle model availability and validation errors
- Handle network connectivity issues
- Provide actionable solutions for each error type
- Prevent duplicate error messages by returning early after showing friendly error
- Fix telemetry tests to use correct environment variable names (TASKMASTER_API_KEY)
- Fix config manager getUserId function to properly save default userId to file
- All tests now passing (34 test suites, 360 tests)
This commit is contained in:
Eyal Toledano
2025-06-02 12:34:47 -04:00
parent 2819be51d3
commit 58aa0992f6
8 changed files with 304 additions and 87 deletions

View File

@@ -44,6 +44,7 @@ import {
} from "../../src/ai-providers/index.js";
import { zodToJsonSchema } from "zod-to-json-schema";
import { handleGatewayError } from "./utils/gatewayErrorHandler.js";
// Create provider instances
const PROVIDERS = {
@@ -346,31 +347,51 @@ async function _callGatewayAI(
headers["X-User-Email"] = userEmail;
}
const response = await fetch(endpoint, {
method: "POST",
headers,
body: JSON.stringify(requestBody),
});
try {
const response = await fetch(endpoint, {
method: "POST",
headers,
body: JSON.stringify(requestBody),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Gateway AI call failed: ${response.status} ${errorText}`);
if (!response.ok) {
const errorText = await response.text();
throw new Error(
`Gateway AI call failed: ${response.status} ${errorText}`
);
}
const result = await response.json();
if (!result.success) {
throw new Error(result.error || "Gateway AI call failed");
}
// Return the AI response in the expected format
return {
text: result.data.text,
object: result.data.object,
usage: result.data.usage,
// Include any account info returned from gateway
accountInfo: result.accountInfo,
};
} catch (error) {
// Use the enhanced error handler for user-friendly messages
handleGatewayError(error, commandName);
// Throw a much cleaner error message to prevent ugly double logging
const match = error.message.match(/Gateway AI call failed: (\d+)/);
if (match) {
const statusCode = match[1];
throw new Error(
`TaskMaster gateway error (${statusCode}). See details above.`
);
} else {
throw new Error(
"TaskMaster gateway communication failed. See details above."
);
}
}
const result = await response.json();
if (!result.success) {
throw new Error(result.error || "Gateway AI call failed");
}
// Return the AI response in the expected format
return {
text: result.data.text,
object: result.data.object,
usage: result.data.usage,
// Include any account info returned from gateway
accountInfo: result.accountInfo,
};
}
/**