Merge 953a401c2fbca7627840675315b388fe364ffe13 into 9fb78453e088cd7b553d7779faa0de5c83708e70
This commit is contained in:
commit
a32bc55391
@ -154,13 +154,31 @@ describe("trigger handling", () => {
|
||||
{
|
||||
error: "sandbox is not defined.",
|
||||
expected:
|
||||
"⚠️ Agent failed before reply: sandbox is not defined.\nLogs: openclaw logs --follow",
|
||||
"Something unexpected happened. Try /new to start a fresh conversation, or try again in a moment.",
|
||||
},
|
||||
{
|
||||
error: "Context window exceeded",
|
||||
expected:
|
||||
"⚠️ Context overflow — prompt too large for this model. Try a shorter message or a larger-context model.",
|
||||
},
|
||||
{
|
||||
error: "rate_limit_exceeded: API rate limit exceeded",
|
||||
expected: "The AI service is busy. Please wait a moment and try again.",
|
||||
},
|
||||
{
|
||||
error: "401 Unauthorized: Invalid API key",
|
||||
expected:
|
||||
"I couldn't connect to the AI service. Please verify your API key is configured correctly.",
|
||||
},
|
||||
{
|
||||
error: "402 Payment Required: billing limit exceeded",
|
||||
expected:
|
||||
"I've reached my limit with the AI service. Please check your account balance and try again.",
|
||||
},
|
||||
{
|
||||
error: "408 Request Timeout: connection timed out",
|
||||
expected: "The request timed out. Please try again, or start a fresh session with /new.",
|
||||
},
|
||||
] as const;
|
||||
for (const testCase of errorCases) {
|
||||
runEmbeddedPiAgentMock.mockClear();
|
||||
|
||||
@ -7,13 +7,16 @@ import { getCliSessionId } from "../../agents/cli-session.js";
|
||||
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
||||
import { isCliProvider } from "../../agents/model-selection.js";
|
||||
import {
|
||||
BILLING_ERROR_USER_MESSAGE,
|
||||
isAuthErrorMessage,
|
||||
isBillingErrorMessage,
|
||||
isCompactionFailureError,
|
||||
isContextOverflowError,
|
||||
isBillingErrorMessage,
|
||||
isLikelyContextOverflowError,
|
||||
isTransientHttpError,
|
||||
isOverloadedErrorMessage,
|
||||
isRateLimitErrorMessage,
|
||||
sanitizeUserFacingText,
|
||||
isTimeoutErrorMessage,
|
||||
isTransientHttpError,
|
||||
} from "../../agents/pi-embedded-helpers.js";
|
||||
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
||||
import {
|
||||
@ -537,6 +540,12 @@ export async function runAgentTurnWithFallback(params: {
|
||||
const isRoleOrderingError = /incorrect role information|roles must alternate/i.test(message);
|
||||
const isTransientHttp = isTransientHttpError(message);
|
||||
|
||||
const isRateLimit = isRateLimitErrorMessage(message);
|
||||
const isAuthError = isAuthErrorMessage(message);
|
||||
const isBillingError = isBillingErrorMessage(message);
|
||||
const isTimeoutError = isTimeoutErrorMessage(message);
|
||||
const isOverloaded = isOverloadedErrorMessage(message);
|
||||
|
||||
if (
|
||||
isCompactionFailure &&
|
||||
!didResetAfterCompactionFailure &&
|
||||
@ -623,17 +632,30 @@ export async function runAgentTurnWithFallback(params: {
|
||||
}
|
||||
|
||||
defaultRuntime.error(`Embedded agent failed before reply: ${message}`);
|
||||
const safeMessage = isTransientHttp
|
||||
? sanitizeUserFacingText(message, { errorContext: true })
|
||||
: message;
|
||||
const trimmedMessage = safeMessage.replace(/\.\s*$/, "");
|
||||
const fallbackText = isBilling
|
||||
? BILLING_ERROR_USER_MESSAGE
|
||||
: isContextOverflow
|
||||
? "⚠️ Context overflow — prompt too large for this model. Try a shorter message or a larger-context model."
|
||||
: isRoleOrderingError
|
||||
? "⚠️ Message ordering conflict - please try again. If this persists, use /new to start a fresh session."
|
||||
: `⚠️ Agent failed before reply: ${trimmedMessage}.\nLogs: openclaw logs --follow`;
|
||||
|
||||
let fallbackText: string;
|
||||
|
||||
if (isContextOverflow) {
|
||||
fallbackText =
|
||||
"⚠️ Context overflow — prompt too large for this model. Try a shorter message or a larger-context model.";
|
||||
} else if (isRoleOrderingError) {
|
||||
fallbackText =
|
||||
"⚠️ Message ordering conflict - please try again. If this persists, use /new to start a fresh session.";
|
||||
} else if (isRateLimit || isOverloaded) {
|
||||
fallbackText = "The AI service is busy. Please wait a moment and try again.";
|
||||
} else if (isAuthError) {
|
||||
fallbackText =
|
||||
"I couldn't connect to the AI service. Please verify your API key is configured correctly.";
|
||||
} else if (isBillingError) {
|
||||
fallbackText =
|
||||
"I've reached my limit with the AI service. Please check your account balance and try again.";
|
||||
} else if (isTimeoutError) {
|
||||
fallbackText =
|
||||
"The request timed out. Please try again, or start a fresh session with /new.";
|
||||
} else {
|
||||
fallbackText =
|
||||
"Something unexpected happened. Try /new to start a fresh conversation, or try again in a moment.";
|
||||
}
|
||||
|
||||
return {
|
||||
kind: "final",
|
||||
|
||||
@ -1485,7 +1485,7 @@ describe("runReplyAgent typing (heartbeat)", () => {
|
||||
const res = await run();
|
||||
|
||||
expect(res).toMatchObject({
|
||||
text: expect.stringContaining("Agent failed before reply"),
|
||||
text: "Something unexpected happened. Try /new to start a fresh conversation, or try again in a moment.",
|
||||
});
|
||||
expect(sessionStore.main).toBeDefined();
|
||||
await expect(fs.access(transcriptPath)).resolves.toBeUndefined();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user