Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/JAVA/Openclaw/src/gateway/protocol/   (KI Agentensystem Version 22©)  Datei vom 26.3.2026 mit Größe 15 kB image not shown  

Quelle  connect-error-details.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import { normalizeOptionalString } from "../../shared/string-coerce.js";

export const ConnectErrorDetailCodes = {
  AUTH_REQUIRED: "AUTH_REQUIRED",
  AUTH_UNAUTHORIZED: "AUTH_UNAUTHORIZED",
  AUTH_TOKEN_MISSING: "AUTH_TOKEN_MISSING",
  AUTH_TOKEN_MISMATCH: "AUTH_TOKEN_MISMATCH",
  AUTH_TOKEN_NOT_CONFIGURED: "AUTH_TOKEN_NOT_CONFIGURED",
  AUTH_PASSWORD_MISSING: "AUTH_PASSWORD_MISSING", // pragma: allowlist secret
  AUTH_PASSWORD_MISMATCH: "AUTH_PASSWORD_MISMATCH", // pragma: allowlist secret
  AUTH_PASSWORD_NOT_CONFIGURED: "AUTH_PASSWORD_NOT_CONFIGURED", // pragma: allowlist secret
  AUTH_BOOTSTRAP_TOKEN_INVALID: "AUTH_BOOTSTRAP_TOKEN_INVALID",
  AUTH_DEVICE_TOKEN_MISMATCH: "AUTH_DEVICE_TOKEN_MISMATCH",
  AUTH_RATE_LIMITED: "AUTH_RATE_LIMITED",
  AUTH_TAILSCALE_IDENTITY_MISSING: "AUTH_TAILSCALE_IDENTITY_MISSING",
  AUTH_TAILSCALE_PROXY_MISSING: "AUTH_TAILSCALE_PROXY_MISSING",
  AUTH_TAILSCALE_WHOIS_FAILED: "AUTH_TAILSCALE_WHOIS_FAILED",
  AUTH_TAILSCALE_IDENTITY_MISMATCH: "AUTH_TAILSCALE_IDENTITY_MISMATCH",
  CONTROL_UI_ORIGIN_NOT_ALLOWED: "CONTROL_UI_ORIGIN_NOT_ALLOWED",
  CONTROL_UI_DEVICE_IDENTITY_REQUIRED: "CONTROL_UI_DEVICE_IDENTITY_REQUIRED",
  DEVICE_IDENTITY_REQUIRED: "DEVICE_IDENTITY_REQUIRED",
  DEVICE_AUTH_INVALID: "DEVICE_AUTH_INVALID",
  DEVICE_AUTH_DEVICE_ID_MISMATCH: "DEVICE_AUTH_DEVICE_ID_MISMATCH",
  DEVICE_AUTH_SIGNATURE_EXPIRED: "DEVICE_AUTH_SIGNATURE_EXPIRED",
  DEVICE_AUTH_NONCE_REQUIRED: "DEVICE_AUTH_NONCE_REQUIRED",
  DEVICE_AUTH_NONCE_MISMATCH: "DEVICE_AUTH_NONCE_MISMATCH",
  DEVICE_AUTH_SIGNATURE_INVALID: "DEVICE_AUTH_SIGNATURE_INVALID",
  DEVICE_AUTH_PUBLIC_KEY_INVALID: "DEVICE_AUTH_PUBLIC_KEY_INVALID",
  PAIRING_REQUIRED: "PAIRING_REQUIRED",
} as const;

export type ConnectErrorDetailCode =
  (typeof ConnectErrorDetailCodes)[keyof typeof ConnectErrorDetailCodes];

export const ConnectPairingRequiredReasons = {
  NOT_PAIRED: "not-paired",
  ROLE_UPGRADE: "role-upgrade",
  SCOPE_UPGRADE: "scope-upgrade",
  METADATA_UPGRADE: "metadata-upgrade",
} as const;

