UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

107 lines (106 loc) 5.48 kB
import { r as asNullableRecord } from "./record-coerce-DItp3I4t.js"; //#region packages/gateway-protocol/src/gateway-error-details.ts /** Gateway JSON-RPC style error codes shared by clients and server handlers. */ const ErrorCodes = { /** @deprecated Retained for source compatibility; no current server emitter. */ NOT_LINKED: "NOT_LINKED", /** Device exists but still needs an explicit pairing approval. */ NOT_PAIRED: "NOT_PAIRED", /** @deprecated Retained for source compatibility; no current server emitter. */ AGENT_TIMEOUT: "AGENT_TIMEOUT", /** Request payload failed protocol validation or method preconditions. */ INVALID_REQUEST: "INVALID_REQUEST", /** Authenticated caller lacks permission for the requested operation. */ FORBIDDEN: "FORBIDDEN", /** Approval resolution referenced a missing or expired approval request. */ APPROVAL_NOT_FOUND: "APPROVAL_NOT_FOUND", /** Gateway service or required backend is temporarily unavailable. */ UNAVAILABLE: "UNAVAILABLE" }; /** Stable discriminants for structured method-level failures. */ const GatewayErrorDetailCodes = { CRON_JOB_NOT_FOUND: "CRON_JOB_NOT_FOUND", MISSING_SCOPE: "MISSING_SCOPE", MCP_APP_VIEW_EXPIRED: "MCP_APP_VIEW_EXPIRED", OUTBOUND_DELIVERY_QUEUED: "OUTBOUND_DELIVERY_QUEUED", USER_PREFS_LIMIT_EXCEEDED: "USER_PREFS_LIMIT_EXCEEDED", SESSION_COMPANION_BUSY: "SESSION_COMPANION_BUSY", SKILL_PROPOSAL_REVISION_CHANGED: "SKILL_PROPOSAL_REVISION_CHANGED", PROJECT_CLONE_FAILED: "PROJECT_CLONE_FAILED", UNKNOWN_AGENT_ID: "UNKNOWN_AGENT_ID", WIZARD_NOT_FOUND: "WIZARD_NOT_FOUND", SETUP_ADMISSION_BUSY: "SETUP_ADMISSION_BUSY", GITHUB_PUBLICATION_SELECTION_REJECTED: "GITHUB_PUBLICATION_SELECTION_REJECTED" }; const LEGACY_MISSING_SCOPE_PATTERN = /\bmissing scope:\s*([a-z0-9._-]+)/i; const SHA256_PATTERN = /^[a-fA-F0-9]{64}$/; /** Reads a typed cron lookup miss without parsing operator-facing prose. */ function readCronJobNotFoundError(error) { const record = asNullableRecord(error); const details = asNullableRecord(record?.details); if (details?.code !== GatewayErrorDetailCodes.CRON_JOB_NOT_FOUND) return null; const jobId = typeof details.jobId === "string" ? details.jobId.trim() : ""; return jobId ? { code: GatewayErrorDetailCodes.CRON_JOB_NOT_FOUND, jobId } : null; } /** Builds the canonical stale-draft details shared by Skill Workshop RPCs. */ function buildSkillProposalRevisionChangedErrorDetails(params) { return { code: GatewayErrorDetailCodes.SKILL_PROPOSAL_REVISION_CHANGED, expectedRevisionHash: params.expectedRevisionHash, currentRevisionHash: params.currentRevisionHash }; } /** Reads a stale Skill Workshop decision without parsing operator-facing prose. */ function readSkillProposalRevisionChangedError(error) { const record = asNullableRecord(error); const details = asNullableRecord(record?.details); if (details?.code !== GatewayErrorDetailCodes.SKILL_PROPOSAL_REVISION_CHANGED) return null; const expectedRevisionHash = typeof details.expectedRevisionHash === "string" ? details.expectedRevisionHash : ""; const currentRevisionHash = typeof details.currentRevisionHash === "string" ? details.currentRevisionHash : ""; if (!SHA256_PATTERN.test(expectedRevisionHash) || !SHA256_PATTERN.test(currentRevisionHash)) return null; return buildSkillProposalRevisionChangedErrorDetails({ expectedRevisionHash, currentRevisionHash }); } /** Reads validated missing-scope details from an untrusted protocol payload. */ function readMissingScopeErrorDetails(details) { const record = asNullableRecord(details); if (record?.code !== GatewayErrorDetailCodes.MISSING_SCOPE) return null; const missingScope = typeof record.missingScope === "string" ? record.missingScope.trim() : ""; const requiredScopes = Array.isArray(record.requiredScopes) ? record.requiredScopes.map((scope) => typeof scope === "string" ? scope.trim() : "") : []; if (!missingScope || requiredScopes.length === 0 || requiredScopes.some((scope) => !scope)) return null; return { code: GatewayErrorDetailCodes.MISSING_SCOPE, missingScope, requiredScopes }; } function isMcpAppViewExpiredError(error) { const record = asNullableRecord(error); return asNullableRecord(record?.details)?.code === GatewayErrorDetailCodes.MCP_APP_VIEW_EXPIRED; } /** * Reads a method-level missing-scope failure, preferring structured details. * The message fallback keeps clients compatible with gateways predating structured details. */ function readMissingScopeError(error) { const record = asNullableRecord(error); if (!record) return null; const structured = readMissingScopeErrorDetails(record.details); if (structured) return structured; const gatewayError = record; const code = typeof gatewayError.gatewayCode === "string" ? gatewayError.gatewayCode : typeof gatewayError.code === "string" ? gatewayError.code : ""; if (code !== ErrorCodes.FORBIDDEN && code !== ErrorCodes.INVALID_REQUEST) return null; const missingScope = (typeof gatewayError.message === "string" ? gatewayError.message : "").match(LEGACY_MISSING_SCOPE_PATTERN)?.[1]; return missingScope ? { code: GatewayErrorDetailCodes.MISSING_SCOPE, missingScope, requiredScopes: [missingScope] } : null; } //#endregion export { readCronJobNotFoundError as a, readSkillProposalRevisionChangedError as c, isMcpAppViewExpiredError as i, GatewayErrorDetailCodes as n, readMissingScopeError as o, buildSkillProposalRevisionChangedErrorDetails as r, readMissingScopeErrorDetails as s, ErrorCodes as t };