UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

136 lines (135 loc) 6.86 kB
import { s as visibleWidth } from "./ansi-DrXAcdMD.js"; import { n as sanitizeTerminalText } from "./safe-text-BGBqp1a4.js"; import { i as GATEWAY_CLIENT_NAMES, r as GATEWAY_CLIENT_MODES } from "./client-info-B1bPgeKr.js"; import { o as classifyGatewayConnectFailure } from "./connect-error-details-DaOfGNN8.js"; import { r as projectGatewayUrlForDiagnostics } from "./connection-details-dzrfNKN8.js"; import "./client-I-RoP1Al.js"; import { t as GatewayClientRequestError } from "./request-error-BSFClQsA.js"; import { o as callGateway, r as GatewayStoredDeviceAuthUnavailableError } from "./call-BWR5pPgw.js"; import { t as GatewayTransportError } from "./transport-error-D_LRKgla.js"; import { t as resolveCanonicalMainSessionKey } from "./main-session-key-DOmwwwt0.js"; import { t as formatTextCell } from "./text-format-C-twF_E2.js"; import { r as parseSessionTargetInput, t as SessionTargetParseError } from "./session-ref-B0_fEttv.js"; //#region src/cli/session-target.ts function gatewayUrlForTarget(target) { return target.kind === "url" ? `${target.origin}${target.basePath}` : void 0; } async function callSessionTargetGateway(params) { const explicitUrl = params.gateway.url?.trim() || void 0; try { return await callGateway({ config: params.gateway.config, url: explicitUrl, token: params.gateway.token, password: params.gateway.password, tlsFingerprint: params.gateway.tlsFingerprint, method: params.method, params: params.request, mode: GATEWAY_CLIENT_MODES.CLI, clientName: GATEWAY_CLIENT_NAMES.CLI, ...explicitUrl ? { useStoredDeviceAuth: true, requiredStoredDeviceAuthScopes: [params.requiredScope] } : {} }); } catch (error) { throw shapeTargetError(error, explicitUrl, params.shortRef === true); } } function candidateId(key) { return (key.match(/([0-9a-f]{8}-[0-9a-f-]{27})$/iu)?.[1]?.replaceAll("-", "") ?? key).slice(0, 16); } function formatAmbiguousCandidates(candidates, gatewayUrl) { const rows = candidates.map((candidate) => ({ name: sanitizeTerminalText(candidate.displayName?.trim() || "(unnamed)").replace(/\s+/gu, " "), id: candidateId(candidate.key) })); const nameWidth = Math.max(...rows.map((row) => visibleWidth(row.name))); const width = Math.max(7, Math.min(40, nameWidth)); return [ "Session reference is ambiguous:", `${"SESSION".padEnd(width)} ID PREFIX`, ...rows.map((row) => `${formatTextCell(row.name, width)} ${row.id}`), `Pass a longer reference. ${sessionsListHint(gatewayUrl)}` ].join("\n"); } function sessionsListHint(gatewayUrl) { return gatewayUrl ? `Choose a full session key from that gateway's Control UI (${controlUiBaseUrl(gatewayUrl)}).` : "Run `openclaw sessions list` to choose a full session key."; } function controlUiBaseUrl(gatewayUrl) { const url = new URL(gatewayUrl); url.protocol = url.protocol === "wss:" ? "https:" : url.protocol === "ws:" ? "http:" : url.protocol; return sanitizeTerminalText(url.toString().replace(/\/$/u, "")); } function isPriorGatewayShortIdRejection(error) { return error instanceof GatewayClientRequestError && error.gatewayCode === "INVALID_REQUEST" && error.message.includes("invalid sessions.resolve params:") && error.message.includes("unexpected property 'shortId'"); } function unreachableTargetError(error, gatewayUrl) { if (!gatewayUrl) return error; const hostname = new URL(gatewayUrl).hostname; const displayGatewayUrl = projectGatewayUrlForDiagnostics(gatewayUrl); const tailscaleHint = hostname.endsWith(".ts.net") ? " For this .ts.net host, check that Tailscale is connected and the gateway is reachable on your tailnet." : ""; return /* @__PURE__ */ new Error(`${error.message}\nCould not reach gateway ${displayGatewayUrl}. Check whether the gateway is down and whether its tailnet or SSH tunnel is reachable.${tailscaleHint}`); } function shapeTargetError(error, gatewayUrl, shortRef) { if (shortRef && isPriorGatewayShortIdRejection(error)) return /* @__PURE__ */ new Error(`This gateway predates short-link resolution; pass the full session key. ${sessionsListHint(gatewayUrl)}`); if (error instanceof GatewayStoredDeviceAuthUnavailableError && gatewayUrl) return /* @__PURE__ */ new Error(`No stored device auth for ${gatewayUrl}. Pass --token or --password once, approve the pairing request in that gateway's Control UI (Settings > Devices), then retry.`); if (!(error instanceof Error)) return new Error(String(error)); if (/tls fingerprint/iu.test(error.message)) return error; if (error instanceof GatewayClientRequestError && error.gatewayCode === "INVALID_REQUEST" && error.message.includes("No session found")) return /* @__PURE__ */ new Error(`${error.message}\n${sessionsListHint(gatewayUrl)}`); const failure = classifyGatewayConnectFailure({ ...error instanceof GatewayClientRequestError ? { details: error.details } : {}, ...error instanceof GatewayTransportError ? { reason: error.reason } : {}, message: error.message }); if (failure.kind === "identity-proxy") return /* @__PURE__ */ new Error(`${failure.userMessage}\n${failure.remediation}`); if (failure.kind === "unreachable") return unreachableTargetError(error, gatewayUrl ?? (error instanceof GatewayTransportError ? error.connectionDetails.url : void 0)); return failure.remediation ? /* @__PURE__ */ new Error(`${failure.userMessage}\n${failure.remediation}`) : error; } async function resolveSessionTarget(params) { const parsed = parseSessionTargetInput(params.raw); const targetUrl = gatewayUrlForTarget(parsed); if (targetUrl && params.gateway?.url) throw new Error("pass one target: use either the session URL or --url, not both"); const gateway = { ...params.gateway, url: targetUrl ?? params.gateway?.url }; if (parsed.ref.kind === "main") { if (parsed.kind !== "url") throw new SessionTargetParseError(); const agents = await callSessionTargetGateway({ gateway, method: "agents.list", request: {}, requiredScope: params.requiredScope ?? "operator.read" }); return { parsed, gateway, sessionKey: resolveCanonicalMainSessionKey({ agentId: parsed.agentId, mainKey: agents.mainKey, sessionScope: agents.scope }) }; } const ref = parsed.ref; const result = await callSessionTargetGateway({ gateway, method: "sessions.resolve", request: ref.kind === "short" ? { shortId: ref.shortId, ...ref.slugHint ? { slugHint: ref.slugHint } : {} } : { key: ref.sessionKey }, requiredScope: params.requiredScope ?? "operator.read", shortRef: ref.kind === "short" }); if (result.ok) return { parsed, gateway, sessionKey: result.key }; if (result.candidates?.length) throw new Error(formatAmbiguousCandidates(result.candidates, gateway.url)); throw new Error(`No session found.\n${sessionsListHint(gateway.url)}`); } //#endregion export { resolveSessionTarget as n, callSessionTargetGateway as t };