export type ConnectPairingRequiredReason =
  (typeof ConnectPairingRequiredReasons)[keyof typeof ConnectPairingRequiredReasons];

export type ConnectRecoveryNextStep =
  | "retry_with_device_token"
  | "update_auth_configuration"
  | "update_auth_credentials"
  | "wait_then_retry"
  | "review_auth_configuration";

export type ConnectErrorRecoveryAdvice = {
  canRetryWithDeviceToken?: boolean;
  recommendedNextStep?: ConnectRecoveryNextStep;
};

export type PairingConnectErrorDetails = {
  code: typeof ConnectErrorDetailCodes.PAIRING_REQUIRED;
  reason?: ConnectPairingRequiredReason;
  requestId?: string;
  remediationHint?: string;
  deviceId?: string;
  requestedRole?: string;
  requestedScopes?: string[];
  approvedRoles?: string[];
  approvedScopes?: string[];
};

export type ConnectPairingRequiredDetails = Pick<
  PairingConnectErrorDetails,
  "reason" | "requestId"
>;

const CONNECT_RECOVERY_NEXT_STEP_VALUES: ReadonlySet<ConnectRecoveryNextStep> = new Set([
  "retry_with_device_token",
  "update_auth_configuration",
  "update_auth_credentials",
  "wait_then_retry",
  "review_auth_configuration",
]);

const CONNECT_PAIRING_REQUIRED_REASON_VALUES: ReadonlySet<ConnectPairingRequiredReason> = new Set([
  "not-paired",
  "role-upgrade",
  "scope-upgrade",
  "metadata-upgrade",
]);
const PAIRING_CONNECT_REQUEST_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;

const PAIRING_CONNECT_REASON_METADATA: Readonly<
  Record<
    ConnectPairingRequiredReason,
    {
      requirement: string;
      remediationHint: string;
      recoveryTitle: string;
    }
  >
> = {
  "not-paired": {
    requirement: "device is not approved yet",
    remediationHint: "Approve this device from the pending pairing requests.",
    recoveryTitle: "Gateway pairing approval required.",
  },
  "role-upgrade": {
    requirement: "device is asking for a higher role than currently approved",
    remediationHint: "Review the requested role upgrade, then approve the pending request.",
    recoveryTitle: "Gateway role upgrade approval required.",
  },
  "scope-upgrade": {
    requirement: "device is asking for more scopes than currently approved",
    remediationHint: "Review the requested scopes, then approve the pending upgrade.",
    recoveryTitle: "Gateway scope upgrade approval required.",
  },
  "metadata-upgrade": {
    requirement: "device identity changed and must be re-approved",
    remediationHint: "Review the refreshed device details, then approve the pending request.",
    recoveryTitle: "Gateway device refresh approval required.",
  },
};

const CONNECT_PAIRING_REQUIRED_MESSAGE_BY_REASON: Readonly<
  Record<ConnectPairingRequiredReason, string>
> = {
  "not-paired": "device pairing required",
  "role-upgrade": "role upgrade pending approval",
  "scope-upgrade": "scope upgrade pending approval",
  "metadata-upgrade": "device metadata change pending approval",
};

