UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

432 lines (431 loc) 27.7 kB
import { c as isRecord } from "./record-coerce-DItp3I4t.js"; import { n as createLazyPromise } from "./lazy-promise-DGqyc4Y4.js"; import { l as isOperatorScope, t as ADMIN_SCOPE } from "./operator-scopes-Dw7Gu2cA.js"; import { t as ErrorCodes } from "./gateway-error-details-w0nAGBBp.js"; import { i as gatewayStartupUnavailableDetails } from "./startup-unavailable-D0-EeFjq.js"; import { c as getActivePluginHttpRouteRegistry, u as getActivePluginRegistry } from "./runtime-BL4wZfTq.js"; import { a as getPluginRuntimeGatewayRequestScope, i as getPluginRuntimeGatewayNodeAuthorities, l as withPluginRuntimeGatewayRequestScope } from "./gateway-request-scope-BCMYlsDI.js"; import { Ed as GATEWAY_SUSPEND_UNAVAILABLE_REASON, Td as GATEWAY_RESTART_UNAVAILABLE_REASON } from "./src-BiL5aQto.js"; import { d as isCoreGatewayMethodClassified, n as authorizeOperatorScopesForMethod, p as listCoreGatewayHandlerMethodNames, r as authorizeOperatorScopesForRequiredScope, s as resolveLeastPrivilegeOperatorScopesForMethod, u as createCoreGatewayMethodDescriptors } from "./method-scopes-K6J_UQGL.js"; import { i as sessionMutationTargetFields } from "./session-method-policy-BAkxsFSx.js"; import { D as tryBeginGatewayRootWorkAdmission, T as tryBeginGatewayPreparedRestartRootWorkAdmission, c as getGatewaySuspendAdmissionPhase, u as isGatewayRestartDraining } from "./gateway-work-admission-R1IpuDim.js"; import { d as errorShape, f as missingScopeErrorShape } from "./error-codes-Bo8q2D1o.js"; import { p as authenticatedProfileUnavailableError } from "./operator-role-policy-wsr1DeJv.js"; import { H as SessionMutationAuthorizationChangedError, a as resolveSessionMutationAuthorization, l as resolveDirectIncognitoTargets } from "./session-sharing-B7MI8hNo.js"; import { n as resolveControlPlaneActor, t as formatControlPlaneActor } from "./control-plane-audit-CN8L3SYx.js"; import { n as consumeControlPlaneWriteBudget, t as CONTROL_PLANE_RATE_LIMIT_WINDOW_MS } from "./control-plane-rate-limit-B1YxvgrA.js"; import { n as createGatewayMethodRegistry, r as createPluginGatewayMethodDescriptors, t as createGatewayMethodDescriptorsFromHandlers } from "./registry-CC22si3g.js"; import { n as parseGatewayRole, t as isRoleAuthorizedForMethod } from "./role-policy-B0ZcgXv3.js"; import { t as isTargetedNonSafeGatewayRestartRequest } from "./restart-request-DCnDLrlM.js"; import { n as classifyGatewayStaleInstall } from "./stale-install-EFmAbT2d.js"; //#region src/gateway/server-methods/lazy-core-handlers.ts const preparations = /* @__PURE__ */ new WeakMap(); /** Resolve forwarding wrappers without mistaking them for actual handler entry. */ async function prepareGatewayRequestHandler(handler, entry) { let preparedHandler = handler; let prepare = preparations.get(preparedHandler); while (prepare) { entry?.assertOpen(); preparedHandler = await prepare(); prepare = preparations.get(preparedHandler); } return preparedHandler; } function createLazyCoreHandlers(params) { return Object.fromEntries(params.methods.map((method) => { const forwarding = async (opts) => { const entry = opts.context.requestEntryLifetime?.enter(opts); try { const handler = await prepareGatewayRequestHandler(forwarding, entry); entry?.assertOpen(); entry?.release(); await handler(opts); } finally { entry?.release(); } }; preparations.set(forwarding, async () => { const handler = (await params.loadHandlers())[method]; if (!handler) throw new Error(`lazy gateway handler not found: ${method}`); return handler; }); return [method, forwarding]; })); } //#endregion //#region src/gateway/server-methods/core-handlers.ts const CORE_GATEWAY_HANDLER_MODULES = { agent: () => import("./agent-CtU_yy-h.js").then((module) => module.agentHandlers), "agent-identity": () => import("./agent-identity-BoxxCN_8.js").then((module) => module.agentIdentityHandlers), agents: () => import("./agents-BWKC_q_3.js").then((module) => module.agentsHandlers), "agents-workspace": () => import("./agents-workspace-DQDAR-YJ.js").then((module) => module.agentsWorkspaceHandlers), artifacts: () => import("./artifacts-JO9Gk5j7.js").then((module) => module.artifactsHandlers), board: () => import("./board--_neMKy0.js").then((module) => module.boardHandlers), audit: () => import("./audit-S_7ZZ3bC.js").then((module) => module.auditHandlers), users: () => import("./users-D1ZRT0Go.js").then((module) => module.usersHandlers), "users-mentionable": () => import("./users-mentionable-CgxFX-NH.js").then((module) => module.usersMentionableHandlers), attach: () => import("./attach-Dwb-gqQ8.js").then((module) => module.attachHandlers), channels: () => import("./channels-JO6girQU.js").then((module) => module.channelsHandlers), "channel-pairing": () => import("./channel-pairing-BBc86pRW.js").then((module) => module.channelPairingHandlers), chat: () => import("./chat-BbagnMEy.js").then((module) => module.chatHandlers), "chat-abort": () => import("./chat-abort-handler-Epsorgzl.js").then((module) => ({ "chat.abort": module.handleChatAbortRequest })), commands: () => import("./commands-gMFXplZj.js").then((module) => module.commandsHandlers), config: () => import("./config-B59xD27I.js").then((module) => module.configHandlers), conversations: () => import("./conversations-DeC4L5BF.js").then((module) => module.conversationHandlers), connect: () => import("./connect-CLiHJR_e.js").then((module) => module.connectHandlers), "control-ui": () => import("./control-ui-CEpMNhvS.js").then((module) => module.controlUiHandlers), "plugins-control-ui": () => import("./plugins-control-ui-VpiEnQ3e.js").then((module) => module.pluginsControlUiHandlers), cron: () => import("./cron-7U1Ew90z.js").then((module) => module.cronHandlers), devices: () => import("./devices-DKGmwsom.js").then((module) => module.deviceHandlers), "device-pair-setup": () => import("./device-pair-setup-CCNyHooL.js").then((module) => module.devicePairSetupHandlers), diagnostics: () => import("./diagnostics--_sSKXjd.js").then((module) => module.diagnosticsHandlers), doctor: () => import("./doctor-BIXdyKAO.js").then((module) => module.createDoctorHandlers()), environments: () => import("./environments-C8MwbjM0.js").then((module) => module.environmentsHandlers), worktrees: () => import("./worktrees-CbSMxZ9a.js").then((module) => module.worktreesHandlers), "exec-approvals": () => import("./exec-approvals-C9Z7E1JE.js").then((module) => module.execApprovalsHandlers), fs: () => import("./fs-D709umXk.js").then((module) => module.fsHandlers), health: () => import("./health-DzsY_Wsm.js").then((module) => module.healthHandlers), logs: () => import("./logs-DoEysHca.js").then((module) => module.logsHandlers), "memory-search": () => import("./memory-search-TOiItoJ8.js").then((module) => module.memorySearchHandlers), mentions: () => import("./mentions-CHqG2PKY.js").then((module) => module.mentionHandlers), terminal: () => import("./terminal-nbe15MvQ.js").then((module) => module.terminalHandlers), transcripts: () => import("./transcripts-CBKhAh9H.js").then((module) => module.transcriptsHandlers), "ui-command": () => import("./ui-command-QHs2HB6h.js").then((module) => module.uiCommandHandlers), "models-auth-status": () => import("./models-auth-status-DAUXVTIh.js").then((module) => module.modelsAuthStatusHandlers), "models-auth-order": () => import("./models-auth-order-DXjqYf0q.js").then((module) => module.modelsAuthOrderHandlers), models: () => import("./models-BpK_Unz5.js").then((module) => module.modelsHandlers), "models-probe": () => import("./models-probe-O8Otr9Uy.js").then((module) => module.modelsProbeHandlers), "native-hook-relay": () => import("./native-hook-relay-CuRSVc5o.js").then((module) => module.nativeHookRelayHandlers), "nodes-pending": () => import("./nodes.pending-work-BMm67jvs.js").then((module) => module.nodePendingWorkHandlers), nodes: () => import("./nodes-Bl7lONGY.js").then((module) => module.nodeHandlers), "plugin-host-hooks": () => import("./plugin-host-hooks-DELHg7gq.js").then((module) => module.pluginHostHookHandlers), plugins: () => import("./plugins-DsaV5wTw.js").then((module) => module.pluginsHandlers), "plugins-mutations": () => import("./plugins-mutations-vY3VD5Q4.js").then((module) => module.pluginMutationHandlers), projects: () => import("./projects-CMyeCOka.js").then((module) => module.projectsHandlers), portals: () => import("./portals-oE7sFqMg.js").then((module) => module.portalHandlers), "progress-card": () => import("./progress-card-8WYrncHx.js").then((module) => module.progressCardHandlers), migrations: () => import("./migrations-C7Nxax-u.js").then((module) => module.migrationsHandlers), push: () => import("./push-B67_vAt0.js").then((module) => module.pushHandlers), restart: () => import("./restart-DBhDYZ5f.js").then((module) => module.restartHandlers), suspend: () => import("./suspend-Cogfi4KK.js").then((module) => module.suspendHandlers), send: () => import("./send-DFjT2qiq.js").then((module) => module.sendHandlers), "sessions-files": () => import("./sessions-files-BQOjcO-8.js").then((module) => module.sessionsFilesHandlers), "sessions-github": () => import("./sessions-github-C3TbhST1.js").then((module) => module.sessionsGitHubHandlers), "sessions-diff": () => import("./sessions-diff-Ct-40Pvc.js").then((module) => module.sessionsDiffHandlers), "sessions-abort": () => import("./sessions-abort-CVqBN5l0.js").then((module) => module.sessionAbortHandlers), "sessions-compact": () => import("./sessions-compact-hR5txnt9.js").then((module) => module.sessionCompactHandlers), "sessions-compaction-checkpoints": () => import("./sessions-compaction-checkpoints-CnbPQP12.js").then((module) => module.sessionCheckpointHandlers), "sessions-compaction-queries": () => import("./sessions-compaction-queries-BHP7J2_m.js").then((module) => module.sessionCheckpointQueryHandlers), "sessions-create": () => import("./sessions-create-D5ogFbhB.js").then((module) => module.sessionCreateHandlers), "sessions-title": () => import("./sessions-title-BcO0rK2X.js").then((module) => module.sessionTitleHandlers), "sessions-recover": () => import("./sessions-recover-CKQbl8yU.js").then((module) => module.sessionRecoverHandlers), "sessions-delete": () => import("./sessions-delete-BdffJX6q.js").then((module) => module.sessionDeleteHandlers), "sessions-dispatch": () => import("./sessions-dispatch-DD7xx7fP.js").then((module) => module.sessionDispatchHandlers), "sessions-groups": () => import("./sessions-groups-CFveLpzX.js").then((module) => module.sessionGroupHandlers), "sessions-goal": () => import("./sessions-goal-B0CjJuwo.js").then((module) => module.sessionGoalHandlers), "sessions-messaging": () => import("./sessions-messaging-f99jHeVF.js").then((module) => module.sessionMessagingHandlers), "sessions-mutations": () => import("./sessions-mutations-DrIj53vw.js").then((module) => module.sessionMutationHandlers), "sessions-read": () => import("./sessions-read-BstOzUHP.js").then((module) => module.sessionReadHandlers), "sessions-rewind": () => import("./sessions-rewind-B-Xzdagl.js").then((module) => module.sessionRewindHandlers), "sessions-sharing": () => import("./sessions-sharing-_182TbdI.js").then((module) => module.sessionSharingHandlers), "sessions-subscriptions": () => import("./sessions-subscriptions-WFPjDUb7.js").then((module) => module.sessionSubscriptionHandlers), "sessions-suggestions": () => import("./sessions-suggestions-ByjF4l3U.js").then((module) => module.sessionSuggestionHandlers), "session-catalog": () => import("./session-catalog-ldcbLNrN.js").then((module) => module.sessionCatalogHandlers), "session-discussion": () => import("./session-discussion-BZ9hfAIb.js").then((module) => module.sessionDiscussionHandlers), "session-observer-rpc": () => import("./session-observer-rpc-eLzdNWT1.js").then((module) => module.sessionObserverHandlers), "session-companion-rpc": () => import("./session-companion-rpc-1V91LRwP.js").then((module) => module.sessionCompanionHandlers), "hooks-status": () => import("./hooks-status-CSsiOuyX.js").then((module) => module.hooksStatusHandlers), skills: () => import("./skills-BnlEnM0m.js").then((module) => module.skillsHandlers), system: () => import("./system-CCBwaCHi.js").then((module) => module.systemHandlers), talk: () => import("./talk-BJD_2qrq.js").then((module) => module.talkHandlers), "talk-mode": () => import("./talk-mode-CvyTmanW.js").then((module) => module.talkModeHandlers), tasks: () => import("./tasks-uQ2YA5MZ.js").then((module) => module.tasksHandlers), "task-suggestions": () => import("./task-suggestions-Dly9lEbm.js").then((module) => module.taskSuggestionsHandlers), "tools-catalog": () => import("./tools-catalog-Dg8nxOWX.js").then((module) => module.toolsCatalogHandlers), "tools-github": () => import("./tools-github-D1EmRS7m.js").then((module) => module.toolsGitHubHandlers), "tools-effective": () => import("./tools-effective-C3GWBlgx.js").then((module) => module.toolsEffectiveHandlers), "tools-invoke": () => import("./tools-invoke-Db4h29JJ.js").then((module) => module.toolsInvokeHandlers), "mcp-app": () => import("./mcp-app-x5Jax9QQ.js").then((module) => module.mcpAppHandlers), canvas: () => import("./canvas-CDW_r_Kj.js").then((module) => module.canvasHandlers), tts: () => import("./tts-AvdVcS8p.js").then((module) => module.ttsHandlers), update: () => import("./update-BxCRjwo_.js").then((module) => module.updateHandlers), usage: () => import("./usage-D9hREJA1.js").then((module) => module.usageHandlers), "voicewake-routing": () => import("./voicewake-routing-CQ-6YIJy.js").then((module) => module.voicewakeRoutingHandlers), voicewake: () => import("./voicewake-CcBlGwNu.js").then((module) => module.voicewakeHandlers), web: () => import("./web-BqbkGbu0.js").then((module) => module.webHandlers), "system-agent": () => import("./system-agent-B-RV7UxK.js").then((module) => module.systemAgentHandlers), "system-changes": () => import("./system-changes-Bu3nCuiX.js").then((module) => module.systemChangesHandlers), wizard: () => import("./wizard-Ba9Q3tcy.js").then((module) => module.wizardHandlers) }; const coreGatewayHandlers = Object.fromEntries(Array.from(listCoreGatewayHandlerMethodNames()).flatMap(([family, methods]) => Object.entries(createLazyCoreHandlers({ methods, loadHandlers: createLazyPromise(CORE_GATEWAY_HANDLER_MODULES[family], { cacheRejections: true }) })))); //#endregion //#region src/gateway/server-methods/session-mutation-guards.ts /** Keep the host lifetime and operator target policy on the same commit boundary. */ function withSessionMutationCommitGuard(authorization, assertCommitAllowed) { if (!assertCommitAllowed) return authorization; return { ...authorization, assertCurrent: () => { assertCommitAllowed(); authorization?.assertCurrent(); }, assertTargetCurrent: (target) => { assertCommitAllowed(); authorization?.assertTargetCurrent(target); } }; } //#endregion //#region src/gateway/server-methods.ts function authorizeGatewayMethod(method, client, params, methodRegistry) { if (!client?.connect || method === "health") return null; const roleRaw = client.connect.role ?? "operator"; const role = parseGatewayRole(roleRaw); if (!role) return errorShape(ErrorCodes.INVALID_REQUEST, `unauthorized role: ${roleRaw}`); const scopes = client.connect.scopes ?? []; if (!isRoleAuthorizedForMethod(role, method)) return errorShape(ErrorCodes.INVALID_REQUEST, `unauthorized role: ${role}`); if (role === "node") return null; if (method === "device.scopes.requestUpgrade" || method === "device.scopes.waitUpgrade") return null; if (scopes.includes("operator.admin")) return null; const registeredScope = methodRegistry.getScope(method); const scopeAuth = isOperatorScope(registeredScope) ? authorizeOperatorScopesForRequiredScope(registeredScope, scopes) : authorizeOperatorScopesForMethod(method, scopes, params); if (!scopeAuth.allowed) { const resolvedRequiredScopes = isOperatorScope(registeredScope) ? [registeredScope] : resolveLeastPrivilegeOperatorScopesForMethod(method, params); return missingScopeErrorShape({ missingScope: scopeAuth.missingScope, requiredScopes: resolvedRequiredScopes.length > 0 ? resolvedRequiredScopes : [scopeAuth.missingScope] }); } return null; } const SUSPEND_CONTROL_METHODS = /* @__PURE__ */ new Set([ "gateway.suspend.prepare", "gateway.suspend.status", "gateway.suspend.resume", "gateway.suspend.handoff" ]); function runGatewayPendingWorkContinuation(params) { if (!isRecord(params.requestParams)) return null; const request = params.requestParams; if (params.client?.connect.role === "node") { if (params.admission !== "continuation" && getGatewaySuspendAdmissionPhase() !== "draining" && !isGatewayRestartDraining()) return null; const invokeId = params.method === "node.invoke.progress" ? request.invokeId : params.method === "node.invoke.result" ? request.id : void 0; if (typeof invokeId !== "string" || typeof request.nodeId !== "string") return null; return params.context.nodeRegistry.runPendingInvokeContinuation({ invokeId, nodeId: request.nodeId, connId: params.client.connId, run: params.run }); } if (params.admission === "continuation" || getGatewaySuspendAdmissionPhase() !== "draining" || params.client?.connect.role !== "operator" || typeof request.id !== "string") return null; if (params.method === "question.resolve" || params.method === "question.get") return params.context.questionManager?.runPendingContinuation(request.id, params.run) ?? null; return (params.method === "exec.approval.resolve" ? params.context.execApprovalManager : params.method === "plugin.approval.resolve" ? params.context.pluginApprovalManager : params.method === "approval.resolve" ? request.kind === "exec" ? params.context.execApprovalManager : request.kind === "plugin" ? params.context.pluginApprovalManager : request.kind === "system-agent" ? params.context.systemAgentApprovalManager : void 0 : void 0)?.runPendingContinuation(request.id, params.run) ?? null; } async function authorizeAuthenticatedProfileForMethod(params) { const sync = params.client?.authenticatedGitHubIdentitySync; if (!sync || params.client?.authenticatedUserProfile?.profileId.trim()) return null; if (!(params.methodRegistry.requiresAuthenticatedProfile(params.method) || resolveDirectIncognitoTargets(params.method, params.requestParams).length > 0 || sessionMutationTargetFields(params.method).length > 0 && params.context.getRuntimeConfig().gateway?.roles !== void 0)) return null; try { await sync(); } catch { return authenticatedProfileUnavailableError(); } return params.client?.authenticatedUserProfile?.profileId.trim() ? null : authenticatedProfileUnavailableError(); } /** Builds the per-request method registry from core, plugin, and explicit extra handlers. */ function createRequestGatewayMethodRegistry(extraHandlers) { const gatewayPluginRegistry = getActivePluginHttpRouteRegistry(); const gatewayPluginHandlers = gatewayPluginRegistry?.gatewayHandlers ?? {}; const extraHandlerEntries = Object.entries(extraHandlers ?? {}); const pluginMethodNames = new Set(Object.keys(gatewayPluginHandlers)); const coreDescriptorHandlers = { ...coreGatewayHandlers }; for (const [method, extraHandler] of extraHandlerEntries) if (!pluginMethodNames.has(method) && isCoreGatewayMethodClassified(method)) coreDescriptorHandlers[method] = extraHandler; const auxHandlers = Object.fromEntries(extraHandlerEntries.filter(([method]) => !pluginMethodNames.has(method) && !isCoreGatewayMethodClassified(method))); return createGatewayMethodRegistry([ ...createCoreGatewayMethodDescriptors(coreDescriptorHandlers), ...gatewayPluginRegistry ? createPluginGatewayMethodDescriptors(gatewayPluginRegistry) : [], ...createGatewayMethodDescriptorsFromHandlers({ handlers: auxHandlers, owner: { kind: "aux", area: "gateway-extra" }, defaultScope: ADMIN_SCOPE }) ], gatewayPluginRegistry ?? void 0); } /** Applies the router-owned authorization fence before any transport or typed dispatch. */ async function authorizeGatewayRequestPreDispatch(params) { const authError = authorizeGatewayMethod(params.method, params.client, params.requestParams, params.methodRegistry); if (authError) return { error: authError }; const profileError = await authorizeAuthenticatedProfileForMethod(params); if (profileError) return { error: profileError }; if (params.context.unavailableGatewayMethods?.has(params.method)) return { error: errorShape(ErrorCodes.UNAVAILABLE, `${params.method} unavailable during gateway startup`, { retryable: true, retryAfterMs: 500, details: { ...gatewayStartupUnavailableDetails(), method: params.method } }) }; const sessionMutation = resolveSessionMutationAuthorization({ client: params.client ?? null, method: params.method, requestParams: params.requestParams, context: params.context }); if (sessionMutation.error) return { error: sessionMutation.error }; if (params.client?.connect.role === "node" && (!params.client.connId || !await params.context.nodeRegistry.isConnectionCurrentPairingState(params.client.connId))) return { error: errorShape(ErrorCodes.UNAVAILABLE, "node pairing changed before request dispatch", { retryable: true, details: { code: "PAIRING_CHANGED" } }) }; return { error: null, ...sessionMutation.authorization ? { sessionMutationAuthorization: sessionMutation.authorization } : {} }; } /** Runs admitted Gateway work inside the shared root and plugin request scopes. */ async function runWithGatewayRequestEnvelope(method, client, fn, options) { const rejectRateLimitedControlPlaneWrite = () => { if (!options.methodRegistry.isControlPlaneWrite(method)) return; const budget = consumeControlPlaneWriteBudget({ client, method }); if (budget.allowed) return; const actor = resolveControlPlaneActor(client); options.context.logGateway.warn(`control-plane write rate-limited method=${method} ${formatControlPlaneActor(actor)} retryAfterMs=${budget.retryAfterMs} key=${budget.key}`); return errorShape(ErrorCodes.UNAVAILABLE, `rate limit exceeded for ${method}; retry after ${Math.ceil(budget.retryAfterMs / 1e3)}s`, { retryable: true, retryAfterMs: budget.retryAfterMs, details: { method, limit: `30 per ${CONTROL_PLANE_RATE_LIMIT_WINDOW_MS / 1e3}s` } }); }; const isSuspendPrepare = method === "gateway.suspend.prepare"; const preAdmissionRateLimitError = isSuspendPrepare ? rejectRateLimitedControlPlaneWrite() : void 0; if (preAdmissionRateLimitError) return await options.reject(preAdmissionRateLimitError); const rootWorkAdmission = options.admission === "continuation" ? null : tryBeginGatewayRootWorkAdmission(`ws:${method}`) ?? (method === "gateway.restart.request" && isTargetedNonSafeGatewayRestartRequest(options.requestParams) ? tryBeginGatewayPreparedRestartRootWorkAdmission() : null); if (!rootWorkAdmission) { const continuation = runGatewayPendingWorkContinuation({ method, client, requestParams: options.requestParams, context: options.context, admission: options.admission, run: invokeWithRequestScope }); if (continuation) return await continuation; if (options.admission === "continuation") return await options.reject(errorShape(ErrorCodes.UNAVAILABLE, `${method} unavailable during gateway shutdown`)); } if (isSuspendPrepare && rootWorkAdmission && !rootWorkAdmission.ownsRoot) return await options.reject(errorShape(ErrorCodes.UNAVAILABLE, "gateway suspension cannot begin from a nested request", { retryable: true, retryAfterMs: 1e3, details: { method, reason: "nested-gateway-request" } })); if (!rootWorkAdmission && !SUSPEND_CONTROL_METHODS.has(method)) { const restartDraining = isGatewayRestartDraining(); return await options.reject(errorShape(ErrorCodes.UNAVAILABLE, `${method} unavailable during gateway ${restartDraining ? "restart" : "suspension"}`, { retryable: true, retryAfterMs: 1e3, details: { method, reason: restartDraining ? GATEWAY_RESTART_UNAVAILABLE_REASON : GATEWAY_SUSPEND_UNAVAILABLE_REASON, phase: getGatewaySuspendAdmissionPhase() } })); } async function invokeWithRequestScope() { const postAdmissionRateLimitError = isSuspendPrepare ? void 0 : rejectRateLimitedControlPlaneWrite(); if (postAdmissionRateLimitError) return await options.reject(postAdmissionRateLimitError); try { const pluginRegistry = options.methodRegistry.pluginRegistry ?? getPluginRuntimeGatewayRequestScope()?.pluginRegistry ?? getActivePluginRegistry() ?? void 0; return await withPluginRuntimeGatewayRequestScope({ context: options.context, resolveGatewayContext: options.context.resolveGatewayContext, client, isWebchatConnect: options.isWebchatConnect, ...client?.internal?.nodeInvokeStream ? getPluginRuntimeGatewayNodeAuthorities() : {}, ...pluginRegistry ? { pluginRegistry } : {} }, fn); } catch (error) { if (error instanceof SessionMutationAuthorizationChangedError) return await options.reject(error.error); const staleInstall = classifyGatewayStaleInstall(error); if (staleInstall) return await options.reject(staleInstall.error); throw error; } } if (!rootWorkAdmission) return await invokeWithRequestScope(); try { return await rootWorkAdmission.run(invokeWithRequestScope); } finally { rootWorkAdmission.release(); } } /** Authorizes and dispatches one gateway JSON-RPC-style request. */ async function handleGatewayRequest(opts, diagnostics) { const { req, respond, client, isWebchatConnect, context, signal } = opts; const entry = opts.requestEntry ?? context.requestEntryLifetime?.enter(opts); try { entry?.assertOpen(); const methodRegistry = opts.methodRegistry?.getHandler(req.method) !== void 0 ? opts.methodRegistry : createRequestGatewayMethodRegistry(opts.extraHandlers); const authorization = await authorizeGatewayRequestPreDispatch({ method: req.method, requestParams: req.params, client, context, methodRegistry }); entry?.assertOpen(); if (authorization.error) { respond(false, void 0, authorization.error); return; } const handler = methodRegistry.getHandler(req.method); if (!handler) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `unknown method: ${req.method}`)); return; } const sessionMutationAuthorization = withSessionMutationCommitGuard(authorization.sessionMutationAuthorization, opts.sessionMutationCommitGuard); const invokeHandler = async () => { const preparedHandler = await prepareGatewayRequestHandler(handler, entry); const handlerOptions = { req, params: req.params ?? {}, client, isWebchatConnect, respond, context, signal, sessionMutationCommitGuard: opts.sessionMutationCommitGuard, sessionMutationAuthorization }; opts.sessionMutationCommitGuard?.(); entry?.assertOpen(); if (signal?.aborted) return; entry?.release(); return diagnostics ? diagnostics.runHandler(() => preparedHandler(handlerOptions)) : preparedHandler(handlerOptions); }; await runWithGatewayRequestEnvelope(req.method, client, invokeHandler, { context, isWebchatConnect, methodRegistry, requestParams: req.params, admission: opts.admission, reject: (error) => respond(false, void 0, error) }); } finally { if (!opts.requestEntry) entry?.release(); } } //#endregion export { coreGatewayHandlers as a, runWithGatewayRequestEnvelope as i, createRequestGatewayMethodRegistry as n, handleGatewayRequest as r, authorizeGatewayRequestPreDispatch as t };