UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

346 lines (345 loc) 12.6 kB
import { c as normalizeOptionalString } from "./string-coerce-mnp54Vah.js"; import { i as formatErrorMessage } from "./errors-BXgSefBE.js"; import { a as isSubagentSessionKey, n as isAcpSessionKey } from "./session-key-utils-Bx3apsJ3.js"; import { d as normalizeMainKey } from "./session-key-B_NoIfpX.js"; import { i as getRuntimeConfig } from "./io-Gi7-pyU-.js"; import "./config-C9RxTsn1.js"; import { n as GATEWAY_CLIENT_IDS, o as normalizeGatewayClientId } from "./client-info-CcqJJIan.js"; import { o as callGateway } from "./call-B5-GYOlf.js"; import { a as listSpawnedSessionKeys, s as resolveSandboxSessionToolsVisibility } from "./session-visibility-HcnRYqQk.js"; import "./chat-history-text-D43w1rZt.js"; //#region src/sessions/session-id.ts const SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; function looksLikeSessionId(value) { return SESSION_ID_RE.test(value.trim()); } //#endregion //#region src/agents/tools/sessions-resolution.ts /** * Session key resolution helpers. * * Normalizes display/internal/current-session aliases and resolves session-id inputs through Gateway. */ const defaultSessionsResolutionDeps = { callGateway }; const CURRENT_SESSION_CLIENT_ALIAS_IDS = new Set([ GATEWAY_CLIENT_IDS.TUI, GATEWAY_CLIENT_IDS.CLI, GATEWAY_CLIENT_IDS.WEBCHAT_UI, GATEWAY_CLIENT_IDS.CONTROL_UI, GATEWAY_CLIENT_IDS.MACOS_APP, GATEWAY_CLIENT_IDS.IOS_APP, GATEWAY_CLIENT_IDS.ANDROID_APP ]); let sessionsResolutionDeps = defaultSessionsResolutionDeps; function resolveMainSessionAlias(cfg) { const mainKey = normalizeMainKey(cfg.session?.mainKey); const scope = cfg.session?.scope ?? "per-sender"; return { mainKey, alias: scope === "global" ? "global" : mainKey, scope }; } function resolveDisplaySessionKey(params) { if (params.key === params.alias) return "main"; if (params.key === params.mainKey) return "main"; return params.key; } function resolveInternalSessionKey(params) { if (params.key === "current") return params.requesterInternalKey ?? params.key; if (params.key === "main") return params.alias; return params.key; } function resolveCurrentSessionClientAlias(params) { const requesterKey = normalizeOptionalString(params.requesterInternalKey); if (!requesterKey) return; const clientId = normalizeGatewayClientId(params.key); if (!clientId || !CURRENT_SESSION_CLIENT_ALIAS_IDS.has(clientId)) return; return requesterKey; } async function isRequesterSpawnedSessionVisible(params) { if (params.requesterSessionKey === params.targetSessionKey) return true; try { const resolved = await sessionsResolutionDeps.callGateway({ method: "sessions.resolve", params: { key: params.targetSessionKey, spawnedBy: params.requesterSessionKey } }); if (typeof resolved?.key === "string" && resolved.key.trim() === params.targetSessionKey) return true; } catch {} return (await listSpawnedSessionKeys({ requesterSessionKey: params.requesterSessionKey, limit: params.limit })).has(params.targetSessionKey); } function shouldVerifyRequesterSpawnedSessionVisibility(params) { return params.restrictToSpawned && !params.resolvedViaSessionId && params.requesterSessionKey !== params.targetSessionKey; } async function isResolvedSessionVisibleToRequester(params) { if (!shouldVerifyRequesterSpawnedSessionVisibility({ requesterSessionKey: params.requesterSessionKey, targetSessionKey: params.targetSessionKey, restrictToSpawned: params.restrictToSpawned, resolvedViaSessionId: params.resolvedViaSessionId })) return true; return await isRequesterSpawnedSessionVisible({ requesterSessionKey: params.requesterSessionKey, targetSessionKey: params.targetSessionKey, limit: params.limit }); } function looksLikeSessionKey(value) { const raw = normalizeOptionalString(value) ?? ""; if (!raw) return false; if (raw === "main" || raw === "global" || raw === "unknown" || raw === "current") return true; if (isAcpSessionKey(raw)) return true; if (raw.startsWith("agent:")) return true; if (raw.startsWith("cron:") || raw.startsWith("hook:")) return true; if (raw.startsWith("node-") || raw.startsWith("node:")) return true; if (raw.includes(":group:") || raw.includes(":channel:")) return true; return false; } function shouldResolveSessionIdInput(value) { return looksLikeSessionId(value) || !looksLikeSessionKey(value); } function buildResolvedSessionReference(params) { return { ok: true, key: params.key, displayKey: resolveDisplaySessionKey({ key: params.key, alias: params.alias, mainKey: params.mainKey }), resolvedViaSessionId: params.resolvedViaSessionId }; } function buildSessionIdResolveParams(params) { return { sessionId: params.sessionId, spawnedBy: params.restrictToSpawned ? params.requesterInternalKey : void 0, includeGlobal: !params.restrictToSpawned, includeUnknown: !params.restrictToSpawned }; } async function callGatewayResolveSessionId(params) { const key = normalizeOptionalString((await sessionsResolutionDeps.callGateway({ method: "sessions.resolve", params: buildSessionIdResolveParams(params) }))?.key) ?? ""; if (!key) throw new Error(`Session not found: ${params.sessionId} (use the full sessionKey from sessions_list)`); return key; } async function resolveSessionKeyFromSessionId(params) { try { return buildResolvedSessionReference({ key: await callGatewayResolveSessionId(params), alias: params.alias, mainKey: params.mainKey, resolvedViaSessionId: true }); } catch (err) { if (params.restrictToSpawned) return { ok: false, status: "forbidden", error: `Session not visible from this sandboxed agent session: ${params.sessionId}` }; return { ok: false, status: "error", error: formatErrorMessage(err) || `Session not found: ${params.sessionId} (use the full sessionKey from sessions_list)` }; } } async function resolveSessionKeyFromKey(params) { try { const key = normalizeOptionalString((await sessionsResolutionDeps.callGateway({ method: "sessions.resolve", params: { key: params.key, spawnedBy: params.restrictToSpawned ? params.requesterInternalKey : void 0 } }))?.key) ?? ""; if (!key) return null; return buildResolvedSessionReference({ key, alias: params.alias, mainKey: params.mainKey, resolvedViaSessionId: false }); } catch { return null; } } async function tryResolveSessionKeyFromSessionId(params) { try { return buildResolvedSessionReference({ key: await callGatewayResolveSessionId(params), alias: params.alias, mainKey: params.mainKey, resolvedViaSessionId: true }); } catch { return null; } } async function resolveSessionReferenceByKeyOrSessionId(params) { if (!params.skipKeyLookup) { const resolvedByKey = await resolveSessionKeyFromKey({ key: params.raw, alias: params.alias, mainKey: params.mainKey, requesterInternalKey: params.requesterInternalKey, restrictToSpawned: params.restrictToSpawned }); if (resolvedByKey) return resolvedByKey; } if (!(params.forceSessionIdLookup || shouldResolveSessionIdInput(params.raw))) return null; if (params.allowUnresolvedSessionId) return await tryResolveSessionKeyFromSessionId({ sessionId: params.raw, alias: params.alias, mainKey: params.mainKey, requesterInternalKey: params.requesterInternalKey, restrictToSpawned: params.restrictToSpawned }); return await resolveSessionKeyFromSessionId({ sessionId: params.raw, alias: params.alias, mainKey: params.mainKey, requesterInternalKey: params.requesterInternalKey, restrictToSpawned: params.restrictToSpawned }); } async function resolveSessionReference(params) { const rawInput = resolveCurrentSessionClientAlias({ key: params.sessionKey, requesterInternalKey: params.requesterInternalKey }) ?? params.sessionKey.trim(); if (rawInput === "current") { const resolvedCurrent = await resolveSessionReferenceByKeyOrSessionId({ raw: rawInput, alias: params.alias, mainKey: params.mainKey, requesterInternalKey: params.requesterInternalKey, restrictToSpawned: params.restrictToSpawned, allowUnresolvedSessionId: true, skipKeyLookup: params.restrictToSpawned, forceSessionIdLookup: true }); if (resolvedCurrent) return resolvedCurrent; } const raw = rawInput === "current" && params.requesterInternalKey ? params.requesterInternalKey : rawInput; if (shouldResolveSessionIdInput(raw)) { const resolvedByGateway = await resolveSessionReferenceByKeyOrSessionId({ raw, alias: params.alias, mainKey: params.mainKey, requesterInternalKey: params.requesterInternalKey, restrictToSpawned: params.restrictToSpawned, allowUnresolvedSessionId: false }); if (resolvedByGateway) return resolvedByGateway; } const resolvedKey = resolveInternalSessionKey({ key: raw, alias: params.alias, mainKey: params.mainKey, requesterInternalKey: params.requesterInternalKey }); return { ok: true, key: resolvedKey, displayKey: resolveDisplaySessionKey({ key: resolvedKey, alias: params.alias, mainKey: params.mainKey }), resolvedViaSessionId: false }; } async function resolveVisibleSessionReference(params) { const resolvedKey = params.resolvedSession.key; const displayKey = params.resolvedSession.displayKey; if (!await isResolvedSessionVisibleToRequester({ requesterSessionKey: params.requesterSessionKey, targetSessionKey: resolvedKey, restrictToSpawned: params.restrictToSpawned, resolvedViaSessionId: params.resolvedSession.resolvedViaSessionId })) return { ok: false, status: "forbidden", error: `Session not visible from this sandboxed agent session: ${params.visibilitySessionKey}`, displayKey }; return { ok: true, key: resolvedKey, displayKey }; } //#endregion //#region src/agents/tools/sessions-access.ts /** * Session visibility and access helpers for session tools. * * Adds OpenClaw session-key alias normalization and sandbox requester scoping over SDK visibility contracts. */ /** Resolves the requester context used to filter sandboxed session-tool access. */ function resolveSandboxedSessionToolContext(params) { const { mainKey, alias } = resolveMainSessionAlias(params.cfg); const visibility = resolveSandboxSessionToolsVisibility(params.cfg); const requesterSessionKey = normalizeOptionalString(params.agentSessionKey); const requesterInternalKey = requesterSessionKey ? resolveInternalSessionKey({ key: requesterSessionKey, alias, mainKey }) : void 0; return { mainKey, alias, visibility, requesterInternalKey, effectiveRequesterKey: requesterInternalKey ?? alias, restrictToSpawned: params.sandboxed === true && visibility === "spawned" && Boolean(requesterInternalKey) && !isSubagentSessionKey(requesterInternalKey) }; } //#endregion //#region src/agents/tools/sessions-helpers.ts /** Resolves config plus sandbox visibility context for a session tool call. */ function resolveSessionToolContext(opts) { const cfg = opts?.config ?? getRuntimeConfig(); return { cfg, ...resolveSandboxedSessionToolContext({ cfg, agentSessionKey: opts?.agentSessionKey, sandboxed: opts?.sandboxed }) }; } /** Classifies a session key/gateway kind into the row category used by tools. */ function classifySessionKind(params) { const key = params.key; if (key === params.alias || key === params.mainKey) return "main"; if (key.startsWith("cron:")) return "cron"; if (key.startsWith("hook:")) return "hook"; if (key.startsWith("node-") || key.startsWith("node:")) return "node"; if (params.gatewayKind === "group") return "group"; if (key.includes(":group:") || key.includes(":channel:")) return "group"; return "other"; } /** Derives the best channel label for a session row. */ function deriveChannel(params) { if (params.kind === "cron" || params.kind === "hook" || params.kind === "node") return "internal"; const channel = normalizeOptionalString(params.channel ?? void 0); if (channel) return channel; const lastChannel = normalizeOptionalString(params.lastChannel ?? void 0); if (lastChannel) return lastChannel; const parts = params.key.split(":").filter(Boolean); if (parts.length >= 3 && (parts[1] === "group" || parts[1] === "channel")) return parts[0]; return "unknown"; } //#endregion export { resolveCurrentSessionClientAlias as a, resolveMainSessionAlias as c, shouldResolveSessionIdInput as d, SESSION_ID_RE as f, resolveSandboxedSessionToolContext as i, resolveSessionReference as l, deriveChannel as n, resolveDisplaySessionKey as o, looksLikeSessionId as p, resolveSessionToolContext as r, resolveInternalSessionKey as s, classifySessionKind as t, resolveVisibleSessionReference as u };