export function resolveAuthConnectErrorDetailCode(
  reason: string | undefined,
): ConnectErrorDetailCode {
  switch (reason) {
    case "token_missing":
      return ConnectErrorDetailCodes.AUTH_TOKEN_MISSING;
    case "token_mismatch":
      return ConnectErrorDetailCodes.AUTH_TOKEN_MISMATCH;
    case "token_missing_config":
      return ConnectErrorDetailCodes.AUTH_TOKEN_NOT_CONFIGURED;
    case "password_missing":
      return ConnectErrorDetailCodes.AUTH_PASSWORD_MISSING;
    case "password_mismatch":
      return ConnectErrorDetailCodes.AUTH_PASSWORD_MISMATCH;
    case "password_missing_config":
      return ConnectErrorDetailCodes.AUTH_PASSWORD_NOT_CONFIGURED;
    case "bootstrap_token_invalid":
      return ConnectErrorDetailCodes.AUTH_BOOTSTRAP_TOKEN_INVALID;
    case "tailscale_user_missing":
      return ConnectErrorDetailCodes.AUTH_TAILSCALE_IDENTITY_MISSING;
    case "tailscale_proxy_missing":
      return ConnectErrorDetailCodes.AUTH_TAILSCALE_PROXY_MISSING;
    case "tailscale_whois_failed":
      return ConnectErrorDetailCodes.AUTH_TAILSCALE_WHOIS_FAILED;
    case "tailscale_user_mismatch":
      return ConnectErrorDetailCodes.AUTH_TAILSCALE_IDENTITY_MISMATCH;
    case "rate_limited":
      return ConnectErrorDetailCodes.AUTH_RATE_LIMITED;
    case "device_token_mismatch":
      return ConnectErrorDetailCodes.AUTH_DEVICE_TOKEN_MISMATCH;
    case undefined:
      return ConnectErrorDetailCodes.AUTH_REQUIRED;
    default:
      return ConnectErrorDetailCodes.AUTH_UNAUTHORIZED;
  }
}

export function resolveDeviceAuthConnectErrorDetailCode(
  reason: string | undefined,
): ConnectErrorDetailCode {
  switch (reason) {
    case "device-id-mismatch":
      return ConnectErrorDetailCodes.DEVICE_AUTH_DEVICE_ID_MISMATCH;
    case "device-signature-stale":
      return ConnectErrorDetailCodes.DEVICE_AUTH_SIGNATURE_EXPIRED;
    case "device-nonce-missing":
      return ConnectErrorDetailCodes.DEVICE_AUTH_NONCE_REQUIRED;
    case "device-nonce-mismatch":
      return ConnectErrorDetailCodes.DEVICE_AUTH_NONCE_MISMATCH;
    case "device-signature":
      return ConnectErrorDetailCodes.DEVICE_AUTH_SIGNATURE_INVALID;
    case "device-public-key":
      return ConnectErrorDetailCodes.DEVICE_AUTH_PUBLIC_KEY_INVALID;
    default:
      return ConnectErrorDetailCodes.DEVICE_AUTH_INVALID;
  }
}

export function readConnectErrorDetailCode(details: unknown): string | null {
  if (!details || typeof details !== "object" || Array.isArray(details)) {
    return null;
  }
  const code = (details as { code?: unknown }).code;
  return typeof code === "string" && code.trim().length > 0 ? code : null;
}

export function readConnectErrorRecoveryAdvice(details: unknown): ConnectErrorRecoveryAdvice {
  if (!details || typeof details !== "object" || Array.isArray(details)) {
    return {};
  }
  const raw = details as {
    canRetryWithDeviceToken?: unknown;
    recommendedNextStep?: unknown;
  };
  const canRetryWithDeviceToken =
    typeof raw.canRetryWithDeviceToken === "boolean" ? raw.canRetryWithDeviceToken : undefined;
  const normalizedNextStep = normalizeOptionalString(raw.recommendedNextStep) ?? "";
  const recommendedNextStep = CONNECT_RECOVERY_NEXT_STEP_VALUES.has(
    normalizedNextStep as ConnectRecoveryNextStep,
  )
    ? (normalizedNextStep as ConnectRecoveryNextStep)
    : undefined;
  return {
    canRetryWithDeviceToken,
    recommendedNextStep,
  };
}

function normalizePairingConnectReason(value: unknown): ConnectPairingRequiredReason | undefined {
  const normalized = normalizeOptionalString(value) ?? "";
  return CONNECT_PAIRING_REQUIRED_REASON_VALUES.has(normalized as ConnectPairingRequiredReason)
    ? (normalized as ConnectPairingRequiredReason)
    : undefined;
}

