UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

223 lines (222 loc) • 9.89 kB
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs"; import { w as parseStrictPositiveInteger } from "./number-coercion-CkhMiRw8.mjs"; import { t as formatErrorMessage } from "./errors-BvOkmQM5.mjs"; import { t as createSubsystemLogger } from "./subsystem-4NzR43uz.mjs"; import { t as resolveGatewayPublicOrigin } from "./gateway-public-origin-BcHLka2A.mjs"; import "./error-runtime-oJAVOxQN.mjs"; import "./string-coerce-runtime-BbIJhy7G.mjs"; import { t as buildChannelApprovalNativeTargetKey } from "./approval-native-target-key-s_DV7kzX.mjs"; import "./runtime-env-CySdLHPX.mjs"; import "./number-runtime-D3v2w3D4.mjs"; import { i as buildExecApprovalPendingReplyPayload, n as buildApprovalPresentationFromActionDescriptors, u as formatExecApprovalExpiresIn } from "./exec-approval-reply-DAEbOSV6.mjs"; import { r as createChannelApprovalNativeRuntimeAdapter } from "./approval-handler-runtime-BiWKFCGM.mjs"; import "./approval-handler-runtime-B8LjJ6Wq.mjs"; import "./approval-native-runtime-DZGYjCOE.mjs"; import { r as buildPluginApprovalPendingReplyPayload } from "./approval-renderers-DX8qVcwi.mjs"; import "./approval-reply-runtime-DXHTiQqT.mjs"; import { t as normalizeControlUiBasePath } from "./control-ui-base-path-C7vqrdPT.mjs"; import { l as parseTelegramTarget, o as normalizeTelegramChatId } from "./topic-conversation-S0gZB4iY.mjs"; import { P as escapeTelegramHtml } from "./text-chunk-limit-plWH6e89.mjs"; import { a as isTelegramExecApprovalHandlerConfigured, l as shouldHandleTelegramExecApprovalRequest } from "./exec-approvals-CWfyTLvI.mjs"; import { o as buildTelegramApprovalCallbackData } from "./native-command-callback-data-egNNRPnG.mjs"; import { i as normalizeTelegramButtonStyle, o as resolveTelegramInlineButtons } from "./button-types-DEBkvVXS.mjs"; import { C as editMessageReplyMarkupTelegram, R as sendTypingTelegram, d as sendMessageTelegram, w as editMessageTelegram } from "./send-CpiI0BKu.mjs"; import { a as buildTelegramNativeResolvedApprovalText, i as buildTelegramNativeExpiredApprovalText } from "./approval-terminal-6YJrS5ch.mjs"; //#region extensions/telegram/src/approval-handler.runtime.ts const log = createSubsystemLogger("telegram/approvals"); const terminalizedSystemAgentApprovals = /* @__PURE__ */ new Set(); function resolveHandlerContext(params) { const context = params.context; const accountId = normalizeOptionalString(params.accountId) ?? ""; if (!context?.token || !accountId) return null; return { accountId, context, options: () => ({ cfg: params.cfg, token: context.token, accountId }) }; } function buildPendingPayload(params) { if (params.approvalKind === "system-agent") { const view = params.view; if (view.approvalKind !== "system-agent") throw new Error("system-agent approval request and view kinds do not match"); const origin = resolveGatewayPublicOrigin(params.cfg); const reviewUrl = origin && params.cfg.gateway?.controlUi?.enabled !== false ? `${origin}${normalizeControlUiBasePath(params.cfg.gateway?.controlUi?.basePath?.trim() ?? "", "one")}/approve/${encodeURIComponent(params.request.id)}` : void 0; const lines = [ "🔒 OpenClaw change requires approval", `Change: ${view.operationSummary}`, `Agent: ${view.agentId ?? "unknown"}`, `Expires in: ${formatExecApprovalExpiresIn(params.request.expiresAtMs, params.nowMs)}` ]; const decisionButtons = view.actions.flatMap((action) => { const approvalAction = action.action; if (!approvalAction || approvalAction.type !== "approval") return []; const callbackData = buildTelegramApprovalCallbackData(approvalAction); const style = normalizeTelegramButtonStyle(action.style); return callbackData ? [{ text: action.label, callback_data: callbackData, ...style ? { style } : {} }] : []; }); const buttons = decisionButtons.length > 0 ? [decisionButtons] : []; return { text: lines.join("\n"), buttons: reviewUrl ? [[{ text: "Review in Control UI", url: reviewUrl }], ...buttons] : buttons }; } const execView = params.view.approvalKind === "exec" ? params.view : void 0; return { text: (params.approvalKind === "plugin" ? buildPluginApprovalPendingReplyPayload({ request: params.request, nowMs: params.nowMs }) : buildExecApprovalPendingReplyPayload({ approvalId: params.request.id, approvalSlug: params.request.id.slice(0, 8), approvalCommandId: params.request.id, warningText: execView?.warningText ?? void 0, command: execView?.commandText ?? "", cwd: execView?.cwd ?? void 0, host: execView?.host === "node" ? "node" : "gateway", nodeId: execView?.nodeId ?? void 0, scope: execView?.scope ?? void 0, allowedDecisions: params.view.actions.map((action) => action.decision), expiresAtMs: params.request.expiresAtMs, nowMs: params.nowMs })).text ?? "", buttons: resolveTelegramInlineButtons({ presentation: buildApprovalPresentationFromActionDescriptors(params.view.actions) }) }; } const telegramApprovalNativeRuntime = createChannelApprovalNativeRuntimeAdapter({ eventKinds: [ "exec", "plugin", "system-agent" ], availability: { isConfigured: (params) => { const resolved = resolveHandlerContext(params); return resolved ? isTelegramExecApprovalHandlerConfigured({ cfg: params.cfg, accountId: resolved.accountId }) : false; }, shouldHandle: (params) => { const resolved = resolveHandlerContext(params); return resolved ? shouldHandleTelegramExecApprovalRequest({ cfg: params.cfg, accountId: resolved.accountId, request: params.request }) : false; } }, presentation: { buildPendingPayload, buildResolvedResult: ({ view }) => ({ kind: "update", payload: { text: buildTelegramNativeResolvedApprovalText(view) } }), buildExpiredResult: ({ view }) => ({ kind: "update", payload: { text: buildTelegramNativeExpiredApprovalText(view) } }) }, transport: { prepareTarget: ({ plannedTarget }) => { const parsedTarget = parseTelegramTarget(plannedTarget.target.to); return { dedupeKey: buildChannelApprovalNativeTargetKey(plannedTarget.target), target: { chatId: parsedTarget.chatId, messageThreadId: typeof plannedTarget.target.threadId === "number" ? plannedTarget.target.threadId : parsedTarget.messageThreadId, directMessagesTopicId: parsedTarget.directMessagesTopicId } }; }, deliverPending: async ({ cfg, accountId, context, preparedTarget, pendingPayload }) => { const resolved = resolveHandlerContext({ cfg, accountId, context }); if (!resolved) return null; const sendTyping = resolved.context.deps?.sendTyping ?? sendTypingTelegram; const sendMessage = resolved.context.deps?.sendMessage ?? sendMessageTelegram; const options = { ...resolved.options(), ...preparedTarget.messageThreadId != null ? { messageThreadId: preparedTarget.messageThreadId } : {} }; await sendTyping(preparedTarget.chatId, options).catch(() => {}); const result = await sendMessage(preparedTarget.chatId, pendingPayload.text, { ...options, buttons: pendingPayload.buttons, ...preparedTarget.directMessagesTopicId != null ? { directMessagesTopicId: preparedTarget.directMessagesTopicId } : {} }); return { chatId: result.chatId, messageId: result.messageId }; }, updateEntry: async ({ cfg, accountId, context, entry, payload, request, approvalKind }) => { const resolved = resolveHandlerContext({ cfg, accountId, context }); if (!resolved) return; const editMessage = resolved.context.deps?.editMessage ?? editMessageTelegram; let editError; try { await editMessage(entry.chatId, entry.messageId, escapeTelegramHtml(payload.text), { ...resolved.options(), textMode: "html", buttons: [] }); } catch (error) { editError = error; } if (approvalKind === "system-agent" && request.request.turnSourceChannel?.trim().toLowerCase() === "telegram") { const originTarget = request.request.turnSourceTo?.trim(); const parsedOrigin = originTarget ? parseTelegramTarget(originTarget) : void 0; const originChatId = parsedOrigin ? normalizeTelegramChatId(parsedOrigin.chatId) : void 0; const originThreadId = parseStrictPositiveInteger(request.request.turnSourceThreadId) ?? parsedOrigin?.messageThreadId; const sourceAccountId = request.request.turnSourceAccountId?.trim(); const isSourceAccount = !sourceAccountId || sourceAccountId === resolved.accountId; if (originChatId && isSourceAccount) { if ((entry.chatId !== originChatId || editError !== void 0) && !terminalizedSystemAgentApprovals.has(request.id)) await (resolved.context.deps?.sendMessage ?? sendMessageTelegram)(parsedOrigin?.directMessagesTopicId != null ? originTarget : originChatId, escapeTelegramHtml(payload.text), { ...resolved.options(), textMode: "html", ...originThreadId != null ? { messageThreadId: originThreadId } : {} }); terminalizedSystemAgentApprovals.add(request.id); } } if (editError !== void 0) throw editError instanceof Error ? editError : new Error(formatErrorMessage(editError)); } }, interactions: { clearPendingActions: async ({ cfg, accountId, context, entry }) => { const resolved = resolveHandlerContext({ cfg, accountId, context }); if (!resolved) return; await (resolved.context.deps?.editReplyMarkup ?? editMessageReplyMarkupTelegram)(entry.chatId, entry.messageId, [], resolved.options()); } }, observe: { onDeliveryError: ({ error, request }) => { log.error(`telegram approvals: failed to send request ${request.id}: ${String(error)}`); }, onFinalized: ({ request, approvalKind }) => { if (approvalKind === "system-agent") terminalizedSystemAgentApprovals.delete(request.id); } } }); //#endregion export { telegramApprovalNativeRuntime };