UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

292 lines (291 loc) • 11.6 kB
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs"; import { r as jsonUtf8Bytes } from "./json-utf8-bytes-fm9i4b7G.mjs"; import { G as validateChatInjectParams, K as validateChatMessageGetParams, X as validateChatToolTitlesParams } from "./src-l2dWvEsN.mjs"; import { t as ErrorCodes } from "./gateway-error-details-DIefe7Zy.mjs"; import { f as errorShape } from "./error-codes-Dh56LniQ.mjs"; import { n as CHAT_PENDING_INPUT_MESSAGE_PREFIX } from "./chat-history-constants-C-H8nkgi.mjs"; import { n as beginSessionWorkAdmission } from "./session-lifecycle-admission-GoxISURZ.mjs"; import { F as readSessionPendingInput } from "./session-accessor-BDmTPdtx.mjs"; import { a as MAX_PAYLOAD_BYTES } from "./server-constants-BH_EolwD.mjs"; import { n as resolveRequestedSessionAgentId } from "./session-request-agent-Bxi11ET4.mjs"; import { o as resolveSessionWorkStartError } from "./lifecycle-BU4MFl1q.mjs"; import "./sessions-DQtCC-5j.mjs"; import { r as augmentChatHistoryWithCanvasBlocks } from "./chat-display-projection.canvas-DwEc-tyR.mjs"; import { m as resolveEffectiveChatHistoryMaxChars } from "./chat-display-projection.helpers-pbUdgTgb.mjs"; import { i as readSessionMessageByIdAsync, o as readSessionMessagesAroundIdWithStatsAsync } from "./session-transcript-readers-B2XS9yB_.mjs"; import { t as resolveCurrentUserProfileDisplay } from "./current-user-profile-display-CsoRu_a-.mjs"; import { i as loadGatewaySessionEntryReadOnly, r as loadGatewaySessionEntry } from "./session-utils-store-BAlWJHht.mjs"; import { d as hiddenSessionNotFound } from "./session-sharing-policy-DBD0nzAz.mjs"; import { l as createSessionListEntryFilter } from "./session-sharing-target-read-B1Z4GF6o.mjs"; import "./session-sharing-C16h_pTr.mjs"; import { r as projectOperatorModelRead } from "./operator-model-presentation-tpGai_DS.mjs"; import "./session-utils-seGz8XhX.mjs"; import { l as prepareForwardedMessageCronJobNameResolver, r as dropPreSessionStartAnnouncePairs } from "./chat-display-projection.history-C7mOEuaq.mjs"; import { a as projectChatDisplayMessage, r as isPendingAssistantError } from "./chat-display-projection.core-BRO3Pr6M.mjs"; import "./chat-display-projection-CkWUSNcY.mjs"; import { n as readChatHistoryMessageId } from "./session-history-tail-fjrDpLEk.mjs"; import { t as readChatHistoryPage } from "./chat-history-pages-Dwy5WUPH.mjs"; import { t as formatForLog } from "./ws-log-Lc1qgHtV.mjs"; import { c as resolveGlobalAwareNodeChatDeliveryKeys, l as sendGlobalAwareNodeChatPayload } from "./chat-broadcast-fbR7vwZn.mjs"; import { t as assertValidParams } from "./validation-Bu27N0nv.mjs"; import { t as appendInjectedAssistantMessageToTranscript } from "./chat-transcript-inject-D29kMQVD.mjs"; import { r as projectPendingInputMessage, t as chatHistoryHandlers } from "./chat-history-handler-BKMKq528.mjs"; //#region src/gateway/server-methods/chat-message-get-handler.ts async function isChatMessageIdVisibleAfterHistoryFilters(params) { if (isPendingAssistantError(params.message)) return (await readChatHistoryPage({ entry: params.sessionEntry, provider: void 0, sessionId: params.sessionId, storePath: params.storePath, sessionAgentId: params.agentId, canonicalKey: params.sessionKey, max: 1, maxHistoryBytes: MAX_PAYLOAD_BYTES, effectiveMaxChars: MAX_PAYLOAD_BYTES, offset: void 0, messageId: params.messageId, ignoreCliSessionImports: true })).messages.some((message) => readChatHistoryMessageId(message) === params.messageId); if (params.sessionStartedAt === void 0) return true; const { messages } = await readSessionMessagesAroundIdWithStatsAsync({ agentId: params.agentId, sessionEntry: params.sessionEntry, sessionId: params.sessionId, sessionKey: params.sessionKey, storePath: params.storePath }, { maxMessages: 1, messageId: params.messageId, ...params.allowResetArchiveFallback === true ? { allowResetArchiveFallback: true } : {} }); return dropPreSessionStartAnnouncePairs(messages, params.sessionStartedAt).some((message) => readChatHistoryMessageId(message) === params.messageId); } const chatMessageGetHandlers = { "chat.message.get": async ({ params, respond, context, client, sessionMutationAuthorization }) => { if (!assertValidParams(params, validateChatMessageGetParams, "chat.message.get", respond)) return; const { sessionKey, messageId, maxChars } = params; const agentIdOverride = normalizeOptionalString(params.agentId); const cfg = context.getRuntimeConfig(); const requestedAgent = resolveRequestedSessionAgentId(cfg, sessionKey, agentIdOverride); if (!requestedAgent.ok) { respond(false, void 0, requestedAgent.error); return; } const requestedAgentId = requestedAgent.agentId; const session = loadGatewaySessionEntryReadOnly(sessionKey, { agentId: requestedAgentId }, cfg); const { agentId: sessionAgentId, storePath, entry, canonicalKey } = session; const sessionId = entry?.sessionId; if (!sessionId) { respond(true, { ok: false, unavailableReason: "not_found" }); return; } const canReadSession = (current = loadGatewaySessionEntryReadOnly(sessionKey, { agentId: requestedAgentId, clone: false, projection: "list" })) => { sessionMutationAuthorization?.assertCurrent(); if (!current.entry || current.agentId !== session.agentId || current.canonicalKey !== canonicalKey || current.storePath !== storePath || current.entry.sessionId !== sessionId || current.entry.lifecycleRevision !== entry.lifecycleRevision) { respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, "session changed while reading history; reload the conversation", { retryable: true })); return false; } if (createSessionListEntryFilter({ client, cfg: context.getCommittedRuntimeConfig?.() ?? current.cfg })?.(current.canonicalKey, current.entry) === false) { respond(false, void 0, hiddenSessionNotFound(canonicalKey)); return false; } return true; }; if (!canReadSession(session)) return; const effectiveMaxChars = maxChars ?? Math.min(26214400, 1e6); if (messageId.startsWith("pending:")) { const pending = await readSessionPendingInput({ agentId: sessionAgentId, sessionKey: canonicalKey, sessionId, storePath }, messageId.slice(CHAT_PENDING_INPUT_MESSAGE_PREFIX.length)); if (!canReadSession()) return; if (!pending) { respond(true, { ok: false, unavailableReason: "not_found" }); return; } const resolveCronJobName = await prepareForwardedMessageCronJobNameResolver([pending.message], context.cronStorePath); if (!canReadSession()) return; const message = projectPendingInputMessage(pending, effectiveMaxChars, void 0, resolveCronJobName); if (!message) { respond(true, { ok: false, unavailableReason: "not_visible" }); return; } respond(true, jsonUtf8Bytes(message) > 26213376 ? { ok: false, unavailableReason: "oversized" } : { ok: true, message }); return; } const resolved = await readSessionMessageByIdAsync({ agentId: sessionAgentId, sessionEntry: entry, sessionId, sessionKey, storePath }, messageId, { allowResetArchiveFallback: true }); const visible = resolved.found && await isChatMessageIdVisibleAfterHistoryFilters({ sessionId, storePath, sessionEntry: entry, sessionKey, agentId: sessionAgentId, message: resolved.message, messageId, sessionStartedAt: typeof entry?.sessionStartedAt === "number" ? entry.sessionStartedAt : void 0, allowResetArchiveFallback: true }); if (!canReadSession()) return; if (!visible) { respond(true, { ok: false, unavailableReason: "not_found" }); return; } if (resolved.oversized) { respond(true, { ok: false, unavailableReason: "oversized" }); return; } const resolveCronJobName = await prepareForwardedMessageCronJobNameResolver([resolved.message], context.cronStorePath); if (!canReadSession()) return; const projectedMessage = resolved.message ? projectChatDisplayMessage(resolved.message, { maxChars: effectiveMaxChars, resolveCurrentUserProfileDisplay, resolveCronJobName }) : void 0; const projected = projectedMessage ? augmentChatHistoryWithCanvasBlocks([projectedMessage])[0] : void 0; if (!projected) { respond(true, { ok: false, unavailableReason: "not_visible" }); return; } respond(true, jsonUtf8Bytes(projected) > 26213376 ? { ok: false, unavailableReason: "oversized" } : projectOperatorModelRead({ context, client, agentId: sessionAgentId }, { ok: true, message: projected })); } }; //#endregion //#region src/gateway/server-methods/chat.ts const chatHandlers = { ...chatHistoryHandlers, ...chatMessageGetHandlers, "chat.toolTitles": async ({ params, respond }) => { if (!assertValidParams(params, validateChatToolTitlesParams, "chat.toolTitles", respond)) return; respond(true, { titles: {}, disabled: true }); }, "chat.inject": async ({ params, respond, context }) => { if (!assertValidParams(params, validateChatInjectParams, "chat.inject", respond)) return; const p = params; const rawSessionKey = p.sessionKey; const agentIdOverride = normalizeOptionalString(p.agentId); const cfg = context.getRuntimeConfig(); const requestedAgent = resolveRequestedSessionAgentId(cfg, rawSessionKey, agentIdOverride); if (!requestedAgent.ok) { respond(false, void 0, requestedAgent.error); return; } const sessionLoadOptions = { agentId: requestedAgent.agentId }; const { agentId, storePath, entry, canonicalKey: sessionKey } = loadGatewaySessionEntry(rawSessionKey, sessionLoadOptions, cfg); const sessionId = entry?.sessionId; if (!sessionId || !storePath) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "session not found")); return; } let appended; try { const admission = await beginSessionWorkAdmission({ scope: storePath, identities: [sessionKey, sessionId], assertAllowed: () => { const latestEntry = loadGatewaySessionEntry(rawSessionKey, sessionLoadOptions).entry; if (!latestEntry) throw new Error(`Session "${sessionKey}" was deleted while starting work. Retry.`); if (latestEntry.sessionId !== sessionId) throw new Error(`Session "${sessionKey}" changed while starting work. Retry.`); const archivedError = resolveSessionWorkStartError(sessionKey, latestEntry); if (archivedError) throw new Error(archivedError); } }); try { appended = await admission.run(async () => await appendInjectedAssistantMessageToTranscript({ sessionKey, message: p.message, label: p.label, sessionId, storePath, agentId, config: cfg })); } finally { admission.release(); } } catch (err) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, formatForLog(err))); return; } if (!appended.ok || !appended.messageId || !appended.message) { respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, `failed to write transcript: ${appended.error ?? "unknown error"}`)); return; } const message = projectChatDisplayMessage(appended.message, { maxChars: resolveEffectiveChatHistoryMaxChars() }); const chatPayload = { runId: `inject-${appended.messageId}`, sessionKey, ...agentId ? { agentId } : {}, seq: 0, state: "final", message }; context.broadcast("chat", chatPayload, { sessionKeys: resolveGlobalAwareNodeChatDeliveryKeys({ cfg, sessionKey, agentId }) }); sendGlobalAwareNodeChatPayload({ context, sessionKey, agentId, event: "chat", payload: chatPayload }); respond(true, { ok: true, messageId: appended.messageId }); } }; //#endregion export { chatHandlers };