export function normalizePairingConnectRequestId(value: unknown): string | undefined {
  const normalized = normalizeOptionalString(value);
  return normalized && PAIRING_CONNECT_REQUEST_ID_PATTERN.test(normalized) ? normalized : undefined;
}

function normalizeStringArray(value: unknown): string[] | undefined {
  if (!Array.isArray(value)) {
    return undefined;
  }
  const normalized = value
    .map((item) => normalizeOptionalString(item))
    .filter((item): item is string => Boolean(item));
  return normalized.length > 0 ? normalized : [];
}

function createPairingConnectErrorDetails(params: {
  reason?: ConnectPairingRequiredReason;
  requestId?: string;
  remediationHint?: string;
  deviceId?: string;
  requestedRole?: string;
  requestedScopes?: string[];
  approvedRoles?: string[];
  approvedScopes?: string[];
}): PairingConnectErrorDetails {
  return {
    code: ConnectErrorDetailCodes.PAIRING_REQUIRED,
    ...(params.reason ? { reason: params.reason } : {}),
    ...(params.requestId ? { requestId: params.requestId } : {}),
    ...(params.remediationHint ? { remediationHint: params.remediationHint } : {}),
    ...(params.deviceId ? { deviceId: params.deviceId } : {}),
    ...(params.requestedRole ? { requestedRole: params.requestedRole } : {}),
    ...(params.requestedScopes ? { requestedScopes: params.requestedScopes } : {}),
    ...(params.approvedRoles ? { approvedRoles: params.approvedRoles } : {}),
    ...(params.approvedScopes ? { approvedScopes: params.approvedScopes } : {}),
  };
}

export function describePairingConnectRequirement(
  reason: ConnectPairingRequiredReason | undefined,
): string {
  return reason
    ? PAIRING_CONNECT_REASON_METADATA[reason].requirement
    : "device approval is required";
}

export function buildPairingConnectErrorMessage(
  reason: ConnectPairingRequiredReason | undefined,
): string {
  return reason
    ? `pairing required: ${describePairingConnectRequirement(reason)}`
    : "pairing required";
}

export function buildPairingConnectRemediationHint(
  reason: ConnectPairingRequiredReason | undefined,
): string {
  return reason
    ? PAIRING_CONNECT_REASON_METADATA[reason].remediationHint
    : "Approve the pending device request before retrying.";
}

export function buildPairingConnectRecoveryTitle(
  reason: ConnectPairingRequiredReason | undefined,
): string {
  return reason
    ? PAIRING_CONNECT_REASON_METADATA[reason].recoveryTitle
    : "Gateway pairing approval required.";
}

export function buildPairingConnectErrorDetails(params: {
  reason: ConnectPairingRequiredReason | undefined;
  requestId?: string;
  remediationHint?: string;
  deviceId?: string;
  requestedRole?: string;
  requestedScopes?: string[];
  approvedRoles?: string[];
  approvedScopes?: string[];
}): PairingConnectErrorDetails {
  const requestId = normalizePairingConnectRequestId(params.requestId);
  const remediationHint =
    normalizeOptionalString(params.remediationHint) ??
    buildPairingConnectRemediationHint(params.reason);
  const deviceId = normalizeOptionalString(params.deviceId);
  const requestedRole = normalizeOptionalString(params.requestedRole);
  const requestedScopes = normalizeStringArray(params.requestedScopes);
  const approvedRoles = normalizeStringArray(params.approvedRoles);
  const approvedScopes = normalizeStringArray(params.approvedScopes);
  return createPairingConnectErrorDetails({
    reason: params.reason,
    requestId,
    remediationHint,
    deviceId,
    requestedRole,
    requestedScopes,
    approvedRoles,
    approvedScopes,
  });
}

