























@@ -1,6 +1,9 @@
11import {
22ConnectErrorDetailCodes,
3+describePairingConnectRequirement,
34formatConnectPairingRequiredMessage,
5+readConnectPairingRequiredMessage,
6+readPairingConnectErrorDetails,
47} from "../../../src/gateway/protocol/connect-error-details.js";
58import { resolveGatewayErrorDetailCode } from "./gateway.ts";
69import { normalizeLowercaseStringOrEmpty } from "./string-coerce.ts";
@@ -20,6 +23,41 @@ function normalizeErrorMessage(message: unknown): string {
2023return "unknown error";
2124}
222526+function formatPairingRequiredError(error: ErrorWithMessageAndDetails): string {
27+const message = normalizeErrorMessage(error.message);
28+const normalizedMessage = normalizeLowercaseStringOrEmpty(message);
29+const pairing = readPairingConnectErrorDetails(error.details);
30+const pairingMessage = readConnectPairingRequiredMessage(message);
31+const pairingReason = pairing?.reason ?? pairingMessage?.reason;
32+if (normalizedMessage.startsWith("pairing required:") && pairingReason) {
33+return `gateway pairing required: ${describePairingConnectRequirement(pairingReason)}`;
34+}
35+if (pairingMessage && normalizedMessage !== "pairing required") {
36+return message;
37+}
38+39+const approvedRoles = pairing?.approvedRoles?.join(", ") ?? "none";
40+const requestedRole = pairing?.requestedRole ?? "none";
41+const approvedScopes = pairing?.approvedScopes?.join(", ") ?? "none";
42+const requestedScopes = pairing?.requestedScopes?.join(", ") ?? "none";
43+switch (pairing?.reason) {
44+case "scope-upgrade":
45+if (pairing.approvedScopes || pairing.requestedScopes) {
46+return `device scope upgrade requires approval (approved: ${approvedScopes}; requested: ${requestedScopes})`;
47+}
48+return formatConnectPairingRequiredMessage(error.details);
49+case "role-upgrade":
50+if (pairing.approvedRoles || pairing.requestedRole) {
51+return `device role upgrade requires approval (approved: ${approvedRoles}; requested: ${requestedRole})`;
52+}
53+return formatConnectPairingRequiredMessage(error.details);
54+case "metadata-upgrade":
55+return "device reconnect details changed and require approval";
56+default:
57+return "gateway pairing required";
58+}
59+}
60+2361function formatErrorFromMessageAndDetails(error: ErrorWithMessageAndDetails): string {
2462const message = normalizeErrorMessage(error.message);
2563const detailCode = resolveGatewayErrorDetailCode(error);
@@ -32,7 +70,7 @@ function formatErrorFromMessageAndDetails(error: ErrorWithMessageAndDetails): st
3270case ConnectErrorDetailCodes.AUTH_RATE_LIMITED:
3371return "too many failed authentication attempts";
3472case ConnectErrorDetailCodes.PAIRING_REQUIRED:
35-return formatConnectPairingRequiredMessage(error.details);
73+return formatPairingRequiredError(error);
3674case ConnectErrorDetailCodes.CONTROL_UI_DEVICE_IDENTITY_REQUIRED:
3775return "device identity required (use HTTPS/localhost or allow insecure auth explicitly)";
3876case ConnectErrorDetailCodes.CONTROL_UI_ORIGIN_NOT_ALLOWED:
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。