mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-17 11:31:38 +00:00
* fix(tui): keep skill approvals in the terminal * fix(tui): keep skill approvals in the terminal
54 lines
2.0 KiB
TypeScript
54 lines
2.0 KiB
TypeScript
// Detects approval-not-found errors across gateway response shapes.
|
|
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
|
|
|
const INVALID_REQUEST = "INVALID_REQUEST";
|
|
const APPROVAL_NOT_FOUND = "APPROVAL_NOT_FOUND";
|
|
const APPROVAL_ALREADY_RESOLVED = "APPROVAL_ALREADY_RESOLVED";
|
|
|
|
function readErrorCode(value: unknown): string | null {
|
|
return typeof value === "string" ? (normalizeOptionalString(value) ?? null) : null;
|
|
}
|
|
|
|
function readApprovalErrorDetailsReason(value: unknown): string | null {
|
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
return null;
|
|
}
|
|
const reason = (value as { reason?: unknown }).reason;
|
|
return typeof reason === "string" ? (normalizeOptionalString(reason) ?? null) : null;
|
|
}
|
|
|
|
/**
|
|
* Detects approval-not-found failures across gateway error shapes.
|
|
* Kept broad enough for legacy message-only errors emitted before structured codes.
|
|
*/
|
|
export function isApprovalNotFoundError(err: unknown): boolean {
|
|
if (!(err instanceof Error)) {
|
|
return false;
|
|
}
|
|
const gatewayCode = readErrorCode((err as { gatewayCode?: unknown }).gatewayCode);
|
|
if (gatewayCode === APPROVAL_NOT_FOUND) {
|
|
return true;
|
|
}
|
|
const detailsReason = readApprovalErrorDetailsReason((err as { details?: unknown }).details);
|
|
if (gatewayCode === INVALID_REQUEST && detailsReason === APPROVAL_NOT_FOUND) {
|
|
return true;
|
|
}
|
|
return /unknown or expired approval id/i.test(err.message);
|
|
}
|
|
|
|
/** Detects approval failures that mean a pending prompt is no longer actionable. */
|
|
export function isApprovalStaleError(err: unknown): boolean {
|
|
if (isApprovalNotFoundError(err)) {
|
|
return true;
|
|
}
|
|
if (!(err instanceof Error)) {
|
|
return false;
|
|
}
|
|
const gatewayCode = readErrorCode((err as { gatewayCode?: unknown }).gatewayCode);
|
|
const detailsReason = readApprovalErrorDetailsReason((err as { details?: unknown }).details);
|
|
return (
|
|
(gatewayCode === INVALID_REQUEST && detailsReason === APPROVAL_ALREADY_RESOLVED) ||
|
|
/approval already resolved/i.test(err.message)
|
|
);
|
|
}
|