From 4bbca30990424575273c0fc788fc65dfc7ba1bbc Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Sat, 11 Jul 2026 22:42:35 +0530 Subject: [PATCH] fix(plugin-sdk): keep shipped ErrorKind/detectErrorKind as deprecated compat The latest stable package exposes both names via the deprecated openclaw/plugin-sdk/infra-runtime subpath. Compat now lives in the barrel itself with the old substring semantics and a removal plan; core runtime no longer uses them. Also converts the chat mapping switch to an if-chain for switch-exhaustiveness lint. --- src/gateway/server-chat.ts | 12 ++++----- src/plugin-sdk/infra-runtime.ts | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/gateway/server-chat.ts b/src/gateway/server-chat.ts index 50e986b35aa9..af597b9962e6 100644 --- a/src/gateway/server-chat.ts +++ b/src/gateway/server-chat.ts @@ -243,12 +243,12 @@ export function resolveChatErrorKindFromError(error: unknown): ChatErrorKind | u ) { return "refusal"; } - switch (resolveFailoverReasonFromError(error)) { - case "rate_limit": - case "overloaded": - return "rate_limit"; - case "context_overflow": - return "context_length"; + const reason = resolveFailoverReasonFromError(error); + if (reason === "rate_limit" || reason === "overloaded") { + return "rate_limit"; + } + if (reason === "context_overflow") { + return "context_length"; } // FailoverReason "timeout" is the retryable-transient bucket and deliberately // swallows generic 5xx; only genuinely timeout-shaped errors get the badge. diff --git a/src/plugin-sdk/infra-runtime.ts b/src/plugin-sdk/infra-runtime.ts index e17ece4d7cc9..99220911bf96 100644 --- a/src/plugin-sdk/infra-runtime.ts +++ b/src/plugin-sdk/infra-runtime.ts @@ -19,6 +19,52 @@ export { export * from "../infra/diagnostic-flags.js"; export * from "../infra/env.js"; export * from "../infra/errors.js"; +import { extractErrorCode, formatErrorMessage } from "../infra/errors.js"; + +/** @deprecated Shipped compat only (removed from core in #104546); no core caller. Removal with the next plugin-SDK major. */ +export type ErrorKind = "refusal" | "timeout" | "rate_limit" | "context_length" | "unknown"; + +/** + * @deprecated Shipped compat only; preserves the old substring semantics for + * external plugins. Core chat classification now maps canonical failover + * reasons (see gateway resolveChatErrorKindFromError). Removal with the next + * plugin-SDK major. + */ +export function detectErrorKind(err: unknown): ErrorKind | undefined { + if (err === undefined) { + return undefined; + } + const message = formatErrorMessage(err).toLowerCase(); + const code = extractErrorCode(err)?.toLowerCase(); + if ( + message.includes("refusal") || + message.includes("content_filter") || + message.includes("sensitive") || + message.includes("unhandled stop reason: refusal_policy") + ) { + return "refusal"; + } + if ( + message.includes("rate limit") || + message.includes("too many requests") || + message.includes("429") || + code === "429" + ) { + return "rate_limit"; + } + if (message.includes("timeout") || code === "etimedout" || code === "timeout") { + return "timeout"; + } + if ( + message.includes("context length") || + message.includes("too many tokens") || + message.includes("token limit") || + message.includes("context_window") + ) { + return "context_length"; + } + return undefined; +} export * from "../infra/exec-approval-command-display.ts"; export * from "../infra/exec-approval-channel-runtime.ts"; export * from "../infra/exec-approval-reply.ts";