Files
openclaw/src/agents/pi-embedded-helpers.ts
Glucksberg d4c560853c fix(errors): show clear billing error instead of cryptic API response (#8391)
* fix(errors): return clear billing error message instead of cryptic raw error (#8136)

When an LLM API provider returns a credit/billing-related error (HTTP 402,
insufficient credits, low balance, etc.), OpenClaw now shows a clear,
actionable message instead of passing through the raw/cryptic error text:

  ⚠️ API provider returned a billing error — your API key has run out of
  credits or has an insufficient balance. Check your provider's billing
  dashboard and top up or switch to a different API key.

Changes:
- formatAssistantErrorText: detect billing errors via isBillingErrorMessage()
  and return a user-friendly message (placed before the generic HTTP/JSON
  error fallthrough)
- sanitizeUserFacingText: same billing detection for the sanitization path
- pi-embedded-runner/run.ts: add billingFailure detection in the profile
  exhaustion fallback, so the FailoverError message is billing-specific
- Added 3 new tests for credit balance, HTTP 402, and insufficient credits

* fix: extract billing error message to shared constant
2026-02-05 13:58:43 -08:00

60 lines
1.8 KiB
TypeScript

export {
buildBootstrapContextFiles,
DEFAULT_BOOTSTRAP_MAX_CHARS,
ensureSessionHeader,
resolveBootstrapMaxChars,
stripThoughtSignatures,
} from "./pi-embedded-helpers/bootstrap.js";
export {
BILLING_ERROR_USER_MESSAGE,
classifyFailoverReason,
formatRawAssistantErrorForUi,
formatAssistantErrorText,
getApiErrorPayloadFingerprint,
isAuthAssistantError,
isAuthErrorMessage,
isBillingAssistantError,
parseApiErrorInfo,
sanitizeUserFacingText,
isBillingErrorMessage,
isCloudCodeAssistFormatError,
isCompactionFailureError,
isContextOverflowError,
isLikelyContextOverflowError,
isFailoverAssistantError,
isFailoverErrorMessage,
isImageDimensionErrorMessage,
isImageSizeError,
isOverloadedErrorMessage,
isRawApiErrorPayload,
isRateLimitAssistantError,
isRateLimitErrorMessage,
isTimeoutErrorMessage,
parseImageDimensionError,
parseImageSizeError,
} from "./pi-embedded-helpers/errors.js";
export { isGoogleModelApi, sanitizeGoogleTurnOrdering } from "./pi-embedded-helpers/google.js";
export { downgradeOpenAIReasoningBlocks } from "./pi-embedded-helpers/openai.js";
export {
isEmptyAssistantMessageContent,
sanitizeSessionMessagesImages,
} from "./pi-embedded-helpers/images.js";
export {
isMessagingToolDuplicate,
isMessagingToolDuplicateNormalized,
normalizeTextForComparison,
} from "./pi-embedded-helpers/messaging-dedupe.js";
export { pickFallbackThinkingLevel } from "./pi-embedded-helpers/thinking.js";
export {
mergeConsecutiveUserTurns,
validateAnthropicTurns,
validateGeminiTurns,
} from "./pi-embedded-helpers/turns.js";
export type { EmbeddedContextFile, FailoverReason } from "./pi-embedded-helpers/types.js";
export type { ToolCallIdMode } from "./tool-call-id.js";
export { isValidCloudCodeAssistToolId, sanitizeToolCallId } from "./tool-call-id.js";