Merge 953a401c2fbca7627840675315b388fe364ffe13 into 9fb78453e088cd7b553d7779faa0de5c83708e70

This commit is contained in:
Sahil Satralkar 2026-03-20 22:19:12 -07:00 committed by GitHub
commit a32bc55391
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 56 additions and 16 deletions

View File

@ -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();

View File

@ -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",

View File

@ -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();