export function buildPairingConnectCloseReason(params: {
  reason: ConnectPairingRequiredReason | undefined;
  requestId?: string;
}): string {
  const requestId = normalizePairingConnectRequestId(params.requestId);
  const message = buildPairingConnectErrorMessage(params.reason);
  return requestId ? `${message} (requestId: ${requestId})` : message;
}

export function readPairingConnectErrorDetails(
  details: unknown,
): PairingConnectErrorDetails | null {
  if (readConnectErrorDetailCode(details) !== ConnectErrorDetailCodes.PAIRING_REQUIRED) {
    return null;
  }
  if (!details || typeof details !== "object" || Array.isArray(details)) {
    return null;
  }
  const raw = details as {
    reason?: unknown;
    requestId?: unknown;
    remediationHint?: unknown;
    deviceId?: unknown;
    requestedRole?: unknown;
    requestedScopes?: unknown;
    approvedRoles?: unknown;
    approvedScopes?: unknown;
  };
  const reason = normalizePairingConnectReason(raw.reason);
  const requestId = normalizePairingConnectRequestId(raw.requestId);
  const remediationHint =
    normalizeOptionalString(raw.remediationHint) ?? buildPairingConnectRemediationHint(reason);
  const deviceId = normalizeOptionalString(raw.deviceId);
  const requestedRole = normalizeOptionalString(raw.requestedRole);
  const requestedScopes = normalizeStringArray(raw.requestedScopes);
  const approvedRoles = normalizeStringArray(raw.approvedRoles);
  const approvedScopes = normalizeStringArray(raw.approvedScopes);
  return createPairingConnectErrorDetails({
    reason,
    requestId,
    remediationHint,
    deviceId,
    requestedRole,
    requestedScopes,
    approvedRoles,
    approvedScopes,
  });
}

export function readConnectPairingRequiredDetails(
  details: unknown,
): ConnectPairingRequiredDetails | null {
  const pairing = readPairingConnectErrorDetails(details);
  if (!pairing) {
    return null;
  }
  return {
    ...(pairing.requestId ? { requestId: pairing.requestId } : {}),
    ...(pairing.reason ? { reason: pairing.reason } : {}),
  };
}

export function readConnectPairingRequiredMessage(
  message: string | null | undefined,
): ConnectPairingRequiredDetails | null {
  const normalizedMessage = normalizeOptionalString(message);
  if (!normalizedMessage) {
    return null;
  }
  const normalized = normalizedMessage.trim().toLowerCase();
  let reason: ConnectPairingRequiredReason | undefined;
  for (const [candidate, prefix] of Object.entries(
    CONNECT_PAIRING_REQUIRED_MESSAGE_BY_REASON,
  ) as Array<[ConnectPairingRequiredReason, string]>) {
    if (normalized.includes(prefix)) {
      reason = candidate;
      break;
    }
  }
  if (!reason && normalized.includes("pairing required")) {
    reason = ConnectPairingRequiredReasons.NOT_PAIRED;
  }
  if (!reason) {
    return null;
  }
  const requestId = normalizePairingConnectRequestId(
    normalizedMessage.match(/\(requestId:\s*([^\s)]+)\)/i)?.[1],
  );
  return {
    ...(requestId ? { requestId } : {}),
    reason,
  };
}

export function formatConnectPairingRequiredMessage(details: unknown): string {
  const pairing = readPairingConnectErrorDetails(details);
  const base =
    CONNECT_PAIRING_REQUIRED_MESSAGE_BY_REASON[
      pairing?.reason ?? ConnectPairingRequiredReasons.NOT_PAIRED
    ];
  return pairing?.requestId ? `${base} (requestId: ${pairing.requestId})` : base;
}

export function formatConnectErrorMessage(params: { message?: string; details?: unknown }): string {
  if (readConnectErrorDetailCode(params.details) === ConnectErrorDetailCodes.PAIRING_REQUIRED) {
    return formatConnectPairingRequiredMessage(params.details);
  }
  return normalizeOptionalString(params.message) ?? "gateway request failed";
}

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.