UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

6,235 lines • 282 kB
import { l as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-1VuiLaaR.mjs";
import { g as isFutureDateTimestampMs } from "./number-coercion-CkhMiRw8.mjs";
import { t as createDeferredCore } from "./deferred-D0La5CRk.mjs";
import "./src-BirUqOZp.mjs";
import { t as expectDefined } from "./expect-lbe3Hgrh.mjs";
import { a as asOptionalRecord } from "./record-coerce-TIsquoVR.mjs";
import { t as stableStringify } from "./stable-stringify-Djn3uxNo.mjs";
import { t as containsAsciiControlCharacter, y as uniqueStrings } from "./string-normalization-D6DKCpwE.mjs";
import { r as truncateUtf16Safe } from "./utf16-slice-D_ngcYKd.mjs";
import { i as createAbortError } from "./src-D1BHGNTj.mjs";
import "./abort-signal-QqAmLWTl.mjs";
import { _ as redactSensitiveText } from "./redact-BV3wTtTv.mjs";
import { t as formatErrorMessage } from "./errors-BvOkmQM5.mjs";
import { r as assertExistingDatabaseIdentity } from "./sqlite-worker-identity-BRNRpRyc.mjs";
import { p as isDiagnosticsEnabled } from "./diagnostic-events-DT4ejwoa.mjs";
import { t as createSubsystemLogger } from "./subsystem-4NzR43uz.mjs";
import { n as sha256Hex, r as sha256HexPrefixCore } from "./node-crypto-BG4u3UnX.mjs";
import { v as SessionGoalOperationError } from "./openclaw-state-worker-error-Bi-BnNrV.mjs";
import { t as createLazyImportLoader } from "./lazy-promise-DGqyc4Y4.mjs";
import { n as normalizeAgentId } from "./agent-id-D1-Q6vR4.mjs";
import { r as isIncognitoSessionKey } from "./session-key-CmZ4o9-l.mjs";
import "./session-key-DY3MOX4N.mjs";
import { a as isCronSessionKey, f as resolveSessionDispatchKind, h as parseAgentSessionKey, r as isAcpSessionKey, s as isSubagentSessionKey } from "./session-key-utils-CDyBC9Gn.mjs";
import { c as resolveSessionStorePathCore } from "./paths-Bonddxfk.mjs";
import { d as resolveAgentWorkspaceDir, o as resolveAgentEntry } from "./agent-scope-config-BEk6-ThS.mjs";
import { o as isSameOpenClawAgentDatabasePath } from "./openclaw-agent-db.paths-BbmZlEP5.mjs";
import { n as withOpenClawAgentDatabaseReadOnly } from "./openclaw-agent-db-readonly-DAqV3tqr.mjs";
import { c as createAgentDatabaseAdmissionErrorShape, t as AgentDatabaseAdmissionError } from "./agent-database-admission-CRwW7FsI.mjs";
import { r as captureOpenClawStateWorkerContext } from "./openclaw-state-worker-context-BvvgY6-t.mjs";
import { E as runWithGatewayIndependentRootWorkContinuation, y as retainGatewayRootWorkAdmissionContinuation } from "./gateway-work-admission-DAV5kkgV.mjs";
import { s as readSessionTranscriptRunId } from "./transcript-events-DSEdnn1V.mjs";
import { d as sessionDeliveryOrigin, l as deliveryContextFromSession, u as sessionDeliveryChannel } from "./store-entry-ClyG-tia.mjs";
import { i as toDatabaseOptions } from "./session-accessor.sqlite-scope-helpers-CfDTAEsL.mjs";
import { t as INTERNAL_MESSAGE_CHANNEL } from "./message-channel-constants-B3vfipkP.mjs";
import { n as normalizeMessageChannel } from "./message-channel-core-D9WI2Y8r.mjs";
import { t as captureSessionTranscriptStorageEnvironment } from "./transcript-target-binding-DpcuSIFy.mjs";
import { t as _usingCtx } from "./usingCtx-BhiZp_rS.mjs";
import { n as emitDiagnosticsTimelineEvent, o as measureDiagnosticsTimelineSpan } from "./diagnostics-timeline-Dn9nJTaj.mjs";
import { a as modelFallbackOverrideFromAvailability, p as resolveModelFallbackAvailability } from "./agent-scope-bJOokm5r.mjs";
import { i as resolveProviderIdForAuth } from "./provider-auth-aliases-CAzJGfWN.mjs";
import "./agent-runtime-id-BZLMe-UU.mjs";
import { i as classifyAgentRunTerminalOutcome } from "./agent-run-terminal-outcome-CrMEEYuY.mjs";
import { D as resolveProjectedAgentRunProgressState, i as claimAgentRunContext, o as clearAgentRunContext, u as getAgentRunContext } from "./agent-run-registry-Cm8FlLIi.mjs";
import { d as getAgentEventLifecycleGeneration, h as onAgentEventForRun } from "./agent-events-jWdQ_ESE.mjs";
import { a as composeSessionSourceAssertion } from "./session-source-authority-h1UO3u0I.mjs";
import { n as parseModelRef, t as findNormalizedProviderValue } from "./model-selection-normalize-B-Anaau2.mjs";
import { d as hasGatewayAdminScope } from "./operator-scopes-BO7_XQCg.mjs";
import { a as hasGatewayClientCap, i as GATEWAY_CLIENT_NAMES, r as GATEWAY_CLIENT_MODES, t as GATEWAY_CLIENT_CAPS } from "./client-info-BgcoFakQ.mjs";
import { a as isInternalMessageChannel, i as isGatewayCliClient, l as isWebchatClient, n as isBrowserOperatorUiClient, s as isOperatorUiClient, t as isBrowserCopilotClient } from "./message-channel-AvA3r_Xp.mjs";
import { i as sessionToolOverridesEqual, r as normalizeSessionToolOverrides } from "./session-tool-overrides-B6c6gJaM.mjs";
import { Eh as readAgentRuntimeRestrictionErrorDetails, X as validateChatSendParams } from "./src-D6kL8tMP.mjs";
import { r as logVerbose } from "./globals-yEiTitH8.mjs";
import { m as withSessionTranscriptSourcePublication, s as getOwnedSessionTranscriptReader } from "./transcript-write-context-DwwjCPCE.mjs";
import { o as resolveSessionRoutingContract, t as SESSION_ROUTING_CHANGED_ERROR_REASON } from "./main-session-BOUJdkxQ.mjs";
import { o as createAgentRunRestartAbortError, p as resolveAgentRunAbortLifecycleFields, u as isAgentRunRestartAbortReason } from "./run-termination-5c-0T0hN.mjs";
import { n as adoptExecRequestSession, u as withExecRequestTurn } from "./exec-request-context-u4rNuPjF.mjs";
import { i as hasGlobalHooks, n as getGlobalHookRunner } from "./hook-runner-global-Cn3xHNvt.mjs";
import { A as stripReplyMediaFailureFallback, _ as isReplyPayloadStatusNotice, a as buildTtsSupplementMediaPayload, b as isReplyPayloadTtsSupplement, c as getReplyPayloadMetadata, g as isReplyPayloadSessionWriterDeliveryAuthorized, l as getReplyPayloadTtsSupplement, o as copyReplyPayloadMetadata } from "./reply-payload-BEgsL2xJ.mjs";
import "./channel-outbound-2iQdEUqa.mjs";
import { i as resolveCommandAuthorization } from "./command-auth-BHrKDij6.mjs";
import { s as prepareSessionParticipantInput, u as bindRequesterProfile } from "./host-context-builder-DqHC41dw.mjs";
import { t as ErrorCodes } from "./gateway-error-details-gTekQWj2.mjs";
import { d as errorShape } from "./error-codes-D0WRV4Bq.mjs";
import { w as formatValidationErrors } from "./worker-protocol-primitives-ulaCa2Ea.mjs";
import { l as resolveCreatorSandbox, n as authorizeGatewaySessionCreation } from "./operator-role-policy-BPiQfn95.mjs";
import { n as getRegisteredAgentHarness } from "./registry-DLDDp3Ju.mjs";
import { a as isAgentHarnessSessionKey, m as resolveMissingAgentHarnessSessionError } from "./agent-harness-session-key-Dx0vv6oG.mjs";
import { o as resolveEffectiveAgentRuntime } from "./thinking-runtime-CveqpPq0.mjs";
import { f as readPersistedMediaFacts } from "./media-facts-BIPREXi-.mjs";
import { i as getAgentWorkspaceAccess } from "./workspace-access-sHrkH_3z.mjs";
import { i as prepareSqliteScope, s as resolveSqliteScope } from "./session-accessor.sqlite-scope-BkgwxatT.mjs";
import { i as captureIncognitoSessionSource, r as captureIncognitoSessionOperation } from "./session-incognito-binding-Dp6RTei2.mjs";
import { c as waitForSessionTranscriptProjection } from "./session-transcript-reconcile-BwrFIOby.mjs";
import { F as isRetryableUnadoptedChatClaim, N as hasRestartRecoveryTerminalRun } from "./session-accessor.sqlite-entry-worker-publication-BNeFwCVE.mjs";
import { n as loadExactSessionEntryCandidates } from "./session-accessor.sqlite-exact-read-HBi2gDDN.mjs";
import { c as withSessionHistoryWorkerDatabase } from "./session-transcript-worker-runtime-BdmdicNg.mjs";
import { r as isSessionTranscriptProjectionUnavailableError, t as SessionTranscriptProjectionUnavailableError } from "./session-transcript-projection-error-B7C6SQei.mjs";
import { h as isCompetingSessionWorkAdmissionActive, m as interruptSessionWorkAdmissions, n as beginSessionWorkAdmission } from "./session-lifecycle-admission-B5CJ-emz.mjs";
import { r as buildSessionCreationStamp } from "./session-entry-provenance-C8CX2hws.mjs";
import { s as readSessionTranscriptActivePathEntryRelation } from "./session-accessor.sqlite-active-events-Zkd0MAwt.mjs";
import { t as readSessionTranscriptWatermark } from "./session-accessor.sqlite-transcript-watermark-C7PwEdqC.mjs";
import { i as buildRunUserTurnIdempotencyKey } from "./user-turn-transcript.metadata-DHDwAwgF.mjs";
import { g as progressCardRefreshRunProjection, h as normalizeInputProvenance, p as isProgressCardRefreshInputProvenance } from "./input-provenance-B5YZS2Do.mjs";
import { n as extractAssistantTextForPhase, t as extractAssistantPhaseText } from "./chat-message-content-C-d0FKNG.mjs";
import { _ as readTranscriptEventId, v as readTranscriptEventMessage } from "./session-accessor.sqlite-read-UBWmiUlC.mjs";
import { n as buildRestartRecoveryExpectedState } from "./session-transcript-turn-state-Bqkxfhzx.mjs";
import { n as formatChatWorkContext, t as captureChatWorkContext } from "./work-context-Cn4SLmAO.mjs";
import { a as readSessionGoalOperationInDatabase, n as assertSessionGoalOperationTime } from "./goals-operations-Dgcsd7BD.mjs";
import { r as loadOrCreateProcessDeviceIdentityAsync } from "./device-identity-async-D7c_3lSx.mjs";
import { n as readSessionTranscriptAnchorsAsync } from "./session-transcript-anchor-read-D6gfv_oG.mjs";
import { l as sanitizeAssistantVisibleTextWithProfile } from "./assistant-visible-text-CWq-s28E.mjs";
import { U as extractTextFromChatContent, t as renderAgentHarnessPreflightUserMessage, y as renderFailoverCodeUserCopy } from "./user-facing-text-BCPDY-39.mjs";
import { n as applySessionEntryTargetOperation, o as loadSessionEntry } from "./session-accessor.sqlite-entry-DLa7_9ui.mjs";
import { r as readAssistantDisplayContent } from "./assistant-display-content-mzartsGP.mjs";
import { i as parseInlineDirectives } from "./directive-tags-DLtws5Pc.mjs";
import { t as applyAssistantDeliveryDirectives } from "./transcript-assistant-delivery-CGqOQ0cS.mjs";
import { D as readSessionSubmittedInput, j as normalizeMessageClientSources } from "./session-accessor-C3ljJ974.mjs";
import { n as withSessionPendingInputAuthorityGuard } from "./session-pending-input-authority-CoXHTQsM.mjs";
import { r as resolveRequestedSessionAgentId, s as tryResolveSessionCompatibilityOwnerAgentId, t as resolveChatSendSessionKey } from "./session-request-agent-BWnhhVvT.mjs";
import { i as prepareQualifiedSessionEntryTarget } from "./session-accessor.entry-xtqpYxWo.mjs";
import { l as updateSessionEntry } from "./session-accessor.entry-mutation-telsi3Ig.mjs";
import { d as readProviderReviewAcknowledgment, i as resolveSessionWorkStartError, p as retireProviderReviewAcknowledgment } from "./session-work-start-Bkld8CTK.mjs";
import { t as findTranscriptEvent } from "./session-transcript-match-DM9H8_yA.mjs";
import { i as resolveSessionTranscriptDatabasePath } from "./session-accessor.transcript-target-DdAdqCJ1.mjs";
import { n as resolveSessionResetType, t as resolveChannelResetConfig } from "./reset-SWON9U-K.mjs";
import { n as resolveSendPolicy } from "./send-policy-BbMAtCtM.mjs";
import { n as resolveAgentTimeoutMs } from "./timeout-BBs3o51w.mjs";
import { t as readAcpSessionMetaForEntries } from "./session-meta-readonly-CDWxL7Mp.mjs";
import { s as createMessageInjectionAuthority } from "./message-injection-authority-D0WxWVfd.mjs";
import { I as resolveActiveReplyRunOwnerForSignal, Q as REPLY_RUN_IDLE_SETTLE_TIMEOUT_MS, x as isReplyRunAbortableForSignal } from "./reply-run-registry.state-BgHFgrrj.mjs";
import { r as bindWorkerToolPreparation } from "./host-private-capabilities-BL8gRbZP.mjs";
import { r as bindPreparedToolAuthority } from "./tool-authority-preparation-DJlHa3mM.mjs";
import { M as finalizeReplyMessageInjectionAttempt, c as interruptReplyRunTarget, g as replyRunRegistry, j as beginReplyMessageInjectionTarget } from "./reply-run-registry.registry-ICalZVvY.mjs";
import { t as hasInboundAudio } from "./inbound-media-D9dVgt41.mjs";
import { n as chatRunBelongsToSelectedAgent, r as resolveChatRunOwnerAgentId } from "./chat-run-owner-DsPSU6Vj.mjs";
import "./reply-run-registry-1HN3_KMU.mjs";
import { a as logMessageReceived, r as logMessageProcessed } from "./diagnostic-jtgHaFVw.mjs";
import { n as listActiveEmbeddedRunSessionIds } from "./active-run-projections-TAxZeJ_S.mjs";
import { t as finalizeInboundContext } from "./inbound-context-CRxwq3D_.mjs";
import { r as parseInboundMediaUri } from "./inbound-media-uri-Bc4RWtcM.mjs";
import "./reply-payload-eiK8mKuN.mjs";
import "./sessions-CRUJeu5H.mjs";
import "./media-reference-CTQTi3FT.mjs";
import { r as resolveTextCommand } from "./commands-registry-normalize-BUPL-PYW.mjs";
import "./commands-registry-Dr2bNuzu.mjs";
import { n as readAgentRunTerminalOutcome } from "./agent-run-terminal-outcome-BOQC0T2X.mjs";
import { i as dispatchInboundMessageWithProjectedDispatcher } from "./dispatch-24DdbDip.mjs";
import { C as isPluginOwnedSessionBindingRecord } from "./current-conversation-bindings.kernel-DWqaaBL6.mjs";
import { t as getSessionBindingService } from "./session-binding-service-wvWqRl2A.mjs";
import { a as emitInboundMessageAuditTerminal, r as emitMessageReceivedHooks, s as DispatchSessionRefreshRequiredError } from "./dispatch-from-config-D0ByBFxM.mjs";
import { C as reserveReplyAdmissionTicket, S as REPLY_ADMISSION_TICKET } from "./commentary-progress-owner-DcmR1wPD.mjs";
import { i as describeFailoverError } from "./failover-error-JM6M2oyF.mjs";
import { n as resolvePreparedSessionEntryResetFreshness, r as resolveSessionEntryResetFreshness } from "./entry-freshness-w7a3CGPV.mjs";
import { o as isMainSessionRecoveryReconciliationCandidate } from "./main-session-recovery-state-DuO6mGeL.mjs";
import { n as runAgentHarnessBeforeMessageWriteHook } from "./hook-helpers-DQD6Kn21.mjs";
import "./agent-run-terminal-outcome-8xoMCk5L.mjs";
import { l as withQualifiedGatewaySessionStoreTarget, o as resolveGatewaySessionStoreTarget } from "./session-utils-store-lookup-B6u4MxNj.mjs";
import { n as omitInternalSessionEffectsEntries, t as findCanonicalStoreMatch } from "./session-utils-store-selection-0-siU-tY.mjs";
import { a as shouldComputeCommandAuthorized } from "./command-detection-DD2oRRYt.mjs";
import { t as isInternalSourceReplyChannel } from "./source-reply-delivery-mode-D_BY_QoJ.mjs";
import { t as createUserTurnTranscriptRecorder } from "./user-turn-transcript-DuAfBkUt.mjs";
import { t as createRestartRecoveryOperatorSource } from "./operator-run-recovery-source-C5n2jGiN.mjs";
import { t as boundedWorkerError } from "./worker-error-Db8qkNbb.mjs";
import { t as resolveSessionWorkerPlacementContext } from "./session-worker-placement-context-CvBn6ZZM.mjs";
import { r as resolveSessionModelRef } from "./session-model-ref-CS-wdkCn.mjs";
import { s as markChatAbortTerminalOutcome } from "./chat-abort-lifecycle-internal-CmV6_-ef.mjs";
import { n as appendChatCanvasBlocksToMessage, o as isToolHistoryBlockType } from "./chat-display-projection.canvas-BMMjLtjY.mjs";
import { r as isSuppressedControlReplyText } from "./control-reply-text-CdlY-Sik.mjs";
import { c as updateChatRunProvider, i as registerChatAbortController, o as resolveChatRunExpiresAtMs, r as isChatAbortControllerEntryAbortable } from "./chat-abort-BnB7jJDN.mjs";
import { t as chatAbortMarkerTimestampMs } from "./server-chat-state-3St6BUdO.mjs";
import { c as resolveChatAbortDiagnosticReason, o as registerQueuedChatTurn, r as completeQueuedChatTurn, s as retireQueuedChatTurnCancellation } from "./chat-queued-turns-Cr3X0g10.mjs";
import { a as projectChatDisplayMessage, l as resolveStateContentionPresentation } from "./chat-display-projection.core-BOF-lEvI.mjs";
import { a as readSessionMessageByIdAsync } from "./session-transcript-readers-Bka5K3vB.mjs";
import { a as resolveEnvelopeFormatOptions } from "./envelope-UOtEX9A5.mjs";
import { t as assertPreparedSkillLibrarySelection } from "./selection-CLpBV2Ib.mjs";
import { t as SessionMutationAuthorizationChangedError } from "./session-mutation-authorization-error-Cdqn6r49.mjs";
import { n as isSyntheticGatewayCaller } from "./gateway-personal-caller-oW0gLIdc.mjs";
import { i as gatewayClientSessionCreator, o as resolveChatSendCallerContext, r as gatewayClientSenderFields } from "./gateway-client-identity-C-9Xwi8i.mjs";
import { l as hasPendingFollowupQueueWork } from "./state-Bzhk4z8e.mjs";
import { r as resolveGatewayModelSupportsImages } from "./session-utils-model-CKJmLsCf.mjs";
import { o as resolveAssistantIdentity } from "./assistant-avatar-DvPLNhcv.mjs";
import { t as captureSessionMutationRouting } from "./session-sharing-preparation-CjnXaLTm.mjs";
import { d as withQualifiedGatewaySessionEntry, o as prepareDeletedAgentSessionCheck, r as loadGatewaySessionEntry, u as withGatewaySessionEntry } from "./session-utils-store-qn-zT-Fk.mjs";
import { t as resolveSessionMutationAuthorization } from "./session-sharing-BFM0s33P.mjs";
import { t as ExpectedProfileMismatchError } from "./expected-profile-OGYkwAOc.mjs";
import { r as hasTrackedActiveSessionRun } from "./session-active-runs-pu_Yqu-E.mjs";
import { t as loadGatewaySessionEntryReadOnlyInWorker } from "./session-utils-store-worker-9uML4l0-.mjs";
import { t as recordGatewaySessionRunFailure } from "./session-run-error-DL9mxOIJ.mjs";
import { o as transferGatewayLocalUserIngress } from "./local-user-ingress-PBPakyQk.mjs";
import { i as resolveInboundReplyToolAuthorityOverlay } from "./reply-tool-authority-DTs080TY.mjs";
import { t as resolveQueueSettings } from "./queue-DoAEwH02.mjs";
import { i as resolveRestartRecoverySteeringBlockReason } from "./restart-recovery-receipt-_WLztcb9.mjs";
import { t as recordSessionCreated } from "./session-created-CYn2su72.mjs";
import { i as maybeGenerateDashboardSessionTitle, r as isDashboardSessionTitleCandidate, t as buildDashboardSessionTitleSource } from "./dashboard-session-title-C5SLMC2r.mjs";
import { t as buildInboundMediaNoteProjection } from "./media-note-F833NgiV.mjs";
import { s as withCurrentUserTurnInput } from "./user-turn-transcript-runtime-context-BtMCMUja.mjs";
import "./session-utils-BLqrCe75.mjs";
import "./chat-display-projection-B_RuafB6.mjs";
import { n as isAbortRequestText } from "./abort-primitives-BWGbzk7d.mjs";
import { n as buildInboundUserContextPrefix } from "./inbound-meta-Bz4_wsIB.mjs";
import { t as recordAcceptedSessionParticipantInput } from "./session-participant-input-recording-BS-iewnb.mjs";
import { n as isBtwRequestText } from "./btw-command-COac47pT.mjs";
import { t as createChannelReplyPipeline } from "./reply-pipeline-Tm9TGN8z.mjs";
import { i as setGatewayDedupeEntry, t as captureAgentJobSession } from "./agent-job-DnnG0jUk.mjs";
import { i as resolveAgentSessionWorkStartError } from "./agent-handler-helpers-De9_7sNd.mjs";
import { n as resolveChatAttachmentMaxBytes } from "./chat-attachment-policy-B0H4omOp.mjs";
import { t as prepareSteeringDelivery } from "./steering-delivery-preparation-C2bdoo1d.mjs";
import { t as formatForLog } from "./ws-log-DmZrdpqI.mjs";
import { n as attachManagedOutgoingMediaToMessage } from "./managed-image-attachments-CNmXrf8z.mjs";
import { a as hasAssistantDisplayMediaContent, c as isMediaBearingPayload, d as stripManagedOutgoingAssistantContentBlocks, i as extractAssistantDisplayText, l as prepareAssistantDisplayText, o as hasManagedOutgoingAssistantContent, r as combineNonStreamingReplyParts, s as hasVisibleAssistantFinalMessage, u as sanitizeAssistantDisplayText } from "./chat-assistant-content-CZwd1b0s.mjs";
import { c as readChatSendReplyPayload, i as prepareWebchatReplyMediaForDisplay, l as replaceChatSendReplyPayload, o as withPreparedWebchatReplyMedia, s as buildTranscriptReplyTextFromInputs, t as captureWebchatReplyMediaScope, u as selectChatSendFinalReplyInputs } from "./chat-reply-media-Bu6kF3Cz.mjs";
import { a as publishAssistantTranscriptRewrite, c as rewriteSourceReplyTranscriptMirrors, o as rewriteAssistantTranscriptMessageByIdempotencyKey, s as rewriteAssistantTranscriptMessageByTurnIndexAndMedia, t as assistantTranscriptScope } from "./chat-transcript-persistence-JKSwSL50.mjs";
import { a as broadcastSideResult, i as broadcastChatTerminal, n as broadcastChatError, o as isBtwReplyPayload, r as broadcastChatFinal, s as isSourceReplyTranscriptMirrorPayload, t as broadcastChatDelta } from "./chat-broadcast-C5jCvi-5.mjs";
import { a as withAbortedPartialPersistenceWarning, n as abortedPartialPersistenceError } from "./chat-aborted-partial-C13jjK9r.mjs";
import { t as appendInjectedAssistantMessageToTranscript } from "./chat-transcript-inject-CC_wJAPK.mjs";
import { t as createAssistantCommentaryMediaCustody } from "./chat-send-commentary-media-DRT1NIRD.mjs";
import { a as logAttachmentFailure, c as stripImageMediaMarkers, i as discardPreparedInboundMedia, n as MediaOffloadError, o as parseMessageWithAttachments, r as UnsupportedAttachmentError, s as persistInboundImagesForTranscript, t as INLINE_IMAGE_DURABLE_OMISSION_MARKER } from "./chat-attachments-dDb0dgqy.mjs";
import { t as errorShapeFromError } from "./error-shape-CslZ9Xfr.mjs";
import { n as deriveGatewaySessionLifecycleSnapshot, r as persistGatewaySessionLifecycleEvent } from "./session-event-payload-DJYcD4OX.mjs";
import { n as emitSessionsChanged } from "./session-change-event-DbHnHE9x.mjs";
import { n as resolveOperatorSessionCreation } from "./session-creation-provenance-CZ3I7AOG.mjs";
import { a as prepareSessionWorkspace, d as isDirectGatewayUserClient, h as prepareSkillLibrarySessionCreation, l as resolveGatewayInputParticipant, m as retainGatewayOperatorRun, n as prepareGatewaySkillAuthoring, t as invalidateSkillAuthoringForOtherRequester } from "./skill-library-authoring-BtQ8XZ4o.mjs";
import { t as normalizeRpcAttachmentsToChatAttachments } from "./attachment-normalize-Df7a_Whx.mjs";
import { n as createChatAbortOps } from "./chat-abort-ops-Cgfm8bo7.mjs";
import { a as captureGatewayClientUploadCommitGuard } from "./upload-policy-0xeWXZ7P.mjs";
import { t as captureGatewayUiCommandTarget } from "./ui-command-target-WjDnJd4j.mjs";
import { n as readChatSendDiagnostics, r as startChatSendDiagnostics } from "./chat-send-diagnostics-CPWCjGlD.mjs";
import { i as roundedChatSendTimingMs, n as prepareChatSendAckTiming, r as resolveControlUiReconnectResumeParams, t as createOperatorChatSendServerTiming } from "./chat-server-timing-DZGyaFdN.mjs";
import { n as pendingChatSendDedupeKey, t as PENDING_CHAT_SEND_DEDUPE_PREFIX } from "./server-shared-C-7Ahu3n.mjs";
import { a as buildAbortedChatSendPayload, d as resolveChatAbortRequester, i as descendantAbortError, p as writePreRegisteredChatAbort, t as abortChatRunsForSessionKeyWithPartials, u as readPreRegisteredRun } from "./chat-abort-runtime-DNr1DIGd.mjs";
import { a as resolveSessionNativeRuntimeRestriction } from "./sessions-patch-model-selection-CKJu1e6H.mjs";
import { n as fingerprintSessionGoalRequest, t as publishCommittedSessionGoalChange } from "./session-goal-change-C-tgbeqh.mjs";
import path from "node:path";
import { isDeepStrictEqual } from "node:util";
import { createHmac, randomUUID } from "node:crypto";
import { performance } from "node:perf_hooks";
//#region src/config/sessions/goals-operations-read.ts
/** Durable ingress receipts precede transient dedupe and busy-session refusals. */
async function lookupSessionGoalOperation(options) {
	const captured = {
		...options,
		...options.storePath ? { storePath: path.resolve(options.storePath) } : {},
		operation: { ...options.operation },
		env: captureSessionTranscriptStorageEnvironment(options.env ?? process.env)
	};
	assertSessionGoalOperationTime(captured.operation, Date.now());
	const source = captureIncognitoSessionSource(options);
	if (source && "kind" in source) {
		source.assertCurrent();
		return;
	}
	const incognito = captureIncognitoSessionOperation(options);
	if (incognito) {
		const target = resolveSqliteScope({
			...options,
			agentId: incognito.actor.agentId,
			storePath: incognito.actor.path
		});
		return incognito.actor.sessions.transcript(incognito.authority, {
			type: "session.goalReceipt.read",
			input: {
				sessionKey: target.sessionKey,
				sessionId: captured.expectedSessionId,
				expectedSessionId: captured.expectedSessionId,
				operation: captured.operation,
				fence: {}
			}
		}, incognito.admissionSignal);
	}
	if (isIncognitoSessionKey(captured.sessionKey)) {
		const target = resolveSqliteScope(captured);
		const result = withOpenClawAgentDatabaseReadOnly((database) => readSessionGoalOperationInDatabase(database, {
			...captured,
			sessionKey: target.sessionKey
		}), toDatabaseOptions(target));
		return result.found ? result.value : void 0;
	}
	const context = captureOpenClawStateWorkerContext({ env: captured.env });
	const assertCurrent = () => {
		context.maintenanceScope?.assertAdmission();
		context.admission.assertCurrent();
	};
	const target = await prepareSqliteScope(captured);
	assertCurrent();
	return withSessionHistoryWorkerDatabase(toDatabaseOptions(target), async (owner) => {
		const result = await owner.readGoalOperationReceipt({
			sessionKey: target.sessionKey,
			expectedSessionId: captured.expectedSessionId,
			operation: captured.operation,
			env: captured.env
		});
		assertCurrent();
		owner.assertCurrent();
		if ("error" in result) throw new SessionGoalOperationError(result.error.code, result.error.message);
		return result.receipt;
	});
}
//#endregion
//#region src/gateway/server-methods/chat-send-background.ts
function resolveWebchatPromptCacheKey(params) {
	return `openclaw-webchat-${sha256HexPrefixCore([
		"v1",
		params.provider.trim().toLowerCase(),
		params.model.trim(),
		normalizeAgentId(params.agentId),
		params.sessionKey
	].join("\0"), 32)}`;
}
function scheduleCreatedDashboardSessionTitle(created, cfg, context, titleSource) {
	if (!created.isNew || created.entry.incognito || !titleSource) return;
	scheduleChatDashboardSessionTitle({
		admittedSessionId: created.entry.sessionId,
		agentId: created.agentId,
		cfg,
		context,
		request: {
			rawMessage: titleSource,
			normalizedAttachments: []
		},
		sessionKey: created.key,
		storePath: created.storePath
	});
}
function scheduleChatDashboardSessionTitle(params, turn) {
	const titleSource = buildDashboardSessionTitleSource({
		message: params.request.rawMessage,
		attachments: params.request.normalizedAttachments
	});
	if (!isDashboardSessionTitleCandidate({
		sessionKey: params.sessionKey,
		userMessage: titleSource
	})) return;
	runWithGatewayIndependentRootWorkContinuation(async () => {
		const retryAfter = turn && await turn.released ? turn.settled : void 0;
		if (await maybeGenerateDashboardSessionTitle({
			cfg: params.cfg,
			agentId: params.agentId,
			sessionId: params.admittedSessionId,
			sessionKey: params.sessionKey,
			storePath: params.storePath,
			currentUserMessage: params.request.rawMessage,
			userMessage: titleSource,
			...retryAfter ? { retryAfter } : {},
			onFallback: () => params.context.logGateway.warn("dashboard session title generation exhausted; using a crustacean fallback name")
		})) emitSessionsChanged(params.context, {
			sessionKey: params.sessionKey,
			agentId: params.agentId,
			reason: "chat.title"
		});
	}, "chat-send:background").catch((err) => {
		params.context.logGateway.warn(`dashboard session title generation failed: ${formatForLog(err)}`);
	});
}
//#endregion
//#region src/gateway/server-methods/chat-send-retry.ts
const ACCEPTED_CHAT_SEND_MAX_DISPATCH_ATTEMPTS = 3;
/** Classify an accepted-send failure without relying on unstable error text. */
function classifyAcceptedChatSendFailure(params) {
	if (params.executionStarted || params.sideEffectsObserved) return "reconcile";
	if (params.phase === "pre-ack" && params.error instanceof AgentDatabaseAdmissionError && createAgentDatabaseAdmissionErrorShape(params.error.refusal).retryable) return "client-retry";
	if (!isSessionTranscriptProjectionUnavailableError(params.error)) return "terminal";
	return params.phase === "post-ack" ? "retry" : "client-retry";
}
/** Preserve same-ID recovery unless execution may already have produced side effects. */
function shouldRetainAcceptedChatSendRetryIdentity(disposition) {
	return disposition !== "reconcile";
}
/** Wait for the exact failed projection before another accepted-send dispatch attempt. */
async function waitForAcceptedChatSendRetry(scope, error, abortSignal) {
	if (!isSessionTranscriptProjectionUnavailableError(error)) throw error;
	await waitForSessionTranscriptProjection({
		...scope,
		sessionId: error.sessionId
	}, abortSignal);
}
/** Retry only typed, pre-execution accepted-send failures while Gateway custody remains active. */
async function runAcceptedChatSendDispatch(params) {
	for (let attempt = 1;; attempt += 1) try {
		return await params.operation();
	} catch (error) {
		if (attempt >= ACCEPTED_CHAT_SEND_MAX_DISPATCH_ATTEMPTS || params.classify(error) !== "retry") throw error;
		await params.waitForRetry(error);
	}
}
//#endregion
//#region src/gateway/server-methods/chat-send-dispatch-errors.ts
function formatReturnedAgentErrors(messages) {
	const [primary, ...additional] = [...new Set(messages)];
	if (!primary || additional.length === 0) return primary;
	if (additional.length === 1) return `${primary}\n\nAdditional error: ${additional[0]}`;
	return `${primary}\n\nAdditional errors:\n${additional.map((message) => `- ${message}`).join("\n")}`;
}
function formatChatSendError(error) {
	if (error instanceof DispatchSessionRefreshRequiredError) return `Your message didn't run because the conversation changed. Refresh the conversation, then send it again.\n\n${String(error)}`;
	return resolveStateContentionPresentation(error)?.errorMessage ?? renderAgentHarnessPreflightUserMessage(error) ?? renderFailoverCodeUserCopy(describeFailoverError(error).code) ?? String(error);
}
async function handleChatSendSetupError(params) {
	const { cleanupAdmittedRun, lifecycleGeneration, restartSafeAdmission } = params.admission;
	const { agentId, clientRunId, sessionKey } = params.session;
	const hidden = getAgentRunContext(clientRunId)?.projectSessionMessages === false;
	const jobSessionBinding = params.admission.sessionBinding;
	if (params.error instanceof ExpectedProfileMismatchError) {
		cleanupAdmittedRun();
		clearAgentRunContext(clientRunId, lifecycleGeneration);
		params.context.removeChatRun(clientRunId, clientRunId, sessionKey);
		params.respond(false, void 0, params.error.error);
		return;
	}
	const errorMessage = formatChatSendError(params.error);
	const errorKind = resolveStateContentionPresentation(params.error)?.errorKind;
	const failureDisposition = classifyAcceptedChatSendFailure({
		error: params.error,
		phase: "pre-ack"
	});
	if (restartSafeAdmission) {
		if (await params.terminalizeRestartSafeAdmission({
			error: errorMessage,
			errorKind,
			retryable: shouldRetainAcceptedChatSendRetryIdentity(failureDisposition),
			status: "failed"
		}).catch((terminalizeError) => {
			params.context.logGateway.warn(`failed to release restart-safe chat admission after setup error: ${formatForLog(terminalizeError)}`);
			return false;
		})) emitSessionsChanged(params.context, {
			sessionKey,
			...agentId ? { agentId } : {},
			reason: "chat.dispatch-error"
		});
	}
	cleanupAdmittedRun();
	clearAgentRunContext(clientRunId, lifecycleGeneration);
	params.context.removeChatRun(clientRunId, clientRunId, sessionKey);
	const error = params.error instanceof SessionMutationAuthorizationChangedError ? params.error.error : params.error instanceof SessionGoalOperationError ? errorShape(ErrorCodes.INVALID_REQUEST, params.error.message, { details: {
		code: "GOAL_OPERATION_REJECTED",
		reason: params.error.code
	} }) : errorShapeFromError(ErrorCodes.UNAVAILABLE, params.error, {
		message: errorMessage,
		...failureDisposition === "client-retry" ? {
			retryable: true,
			retryAfterMs: 250
		} : {}
	});
	const payload = {
		runId: clientRunId,
		status: "error",
		summary: errorMessage
	};
	if (params.cacheResult !== false && failureDisposition !== "client-retry") setGatewayDedupeEntry({
		dedupe: params.context.dedupe,
		key: `chat:${clientRunId}`,
		session: captureAgentJobSession(jobSessionBinding),
		entry: {
			ts: Date.now(),
			ok: false,
			payload,
			error
		}
	});
	params.respond(false, payload, error, {
		runId: clientRunId,
		error: formatForLog(params.error)
	});
	if (!hidden && failureDisposition !== "client-retry") broadcastChatError({
		terminalEntry: jobSessionBinding,
		context: params.context,
		runId: clientRunId,
		sessionKey,
		agentId,
		errorMessage,
		errorKind
	});
}
/** Own dispatch settlement and post-cleanup lifecycle persistence. */
function createChatSendDispatchErrorLifecycle(params) {
	const { admission, context, isQueuedFollowupEnqueued, persistUserTurnTranscript, session, terminalizeRestartSafeAdmission, userTurnRecorder } = params;
	const { activeRunAbort, cleanupAdmittedRun, lifecycleGeneration, restartSafeAdmission } = admission;
	const { agentId, backingSessionId, cfg, clientRunId, now, rawSessionKey, sessionKey } = session;
	const jobSessionBinding = admission.sessionBinding;
	const visibility = getAgentRunContext(clientRunId);
	const hidden = visibility?.projectSessionMessages === false;
	const suppressLifecycle = visibility?.projectSessionLifecycle === false;
	let abortedDispatchMarker;
	let pendingDispatchLifecycleError;
	let persistDispatchErrorUserTurn;
	let publishDispatchError;
	const broadcastError = (error) => {
		if (!hidden && (params.isReplyDispatchRun?.() || activeRunAbort.entry?.terminalOutcomeObserved !== true)) broadcastChatError({
			terminalEntry: jobSessionBinding,
			context,
			runId: clientRunId,
			sessionKey,
			agentId,
			...error
		});
	};
	const handleError = async (err) => {
		const errorMessage = formatChatSendError(err);
		const errorKind = resolveStateContentionPresentation(err)?.errorKind;
		const failureDisposition = params.classifyFailure?.(err) ?? classifyAcceptedChatSendFailure({
			error: err,
			phase: "post-ack"
		});
		if (isQueuedFollowupEnqueued()) {
			context.logGateway.warn(`webchat dispatch failed after followup queue admission: ${formatForLog(err)}`);
			return;
		}
		const abortedAtDispatchReject = activeRunAbort.controller.signal.aborted;
		const abortMarkerAtDispatchReject = context.chatRunState.runs.get(clientRunId)?.abortMarker;
		const agentTerminalOwnedAtDispatchReject = activeRunAbort.entry?.terminalOutcomeObserved === true;
		if (abortedAtDispatchReject && abortMarkerAtDispatchReject !== void 0) {
			abortedDispatchMarker = abortMarkerAtDispatchReject;
			context.logGateway.warn(`chat.send post-dispatch threw after abort for runId=${clientRunId}: ${formatForLog(err)}`);
			if (!userTurnRecorder.hasPersisted() && !userTurnRecorder.isBlocked()) try {
				await persistUserTurnTranscript();
			} catch (transcriptError) {
				context.logGateway.warn(`webchat user transcript update failed after abort: ${formatForLog(transcriptError)}`);
			}
			return;
		}
		context.chatRunState.deleteAbortMarker(clientRunId);
		if (agentTerminalOwnedAtDispatchReject && activeRunAbort.entry) activeRunAbort.entry.isAbortable = () => false;
		activeRunAbort.cleanup();
		let restartSafeDispatchFailureTerminalized = false;
		if (restartSafeAdmission && !agentTerminalOwnedAtDispatchReject) {
			restartSafeDispatchFailureTerminalized = await terminalizeRestartSafeAdmission({
				error: errorMessage,
				errorKind,
				retryable: shouldRetainAcceptedChatSendRetryIdentity(failureDisposition),
				status: "failed"
			}).catch((terminalizeError) => {
				context.logGateway.warn(`failed to release restart-safe chat admission after dispatch error: ${formatForLog(terminalizeError)}`);
				return false;
			});
			if (restartSafeDispatchFailureTerminalized) emitSessionsChanged(context, {
				sessionKey,
				...agentId ? { agentId } : {},
				reason: "chat.dispatch-error"
			});
		}
		persistDispatchErrorUserTurn = userTurnRecorder.hasPersisted() || userTurnRecorder.isBlocked() ? void 0 : async () => {
			await persistUserTurnTranscript();
		};
		if (!suppressLifecycle && !restartSafeDispatchFailureTerminalized && abortMarkerAtDispatchReject === void 0 && !agentTerminalOwnedAtDispatchReject) pendingDispatchLifecycleError = {
			endedAt: Date.now(),
			error: errorMessage,
			errorKind,
			sessionId: activeRunAbort.entry?.sessionId ?? backingSessionId ?? clientRunId,
			startedAt: activeRunAbort.entry?.startedAtMs ?? now
		};
		if (!agentTerminalOwnedAtDispatchReject || params.isReplyDispatchRun?.()) {
			const publish = () => {
				const error = errorShapeFromError(ErrorCodes.UNAVAILABLE, err, { message: errorMessage });
				setGatewayDedupeEntry({
					dedupe: context.dedupe,
					key: `chat:${clientRunId}`,
					session: captureAgentJobSession(jobSessionBinding),
					entry: {
						ts: Date.now(),
						ok: false,
						payload: {
							runId: clientRunId,
							status: "error",
							summary: errorMessage
						},
						error
					}
				});
				broadcastError({
					errorMessage,
					errorKind
				});
			};
			if (pendingDispatchLifecycleError) publishDispatchError = publish;
			else publish();
		}
	};
	const finalize = async () => {
		const dispatchError = pendingDispatchLifecycleError;
		const clearRun = () => {
			if (!isQueuedFollowupEnqueued() && (!params.isAgentRunStarted() || params.isReplyDispatchRun?.())) {
				context.chatRunState.clearRun(clientRunId);
				context.agentRunSeq.delete(clientRunId);
			}
		};
		if (!dispatchError) {
			const abortMarker = abortedDispatchMarker ?? (activeRunAbort.controller.signal.aborted ? context.chatRunState.runs.get(clientRunId)?.abortMarker : void 0);
			if (abortMarker) {
				const endedAt = chatAbortMarkerTimestampMs(abortMarker);
				setGatewayDedupeEntry({
					dedupe: context.dedupe,
					key: `chat:${clientRunId}`,
					session: captureAgentJobSession(jobSessionBinding),
					entry: {
						ts: endedAt,
						ok: true,
						payload: buildAbortedChatSendPayload({
							runId: clientRunId,
							stopReason: activeRunAbort.entry?.abortStopReason ?? "rpc",
							endedAt
						})
					}
				});
			}
			clearRun();
			cleanupAdmittedRun();
			clearAgentRunContext(clientRunId, lifecycleGeneration);
			context.removeChatRun(clientRunId, clientRunId, sessionKey);
			return;
		}
		clearAgentRunContext(clientRunId, lifecycleGeneration);
		context.removeChatRun(clientRunId, clientRunId, sessionKey);
		try {
			await persistDispatchErrorUserTurn?.().catch((transcriptErr) => {
				context.logGateway.warn(`webchat user transcript update failed after error: ${formatForLog(transcriptErr)}`);
			});
			if (!hasTrackedActiveSessionRun({
				context,
				requestedKey: rawSessionKey,
				canonicalKey: sessionKey,
				...agentId ? { agentId } : {},
				defaultAgentId: tryResolveSessionCompatibilityOwnerAgentId(cfg, sessionKey)
			})) try {
				await persistGatewaySessionLifecycleEvent({
					sessionKey,
					...agentId ? { agentId } : {},
					event: {
						runId: clientRunId,
						sessionId: dispatchError.sessionId,
						lifecycleGeneration,
						ts: dispatchError.endedAt,
						data: {
							phase: "error",
							startedAt: dispatchError.startedAt,
							endedAt: dispatchError.endedAt,
							error: dispatchError.error,
							errorKind: dispatchError.errorKind
						}
					}
				});
				emitSessionsChanged(context, {
					sessionKey,
					...agentId ? { agentId } : {},
					reason: "chat.dispatch-error"
				});
			} catch (persistErr) {
				context.logGateway.warn(`webchat session lifecycle persist failed after error: ${formatForLog(persistErr)}`);
			}
		} catch (continuationErr) {
			context.logGateway.warn(`webchat session lifecycle continuation failed: ${formatForLog(continuationErr)}`);
		} finally {
			try {
				publishDispatchError?.();
			} finally {
				clearRun();
				cleanupAdmittedRun();
			}
		}
	};
	return {
		broadcastError,
		finalize,
		handleError
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-reply-context.ts
const REPLY_CONTEXT_BODY_MAX_CHARS = 2e3;
/** Adds hydrated reply metadata to the direct-injection user prompt. */
function buildChatSendReplyInjectionText(params) {
	const prefix = buildInboundUserContextPrefix(params.ctx, resolveEnvelopeFormatOptions(params.cfg), params.sessionEntry);
	return prefix ? `${prefix}\n\n${params.body}` : params.body;
}
function extractReplyTargetText(entry) {
	if (typeof entry.text === "string" && entry.text.trim()) return entry.text;
	if (typeof entry.content === "string" && entry.content.trim()) return entry.content;
	if (!Array.isArray(entry.content)) return;
	const parts = entry.content.map((block) => {
		const record = asOptionalRecord(block);
		return record && typeof record.text === "string" ? record.text : "";
	}).filter((text) => text.trim());
	return parts.length > 0 ? parts.join("\n") : void 0;
}
/** Copies hydrated reply fields onto the inbound context without clobbering unset keys. */
function applyChatSendReplyContextFields(ctx, fields) {
	for (const key of [
		"ReplyToId",
		"ReplyToBody",
		"ReplyToSender"
	]) if (fields[key] !== void 0) ctx[key] = fields[key];
}
/**
* Resolves a webchat reply target from session history. Always preserves the
* reply_to_id linkage; body/sender hydrate only when the transcript message
* still resolves, mirroring Discord's missing-referenced-message tolerance.
*/
async function resolveChatSendReplyContext(params) {
	const replyToId = params.replyToId?.trim();
	if (!replyToId) return {};
	const fields = { ReplyToId: replyToId };
	const sessionId = params.sessionEntry?.sessionId;
	if (!sessionId) return fields;
	try {
		const resolved = await readSessionMessageByIdAsync({
			agentId: params.agentId,
			sessionEntry: params.sessionEntry,
			sessionId,
			sessionKey: params.sessionKey,
			storePath: params.storePath
		}, replyToId, { allowResetArchiveFallback: true });
		if (!resolved.found) return fields;
		const displayMessage = projectChatDisplayMessage(resolved.message, { resolveCronJobName: () => void 0 });
		if (!displayMessage) return fields;
		const rawBody = extractReplyTargetText(displayMessage)?.trim();
		const body = rawBody && displayMessage.role === "assistant" ? sanitizeAssistantVisibleTextWithProfile(rawBody, "history").trim() : rawBody;
		if (!body) return fields;
		fields.ReplyToBody = truncateUtf16Safe(body, REPLY_CONTEXT_BODY_MAX_CHARS);
		fields.ReplyToSender = displayMessage.role === "assistant" ? (await resolveAssistantIdentity({
			cfg: params.cfg,
			agentId: params.agentId
		})).name : params.userSenderLabel?.trim() || "User";
		return fields;
	} catch (err) {
		params.warn?.(`chat.send reply context hydration failed for ${replyToId}: ${String(err)}`);
		return fields;
	}
}
//#endregion
//#region src/gateway/server-methods/chat-send-message-injection.ts
/** Captures the prepared request data used by both pre-ACK and detached injection attempts. */
function createChatSendMessageInjectionStarter(params) {
	const { p, rawMessage, supportsTaskSuggestions } = params.request;
	const { agentId, cfg, entry, sessionKey, storePath, clientRunId } = params.session;
	const { ctx, isInternalTextSlashCommandTurn, replyOptionImages, replyOptionMedia } = params.turn;
	const assertCurrent = () => {
		params.abortSignal.throwIfAborted();
		params.assertCurrent?.();
		params.operatorAuthority?.assertCurrent();
	};
	return async () => {
		const target = params.target;
		if (!target || isInternalTextSlashCommandTurn) return;
		assertCurrent();
		const delivery = prepareSteeringDelivery({
			agentId,
			sessionKey,
			storePath,
			sessionId: entry?.sessionId,
			sourceTurnId: normalizeOptionalString(target.sourceTurnId),
			entry,
			assertCurrent
		});
		let admissionRefused = false;
		const canAdmit = () => {
			assertCurrent();
			let fenceEntry = entry;
			if (sessionKey) try {
				fenceEntry = loadSessionEntry({
					sessionKey,
					storePath,
					readConsistency: "latest"
				}) ?? entry;
			} catch (error) {
				params.logGateway.warn("chat steering rejected; falling back to follow-up dispatch", {
					reason: "session-entry-unavailable",
					runId: clientRunId,
					activeRunId: target.runId,
					sessionKey,
					error: String(error)
				});
				return false;
			}
			const activeSourceTurnId = normalizeOptionalString(target.sourceTurnId) ?? normalizeOptionalString(fenceEntry?.restartRecoveryDeliverySourceRunId) ?? "";
			const blockReason = fenceEntry ? resolveRestartRecoverySteeringBlockReason(fenceEntry, fenceEntry.sessionId, activeSourceTurnId) : void 0;
			if (blockReason) {
				params.logGateway.warn("chat steering rejected; falling back to follow-up dispatch", {
					reason: blockReason,
					runId: clientRunId,
					activeRunId: target.runId,
					sourceTurnId: activeSourceTurnId || void 0,
					sourceTurnIdOrigin: target.sourceTurnId ? "active-run" : activeSourceTurnId ? "recovery-claim" : "unknown",
					sessionKey,
					sessionId: fenceEntry?.sessionId,
					sessionStatus: fenceEntry?.status,
					recoveryRunId: fenceEntry?.restartRecoveryDeliveryRunId,
					recoverySourceTurnId: fenceEntry?.restartRecoveryDeliverySourceRunId
				});
				return false;
			}
			return true;
		};
		const { debounceMs } = resolveQueueSettings({
			cfg,
			channel: ctx.Provider,
			sessionEntry: entry,
			inlineMode: p.queueMode
		});
		const baseText = ctx.BodyForAgent ?? ctx.Body ?? rawMessage;
		const rendered = params.documentContext?.status === "rendered" ? params.documentContext : void 0;
		const documentContext = rendered?.text.trim();
		let text = baseText;
		if (documentContext || params.documentContext?.status === "failed") text = [
			buildInboundMediaNoteProjection(ctx).text,
			baseText.trim(),
			documentContext
		].filter(Boolean).join("\n\n");
		const documentImages = rendered?.images ?? [];
		const injectionImages = documentImages.length > 0 ? [...replyOptionImages ?? [], ...documentImages.map((image) => ({
			type: "image",
			data: image.data,
			mimeType: image.mimeType,
			sourceIndex: image.attachmentIndex
		}))] : replyOptionImages;
		const authorization = resolveCommandAuthorization({
			ctx,
			cfg,
			commandAuthorized: ctx.CommandAuthorized === true
		});
		const attempt = await beginReplyMessageInjectionTarget(target, p.replyToId ? buildChatSendReplyInjectionText({
			body: text,
			cfg,
			ctx,
			sessionEntry: entry
		}) : text, {
			currentInboundContext: p.replyToId ? void 0 : { text: buildInboundUserContextPrefix(ctx, resolveEnvelopeFormatOptions(cfg), entry) },
			canAdmit: () => {
				admissionRefused = !canAdmit();
				return !admissionRefused;
			},
			assertCurrent: params.assertCurrent || params.operatorAuthority ? assertCurrent : void 0,
			toolAuthorityPreparation: bindPreparedToolAuthority(bindWorkerToolPreparation({
				authorityKind: params.assertCurrent || params.operatorAuthority ? "source-bound" : "run",
				assertCurrent,
				compatAssertCurrent: assertCurrent,
				prepareCurrent: delivery.prepareCurrent
			})),
			inboundAudio: hasInboundAudio(ctx),
			steeringMode: "all",
			isInboundUserMessage: true,
			...isProgressCardRefreshInputProvenance(ctx.InputProvenance) ? {
				allowPendingUserInputAnswer: false,
				debounceMs: 0
			} : {},
			toolAuthorityOverlay: resolveInboundReplyToolAuthorityOverlay({
				ctx,
				sessionEntry: {
					spawnedBy: entry?.spawnedBy,
					permissionMode: params.admittedSessionSettings?.permissionMode,
					toolOverrides: params.admittedSessionSettings?.toolOverrides
				},
				senderIsOwner: authorization.senderIsOwner,
				operatorAuthority: params.operatorAuthority,
				disableTools: false
			}),
			...injectionImages?.length ? { images: injectionImages } : {},
			...params.imageOrder?.length ? { imageOrder: params.imageOrder } : {},
			...replyOptionMedia?.length ? { media: replyOptionMedia } : {},
			waitForTranscriptCommit: true,
			abortSignal: params.abortSignal,
			...!isProgressCardRefreshInputProvenance(ctx.InputProvenance) && debounceMs !== void 0 ? { debounceMs } : {},
			taskSuggestionDeliveryMode: supportsTaskSuggestions ? "gateway" : void 0,
			userTurnTranscriptRecorder: params.userTurnTranscriptRecorder
		});
		return admissionRefused ? void 0 : attempt;
	};
}
/** Wait for runtime ownership before ACK without waiting for transcript commitment. */
async function settleChatSendPreAckMessageInjection(params) {
	if (!params.attempt || await params.attempt.acceptance) return {
		status: "continue",
		attempt: params.attempt
	};
	const outcome = await params.attempt.outcome;
	if (outcome.status === "failed") throw outcome.error;
	if (params.isAborted()) {
		params.onAborted();
		return { status: "handled" };
	}
	if (params.sessionRoutingChanged()) {
		params.onSessionRoutingChanged();
		return { status: "handled" };
	}
	return {
		status: "continue",
		attempt: void 0
	};
}
/** Pre-ACK steering is already owned; join it before fallible source preparation. */
async function settleChatSendMessageInjection(attempt) {
	if (!attempt) return false;
	const outcome = await attempt.outcome;
	if (outcome.status === "failed") throw outcome.error;
	return outcome.status !== "rejected";
}
/** Finish an accepted steer without entering reply dispatch, or return false for fallback. */
async function finalizeAcceptedChatSendMessageInjection(params) {
	const { context, ctx, session } = params;
	const { agentId, cfg, clientRunId, entry, sessionKey, storePath } = session;
	const finalizedCtx = finalizeInboundContext(ctx);
	const progressRefresh = isProgressCardRefreshInputProvenance(ctx.InputProvenance);
	const finalization = await finalizeReplyMessageInjectionAttempt({
		attempt: params.attempt,
		target: params.target,
		inboundAudio: hasInboundAudio(finalizedCtx)
	});
	if (finalization.status === "rejected") return false;
	recordAcceptedSessionParticipantInput(ctx, {
		agentId,
		sessionKey,
		storePath
	});
	const channel = normalizeLowercaseStringOrEmpty(finalizedCtx.Surface ?? finalizedCtx.Provider ?? "unknown");
	const chatId = finalizedCtx.To ?? finalizedCtx.From;
	const messageId = finalizedCtx.MessageSidFull ?? finalizedCtx.MessageSid ?? finalizedCtx.MessageSidFirst ?? finalizedCtx.MessageSidLast;
	const indeterminate = finalization.status === "indeterminate" ? finalization.outcome.errorMessage : void 0;
	const outcomeReason = indeterminate ? progressRefresh ? "progress_refresh_receipt_unconfirmed" : "question_response_indeterminate" : "active_run_injected";
	await params.persistUserTurnTranscriptBestEffort();
	if (isDiagnosticsEnabled(cfg)) {
		logMessageReceived({
			sessionKey,
			channel,
			chatId,
			messageId,
			source: "dispatchInboundMessage"
		});
		logMessageProcessed({
			channel,
			chatId,
			messageId,
			sessionId: entry?.sessionId,
			sessionKey,
			durationMs: Math.max(0, Date.now() - params.startedAt),
			outcome: indeterminate ? "error" : "completed",
			reason: outcomeReason
		});
	}
	emitMessageReceivedHooks({
		ctx: finalizedCtx,
		hookRunner: getGlobalHookRunner(),
		sessionKey,
		timestamp: typeof finalizedCtx.Timestamp === "number" && Number.isFinite(finalizedCtx.Timestamp) ? finalizedCtx.Timestamp : void 0
	});
	emitInboundMessageAuditTerminal({
		cfg,
		counts: {
			tool: 0,
			block: 0,
			final: 0
		},
		ctx: finalizedCtx,
		observedRunId: clientRunId,
		startedAt: params.startedAt,
		terminal: indeterminate ? {
			outcome: "error",
			options: {
				reason: outcomeReason,
				error: indeterminate
			}
		} : {
			outcome: "completed",
			options: { reason: outcomeReason }
		}
	});
	const updatedAt = Date.now();
	if (entry) entry.updatedAt = updatedAt;
	await updateSessionEntry({
		storePath,
		sessionKey
	}, () => ({ updatedAt }), {
		skipMaintenance: true,
		takeCacheOwnership: true
	}).catch((error) => {
		context.logGateway.warn(`failed to touch session after accepted steering: ${String(error)}`);
	});
	if (!context.chatRunState.hasAbortMarker(clientRunId)) {
		setGatewayDedupeEntry({
			dedupe: context.dedupe,
			key: `chat:${clientRunId}`,
			session: captureAgentJobSession(params.sessionBinding),
			entry: {
				ts: Date.now(),
				ok: progressRefresh || !indeterminate,
				payload: {
					runId: clientRunId,
					status: progressRefresh ? "accepted" : indeterminate ? "error" : "ok",
					...indeterminate ? { summary: indeterminate } : {}
				},
				...!progressRefresh && indeterminate ? { error: errorShape(ErrorCodes.UNAVAILABLE, indeterminate) } : {}
			}
		});
		if (indeterminate) broadcastChatError({
			terminalEntry: params.sessionBinding,
			context,
			runId: clientRunId,
			sessionKey,
			agentId,
			errorMessage: indeterminate
		});
		else broadcastChatFinal({
			context,
			runId: clientRunId,
			sessionKey,
			agentId,
			terminalEntry: params.sessionBinding
		});
	}
	return true;
}
//#endregion
//#region src/gateway/server-methods/chat-send-reply-delivery.ts
/** Match prepared evidence to the current session without querying its transcript. */
function resolveChatReplyTranscriptStart(session, current, prepared) {
	const scope = {
		agentId: session.agentId,
		sessionKey: session.sessionKey,
		sessionId: current.entry?.sessionId ?? session.backingSessionId,
		storePath: current.storePath
	};
	if (prepared && (prepared.agentId !== scope.agentId || prepared.sessionId !== scope.sessionId || prepared.sessionKey !== scope.sessionKey || !isSameOpenClawAgentDatabasePath(prepared.storePath, scope.storePath))) return;
	const watermark = prepared === void 0 && scope.sessionId ? readSessionTranscriptWatermark({
		...scope,
		sessionId: scope.sessionId
	}) : prepared ?? {
		generation: null,
		maxSeq: null
	};
	return {
		sessionId: scope.sessionId,
		generation: watermark.generation,
		afterSeq: watermark.maxSeq ?? 0
	};
}
/** Decide receipt coverage from one current anchor snapshot and the observed transcript bounds. */
function resolveChatReplyDeliveryFromAnchors(params) {
	const { facts, afterSeq, watermark, currentWatermark } = params;
	const admitted = facts.anchors.find((entry) => entry.entryId === params.admissionId);
	const input = facts.anchors.find((entry) => entry.entryId === params.inputId);
	const anchor = facts.anchors.find((entry) => entry.entryId === params.messageId);
	if (!admitted || !input) return "missing";
	if (!anchor || anchor.rawSeq <= afterSeq || anchor.activeMessagePosition <= input.activeMessagePosition) return;
	if (facts.tail?.entries.some((entry) => entry.role === "user" && entry.anchor && entry.anchor.activeMessagePosition > anchor.activeMessagePosition)) return "missing";
	if (currentWatermark.generation !== watermark.generation || currentWatermark.maxSeq !== watermark.maxSeq || anchor.generation !== currentWatermark.generation || facts.tail?.lastSeq !== currentWatermark.maxSeq) return "pending";
	return "delivered";
}
//#endregion
//#region src/gateway/server-methods/chat-send-delivery-authority.ts
function createChatSendReplyFinalizationAuthority(params, payloads, onUnauthorized) {
	const { cfg, sessionKey, agentId, sessionLoadOptions } = params.session;
	const deliveryAuthorized = () => (!params.isCurrent || params.isCurrent()) && payloads.every((payload) => {
		const authority = getReplyPayloadMetadata(payload)?.sessionWriterDeliveryAuthority;
		if (!authority) return true;
		const current = loadGatewaySessionEntry(authority.sessionKey, {
			...sessionLoadOptions,
			...authority.agentId || agentId ? { agentId: authority.agentId ?? agentId } : {}
		}).entry;
		return isReplyPayloadSessionWriterDeliveryAuthorized(payload, current);
	});
	return {
		deliveryAuthorized,
		authorizeDelivery: (stage) => {
			if (deliveryAuthorized()) return true;
			params.context.logGateway.warn(`webchat settled final reply skipped: session writer changed before ${stage}`);
			onUnauthorized?.();
			return false;
		},
		captureMediaScope: () => captureWebchatReplyMediaScope({
			cfg,
			sessionKey,
			agentId,
			sessionLoadOptions,
			requesterContext: params.requesterContext,
			accountId: params.accountId,
			assertCurrent: () => {
				if (!deliveryAuthorized()) throw new Error("Chat media delivery is no longer authorized.");
			}
		})
	};
}
//#endregion
//#region src/gateway/server-methods/chat-tts-markers.ts
function stripVisibleTextFromTtsSupplement(payload) {
	return isReplyPayloadTtsSupplement(payload) ? buildTtsSupplementMediaPayload(payload) : payload;
}
function resolveTtsSupplementMarkerText(text) {
	const trimmed = text.trim();
	const projected = projectChatDisplayMessage({
		role: "assistant",
		content: [{
			type: "text",
			text: trimmed
		}]
	}, { maxChars: Number.MAX_SAFE_INTEGER });
	const projectedContent = Array.isArray(projected?.content) ? projected.content : void 0;
	return extractAssistantDisplayText(projectedContent) ?? (typeof projected?.text === "string" ? projected.text.trim() : void 0) ?? trimmed;
}
function buildTtsSupplementTranscriptMarker(payload) {
	const supplement = getReplyPayloadTtsSupplement(payload);
	if (!supplement) return;
	const visibleText = resolveTtsSupplementMarkerText(payload.text?.trim() || supplement.spokenText.trim());
	return { textSha256: sha256Hex(visibleText) };
}
function buildMediaOnlyTtsSupplementTranscriptMarker(payload) {
	if (payload.text?.trim()) return;
	return buildTtsSupplementTranscriptMarker(payload);
}
//#endregion
//#region src/gateway/server-methods/chat-send-reply-finalization.ts
const retainCommittedChatReplyMedia = (receipt, acceptCompletion) => {
	const blocks = readAssistantDisplayContent(receipt.message);
	if (hasManagedOutgoingAssistantContent(blocks)) acceptCompletion(async () => {
		await attachManagedOutgoingMediaToMessage({
			messageId: receipt.messageId,
			blocks
		});
	});
};
function resolveTranscriptMirrorOwner(payloads) {
	const owners = payloads.map((payload) => getReplyPayloadMetadata(payload)?.sourceReplyTranscriptMirror);
	if (owners.every((owner) => owner?.expectedSessionId === void 0 && !owner?.transcriptWriteBlocked)) return { kind: "none" };
	const first = owners[0];
	if (!first) return { kind: "invalid" };
	const sessionKey = first.sessionKey.trim();
	const expectedSessionId = first.expectedSessionId?.trim();
	if (!sessionKey || !first.transcriptWriteBlocked && !expectedSessionId || owners.some((owner) => first.transcriptWriteBlocked && !owner?.transcriptWriteBlocked || owner?.sessionKey.trim() !== sessionKey || owner.expectedSessionId?.trim() !== expectedSessionId || owner.agentId !== first.agentId || !first.transcriptWriteBlocked && owner.transcriptWriteBlocked === true)) return { kind: "invalid" };
	return {
		kind: first.transcriptWriteBlocked ? "blocked" : "owner",
		owner: {
			sessionKey,
			...expectedSessionId ? { expectedSessionId } : {},
			...first.agentId ? { agentId: first.agentId } : {}
		}
	};
}
function buildChatSendBtwSideResult(deliveredReplies) {
	const replies = deliveredReplies.map((entry) => readChatSendReplyPayload(entry.input)).filter(isBtwReplyPayload);
	const text = combineNonStreamingReplyParts(replies.map((payload) => payload.text));
	if (replies.length === 0 || !text) return;
	return {
		question: expectDefined(replies[0], "btw replies entry at 0").btw.question.trim(),
		text,
		isError: replies.some((payload) => payload.isError)
	};
}
/** Finalize settled reply payloads, retaining the runtime's transcript ownership and outcome. */
async function finalizeChatSendDispatchedReplies(params) {
	const { context, deliveredReplies, emitFirstAssistantServerTiming, foldCommandBlocks, persistUserTurnTranscript, session, suppressReplies } = params;
	const { agentId, backingSessionId, cfg, clientRunId, sessionKey, sessionLoadOptions } = session;
	const stopReason = params.state === "aborted" ? "aborted" : "stop";
	const btwResult = buildChatSendBtwSideResult(deliveredReplies);
	if (btwResult) {
		broadcastSideResult({
			context,
			payload: {
				kind: "btw",
				runId: clientRunId,
				sessionKey,
				...agentId ? { agentId } : {},
				...btwResult,
				ts: Date.now()
			}
		});
		broadcastChatFinal({
			terminalEntry: params.terminalEntry,
			context,
			runId: clientRunId,
			sessionKey,
			agentId
		});
		return;
	}
	const contextFreeCommand = !params.runtimeOwnsTranscript && deliveredReplies.length > 0 && deliveredReplies.every(({ input }) => {
		const payload = readChatSendReplyPayload(input);
		const metadata = getReplyPayloadMetadata(payload);
		return metadata?.commandReply === true && metadata.contextFreeCommand === true && metadata.assistantTranscriptOwned !== true;
	});
	const selectedInputs = selectChatSendFinalReplyInputs({
		deliveredReplies,
		foldCommandBlocks,
		suppressReplies
	});
	const rawFinalPayloads = selectedInputs.map(readChatSendReplyPayload);
	const { authorizeDelivery, captureMediaScope } = createChatSendReplyFinalizationAuthority(params, rawFinalPayloads, () => broadcastChatFinal({
		context,
		runId: clientRunId,
		sessionKey,
		agentId,
		terminalEntry: params.terminalEntry
	}));
	if (!authorizeDelivery("finalization")) return;
	const transcriptMirrorResolution = resolveTranscriptMirrorOwner(rawFinalPayloads);
	const transcriptMirrorOwner = transcriptMirrorResolution.kind === "owner" || transcriptMirrorResolution.kind === "blocked" ? transcriptMirrorResolution.owner : void 0;
	const mediaScope = captureMediaScope();
	const sourceSession = await loadGatewaySessionEntryReadOnlyInWorker({
		cfg: context.getRuntimeConfig(),
		key: sessionKey,
		...sessionLoadOptions,
		projection: []
	});
	const requestedTranscriptSession = transcriptMirrorOwner ? await loadGatewaySessionEntryReadOnlyInWorker({
		cfg: context.getRuntimeConfig(),
		key: transcriptMirrorOwner.sessionKey,
		...sessionLoadOptions,
		...transcriptMirrorOwner.agentId ? { agentId: transcriptMirrorOwner.agentId } : {},
		projection: []
	}) : void 0;
	if (!authorizeDelivery("session preparation")) return;
	const useTranscriptMirrorOwner = Boolean(transcriptMirrorResolution.kind === "owner" && transcriptMirrorOwner && requestedTranscriptSession?.entry?.sessionId === transcriptMirrorOwner.expectedSessionId);
	if (transcriptMirrorResolution.kind === "owner" && !useTranscriptMirrorOwner) context.logGateway.warn(`webchat transcript append skipped: binding-owned session changed before finalization`);
	if (transcriptMirrorResolution.kind === "invalid") context.logGateway.warn(`webchat transcript append skipped: inconsistent binding-owned transcript metadata`);
	if (transcriptMirrorResolution.kind === "blocked") context.logGateway.warn(`webchat transcript append skipped: binding-owned user turn was not persisted`);
	const canAppendAssistantTranscript = transcriptMirrorResolution.kind === "none" || useTranscriptMirrorOwner;
	const transcriptSessionKey = useTranscriptMirrorOwner && transcriptMirrorOwner ? transcriptMirrorOwner.sessionKey : sessionKey;
	const transcriptAgentId = useTranscriptMirrorOwner && transcriptMirrorOwner ? transcriptMirrorOwner.agentId ?? agentId : agentId;
	const { storePath: latestStorePath, entry: latestEntry } = useTranscriptMirrorOwner && requestedTranscriptSession ? requestedTranscriptSession : sourceSession;
	const sessionId = latestEntry?.sessionId ?? backingSessionId ?? clientRunId;
	let managedMediaPrepareFailed = false;
	const { payloads: finalPayloads, inputs: finalInputs, mediaMessage, assistantContent, persistedAssistantContent } = await prepareWebchatReplyMediaForDisplay({
		scope: mediaScope,
		storePath: sourceSession.storePath,
		transcriptTarget: {
			sessionKey: transcriptSessionKey,
			agentId: transcriptAgentId
		},
		inputs: selectedInputs,
		abortSignal: params.abortSignal,
		includeSensitiveMedia: false,
		includeSensitiveDisplay: true,
		onLocalAudioAccessDenied: (err) => {
			context.logGateway.warn(`webchat audio embedding denied local path: ${formatForLog(err)}`);
		},
		onManagedMediaPrepareError: (message) => {
			managedMediaPrepareFailed = true;
			context.logGateway.warn(`webchat media embedding skipped attachment: ${message}`);
		},
		onSensitiveDisplayPrepareError: (message) => {
			context.logGateway.warn(`webchat sensitive display skipped attachment: ${message}`);
		}
	});
	const ttsSupplementMarker = finalPayloads.map((payload) => buildMediaOnlyTtsSupplementTranscriptMarker(payload)).find((marker) => Boolean(marker));
	const persistedContentForAppend = hasAssistantDisplayMediaContent(persistedAssistantContent) ? persistedAssistantContent : void 0;
	const broadcastAssistantContent = hasAssistantDisplayMediaContent(assistantContent) ? assistantContent : hasAssistantDisplayMediaContent(mediaMessage?.content) ? mediaMessage?.content : assistantContent;
	const displayReply = extractAssistantDisplayText(assistantContent) ?? buildTranscriptReplyTextFromInputs(finalInputs);
	const transcriptDisplayReply = displayReply?.trim() ?? "";
	const transcriptReply = mediaMessage?.transcriptText || (managedMediaPrepareFailed ? transcriptDisplayReply : buildTranscriptReplyTextFromInputs(finalInputs)) || transcriptDisplayReply;
	let message;
	const payloadOwnsAssistantTranscript = rawFinalPayloads.some((payload) => getReplyPayloadMetadata(payload)?.assistantTranscriptOwned === true);
	const shouldAppendAssistantTranscript = Boolean((!params.runtimeOwnsTranscript && !payloadOwnsAssistantTranscript || useTranscriptMirrorOwner) && canAppendAssistantTranscript && (transcriptReply || persistedContentForAppend?.length));
	if (contextFreeCommand) await persistUserTurnTranscript({ contextFreeCommand: true });
	else await persistUserTurnTranscript();
	if (!authorizeDelivery("transcript append")) return;
	if (shouldAppendAssistantTranscript) {
		const appended = await appendInjectedAssistantMessageToTranscript({
			sessionKey: transcriptSessionKey,
			message: transcriptReply,
			...persistedContentForAppend?.length ? { content: persistedContentForAppend } : {},
			sessionId,
			storePath: latestStorePath,
			agentId: transcriptAgentId,
			idempotencyKey: clientRunId,
			stopReason,
			ttsSupplement: ttsSupplementMarker,
			...contextFreeCommand ? { contextFreeCommand: true } : {},
			config: cfg,
			onMessageCommitted: retainCommittedChatReplyMedia
		});
		if (appended.ok) message = broadcastAssistantContent?.length ? applyAssistantDeliveryDirectives({
			...appended.message,
			content: broadcastAssistantContent.map((block) => ({ ...block }))
		}) : appended.message;
		else {
			context.logGateway.warn(`webchat transcript append failed: ${appended.error ?? "unknown error"}`);
			const fallbackAssistantContent = stripManagedOutgoingAssistantContentBlocks(persistedAssistantContent) ?? stripManagedOutgoingAssistantContentBlocks(assistantContent);
			const fallbackText = extractAssistantDisplayText(fallbackAssistantContent) ?? displayReply;
			message = {
				role: "assistant",
				...fallbackAssistantContent?.length ? { content: fallbackAssistantContent } : fallbackText ? { content: [{
					type: "text",
					text: fallbackText
				}] } : {},
				...fallbackText ? { text: fallbackText } : {},
				timestamp: Date.now(),
				...ttsSupplementMarker ? { openclawTtsSupplement: ttsSupplementMarker } : {},
				stopReason,
				usage: {
					input: 0,
					output: 0,
					totalTokens: 0
				}
			};
		}
	} else if (broadcastAssistantContent?.length) message = {
		role: "assistant",
		content: broadcastAssistantContent,
		text: extractAssistantDisplayText(broadcastAssistantContent) ?? "",
		timestamp: Date.now(),
		stopReason,
		usage: {
			input: 0,
			output: 0,
			totalTokens: 0
		}
	};
	if (!authorizeDelivery("broadcast")) return;
	const run = context.chatRunState.runs.get(clientRunId);
	if (!suppressReplies && run?.bufferIsCurrent?.() !== false) message = appendChatCanvasBlocksToMessage(message, run?.canvasBlocks ?? []);
	if (hasVisibleAssistantFinalMessage(message)) emitFirstAssistantServerTiming();
	broadcastChatTerminal({
		terminalEntry: params.terminalEntry,
		context,
		runId: clientRunId,
		sessionKey,
		agentId,
		message,
		state: params.state,
		stopReason: params.stopReason
	});
}
//#endregion
//#region src/gateway/server-methods/chat-send-reply-session.ts
/** Initialization owns the start binding; later delivery decisions read fresh stored rows. */
function createChatReplySessionReader(session, getRuntimeConfig, assertWorkCurrent) {
	const initialStorePath = session.storePath ?? resolveSessionStorePathCore(session.cfg.session?.store, { agentId: session.agentId });
	let preparedSession = {
		sessionKey: session.sessionKey,
		sessionId: session.entry?.sessionId ?? session.backingSessionId,
		lifecycleRevision: session.entry?.lifecycleRevision,
		storePath: initialStorePath
	};
	const target = session.sessionTarget;
	const source = target?.readSource;
	const assertTargetCurrent = session.assertSessionTargetCurrent;
	const borrowed = target && source && typeof source.databaseIdentity === "string" && assertWorkCurrent && assertTargetCurrent && target.storeKeys.length === 1 && target.storeKeys[0] === target.storeKey && session.capturedReadSources?.length === 1 && isDeepStrictEqual(session.capturedReadSources[0], source) ? {
		target,
		source: {
			...source,
			databaseIdentity: source.databaseIdentity
		},
		assertTargetCurrent,
		assertWorkCurrent
	} : void 0;
	const assertBorrowedRouting = captureSessionMutationRouting(session.cfg);
	const assertRetainedSourceCurrent = borrowed ? () => {
		borrowed.assertWorkCurrent();
		borrowed.assertTargetCurrent();
		assertBorrowedRouting(getRuntimeConfig());
	} : void 0;
	return {
		assertRetainedSourceCurrent,
		notePreparedSession(binding) {
			if (binding.sessionKey === session.sessionKey) preparedSession = { ...binding };
		},
		captureTranscriptStart(prepared) {
			const start = resolveChatReplyTranscriptStart(session, {
				entry: preparedSession,
				storePath: preparedSession.storePath ?? initialStorePath
			}, prepared);
			return start ? {
				...start,
				lifecycleRevision: preparedSession.lifecycleRevision
			} : void 0;
		},
		async readCurrentSession(key = session.sessionKey, agentId = session.agentId) {
			const cfg = getRuntimeConfig();
			if (borrowed && assertRetainedSourceCurrent && key === session.sessionKey && agentId === session.agentId) {
				const assertCurrent = assertRetainedSourceCurrent;
				assertCurrent();
				return withQualifiedGatewaySessionStoreTarget({
					target: borrowed.target,
					logicalStorePath: initialStorePath,
					preparedSource: {
						...borrowed.source,
						assertCurrent
					},
					includeMembership: false,
					readOptions: {
						projection: "exact",
						lifecycleSessionKey: void 0
					},
					consume: (selected, _membership, assertSourceCurrent) => {
						assertSourceCurrent();
						assertCurrent();
						omitInternalSessionEffectsEntries(selected.store, selected.storeKeys);
						const match = findCanonicalStoreMatch(selected.store, selected.storeKeys);
						return {
							...selected,
							cfg,
							entry: match?.entry,
							legacyKey: match?.key !== selected.canonicalKey ? match?.key : void 0
						};
					}
				});
			}
			const assertRoutingCurrent = captureSessionMutationRouting(cfg);
			return await loadGatewaySessionEntryReadOnlyInWorker({
				...session.sessionLoadOptions,
				cfg,
				key,
				excludeInternalEffects: true,
				agentId,
				assertActive: () => assertRoutingCurrent(getRuntimeConfig())
			});
		}
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-reply-dispatch.ts
/** Build delivery options and capture state for the core-owned webchat dispatcher. */
function createChatSendReplyDispatch(params) {
	const { accountId, getRuntimeConfig, isAgentRunStarted, logGateway, session, userTurnRecorder } = params;
	const { backingSessionId, cfg, clientRunId } = session;
	const sessionLoadOptions = {
		...session.sessionLoadOptions,
		clone: false
	};
	const { notePreparedSession, readCurrentSession, captureTranscriptStart, assertRetainedSourceCurrent } = createChatReplySessionReader(session, getRuntimeConfig, params.assertWorkCurrent);
	let assistantTranscriptRewriteState;
	let agentRunId = clientRunId;
	const captureAgentTranscriptStart = (runId = clientRunId, prepared) => {
		agentRunId = runId;
		const transcriptStart = captureTranscriptStart(prepared);
		assistantTranscriptRewriteState = transcriptStart;
		return transcriptStart !== void 0;
	};
	const { onModelSelected, ...replyPipeline } = createChannelReplyPipeline({
		cfg,
		agentId: session.agentId,
		channel: INTERNAL_MESSAGE_CHANNEL
	});
	const deliveredReplies = [];
	const finalizedAgentMediaTranscriptKeys = /* @__PURE__ */ new Set();
	const commentaryMedia = createAssistantCommentaryMediaCustody({
		requesterContext: params.requesterContext,
		session,
		accountId,
		getRunId: () => agentRunId,
		isCurrent: () => isAgentRunStarted() && params.isRunCurrent?.() === true,
		abortSignal: params.abortSignal,
		logGateway,
		prepareAssistantTranscriptMessage: params.prepareAssistantTranscriptMessage
	});
	const resolveReplyDelivery = async (minimumAssistantMessageIndex = 0) => {
		const admission = userTurnRecorder.getAdmissionReceipt();
		const transcriptStart = assistantTranscriptRewriteState;
		const runId = agentRunId;
		const lifecycleRevision = transcriptStart?.lifecycleRevision;
		const reader = admission && getOwnedSessionTranscriptReader(admission);
		const isRunCurrent = () => {
			const currentAdmission = userTurnRecorder.getAdmissionReceipt();
			return Boolean(admission && admission.agentId === session.agentId && admission.sessionKey === session.sessionKey && isAgentRunStarted() && params.isRunCurrent?.() === true && !params.abortSignal?.aborted && agentRunId === runId && assistantTranscriptRewriteState === transcriptStart && currentAdmission?.logicalTurnId === admission.logicalTurnId && currentAdmission?.entryId === admission.entryId);
		};
		const isInspectionCurrent = () => {
			if (!isRunCurrent()) return false;
			assertRetainedSourceCurrent?.();
			reader?.assertCurrent();
			return true;
		};
		const isCurrent = async () => {
			if (!admission || !isRunCurrent()) return false;
			const current = await readCurrentSession();
			return isRunCurrent() && current.entry?.sessionId === admission.sessionId && current.entry.lifecycleRevision === lifecycleRevision && resolveSessionTranscriptDatabasePath({
				agentId: session.agentId,
				sessionId: admission.sessionId,
				sessionKey: session.sessionKey,
				storePath: current.storePath
			}) === admission.storePath;
		};
		if (!admission || !transcriptStart || transcriptStart.sessionId !== admission.sessionId || !(reader ? isInspectionCurrent() : await isCurrent())) return "missing";
		const scope = admission;
		await waitForSessionTranscriptProjection(scope, params.abortSignal);
		if (!(reader || assertRetainedSourceCurrent ? isInspectionCurrent() : await isCurrent())) return "missing";
		const assertRoutingCurrent = captureSessionMutationRouting(getRuntimeConfig());
		let decision = "pending";
		await readSessionTranscriptAnchorsAsync(scope, {
			entryIds: [admission.entryId],
			afterSeq: transcriptStart.afterSeq,
			includeSession: true,
			includeWatermark: true,
			includeMessagesForRunId: runId
		}, params.abortSignal, (facts) => {
			assertRoutingCurrent(getRuntimeConfig());
			if (!isInspectionCurrent() || facts.session?.sessionId !== admission.sessionId || facts.session.lifecycleRevision !== lifecycleRevision || !facts.watermark) {
				decision = "missing";
				return;
			}
			const input = facts.anchors.find((anchor) => anchor.entryId === admission.entryId);
			if (!input || input.rawSeq !== admission.rawSeq) {
				decision = "missing";
				return;
			}
			let latestInput = input;
			for (const row of facts.tail?.entries ?? []) if (row.role === "user" && row.anchor && row.anchor.activeMessagePosition > latestInput.activeMessagePosition) latestInput = row.anchor;
			if (minimumAssistantMessageIndex > 0 && latestInput.entryId === input.entryId) {
				decision = "missing";
				return;
			}
			decision = "missing";
			for (const row of facts.tail?.entries ?? []) {
				const message = asOptionalRecord(row.message);
				if (message?.role !== "assistant" || readSessionTranscriptRunId(message) !== runId) continue;
				const answer = message.stopReason === "toolUse" || Array.isArray(message.content) && message.content.some((block) => isToolHistoryBlockType(asOptionalRecord(block)?.type)) ? extractAssistantTextForPhase(message, { phase: "final_answer" }) : extractAssistantPhaseText(message);
				if (!answer || isSuppressedControlReplyText(answer) || !extractAssistantPhaseText(projectChatDisplayMessage(message))) continue;
				const selected = resolveChatReplyDeliveryFromAnchors({
					facts,
					admissionId: admission.entryId,
					inputId: latestInput.entryId,
					messageId: row.entryId,
					afterSeq: transcriptStart.afterSeq,
					watermark: facts.watermark,
					currentWatermark: facts.watermark
				});
				if (selected !== void 0) {
					decision = selected;
					return;
				}
			}
		});
		assertRoutingCurrent(getRuntimeConfig());
		return isInspectionCurrent() ? decision : "missing";
	};
	const needsAgentMediaTranscriptFinalization = (payload) => isMediaBearingPayload(payload) || Boolean(getReplyPayloadMetadata(payload)?.assistantMediaFailures?.length);
	const agentMediaTranscriptKey = (payload) => {
		const metadata = getReplyPayloadMetadata(payload);
		const ownedIdempotencyKey = metadata?.assistantTranscriptOwned === true ? metadata.assistantTranscriptIdempotencyKey?.trim() : void 0;
		if (ownedIdempotencyKey) return `owned:${ownedIdempotencyKey}`;
		if (metadata?.assistantMessageIndex !== void 0) return `index:${metadata.assistantMessageIndex}`;
		return "unkeyed";
	};
	const appendWebchatAgentMediaTranscriptIfNeeded = async (input) => {
		const payload = readChatSendReplyPayload(input);
		if (!isAgentRunStarted() || !needsAgentMediaTranscriptFinalization(payload)) return;
		const finalizationKey = agentMediaTranscriptKey(payload);
		if (finalizedAgentMediaTranscriptKeys.has(finalizationKey)) return;
		if (isSourceReplyTranscriptMirrorPayload(payload)) return;
		const replyDispatchRun = params.getReplyDispatchRun?.();
		const transcript = replyDispatchRun?.getResult().assistantTranscript;
		if (replyDispatchRun && !transcript) {
			logGateway.warn("webchat runtime-owned media skipped: assistant transcript was not persisted");
			return;
		}
		const sessionKey = transcript?.sessionKey ?? session.sessionKey;
		const agentId = transcript?.agentId ?? session.agentId;
		const ttsSupplementMarker = buildTtsSupplementTranscriptMarker(payload);
		const mediaScope = captureWebchatReplyMediaScope({
			requesterContext: params.requesterContext,
			cfg,
			sessionKey,
			agentId,
			sessionLoadOptions: {
				...sessionLoadOptions,
				agentId
			},
			accountId,
			assertCurrent: () => {
				params.abortSignal?.throwIfAborted();
				if (params.isRunCurrent && !params.isRunCurrent()) throw new Error("Chat media run is no longer current.");
			}
		});
		const { storePath: latestStorePath, entry: latestEntry } = await readCurrentSession(sessionKey, agentId);
		const sessionId = latestEntry?.sessionId ?? backingSessionId ?? clientRunId;
		const { payloads: [transcriptPayload], inputs: transcriptInputs, mediaMessage, assistantContent, persistedAssistantContent } = await prepareWebchatReplyMediaForDisplay({
			scope: mediaScope,
			storePath: latestStorePath,
			inputs: replaceChatSendReplyPayload(input, stripVisibleTextFromTtsSupplement(payload)),
			abortSignal: params.abortSignal,
			includeSensitiveMedia: payload.sensitiveMedia !== true,
			onLocalAudioAccessDenied: (err) => {
				logGateway.warn(`webchat audio embedding denied local path: ${formatForLog(err)}`);
			},
			onManagedMediaPrepareError: (message) => {
				logGateway.warn(`webchat media embedding skipped attachment: ${message}`);
			}
		});
		if (!transcriptPayload) return;
		const mediaFailures = getReplyPayloadMetadata(transcriptPayload)?.assistantMediaFailures ?? [];
		const mediaNormalizationFailed = mediaFailures.length > 0;
		const persistedContentForAppend = hasAssistantDisplayMediaContent(persistedAssistantContent) || mediaNormalizationFailed ? persistedAssistantContent : void 0;
		if (!persistedContentForAppend?.length) return;
		const transcriptReply = mediaMessage?.transcriptText ?? extractAssistantDisplayText(assistantContent) ?? buildTranscriptReplyTextFromInputs(transcriptInputs);
		const payloadMetadata = getReplyPayloadMetadata(payload);
		const sourceMediaUrls = uniqueStrings(payloadMetadata?.assistantTranscriptMediaUrls?.length ? payloadMetadata.assistantTranscriptMediaUrls : [...Array.isArray(payload.mediaUrls) ? payload.mediaUrls : [], ...typeof payload.mediaUrl === "string" ? [payload.mediaUrl] : []]);
		const ownedTranscriptIdempotencyKey = transcript?.idempotencyKey ?? (payloadMetadata?.assistantTranscriptOwned === true ? payloadMetadata.assistantTranscriptIdempotencyKey?.trim() : void 0);
		const transcriptScope = assistantTranscriptScope({
			sessionKey,
			sessionId,
			storePath: latestStorePath,
			agentId
		});
		const assistantMessageIndex = payloadMetadata?.assistantMessageIndex;
		let rewritten = null;
		if (ownedTranscriptIdempotencyKey && transcriptScope) {
			if (transcript && (await readCurrentSession(sessionKey, agentId)).entry?.sessionId !== transcript.sessionId) {
				logGateway.warn("webchat runtime-owned media skipped: transcript session changed");
				return;
			}
			rewritten = await rewriteAssistantTranscriptMessageByIdempotencyKey({
				content: persistedContentForAppend,
				idempotencyKey: ownedTranscriptIdempotencyKey,
				managedMediaUrls: sourceMediaUrls,
				scope: transcriptScope
			});
			if (!rewritten) {
				logGateway.warn("webchat runtime-owned assistant media rewrite skipped: transcript identity not found");
				return;
			}
		} else if (assistantMessageIndex !== void 0 && transcriptScope) {
			if (assistantTranscriptRewriteState?.sessionId !== sessionId) return;
			const indexedRewrite = await rewriteAssistantTranscriptMessageByTurnIndexAndMedia({
				afterSeq: assistantTranscriptRewriteState.afterSeq,
				assistantMessageIndex,
				content: persistedContentForAppend,
				expectedGeneration: assistantTranscriptRewriteState.generation,
				mediaUrls: sourceMediaUrls,
				rejectedMediaCount: mediaFailures.filter((failure) => failure.code === "invalid-reference").length,
				scope: transcriptScope
			});
			if (indexedRewrite) {
				assistantTranscriptRewriteState.generation = indexedRewrite.generation;
				rewritten = indexedRewrite;
			}
		}
		if (rewritten && transcriptScope) {
			finalizedAgentMediaTranscriptKeys.add(finalizationKey);
			if (assistantContent?.length) await attachManagedOutgoingMediaToMessage({
				messageId: rewritten.messageId,
				blocks: assistantContent
			});
			await publishAssistantTranscriptRewrite({
				scope: transcriptScope,
				rewritten: [rewritten]
			});
			return;
		}
		const hasOnlyFailureDisplay = persistedContentForAppend.some((block) => block.type === "attachment_error") && persistedContentForAppend.every((block) => block.type === "text" || block.type === "attachment_error");
		const runtimeOwnedText = stripReplyMediaFailureFallback(transcriptPayload.text, mediaFailures)?.trim();
		if (assistantMessageIndex === void 0 && mediaNormalizationFailed && hasOnlyFailureDisplay && runtimeOwnedText) return;
		const isRuntimeMediaSupplement = assistantMessageIndex !== void 0 && assistantMessageIndex >= 1 && !mediaNormalizationFailed && !ttsSupplementMarker && !payload.isError && !isReplyPayloadStatusNotice(payload) && !payloadMetadata?.toolErrorWarning && !payloadMetadata?.nonTerminalToolErrorWarning && !payloadMetadata?.terminalProviderError;
		const appendContent = isRuntimeMediaSupplement ? persistedContentForAppend.filter((block) => block.type !== "text") : persistedContentForAppend;
		const appended = await appendInjectedAssistantMessageToTranscript({
			sessionKey,
			message: isRuntimeMediaSupplement ? "" : transcriptReply,
			content: appendContent,
			sessionId,
			storePath: latestStorePath,
			agentId,
			idempotencyKey: assistantMessageIndex !== void 0 && assistantMessageIndex >= 1 ? `${clientRunId}:assistant-media:${assistantMessageIndex}` : `${clientRunId}:assistant-media`,
			ttsSupplement: ttsSupplementMarker,
			config: cfg,
			onMessageCommitted: retainCommittedChatReplyMedia
		});
		if (appended.ok) {
			finalizedAgentMediaTranscriptKeys.add(finalizationKey);
			return;
		}
		logGateway.warn(`webchat transcript append failed for media reply: ${appended.error ?? "unknown error"}`);
	};
	const deliverInput = async (input, info) => {
		const payload = readChatSendReplyPayload(input);
		const payloadMetadata = getReplyPayloadMetadata(payload);
		if (payloadMetadata?.beforeAgentRunBlocked === true || payloadMetadata?.sourceReplyTranscriptMirror?.transcriptWriteBlocked === true) userTurnRecorder.markBlocked();
		switch (info.kind) {
			case "block":
			case "final":
				deliveredReplies.push({
					input,
					kind: info.kind
				});
				if (info.kind === "block" && params.onCommandBlock && !isAgentRunStarted() && params.isRunCurrent?.()) {
					const parts = deliveredReplies.map(({ input: replyInput, kind }) => {
						const reply = readChatSendReplyPayload(replyInput);
						if (kind !== "block" || reply.isReasoning === true || isBtwReplyPayload(reply)) return "";
						const text = (replyInput.kind === "prepared" ? prepareAssistantDisplayText : sanitizeAssistantDisplayText)(reply.text, { preserveBoundaries: true });
						return text && (replyInput.kind === "prepared" || !isSuppressedControlReplyText(text)) ? text : "";
					});
					if (parts.at(-1)) params.onCommandBlock(combineNonStreamingReplyParts(parts));
				}
				break;
			case "tool": if (isMediaBearingPayload(payload)) {
				const mediaPayload = copyReplyPayloadMetadata(payload, {
					...payload,
					text: void 0
				});
				deliveredReplies.push(...replaceChatSendReplyPayload(input, mediaPayload).map((mediaInput) => ({
					input: mediaInput,
					kind: "final"
				})));
			}
		}
	};
	const dispatcherOptions = {
		...replyPipeline,
		onError: (err) => {
			logGateway.warn(`webchat dispatch failed: ${formatForLog(err)}`);
		},
		deliver: (payload, info) => deliverInput({
			kind: "raw",
			payload
		}, info),
		deliverPrepared: (plan, info) => deliverInput({
			kind: "prepared",
			plan
		}, info)
	};
	const finalizeAgentMediaTranscript = async () => {
		const latestPayloadByKey = /* @__PURE__ */ new Map();
		for (const { input } of deliveredReplies) {
			const payload = readChatSendReplyPayload(input);
			if (!needsAgentMediaTranscriptFinalization(payload)) continue;
			latestPayloadByKey.set(agentMediaTranscriptKey(payload), input);
		}
		for (const input of latestPayloadByKey.values()) try {
			await appendWebchatAgentMediaTranscriptIfNeeded(input);
		} catch (error) {
			logGateway.warn(`webchat media finalization failed: ${formatForLog(error)}`);
		}
	};
	const runAgentMediaTranscript = async (admission, operation) => {
		return await admission.run(async () => {
			try {
				return await commentaryMedia.run(operation);
			} finally {
				const commentaryRewrite = commentaryMedia.lastRewrite;
				if (commentaryRewrite && assistantTranscriptRewriteState && commentaryRewrite.sessionId === assistantTranscriptRewriteState.sessionId) assistantTranscriptRewriteState.generation = commentaryRewrite.generation;
				await finalizeAgentMediaTranscript();
			}
		});
	};
	return {
		captureAgentTranscriptStart,
		notePreparedSession,
		deliveredReplies,
		dispatcherOptions,
		hasAppendedWebchatAgentMedia: () => finalizedAgentMediaTranscriptKeys.size > 0,
		onModelSelected,
		prepareAssistantTranscriptMessage: commentaryMedia.prepareAssistantTranscriptMessage,
		resolveReplyDelivery,
		runAgentMediaTranscript
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-source-finalization.ts
function selectChatSendAgentReplyInputs(params) {
	return params.deliveredReplies.filter((entry) => {
		const payload = readChatSendReplyPayload(entry.input);
		return getReplyPayloadMetadata(payload)?.sessionWriterDeliveryAuthority || isSourceReplyTranscriptMirrorPayload(payload) ? entry.kind === "final" && payload.isError !== true : !params.hasReturnedAgentErrorPayloads && isReplyPayloadStatusNotice(payload);
	}).map((entry) => entry.input);
}
function createChatSendLateReplyFinalizer(params) {
	return async ({ runId: runtimeRunId, clientRunId: runId, payloads, completion, isCurrent }) => {
		const { context, session } = params;
		const broadcastParams = {
			terminalEntry: runId === session.clientRunId ? params.terminalEntry : void 0,
			context,
			runId,
			sessionKey: session.sessionKey,
			agentId: session.agentId
		};
		const terminal = completion.kind !== "progress";
		let publicationStarted = false;
		try {
			const result = await finalizeChatSendAgentReplyPayloads({
				...params,
				emitFirstAssistantServerTiming: () => {},
				inputs: payloads.map((payload) => ({
					kind: "raw",
					payload
				})),
				isCurrent,
				session: {
					...session,
					clientRunId: runId
				},
				suppressFinal: completion.kind === "failed" || completion.kind === "aborted",
				publishMessage: (message, deliveryAuthorized) => {
					publicationStarted = true;
					if (completion.kind === "progress") {
						const text = typeof message?.text === "string" ? message.text : void 0;
						if (text) {
							const run = context.chatRunState.getOrCreate(runId);
							broadcastChatDelta({
								...broadcastParams,
								text,
								isCurrent: () => context.chatRunState.runs.get(runId) === run && deliveryAuthorized()
							});
						}
					} else {
						const run = context.chatRunState.runs.get(runId);
						const canvas = run?.bufferIsCurrent?.() === false ? [] : run?.canvasBlocks ?? [];
						broadcastChatTerminal({
							...broadcastParams,
							state: "final",
							message: appendChatCanvasBlocksToMessage(message ?? (canvas.length ? {
								role: "assistant",
								content: [],
								timestamp: Date.now()
							} : void 0), canvas),
							stopReason: completion.stopReason
						});
					}
				}
			});
			if (!isCurrent()) return {
				kind: "dropped",
				reason: "no-visible-content"
			};
			if (completion.kind === "failed" || completion.kind === "aborted" || terminal && result.kind === "dropped") {
				const buffered = context.chatRunState.resolveBuffer(runId, { final: true });
				const run = context.chatRunState.runs.get(runId);
				const canvas = run?.bufferIsCurrent?.() === false ? [] : run?.canvasBlocks ?? [];
				const canvasOnly = completion.kind === "completed" && completion.allowCanvasOnly === true && payloads.length === 0 && canvas.length > 0 && !(run?.rawBuffer ?? run?.buffer ?? "").trim();
				if (completion.kind === "failed" || completion.kind === "aborted") context.chatRunState.flushPendingText(runId);
				publicationStarted = true;
				broadcastChatTerminal({
					...broadcastParams,
					stopReason: completion.stopReason,
					...completion.kind === "failed" ? {
						state: "error",
						errorMessage: completion.error,
						errorKind: completion.errorKind
					} : {
						state: completion.kind === "aborted" ? "aborted" : "final",
						...completion.kind === "aborted" && buffered.text && !buffered.suppress || canvasOnly ? { message: appendChatCanvasBlocksToMessage({
							role: "assistant",
							content: canvasOnly ? [] : [{
								type: "text",
								text: buffered.text
							}],
							timestamp: Date.now()
						}, canvas) } : {}
					}
				});
			}
			return terminal ? {
				kind: "delivered",
				hasSourceReplyTranscriptMirror: result.kind === "delivered" && result.hasSourceReplyTranscriptMirror
			} : result;
		} catch (error) {
			if (terminal && !publicationStarted && isCurrent()) {
				context.chatRunState.flushPendingText(runId);
				broadcastChatTerminal({
					...broadcastParams,
					state: "error",
					errorMessage: formatErrorMessage(error)
				});
			}
			throw error;
		} finally {
			if (terminal) {
				context.removeChatRun(runtimeRunId, runId, session.sessionKey);
				if (isCurrent()) {
					context.chatRunState.clearRun(runId);
					context.agentRunSeq.delete(runId);
				}
				context.agentRunSeq.delete(runtimeRunId);
			}
		}
	};
}
async function finalizeChatSendAgentReplyPayloads(params) {
	const { context, emitFirstAssistantServerTiming, session } = params;
	const { agentId, backingSessionId, clientRunId, sessionKey, sessionLoadOptions } = session;
	const agentRunReplyPayloads = params.inputs.map(readChatSendReplyPayload);
	if (agentRunReplyPayloads.length === 0) return {
		kind: "dropped",
		reason: "no-visible-content"
	};
	const { deliveryAuthorized, authorizeDelivery, captureMediaScope } = createChatSendReplyFinalizationAuthority(params, agentRunReplyPayloads);
	if (!authorizeDelivery("finalization")) return {
		kind: "dropped",
		reason: "no-visible-content"
	};
	const hasSourceReplyTranscriptMirror = agentRunReplyPayloads.some(isSourceReplyTranscriptMirrorPayload);
	const mediaScope = captureMediaScope();
	const { storePath: latestStorePath, entry: latestEntry } = await loadGatewaySessionEntryReadOnlyInWorker({
		cfg: context.getRuntimeConfig(),
		key: sessionKey,
		...sessionLoadOptions,
		projection: []
	});
	if (!authorizeDelivery("session preparation")) return {
		kind: "dropped",
		reason: "no-visible-content"
	};
	const sessionId = latestEntry?.sessionId ?? backingSessionId ?? clientRunId;
	const sourceReplyScope = assistantTranscriptScope({
		sessionId,
		sessionKey,
		storePath: latestStorePath,
		agentId
	});
	const committedSourceContent = await Promise.all(agentRunReplyPayloads.map(async (payload) => {
		const mirror = getReplyPayloadMetadata(payload)?.sourceReplyTranscriptMirror;
		if (!sourceReplyScope || !mirror?.transcriptOwner || !mirror.idempotencyKey) return;
		const found = await findTranscriptEvent(sourceReplyScope, {
			kind: "idempotency",
			key: mirror.idempotencyKey,
			deliveryMirror: true
		});
		mediaScope.assertCurrent();
		const messageId = found && readTranscriptEventId(found.event);
		if (!messageId) return;
		const { anchors } = await readSessionTranscriptAnchorsAsync({
			...sourceReplyScope,
			sessionKey
		}, { entryIds: [messageId] }, params.abortSignal);
		mediaScope.assertCurrent();
		const content = readAssistantDisplayContent(readTranscriptEventMessage(found.event));
		return anchors.length > 0 && content.length > 0 ? content : void 0;
	}));
	mediaScope.assertCurrent();
	const hasCommittedSourceReply = committedSourceContent.some(Boolean);
	const { finalInputsByIndex, sourceReplyContentStates, sourceReplyBroadcastContent } = await withPreparedWebchatReplyMedia({
		scope: mediaScope,
		storePath: latestStorePath,
		inputs: params.inputs.filter((_, index) => !committedSourceContent[index]),
		abortSignal: params.abortSignal,
		includeSensitiveMedia: false,
		onLocalAudioAccessDenied: (err) => {
			context.logGateway.warn(`webchat audio embedding denied local path: ${formatForLog(err)}`);
		},
		onManagedMediaPrepareError: (message) => {
			context.logGateway.warn(`webchat media embedding skipped attachment: ${message}`);
		}
	}, async ({ payloads: normalizedPayloads, inputsByIndex, buildContent }) => {
		const contentStates = [];
		const broadcastContent = [];
		let preparedIndex = 0;
		for (const [replyIndex] of agentRunReplyPayloads.entries()) {
			const committedContent = committedSourceContent[replyIndex];
			if (committedContent) {
				contentStates[replyIndex] = {
					broadcastContent: [],
					persistedContent: committedContent,
					hasManagedOutgoingContent: hasManagedOutgoingAssistantContent(committedContent),
					backedManagedOutgoingContent: true
				};
				continue;
			}
			const inputIndex = preparedIndex++;
			if (!normalizedPayloads[inputIndex]) continue;
			const { assistantContent: replyAssistantContent, persistedAssistantContent: persistedContent, mediaMessage: replyMediaMessage } = await buildContent(inputsByIndex[inputIndex] ?? []);
			const replyBroadcastContent = hasAssistantDisplayMediaContent(replyAssistantContent) ? replyAssistantContent : hasAssistantDisplayMediaContent(replyMediaMessage?.content) ? replyMediaMessage?.content : replyAssistantContent;
			const state = {
				broadcastContent: replyBroadcastContent ? [...replyBroadcastContent] : [],
				persistedContent: persistedContent ? [...persistedContent] : [],
				hasManagedOutgoingContent: hasManagedOutgoingAssistantContent(persistedContent),
				backedManagedOutgoingContent: false
			};
			contentStates[replyIndex] = state;
			broadcastContent.push(...state.broadcastContent);
		}
		return {
			finalInputsByIndex: inputsByIndex,
			sourceReplyContentStates: contentStates,
			sourceReplyBroadcastContent: broadcastContent
		};
	});
	const displayReply = extractAssistantDisplayText(sourceReplyBroadcastContent) ?? buildTranscriptReplyTextFromInputs(finalInputsByIndex.flat());
	if (!sourceReplyBroadcastContent.length && !displayReply && !hasCommittedSourceReply) return {
		kind: "dropped",
		reason: "no-visible-content"
	};
	const sourceReplyPersistenceRequests = [];
	const sourceReplyMirrorCandidates = [];
	for (const [replyIndex, sourceReplyPayload] of agentRunReplyPayloads.entries()) {
		const state = sourceReplyContentStates[replyIndex];
		if (!state) continue;
		const mirrorMetadata = getReplyPayloadMetadata(sourceReplyPayload)?.sourceReplyTranscriptMirror;
		const mirrorIdempotencyKey = mirrorMetadata?.idempotencyKey;
		if (typeof mirrorIdempotencyKey !== "string" || mirrorIdempotencyKey.trim().length === 0 || !mirrorMetadata) continue;
		const candidate = {
			idempotencyKey: mirrorIdempotencyKey,
			metadata: mirrorMetadata
		};
		sourceReplyMirrorCandidates.push(candidate);
		if (!state.backedManagedOutgoingContent && hasAssistantDisplayMediaContent(state.persistedContent)) {
			if (!state.hasManagedOutgoingContent) state.backedManagedOutgoingContent = true;
			sourceReplyPersistenceRequests.push({
				...candidate,
				state
			});
		}
	}
	if (!authorizeDelivery("transcript finalization")) return {
		kind: "dropped",
		reason: "no-visible-content"
	};
	if (sourceReplyScope && sourceReplyPersistenceRequests.length > 0) {
		const rewritten = await rewriteSourceReplyTranscriptMirrors({
			candidates: sourceReplyMirrorCandidates,
			requests: sourceReplyPersistenceRequests,
			scope: sourceReplyScope
		});
		if (rewritten.length > 0) {
			for (const target of rewritten) {
				const state = target.request.state;
				if (state.hasManagedOutgoingContent) await attachManagedOutgoingMediaToMessage({
					messageId: target.messageId,
					blocks: state.persistedContent
				});
				state.backedManagedOutgoingContent = true;
			}
			await publishAssistantTranscriptRewrite({
				scope: sourceReplyScope,
				rewritten
			});
		}
	}
	const sourceReplyContent = sourceReplyContentStates.flatMap((state) => {
		if (state.hasManagedOutgoingContent && !state.backedManagedOutgoingContent) return stripManagedOutgoingAssistantContentBlocks(state.broadcastContent) ?? [{
			type: "text",
			text: "Media reply could not be displayed."
		}];
		return state.broadcastContent;
	});
	const sourceReplyText = extractAssistantDisplayText(sourceReplyContent) ?? (sourceReplyContent.length === 0 ? displayReply : void 0);
	const message = sourceReplyContent.length || sourceReplyText ? {
		role: "assistant",
		content: sourceReplyContent.length ? sourceReplyContent : [{
			type: "text",
			text: sourceReplyText
		}],
		...sourceReplyText ? { text: sourceReplyText } : {},
		timestamp: Date.now(),
		stopReason: "stop",
		usage: {
			input: 0,
			output: 0,
			totalTokens: 0
		}
	} : void 0;
	if (!params.suppressFinal) {
		if (!authorizeDelivery("broadcast")) return {
			kind: "dropped",
			reason: "no-visible-content"
		};
		if (hasVisibleAssistantFinalMessage(message)) emitFirstAssistantServerTiming();
		if (params.publishMessage) params.publishMessage(message, deliveryAuthorized);
		else broadcastChatFinal({
			terminalEntry: params.terminalEntry,
			context,
			runId: clientRunId,
			sessionKey,
			agentId,
			message
		});
	}
	return {
		kind: "delivered",
		hasSourceReplyTranscriptMirror
	};
}
/** Persist and broadcast agent-run source/status replies that bypass the normal model turn. */
async function finalizeChatSendSourceReplies(params) {
	const result = await finalizeChatSendAgentReplyPayloads({
		...params,
		inputs: selectChatSendAgentReplyInputs(params)
	});
	return result.kind === "delivered" && result.hasSourceReplyTranscriptMirror;
}
//#endregion
//#region src/gateway/server-methods/chat-send-late-followup.ts
/** One Gateway admission owns the outcome of its queued reply, including concurrent duplicates. */
function createChatSendLateFollowupDisposition(params) {
	let terminal = "pending";
	const progressPayloads = [];
	const recordDrop = (batch, reason, settle = true) => {
		if (settle && batch.completion.kind !== "progress") {
			terminal = "settled";
			if (reason === "non-webchat-origin" || reason === "origin-mismatch") params.onTerminalDrop?.(batch.completion);
		}
		params.logGateway.info("webchat late reply disposition", {
			runId: params.runId,
			followupRunId: batch.runId,
			outcome: "late-and-dropped",
			reason
		});
	};
	return {
		recordQueued: () => {
			if (terminal === "pending") terminal = isInternalMessageChannel(params.originatingChannel) ? "deliver" : "drop";
		},
		deliver: Object.assign(async (batch) => {
			if (terminal === "delivering") return recordDrop(batch, "delivery-in-flight", false);
			if (terminal !== "deliver") return recordDrop(batch, terminal === "pending" ? "terminal-not-recorded" : terminal === "drop" ? "non-webchat-origin" : "already-settled");
			if (!isInternalMessageChannel(batch.originatingChannel)) return recordDrop(batch, "origin-mismatch");
			if (batch.completion.kind === "progress") {
				progressPayloads.push(...batch.payloads);
				await params.deliver({
					...batch,
					clientRunId: params.retainSourceIdentity === false ? batch.runId : params.runId,
					isCurrent: () => terminal === "deliver"
				});
				return;
			}
			terminal = "delivering";
			try {
				const result = await params.deliver({
					...batch,
					clientRunId: params.retainSourceIdentity === false ? batch.runId : params.runId,
					payloads: [...progressPayloads, ...batch.payloads],
					isCurrent: () => terminal === "delivering"
				});
				if (result.kind === "dropped") return recordDrop(batch, result.reason);
				terminal = "settled";
			} catch (error) {
				recordDrop(batch, "delivery-failed");
				throw error;
			} finally {
				progressPayloads.length = 0;
			}
		}, {
			ownsCompletion: (originatingChannel) => terminal === "deliver" && isInternalMessageChannel(originatingChannel),
			createSourceRetry: () => {
				if (terminal === "delivering" || terminal === "settled") throw new Error("Queued source reply no longer owns recovery delivery");
				if (terminal === "pending") terminal = "settled";
				const retry = createChatSendLateFollowupDisposition({
					...params,
					retainSourceIdentity: false,
					onTerminalDrop: void 0
				});
				retry.recordQueued();
				return retry.deliver;
			}
		})
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-turn-adoption.ts
function createChatSendTurnAdoptionLifecycle(params) {
	let enqueued = false;
	let terminalKnown = false;
	let steered = false;
	const ownsQueueIdentity = () => {
		const current = params.chatQueuedTurns.get(params.runId);
		return !current || current.controller === params.controller;
	};
	let adoptionStarted = false;
	let withdrawalHold;
	let releaseWorkAdmission;
	const recordQueuedTerminal = (completion, publish = false) => {
		if (terminalKnown || !ownsQueueIdentity()) return;
		terminalKnown = true;
		markChatAbortTerminalOutcome(params.sessionBinding);
		const now = Date.now();
		const failed = completion.kind === "failed";
		setGatewayDedupeEntry({
			dedupe: params.context.dedupe,
			key: `chat:${params.runId}`,
			session: captureAgentJobSession(params.sessionBinding),
			entry: {
				ts: now,
				ok: !failed,
				payload: completion.kind === "aborted" ? buildAbortedChatSendPayload({
					runId: params.runId,
					endedAt: now,
					stopReason: completion.stopReason
				}) : {
					runId: params.runId,
					status: failed ? completion.errorKind ?? "error" : "completed",
					endedAt: now,
					stopReason: completion.stopReason,
					...failed ? { summary: completion.error } : {}
				}
			}
		});
		if (publish && !params.suppressReplies) broadcastChatTerminal({
			terminalEntry: params.sessionBinding,
			context: params.context,
			runId: params.runId,
			sessionKey: params.sessionKey,
			agentId: params.agentId,
			stopReason: completion.stopReason,
			...failed ? {
				state: "error",
				errorMessage: completion.error,
				errorKind: completion.errorKind
			} : { state: completion.kind === "aborted" ? "aborted" : "final" }
		});
	};
	const recordQueuedAbort = (publish) => recordQueuedTerminal({
		kind: "aborted",
		stopReason: params.sessionBinding.abortStopReason ?? resolveAgentRunAbortLifecycleFields(params.controller.signal).stopReason
	}, publish);
	const finalizeReply = params.suppressReplies ? void 0 : createChatSendLateReplyFinalizer({
		terminalEntry: params.sessionBinding,
		requesterContext: params.requesterContext,
		abortSignal: params.controller.signal,
		accountId: params.accountId,
		context: params.context,
		session: params.session
	});
	const lateFollowup = createChatSendLateFollowupDisposition({
		runId: params.runId,
		originatingChannel: params.originatingChannel,
		logGateway: params.context.logGateway,
		onTerminalDrop: (completion) => recordQueuedTerminal(completion, true),
		deliver: async (batch) => {
			if (batch.clientRunId === params.runId && batch.completion.kind !== "progress" && batch.isCurrent() && ownsQueueIdentity()) markChatAbortTerminalOutcome(params.sessionBinding);
			try {
				const result = finalizeReply ? await finalizeReply({
					...batch,
					isCurrent: () => batch.isCurrent() && ownsQueueIdentity()
				}) : {
					kind: "dropped",
					reason: "no-visible-content"
				};
				if (batch.clientRunId === params.runId && batch.completion.kind !== "progress") recordQueuedTerminal(batch.completion);
				return result;
			} catch (error) {
				if (batch.clientRunId === params.runId && batch.completion.kind !== "progress") recordQueuedTerminal({
					kind: "failed",
					error: String(error)
				});
				throw error;
			}
		}
	});
	const lifecycle = {
		admission: "cancel-only",
		abortSignal: params.controller.signal,
		...params.originatingLeafEntryId !== void 0 ? { originatingLeafEntryId: params.originatingLeafEntryId } : {},
		ownerKey: params.ownerKey,
		onAdopted: async () => {
			adoptionStarted = true;
			if (withdrawalHold) await withdrawalHold.promise;
			params.controller.signal.throwIfAborted();
		},
		onDeferred: () => {
			if (params.hasCronCreatorAuthority) lifecycle.cronCreatorAuthorityUnavailable = "queued-local-operator";
			enqueued = registerQueuedChatTurn({
				chatQueuedTurns: params.chatQueuedTurns,
				runId: params.runId,
				controller: params.controller,
				sessionId: params.sessionBinding.sessionId,
				sessionKey: params.sessionKey,
				agentId: params.agentId,
				ownerConnId: normalizeOptionalString(params.ownerConnId),
				ownerDeviceId: normalizeOptionalString(params.ownerDeviceId),
				holdPendingInputWithdrawal: () => {
					if (adoptionStarted || withdrawalHold || params.controller.signal.aborted) return;
					const hold = createDeferredCore();
					withdrawalHold = hold;
					return () => {
						if (withdrawalHold === hold) withdrawalHold = void 0;
						hold.resolve();
					};
				},
				onAborted: (reason) => {
					params.sessionBinding.abortDiagnosticReason = reason;
					if (!adoptionStarted) recordQueuedAbort(!params.context.chatAbortControllers.has(params.runId));
					params.releaseSourceWorkAdmission();
					releaseWorkAdmission?.();
					releaseWorkAdmission = void 0;
				}
			});
			if (enqueued && !releaseWorkAdmission) releaseWorkAdmission = params.retainWorkAdmission();
			if (enqueued) {
				setGatewayDedupeEntry({
					dedupe: params.context.dedupe,
					key: `chat:${params.runId}`,
					session: captureAgentJobSession(params.sessionBinding),
					entry: {
						ts: Date.now(),
						ok: true,
						payload: {
							runId: params.runId,
							status: "accepted"
						}
					}
				});
				lateFollowup.recordQueued();
				params.armOperatorRunCancellation?.();
			}
			return enqueued;
		},
		onCancellationRetired: () => {
			if (retireQueuedChatTurnCancellation(params.chatQueuedTurns, params.runId, params.controller)) params.retireOperatorRunCancellation?.();
		},
		onAbandoned: () => {
			recordQueuedTerminal({
				kind: "aborted",
				stopReason: "aborted"
			}, true);
		},
		onSettled: () => {
			const ownsCompletion = completeQueuedChatTurn(params.chatQueuedTurns, params.runId, params.controller);
			try {
				if (ownsCompletion) params.retireOperatorRunCancellation?.();
				if (!terminalKnown && params.controller.signal.aborted && (params.suppressReplies || !params.context.chatAbortControllers.has(params.runId))) recordQueuedAbort(true);
				if (ownsCompletion && !terminalKnown) {
					enqueued = false;
					steered = true;
				}
			} finally {
				releaseWorkAdmission?.();
				releaseWorkAdmission = void 0;
			}
		}
	};
	return {
		lifecycle,
		isEnqueued: () => enqueued,
		isTerminal: () => terminalKnown,
		isSteered: () => steered,
		onRunStarted: (runId) => {
			if (enqueued && !terminalKnown && ownsQueueIdentity() && lateFollowup.deliver.ownsCompletion(params.originatingChannel)) params.context.addChatRun(runId, {
				sessionKey: params.sessionKey,
				agentId: params.agentId,
				clientRunId: params.runId
			});
		},
		onQueueDisposition: (reason) => {
			recordQueuedTerminal({
				kind: "failed",
				error: `Queued input was dropped (${reason}).`
			}, true);
			params.context.logGateway.info("chat queue turn intentionally skipped", {
				runId: params.runId,
				sessionKey: params.sessionKey,
				outcome: "skipped",
				reason
			});
		},
		onQueuedFollowupReplyBatch: Object.assign(async (batch) => {
			if (!terminalKnown && ownsQueueIdentity()) await lateFollowup.deliver(batch);
		}, lateFollowup.deliver)
	};
}
//#endregion
//#region src/gateway/chat-input-sanitize.ts
const DISALLOWED_CHAT_CONTROL_RANGE = `${String.fromCharCode(0)}-${String.fromCharCode(8)}${String.fromCharCode(11)}${String.fromCharCode(12)}${String.fromCharCode(14)}-${String.fromCharCode(31)}${String.fromCharCode(127)}`;
const DISALLOWED_CHAT_CONTROL_RE = new RegExp(`[${DISALLOWED_CHAT_CONTROL_RANGE}]`, "g");
function sanitizeChatSendMessageInput(message) {
	const normalized = message.normalize("NFC");
	if (normalized.includes("\0")) return {
		ok: false,
		error: "message must not contain null bytes"
	};
	return {
		ok: true,
		message: normalized.replace(DISALLOWED_CHAT_CONTROL_RE, "")
	};
}
//#endregion
//#region src/gateway/server-methods/chat-origin-routing.ts
const CHANNEL_AGNOSTIC_SESSION_SCOPES = /* @__PURE__ */ new Set([
	"main",
	"direct",
	"dm",
	"group",
	"channel",
	"cron",
	"run",
	"subagent",
	"acp",
	"thread",
	"topic"
]);
const CHANNEL_SCOPED_SESSION_SHAPES = /* @__PURE__ */ new Set([
	"direct",
	"dm",
	"group",
	"channel"
]);
function normalizeExplicitChatSendOrigin(params) {
	const originatingChannel = normalizeOptionalString(params.originatingChannel);
	const originatingTo = normalizeOptionalString(params.originatingTo);
	const accountId = normalizeOptionalString(params.accountId);
	const messageThreadId = normalizeOptionalString(params.messageThreadId);
	if (!Boolean(originatingChannel || originatingTo || accountId || messageThreadId)) return { ok: true };
	const normalizedChannel = normalizeMessageChannel(originatingChannel);
	if (!normalizedChannel) return {
		ok: false,
		error: "originatingChannel is required when using originating route fields"
	};
	if (!originatingTo) return {
		ok: false,
		error: "originatingTo is required when using originating route fields"
	};
	return {
		ok: true,
		value: {
			originatingChannel: normalizedChannel,
			originatingTo,
			...accountId ? { accountId } : {},
			...messageThreadId ? { messageThreadId } : {}
		}
	};
}
function resolveChatSendOriginatingRoute(params) {
	if (params.explicitOrigin) return {
		originatingChannel: params.explicitOrigin.originatingChannel,
		originatingTo: params.explicitOrigin.originatingTo,
		...params.explicitOrigin.accountId ? { accountId: params.explicitOrigin.accountId } : {},
		...params.explicitOrigin.messageThreadId ? { messageThreadId: params.explicitOrigin.messageThreadId } : {},
		explicitDeliverRoute: params.deliver === true
	};
	const internalRoute = {
		originatingChannel: INTERNAL_MESSAGE_CHANNEL,
		originatingTo: params.sessionKey,
		explicitDeliverRoute: false
	};
	if (params.deliver !== true) return internalRoute;
	const sessionDeliveryContext = deliveryContextFromSession(params.entry);
	const sessionOrigin = sessionDeliveryOrigin(params.entry);
	const routeChannelCandidate = normalizeMessageChannel(sessionDeliveryContext?.channel ?? sessionOrigin?.provider);
	const routeToCandidate = sessionDeliveryContext?.to;
	const routeAccountIdCandidate = sessionDeliveryContext?.accountId ?? sessionOrigin?.accountId;
	const routeThreadIdCandidate = sessionDeliveryContext?.threadId ?? sessionOrigin?.threadId;
	if (params.sessionKey.length > 512) return internalRoute;
	const sessionScopeParts = (parseAgentSessionKey(params.sessionKey)?.rest ?? params.sessionKey).split(":", 3).filter(Boolean);
	const sessionScopeHead = sessionScopeParts[0];
	const sessionChannelHint = normalizeMessageChannel(sessionScopeHead);
	const normalizedSessionScopeHead = (sessionScopeHead ?? "").trim().toLowerCase();
	const sessionPeerShapeCandidates = [sessionScopeParts[1], sessionScopeParts[2]].map((part) => (part ?? "").trim().toLowerCase()).filter(Boolean);
	const isChannelAgnosticSessionScope = CHANNEL_AGNOSTIC_SESSION_SCOPES.has(normalizedSessionScopeHead);
	const isChannelScopedSession = sessionPeerShapeCandidates.some((part) => CHANNEL_SCOPED_SESSION_SHAPES.has(part));
	const hasLegacyChannelPeerShape = !isChannelScopedSession && typeof sessionScopeParts[1] === "string" && sessionChannelHint === routeChannelCandidate;
	const isFromWebchatClient = isWebchatClient(params.client);
	const isFromGatewayCliClient = isGatewayCliClient(params.client);
	const hasClientMetadata = typeof params.client?.mode === "string" && params.client.mode.trim().length > 0 || typeof params.client?.id === "string" && params.client.id.trim().length > 0;
	const configuredMainKey = (params.mainKey ?? "main").trim().toLowerCase();
	const canInheritConfiguredMainRoute = normalizedSessionScopeHead.length > 0 && normalizedSessionScopeHead === configuredMainKey && params.hasConnectedClient && (isFromGatewayCliClient || !hasClientMetadata);
	if (!(Boolean(!isFromWebchatClient && sessionChannelHint && sessionChannelHint !== "webchat" && (!isChannelAgnosticSessionScope && (isChannelScopedSession || hasLegacyChannelPeerShape) || canInheritConfiguredMainRoute)) && routeChannelCandidate && routeChannelCandidate !== "webchat" && typeof routeToCandidate === "string" && routeToCandidate.trim().length > 0)) return internalRoute;
	return {
		originatingChannel: routeChannelCandidate,
		originatingTo: routeToCandidate,
		accountId: routeAccountIdCandidate,
		messageThreadId: routeThreadIdCandidate,
		explicitDeliverRoute: true
	};
}
async function resolveExplicitOriginBindingTargets(origin) {
	const binding = origin?.accountId && origin.originatingChannel !== "webchat" ? await getSessionBindingService().resolveByConversationAsync({
		channel: origin.originatingChannel,
		accountId: origin.accountId,
		conversationId: origin.originatingTo
	}) : void 0;
	return {
		acp: Boolean(binding?.targetSessionKey?.split(":").includes("acp")),
		plugin: isPluginOwnedSessionBindingRecord(binding)
	};
}
function normalizeOptionalChatSystemReceipt(value) {
	if (value == null) return { ok: true };
	const sanitized = sanitizeChatSendMessageInput(value);
	if (!sanitized.ok) return sanitized;
	return {
		ok: true,
		receipt: sanitized.message.trim() || void 0
	};
}
function isAcpBridgeClient(client) {
	const info = client?.connect?.client;
	return info?.id === GATEWAY_CLIENT_NAMES.CLI && info?.mode === GATEWAY_CLIENT_MODES.CLI && info?.displayName === "ACP" && info?.version === "acp";
}
//#endregion
//#region src/gateway/server-methods/chat-send-user-turn.ts
function resolveChatSendManagedMedia(entries, suppressInlineHydration = false) {
	return entries.map((entry) => ({
		path: entry.path,
		contentType: entry.fact.contentType ?? "application/octet-stream",
		...entry.fact.fileName ? { fileName: entry.fact.fileName } : {},
		...suppressInlineHydration && entry.imageKind === "inline" ? { hydrationSuppressed: true } : {}
	}));
}
function applyChatSendManagedMedia(ctx, media, mode = "replace-empty") {
	if (media.length === 0) return;
	if (mode === "replace-empty") {
		if (!ctx.media || ctx.media.length === 0) ctx.media = media;
		return;
	}
	const existing = ctx.media ?? [];
	const existingPaths = new Set(existing.flatMap((fact) => fact.path ? [fact.path] : []));
	const missing = media.filter((fact) => !fact.path || !existingPaths.has(fact.path));
	if (missing.length > 0) ctx.media = [...existing, ...missing];
}
function buildChatSendPromptMedia(attachments) {
	if (!attachments.imageOrder.includes("offloaded")) return;
	const media = attachments.offloadedRefs.filter((ref) => ref.mimeType.startsWith("image/")).map((ref) => ({
		path: ref.path,
		url: ref.mediaRef,
		contentType: ref.mimeType
	}));
	return media.length > 0 ? media : void 0;
}
/** Assemble transcript media and the portable inbound context after attachment preparation. */
function prepareChatSendUserTurn(params) {
	const { request, session, admission, attachments, client, logGateway, userTurn } = params;
	const persistedMediaForTranscriptPromise = (async () => {
		if (attachments.parsedImages.length === 0 && attachments.offloadedRefs.length === 0 || isAcpBridgeClient(client)) return {
			entries: [],
			omission: "none"
		};
		return await persistInboundImagesForTranscript({
			images: attachments.parsedImages,
			offloadedRefs: attachments.offloadedRefs,
			log: logGateway,
			logContext: "chat.send",
			assertCurrent: () => {
				admission.assertWorkAdmissionCurrent?.();
				admission.assertClientUploadAllowed?.();
			}
		});
	})();
	userTurn.setInputPromise(persistedMediaForTranscriptPromise.then((result) => {
		const media = result.entries.map((entry) => entry.fact);
		const slots = result.entries.flatMap((entry, factIndex) => entry.imageKind ? [{
			kind: entry.imageKind,
			factIndex
		}] : []);
		return {
			...userTurn.baseInput,
			...result.omission === "inline-image-save-failed" ? { text: [userTurn.baseInput.text, INLINE_IMAGE_DURABLE_OMISSION_MARKER].filter(Boolean).join("\n") } : {},
			...media.length > 0 ? { media } : {},
			...slots.length > 0 ? { mediaImageLayout: { slots } } : {}
		};
	}));
	const pluginBoundMediaPromise = attachments.parsedImages.length > 0 ? persistedMediaForTranscriptPromise.then((result) => {
		return resolveChatSendManagedMedia(attachments.explicitOriginTargetsPlugin ? result.entries : result.entries.filter((entry) => entry.imageKind === "inline"), !attachments.explicitOriginTargetsPlugin);
	}) : Promise.resolve([]);
	pluginBoundMediaPromise.catch(() => void 0);
	const commandBody = request.inboundMessage;
	const commandSource = !request.suppressCommandInterpretation && commandBody.trim().startsWith("/") ? "text" : void 0;
	const buildTextContext = (text) => {
		const parsedMessage = text === request.inboundMessage ? attachments.parsedMessage : `${text}${attachments.parsedMessage.slice(request.inboundMessage.length)}`;
		const body = request.systemProvenanceReceipt ? [request.systemProvenanceReceipt, parsedMessage].filter(Boolean).join("\n\n") : parsedMessage;
		return {
			Body: body,
			BodyForAgent: body,
			BodyForCommands: text,
			RawBody: parsedMessage,
			CommandBody: text
		};
	};
	const queuedFollowupOwnerDeviceId = normalizeOptionalString(client?.connect?.device?.id);
	const queuedFollowupOwnerConnId = normalizeOptionalString(client?.connId);
	const gatewayUiCommandTarget = captureGatewayUiCommandTarget(client);
	const queuedFollowupOwnerKey = queuedFollowupOwnerDeviceId ? `device:${queuedFollowupOwnerDeviceId}` : queuedFollowupOwnerConnId ? `connection:${queuedFollowupOwnerConnId}` : void 0;
	const { originatingChannel, originatingTo, accountId, messageThreadId, explicitDeliverRoute } = admission.originatingRoute;
	const creation = resolveOperatorSessionCreation(client);
	admission.assertWorkAdmissionCurrent?.();
	const sandbox = session.cfg ? resolveCreatorSandbox(session.cfg, creation) : void 0;
	const ctx = {
		...buildTextContext(commandBody),
		InputProvenance: request.systemInputProvenance,
		...isProgressCardRefreshInputProvenance(request.systemInputProvenance) ? { InternalTurnSource: "progress-card-refresh" } : {},
		SessionKey: session.sessionKey,
		AgentId: session.agentId,
		OriginatingTo: originatingTo,
		ExplicitDeliverRoute: explicitDeliverRoute,
		AccountId: accountId,
		MessageThreadId: messageThreadId,
		...commandSource ? { CommandSource: commandSource } : {},
		CommandAuthorized: !request.suppressCommandInterpretation,
		CommandTurn: commandSource ? {
			kind: "text-slash",
			source: commandSource,
			authorized: true,
			body: commandBody
		} : {
			kind: "normal",
			source: "message",
			authorized: false,
			body: commandBody
		},
		...request.suppressCommandInterpretation ? { CommandInterpretationSuppressed: true } : {},
		MessageSid: session.clientRunId,
		SessionCreation: {
			...creation,
			...sandbox ? { sandbox } : {}
		},
		...resolveChatSendCallerContext(client, request.clientInfo, originatingChannel),
		GatewayRunToolBindings: request.toolBindings,
		GatewayUiCommandTarget: gatewayUiCommandTarget
	};
	const requester = client?.authenticatedUserProfile;
	if (requester && (client.authenticatedUserId || client.internal?.authenticatedOperator) && isBrowserOperatorUiClient(request.clientInfo) && !isSyntheticGatewayCaller(client) && (!request.systemInputProvenance || request.systemInputProvenance.kind === "external_user")) {
		const authenticatedUserId = client.authenticatedUserId;
		const { profileId, displayName } = requester;
		bindRequesterProfile(ctx, {
			id: profileId,
			displayName,
			isCurrent: () => {
				try {
					admission.assertWorkAdmissionCurrent?.();
				} catch {
					return false;
				}
				return !client.invalidated && !client.connectionSignal?.aborted && !isSyntheticGatewayCaller(client) && Boolean(client.authenticatedUserId || client.internal?.authenticatedOperator) && client.authenticatedUserId === authenticatedUserId && client.authenticatedUserProfile?.profileId === profileId;
			}
		});
	}
	if (client) transferGatewayLocalUserIngress(client, ctx);
	if (attachments.mediaPathOffloads.length > 0) ctx.media = attachments.mediaPathOffloads;
	const mediaPathOffloadsIncludeImages = attachments.mediaPathOffloads.some((fact) => fact.contentType?.startsWith("image/"));
	const participant = resolveGatewayInputParticipant(client, request.systemInputProvenance);
	if (participant) prepareSessionParticipantInput(ctx, participant, userTurn.baseInput.timestamp);
	return {
		prepareSessionCreation: async () => {
			if (!request.systemInputProvenance) {
				const prepared = await prepareSkillLibrarySessionCreation(client, params.getConfig ?? session.cfg ?? {}, creation);
				admission.assertWorkAdmissionCurrent?.();
				ctx.SessionCreation = {
					...prepared,
					...sandbox ? { sandbox } : {}
				};
			}
		},
		applyApprovedText: (text) => {
			if (text === request.inboundMessage.trim()) return;
			Object.assign(ctx, buildTextContext(text));
			if (ctx.CommandTurn) ctx.CommandTurn = {
				...ctx.CommandTurn,
				body: text
			};
		},
		discardUnreferencedMedia: async (approved) => {
			if (!approved) return;
			const retained = new Set((readPersistedMediaFacts(approved) ?? []).flatMap((fact) => [fact.url, fact.path]));
			const prepared = await persistedMediaForTranscriptPromise;
			await discardPreparedInboundMedia(prepared.entries.filter((entry) => !retained.has(entry.fact.url) && !retained.has(entry.path)), logGateway);
		},
		accountId,
		ctx,
		isInternalTextSlashCommandTurn: commandSource === "text",
		queuedFollowupOwnerKey,
		pluginBoundMediaPromise,
		managedMediaApplyMode: attachments.explicitOriginTargetsPlugin ? "replace-empty" : "append-missing",
		replyOptionImages: mediaPathOffloadsIncludeImages ? void 0 : attachments.parsedImages.length > 0 ? attachments.parsedImages : void 0,
		replyOptionMedia: buildChatSendPromptMedia(attachments)
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-agent-dispatch.ts
function startChatDispatch(params) {
	const { replyAdmissionTicket, diagnostics, admissionStartedAt, admission, attachments, client, context, toolsAllow, prepareSkillLibraryAuthoring, cronCreatorAuthority, assertDashboardReadCurrent, externalAuthorityAdmission, injection, request, session, terminalizeRestartSafeAdmission, turn, userTurn } = params;
	const { imageOrder } = attachments;
	const progressRefresh = isProgressCardRefreshInputProvenance(request.systemInputProvenance);
	const { activeRunAbort, admittedSessionId, chatSendTraceAttributes, gatewayWorkAdmission, messageInjectionTarget, retainGatewayWorkAdmission, restartSafeAdmission, sessionBinding } = admission;
	const { activeRunScopeKey, agentId, cfg, clientRunId, entry, expectedLeafEntryId, requestedSessionId, resolvedSessionModel, storePath, selectedAgent, sessionKey } = session;
	const { clientInfo, p, reconnectResumeRequested, supportsTaskSuggestions } = request;
	const { accountId, ctx, isInternalTextSlashCommandTurn, managedMediaApplyMode, pluginBoundMediaPromise, queuedFollowupOwnerKey, replyOptionImages, replyOptionMedia } = turn;
	const { persist: persistGatewayUserTurnTranscript, persistBestEffort: persistGatewayUserTurnTranscriptBestEffort, recorder: userTurnRecorder } = userTurn;
	const { beginCapturedMessageInjection, preAckReplyContextPromise, replyContextFieldsPromise } = injection;
	let { messageInjectionAttempt } = injection;
	const titleReady = createDeferredCore();
	const turnSettled = createDeferredCore();
	let titleWaiting = true;
	let stopTitleWait;
	const releaseTitle = (duringTurn) => {
		stopTitleWait?.();
		stopTitleWait = void 0;
		titleWaiting = false;
		titleReady.resolve(duringTurn);
	};
	let agentRunStarted = false;
	let replyDispatchRun;
	const isRunCurrent = () => !activeRunAbort.controller.signal.aborted && context.chatAbortControllers.get(clientRunId) === activeRunAbort.entry;
	const replyDispatch = createChatSendReplyDispatch({
		getRuntimeConfig: context.getRuntimeConfig,
		assertWorkCurrent: admission.assertWorkAdmissionCurrent,
		requesterContext: ctx,
		accountId,
		prepareAssistantTranscriptMessage: params.prepareAssistantTranscriptMessage,
		isAgentRunStarted: () => agentRunStarted,
		isRunCurrent: () => isRunCurrent() || !activeRunAbort.controller.signal.aborted && context.chatQueuedTurns.get(clientRunId)?.controller === activeRunAbort.controller,
		abortSignal: activeRunAbort.controller.signal,
		onCommandBlock: isInternalTextSlashCommandTurn ? (text) => broadcastChatDelta({
			context,
			runId: clientRunId,
			sessionKey,
			agentId,
			text,
			isCurrent: isRunCurrent
		}) : void 0,
		getReplyDispatchRun: () => replyDispatchRun,
		logGateway: context.logGateway,
		session,
		userTurnRecorder
	});
	const queuedFollowup = createChatSendTurnAdoptionLifecycle({
		requesterContext: ctx,
		accountId,
		chatQueuedTurns: context.chatQueuedTurns,
		context,
		runId: clientRunId,
		controller: activeRunAbort.controller,
		sessionBinding: admission.sessionBinding,
		sessionKey,
		agentId: selectedAgent.agentId,
		ownerConnId: client?.connId,
		ownerDeviceId: client?.connect?.device?.id,
		ownerKey: queuedFollowupOwnerKey,
		...expectedLeafEntryId !== void 0 ? { originatingLeafEntryId: expectedLeafEntryId } : {},
		originatingChannel: admission.originatingRoute.originatingChannel,
		session,
		hasCronCreatorAuthority: cronCreatorAuthority !== void 0,
		suppressReplies: progressRefresh,
		releaseSourceWorkAdmission: admission.releaseSourceWorkAdmission,
		retainWorkAdmission: retainGatewayWorkAdmission,
		armOperatorRunCancellation: admission.armOperatorRunCancellation,
		retireOperatorRunCancellation: admission.retireOperatorRunCancellation
	});
	let acceptedMessageInjection = false;
	const classifyDispatchFailure = (error) => classifyAcceptedChatSendFailure({
		error,
		phase: "post-ack",
		executionStarted: agentRunStarted,
		sideEffectsObserved: acceptedMessageInjection || messageInjectionAttempt !== void 0 || replyDispatch.deliveredReplies.length > 0
	});
	const dispatchErrorLifecycle = createChatSendDispatchErrorLifecycle({
		admission,
		classifyFailure: classifyDispatchFailure,
		context,
		isAgentRunStarted: () => agentRunStarted,
		isQueuedFollowupEnqueued: () => queuedFollowup.isEnqueued() || queuedFollowup.isTerminal(),
		persistUserTurnTranscript: persistGatewayUserTurnTranscript,
		session,
		terminalizeRestartSafeAdmission,
		userTurnRecorder,
		isReplyDispatchRun: () => replyDispatchRun !== void 0
	});
	const { emit: emitServerTiming, emitFirstAssistant: emitFirstAssistantServerTiming, dispatchStartedAtMs } = createOperatorChatSendServerTiming(params);
	emitServerTiming("dispatch-started");
	const dispatchAdmission = { run: (operation) => gatewayWorkAdmission.run(async () => {
		acceptedMessageInjection = await settleChatSendMessageInjection(messageInjectionAttempt);
		return await (acceptedMessageInjection ? operation() : withCurrentUserTurnInput(userTurnRecorder, operation));
	}) };
	const dashboardReadAdmission = assertDashboardReadCurrent ? {
		agentId,
		runId: clientRunId,
		sessionKey,
		get sessionId() {
			return sessionBinding.sessionId;
		},
		assertCurrent: assertDashboardReadCurrent
	} : void 0;
	const phase = diagnostics.scope("dispatch");
	const dispatch = replyDispatch.runAgentMediaTranscript(dispatchAdmission, () => measureDiagnosticsTimelineSpan("gateway.chat_send.dispatch_inbound", async () => {
		if (!acceptedMessageInjection) admission.assertWorkAdmissionCurrent();
		let assertWorkspaceRunOwnership;
		if (!acceptedMessageInjection && entry && (Object.hasOwn(entry, "pendingProjectGitUrl") || entry.pendingWorktree)) {
			phase?.mark("worktree");
			assertWorkspaceRunOwnership = await prepareSessionWorkspace({
				admission,
				client,
				context,
				session
			});
			assertWorkspaceRunOwnership();
		}
		phase?.mark("replyContext");
		if (replyContextFieldsPromise && !preAckReplyContextPromise) {
			const replyContextFields = await replyContextFieldsPromise;
			assertWorkspaceRunOwnership?.();
			applyChatSendReplyContextFields(ctx, replyContextFields);
			messageInjectionAttempt = await withCurrentUserTurnInput(userTurnRecorder, beginCapturedMessageInjection);
		}
		if (messageInjectionAttempt) {
			const injected = await finalizeAcceptedChatSendMessageInjection({
				attempt: messageInjectionAttempt,
				sessionBinding,
				context,
				ctx,
				persistUserTurnTranscriptBestEffort: async () => {
					await persistGatewayUserTurnTranscriptBestEffort();
				},
				session,
				startedAt: admissionStartedAt,
				target: messageInjectionTarget
			});
			assertWorkspaceRunOwnership?.();
			if (injected) {
				acceptedMessageInjection = true;
				return {
					queuedFinal: false,
					counts: {
						tool: 0,
						block: 0,
						final: 0
					}
				};
			}
		}
		phase?.mark("preparation");
		await turn.prepareSessionCreation();
		phase?.mark("authoring");
		const skillLibraryAuthoring = await prepareSkillLibraryAuthoring();
		admission.assertWorkAdmissionCurrent();
		phase?.mark("preparation");
		const pluginBoundMedia = await pluginBoundMediaPromise;
		assertWorkspaceRunOwnership?.();
		applyChatSendManagedMedia(ctx, pluginBoundMedia, managedMediaApplyMode);
		phase?.mark("replyInitialization");
		const dispatchInbound = () => {
			assertWorkspaceRunOwnership?.();
			return dispatchInboundMessageWithProjectedDispatcher({
				ctx,
				cfg,
				toolsAllow,
				dispatcherOptions: replyDispatch.dispatcherOptions,
				onSessionMetadataChanges: (changes) => changes.forEach((change) => emitSessionsChanged(context, change)),
				replyOptions: {
					[REPLY_ADMISSION_TICKET]: replyAdmissionTicket,
					prepareAssistantTranscriptMessage: replyDispatch.prepareAssistantTranscriptMessage,
					...isInternalSourceReplyChannel(ctx) ? { resolveReplyDelivery: replyDispatch.resolveReplyDelivery } : {},
					...admission.admittedSessionSettings ? { admittedSessionSettings: admission.admittedSessionSettings } : {},
					runId: clientRunId,
					operatorAuthority: admission.operatorAuthority,
					providerReviewAcknowledgment: request.providerReviewAcknowledgment,
					dashboardReadAdmission,
					skillLibraryAuthoring,
					...cronCreatorAuthority ? { cronCreatorAuthorityCapability: cronCreatorAuthority } : {},
					...isOperatorUiClient(clientInfo) ? { promptCacheKey: resolveWebchatPromptCacheKey({
						agentId,
						provider: resolvedSessionModel.provider,
						model: resolvedSessionModel.model,
						sessionKey: activeRunScopeKey
					}) } : {},
					...supportsTaskSuggestions ? { taskSuggestionDeliveryMode: "gateway" } : {},
					requestedSessionId,
					expectedActiveReplyOperation: admission.expectedActiveReplyOperation,
					...restartSafeAdmission ? {
						expectedExistingSessionId: admittedSessionId,
						pinExpectedExistingSession: true,
						newlyCreatedSessionId: admission.initialSessionEntry?.sessionId
					} : entry?.sessionId ? { expectedExistingSessionId: entry.sessionId } : {},
					resumeRequestedSession: reconnectResumeRequested,
					onSessionPrepared: (binding) => {
						phase?.mark("preparation");
						admission.onSessionPrepared(binding);
						replyDispatch.notePreparedSession(binding);
					},
					onTranscriptStartPreparation: () => diagnostics.scope("snapshot")?.finish,
					abortSignal: activeRunAbort.controller.signal,
					getProviderLoginConfig: context.getRuntimeConfig,
					assertProviderLoginAuthority: () => {
						client?.connectionSignal?.throwIfAborted();
						if (client?.invalidated || !client?.connect.scopes?.includes("operator.admin")) throw new Error("Provider login authority is no longer active.");
					},
					onFollowupQueueDisposition: queuedFollowup.onQueueDisposition,
					onQueuedFollowupReplyBatch: queuedFollowup.onQueuedFollowupReplyBatch,
					turnAdoptionLifecycle: queuedFollowup.lifecycle,
					images: replyOptionImages,
					imageOrder: imageOrder.length > 0 ? imageOrder : void 0,
					media: replyOptionMedia,
					...p.timeoutMs !== void 0 ? { timeoutOverrideMs: p.timeoutMs } : {},
					thinkingLevelOverride: p.thinking,
					fastModeOverride: p.fastMode,
					queueModeOverride: p.queueMode,
					userTurnTranscriptRecorder: userTurnRecorder,
					...p.queueMode === "steer" && messageInjectionTarget ? { messageInjectionDisposition: "rejected" } : {},
					...restartSafeAdmission ? { suppressNextUserMessagePersistence: true } : {},
					fastModeAutoOnSecondsOverride: p.fastAutoOnSeconds,
					onAgentRunStart: (runId, _identity, options, transcriptStart) => {
						queuedFollowup.onRunStarted(runId);
						diagnostics.finish();
						if (titleWaiting) {
							stopTitleWait?.();
							stopTitleWait = onAgentEventForRun(runId, (event) => {
								if (event.stream === "assistant" || event.stream === "item" || event.stream === "tool" || event.stream === "thinking" || event.stream === "approval") releaseTitle(true);
							});
						}
						replyDispatchRun = options;
						if (activeRunAbort.markExecutionStarted()) {
							admission.armOperatorRunCancellation();
							emitSessionsChanged(context, {
								sessionKey,
								agentId,
								reason: "agent.run.started"
							}, { accessChanged: false });
						}
						agentRunStarted = true;
						replyDispatch.captureAgentTranscriptStart(runId, transcriptStart);
						emitServerTiming("agent-run-started", runId !== clientRunId ? { agentRunId: runId } : void 0, dispatchStartedAtMs);
						const connId = typeof client?.connId === "string" ? client.connId : void 0;
						const wantsToolEvents = hasGatewayClientCap(client?.connect?.caps, GATEWAY_CLIENT_CAPS.TOOL_EVENTS);
						if (connId && wantsToolEvents) {
							context.registerToolEventRecipient(runId, connId);
							const compatibilityOwnerAgentId = tryResolveSessionCompatibilityOwnerAgentId(cfg, sessionKey);
							const selectedSessionAgentId = selectedAgent.agentId;
							for (const [activeRunId, active] of context.chatAbortControllers) {
								const sameSelectedAgent = selectedSessionAgentId !== void 0 && chatRunBelongsToSelectedAgent({
									agentId: active.agentId,
									sessionKey: active.sessionKey,
									defaultAgentId: compatibilityOwnerAgentId,
									selectedAgentId: selectedSessionAgentId
								});
								const sameSession = active.sessionKey === sessionKey && sameSelectedAgent;
								if (activeRunId !== runId && sameSession) context.registerToolEventRecipient(activeRunId, connId);
							}
						}
						return options?.completionSource;
					},
					onModelSelected: (modelSelection) => {
						updateChatRunProvider(context.chatAbortControllers, {
							runId: clientRunId,
							providerId: modelSelection.provider,
							authProviderId: resolveProviderIdForAuth(modelSelection.provider, { config: cfg })
						});
						replyDispatch.onModelSelected(modelSelection);
						emitServerTiming("model-selected", {
							provider: modelSelection.provider,
							model: modelSelection.model
						}, dispatchStartedAtMs);
					}
				}
			});
		};
		const dispatchWithRetry = () => withExecRequestTurn({
			identity: {
				runId: clientRunId,
				sessionKey: sessionBinding.sessionKey,
				sessionId: sessionBinding.sessionId,
				agentId: sessionBinding.agentId,
				ownerConnId: sessionBinding.ownerConnId,
				ownerDeviceId: sessionBinding.ownerDeviceId,
				controlUiVisible: sessionBinding.controlUiVisible,
				turnKind: sessionBinding.turnKind
			},
			abortSignal: activeRunAbort.controller.signal
		}, () => runAcceptedChatSendDispatch({
			operation: () => withCurrentUserTurnInput(userTurnRecorder, dispatchInbound),
			classify: classifyDispatchFailure,
			waitForRetry: (error) => waitForAcceptedChatSendRetry({
				agentId,
				sessionKey,
				storePath
			}, error, activeRunAbort.controller.signal)
		}));
		const dispatchResult = await (cronCreatorAuthority && externalAuthorityAdmission ? externalAuthorityAdmission.run(cronCreatorAuthority, dispatchWithRetry, activeRunAbort.controller.signal) : dispatchWithRetry());
		if (dispatchResult.beforeAgentRunBlocked === true) userTurnRecorder.markBlocked();
		return dispatchResult;
	}, {
		phase: "agent-turn",
		config: cfg,
		attributes: chatSendTraceAttributes
	})).then(async (dispatchResult) => {
		diagnostics.finish();
		if (acceptedMessageInjection || queuedFollowup.isEnqueued() || queuedFollowup.isTerminal()) return;
		emitServerTiming("dispatch-completed", void 0, dispatchStartedAtMs);
		const postDispatchStartedAtMs = performance.now();
		await measureDiagnosticsTimelineSpan("gateway.chat_send.post_dispatch", async () => {
			const replyDispatchResult = replyDispatchRun?.getResult();
			const runtimeOutcome = replyDispatchResult?.terminalOutcome;
			const recordedOutcome = readAgentRunTerminalOutcome(dispatchResult);
			const runtimeClassification = runtimeOutcome ? classifyAgentRunTerminalOutcome(runtimeOutcome) : recordedOutcome && (recordedOutcome === "failed" ? "failure" : "success");
			const runtimeCancelled = runtimeClassification === "cancellation";
			const runtimeFailed = runtimeClassification === "failure" || runtimeClassification === "timeout";
			const returnedAgentErrorPayloads = replyDispatch.deliveredReplies.map((entryInner) => readChatSendReplyPayload(entryInner.input)).filter((payload) => payload.isError);
			const hasOnlyFinalWarnings = returnedAgentErrorPayloads.length > 0 && replyDispatch.deliveredReplies.every(({ kind, input }) => {
				const payload = readChatSendReplyPayload(input);
				return kind === "final" && payload.isError === true || isReplyPayloadStatusNotice(payload);
			});
			const hasReturnedAgentError = runtimeClassification ? runtimeFailed : returnedAgentErrorPayloads.length > 0 && (agentRunStarted || !isInternalTextSlashCommandTurn);
			const returnedAgentErrorMessage = runtimeOutcome?.error ?? (formatReturnedAgentErrors(returnedAgentErrorPayloads.map((payload) => payload.text?.trim()).filter((text) => Boolean(text))) || (runtimeFailed ? "agent run failed" : void 0));
			if (!userTurnRecorder.hasPersisted() && !userTurnRecorder.isBlocked() && (hasReturnedAgentError || agentRunStarted && returnedAgentErrorPayloads.length === 0 && userTurnRecorder.hasRuntimePersistencePending())) await persistGatewayUserTurnTranscriptBestEffort();
			const replyFinalization = {
				terminalEntry: sessionBinding,
				requesterContext: ctx,
				abortSignal: activeRunAbort.controller.signal,
				accountId,
				context,
				deliveredReplies: replyDispatch.deliveredReplies,
				emitFirstAssistantServerTiming,
				session
			};
			let finalizedSourceReply = false;
			if (!progressRefresh && (!agentRunStarted || replyDispatchRun || hasOnlyFinalWarnings) && !hasReturnedAgentError && !context.chatRunState.hasAbortMarker(clientRunId)) await finalizeChatSendDispatchedReplies({
				...replyFinalization,
				foldCommandBlocks: isInternalTextSlashCommandTurn || replyDispatchRun !== void 0,
				persistUserTurnTranscript: persistGatewayUserTurnTranscriptBestEffort,
				suppressReplies: !replyDispatchRun && replyDispatch.hasAppendedWebchatAgentMedia(),
				runtimeOwnsTranscript: replyDispatchResult?.assistantTranscript?.agentId === agentId && replyDispatchResult.assistantTranscript.sessionKey === sessionKey && replyDispatchResult.assistantTranscript.sessionId === activeRunAbort.entry?.sessionId,
				state: runtimeCancelled ? "aborted" : "final",
				stopReason: runtimeOutcome?.stopReason
			});
			else if (!progressRefresh && !context.chatRunState.hasAbortMarker(clientRunId)) finalizedSourceReply = await finalizeChatSendSourceReplies({
				...replyFinalization,
				hasReturnedAgentErrorPayloads: hasReturnedAgentError,
				suppressFinal: runtimeFailed
			});
			const hasTerminalAgentError = hasReturnedAgentError && (runtimeFailed || !finalizedSourceReply);
			if (!context.chatRunState.hasAbortMarker(clientRunId)) {
				if (hasTerminalAgentError) dispatchErrorLifecycle.broadcastError({
					errorMessage: returnedAgentErrorMessage,
					errorKind: runtimeClassification === "timeout" ? "timeout" : void 0,
					stopReason: runtimeOutcome?.stopReason
				});
				const returnedAgentError = hasTerminalAgentError ? errorShape(ErrorCodes.UNAVAILABLE, returnedAgentErrorMessage ?? "agent returned an error payload") : void 0;
				setGatewayDedupeEntry({
					dedupe: context.dedupe,
					key: `chat:${clientRunId}`,
					session: captureAgentJobSession(sessionBinding),
					entry: {
						ts: Date.now(),
						ok: !hasTerminalAgentError,
						payload: hasTerminalAgentError ? {
							runId: clientRunId,
							status: runtimeClassification === "timeout" ? "timeout" : "error",
							summary: returnedAgentErrorMessage ?? "agent returned an error payload",
							...runtimeOutcome ? { endedAt: runtimeOutcome.endedAt } : {},
							...runtimeOutcome?.stopReason ? { stopReason: runtimeOutcome.stopReason } : {}
						} : runtimeCancelled ? buildAbortedChatSendPayload({
							runId: clientRunId,
							endedAt: runtimeOutcome?.endedAt ?? Date.now(),
							stopReason: runtimeOutcome?.stopReason
						}) : {
							runId: clientRunId,
							status: progressRefresh && !queuedFollowup.isSteered() ? "completed" : "ok",
							...replyDispatchResult?.terminalOutcome?.stopReason ? { stopReason: replyDispatchResult.terminalOutcome.stopReason } : {}
						},
						...returnedAgentError ? { error: returnedAgentError } : {}
					}
				});
			}
		}, {
			phase: "agent-turn",
			config: cfg,
			attributes: chatSendTraceAttributes
		});
		emitServerTiming("post-dispatch-completed", { postDispatchMs: roundedChatSendTimingMs(performance.now() - postDispatchStartedAtMs) }, dispatchStartedAtMs);
	}).catch((error) => {
		diagnostics.finish();
		return dispatchErrorLifecycle.handleError(error);
	}).finally(() => replyAdmissionTicket?.release());
	(async () => {
		try {
			await dispatch;
		} finally {
			releaseTitle(false);
			turnSettled.resolve();
			await dispatchErrorLifecycle.finalize();
			emitSessionsChanged(context, {
				sessionKey,
				agentId,
				reason: "agent.input.settled"
			}, {
				accessChanged: false,
				rowScope: "runtime"
			});
			if (userTurnRecorder.isBlocked() && attachments.offloadedRefs.length > 0) discardPreparedInboundMedia(attachments.offloadedRefs);
		}
	})();
	scheduleChatDashboardSessionTitle({
		admittedSessionId,
		agentId,
		cfg,
		context,
		request,
		sessionKey,
		storePath
	}, {
		released: titleReady.promise,
		settled: turnSettled.promise
	});
}
//#endregion
//#region src/gateway/server-methods/chat-send-attachments.ts
function isManagedInboundPdfOffloadRef(ref) {
	const mime = ref.mimeType.trim().toLowerCase();
	if (mime !== "application/pdf" && !mime.endsWith("+pdf") && path.extname(ref.path.split(/[?#]/u)[0] ?? "").toLowerCase() !== ".pdf") return false;
	try {
		return parseInboundMediaUri(ref.mediaRef) !== null;
	} catch {
		return false;
	}
}
async function prestageMediaPathOffloads(params) {
	const mediaPathRefs = params.offloadedRefs.filter((ref) => params.includeImageRefs || !ref.mimeType.startsWith("image/"));
	if (mediaPathRefs.length === 0) return [];
	try {
		const [{ ensureSandboxWorkspaceForSession }, { SANDBOX_MEDIA_MAX_BYTES, stageSandboxMedia }] = await Promise.all([import("./context-DFeu3Oxx.mjs"), import("./stage-sandbox-media-BJMQra5q.mjs")]);
		params.abortSignal.throwIfAborted();
		params.assertWorkAdmissionCurrent();
		const refsByManagedPath = (refs) => refs.map((ref) => ({
			path: ref.path,
			contentType: ref.mimeType,
			fileName: ref.label,
			workspaceDir: path.dirname(ref.path)
		}));
		const refsToStage = mediaPathRefs.filter((ref) => !(ref.sizeBytes > SANDBOX_MEDIA_MAX_BYTES && isManagedInboundPdfOffloadRef(ref)));
		if (refsToStage.length === 0) return refsByManagedPath(mediaPathRefs);
		const workspaceDir = resolveAgentWorkspaceDir(params.cfg, params.agentId);
		if (getAgentWorkspaceAccess(workspaceDir, "prepareTurnAttachments")?.prepareTurnAttachments) return refsByManagedPath(mediaPathRefs);
		const skillsSnapshot = params.skillLibrarySelections?.length ? (await (await import("./session-snapshot-Br4aTzow.mjs")).resolveReusableWorkspaceSkillSnapshot({
			workspaceDir,
			config: params.cfg,
			agentId: params.agentId,
			existingSnapshot: params.existingSkillsSnapshot,
			librarySelections: params.skillLibrarySelections,
			assertCurrent: params.assertWorkAdmissionCurrent
		})).snapshot : void 0;
		params.abortSignal.throwIfAborted();
		params.assertWorkAdmissionCurrent();
		const sandbox = await ensureSandboxWorkspaceForSession({
			config: params.cfg,
			agentId: params.agentId,
			sessionKey: params.sessionKey,
			workspaceDir,
			skillsSnapshot
		});
		params.assertWorkAdmissionCurrent();
		if (!sandbox) return refsByManagedPath(mediaPathRefs);
		const oversizedForSandbox = refsToStage.filter((ref) => ref.sizeBytes > SANDBOX_MEDIA_MAX_BYTES);
		if (oversizedForSandbox.length > 0) {
			const details = oversizedForSandbox.map((ref) => `${ref.label} (${ref.sizeBytes} bytes)`).join(", ");
			throw new UnsupportedAttachmentError("non-image-too-large-for-sandbox", `attachments exceed sandbox staging limit (${SANDBOX_MEDIA_MAX_BYTES} bytes): ${details}`);
		}
		const stagingCtx = { media: refsToStage.map((ref) => ({
			path: ref.path,
			contentType: ref.mimeType
		})) };
		let stageResult;
		try {
			stageResult = await stageSandboxMedia({
				ctx: stagingCtx,
				sessionCtx: stagingCtx,
				cfg: params.cfg,
				agentId: params.agentId,
				sessionKey: params.sessionKey,
				workspaceDir,
				skillsSnapshot,
				abortSignal: params.abortSignal
			});
		} catch (stageErr) {
			if (params.abortSignal.aborted && Object.is(stageErr, params.abortSignal.reason) || refsToStage.some((ref) => !isManagedInboundPdfOffloadRef(ref))) throw stageErr;
			return refsByManagedPath(mediaPathRefs);
		}
		const stagedSources = stageResult.staged;
		const unstageable = refsToStage.filter((_ref, index) => !stagedSources.has(index)).filter((ref) => !isManagedInboundPdfOffloadRef(ref));
		if (unstageable.length > 0) throw new Error(`attachment staging incomplete: ${stagedSources.size}/${refsToStage.length} paths staged into sandbox workspace (missing: ${unstageable.map((ref) => ref.path).join(", ")})`);
		const stagedMedia = stagingCtx.media ?? [];
		const resolvedByRef = new Map(refsToStage.map((ref, index) => [ref, stagedMedia[index]]));
		return mediaPathRefs.map((ref) => {
			const resolved = resolvedByRef.get(ref);
			return {
				path: resolved?.path ?? ref.path,
				url: ref.mediaRef,
				contentType: resolved?.contentType ?? ref.mimeType,
				fileName: ref.label,
				workspaceDir: sandbox.workspaceDir
			};
		});
	} catch (err) {
		if (params.abortSignal.aborted && Object.is(err, params.abortSignal.reason) || err instanceof SessionMutationAuthorizationChangedError || err instanceof MediaOffloadError || err instanceof UnsupportedAttachmentError) throw err;
		throw new MediaOffloadError(`[Gateway Error] Failed to stage attachments into agent workspace: ${formatErrorMessage(err)}`, { cause: err });
	}
}
/** Parse and pre-stage attachments before the caller's synchronous pre-ACK checks. */
async function prepareChatSendAttachments(params) {
	const { request, session, admission, respond, context, client } = params;
	const { inboundMessage, normalizedAttachments, explicitOrigin } = request;
	const { cfg, sessionKey, agentId, resolvedSessionModel, clientRunId } = session;
	const { activeRunAbort, chatSendTraceAttributes, cleanupAdmittedRun, finishAbortedChatSend, lifecycleGeneration } = admission;
	const assertInputCurrent = () => {
		activeRunAbort.controller.signal.throwIfAborted();
		admission.assertWorkAdmissionCurrent();
		admission.assertClientUploadAllowed?.();
	};
	let parsedMessage = inboundMessage;
	let parsedImages = [];
	let imageOrder = [];
	let offloadedRefs = [];
	let mediaPathOffloads = [];
	let explicitOriginTargetsPlugin = false;
	let prepareAttachmentsMs;
	try {
		const explicitOriginTargets = await resolveExplicitOriginBindingTargets(explicitOrigin);
		assertInputCurrent();
		explicitOriginTargetsPlugin = explicitOriginTargets.plugin;
		if (normalizedAttachments.length > 0) {
			const prepareAttachmentsStartedAtMs = performance.now();
			await measureDiagnosticsTimelineSpan("gateway.chat_send.prepare_attachments", async () => {
				const imageSupport = { value: explicitOriginTargets.acp || explicitOriginTargetsPlugin ? true : void 0 };
				const resolveSupportsImages = async () => {
					imageSupport.value ??= await resolveGatewayModelSupportsImages({
						loadGatewayModelCatalog: context.loadGatewayModelCatalog,
						loadGatewayModelCatalogSnapshot: context.loadGatewayModelCatalogSnapshot,
						agentId,
						provider: resolvedSessionModel.provider,
						model: resolvedSessionModel.model
					});
					return imageSupport.value;
				};
				const parsed = await parseMessageWithAttachments(inboundMessage, normalizedAttachments, {
					maxBytes: resolveChatAttachmentMaxBytes(cfg),
					log: context.logGateway,
					supportsImages: imageSupport.value ?? resolveSupportsImages,
					acceptNonImage: true,
					signal: activeRunAbort.controller.signal,
					assertCurrent: assertInputCurrent
				});
				const parsedSupportsImages = imageSupport.value !== false;
				parsedMessage = parsedSupportsImages ? parsed.message : stripImageMediaMarkers(parsed.message, parsed.offloadedRefs);
				parsedImages = parsed.images;
				imageOrder = parsed.imageOrder;
				offloadedRefs = parsed.offloadedRefs;
				const stagingEntry = admission.initialSessionEntry ?? admission.admittedSessionEntry ?? session.entry;
				const selectedSkills = stagingEntry ? stagingEntry.skillLibrarySelections ?? stagingEntry.skillsSnapshot?.librarySelections : request.systemInputProvenance ? void 0 : (await prepareSkillLibrarySessionCreation(client, context.getRuntimeConfig ?? cfg, resolveOperatorSessionCreation(client))).skillLibrarySelections;
				mediaPathOffloads = await prestageMediaPathOffloads({
					offloadedRefs,
					includeImageRefs: !parsedSupportsImages,
					cfg,
					sessionKey,
					agentId,
					skillLibrarySelections: selectedSkills,
					existingSkillsSnapshot: stagingEntry?.skillsSnapshot,
					abortSignal: activeRunAbort.controller.signal,
					assertWorkAdmissionCurrent: assertInputCurrent
				});
			}, {
				phase: "agent-turn",
				config: cfg,
				attributes: {
					...chatSendTraceAttributes,
					attachmentCount: normalizedAttachments.length
				}
			});
			assertInputCurrent();
			activeRunAbort.controller.signal.throwIfAborted();
			prepareAttachmentsMs = roundedChatSendTimingMs(performance.now() - prepareAttachmentsStartedAtMs);
		}
	} catch (err) {
		const aborted = activeRunAbort.controller.signal.aborted && (context.chatRunState.hasAbortMarker(clientRunId) || Object.is(err, activeRunAbort.controller.signal.reason));
		if (!aborted) activeRunAbort.cleanup();
		await discardPreparedInboundMedia(offloadedRefs);
		if (aborted) {
			finishAbortedChatSend();
			return { ok: false };
		}
		cleanupAdmittedRun();
		clearAgentRunContext(clientRunId, lifecycleGeneration);
		logAttachmentFailure(context.logGateway, "chat.send attachment parse/stage failed", err);
		respond(false, void 0, err instanceof SessionMutationAuthorizationChangedError ? err.error : errorShape(err instanceof MediaOffloadError ? ErrorCodes.UNAVAILABLE : ErrorCodes.INVALID_REQUEST, String(err)));
		return { ok: false };
	}
	return {
		ok: true,
		value: {
			explicitOriginTargetsPlugin,
			imageOrder,
			mediaPathOffloads,
			offloadedRefs,
			parsedImages,
			parsedMessage,
			prepareAttachmentsMs
		}
	};
}
/** Preparation owns cleanup until a transcript or pending input takes custody of its media. */
function bindChatSendPreparedMediaCustody(params) {
	let recorder;
	params.admission.setDiscardAbandonedPreparedMedia(() => {
		if (!recorder?.hasPersisted() && !recorder?.getPendingInputMessage?.()) discardPreparedInboundMedia(params.attachments.offloadedRefs);
	});
	return (inputRecorder) => {
		recorder = inputRecorder;
	};
}
//#endregion
//#region src/plugins/restart-recovery-hook-safety.ts
const RESTART_RECOVERY_UNSAFE_CHAT_ADMISSION_HOOKS = [
	"before_dispatch",
	"before_agent_run",
	"before_message_write",
	"reply_dispatch"
];
/** Initial chat admission defers before_agent_reply until after its durable checkpoint. */
function findRestartRecoveryUnsafeChatAdmissionHook(dispatchKind) {
	return RESTART_RECOVERY_UNSAFE_CHAT_ADMISSION_HOOKS.find((hookName) => hookName === "reply_dispatch" ? hasGlobalHooks(hookName, { dispatchKind }) : hasGlobalHooks(hookName));
}
//#endregion
//#region src/gateway/server-methods/chat-restart-recovery.ts
const RESTART_SAFE_CHAT_REQUEST_VERIFIER_DOMAIN = "openclaw.chat.restart-retry.v1";
const log = createSubsystemLogger("gateway/restart-recovery");
function hasRestartUnsafeMessageSemantics(rawMessage, cfg) {
	if (shouldComputeCommandAuthorized(rawMessage, cfg) || rawMessage.startsWith("/") || rawMessage.startsWith("!")) return true;
	const directives = parseInlineDirectives(rawMessage, {
		stripAudioTag: false,
		stripReplyTags: false
	});
	return directives.hasAudioTag || directives.hasReplyTag;
}
async function fingerprintRestartSafeChatRequest(params) {
	const identity = await loadOrCreateProcessDeviceIdentityAsync();
	const digest = createHmac("sha256", identity.privateKeyPem).update(JSON.stringify([
		RESTART_SAFE_CHAT_REQUEST_VERIFIER_DOMAIN,
		params.message,
		params.senderIsOwner,
		...params.mentions?.length ? [params.mentions.map(({ profileId, start, end }) => [
			profileId,
			start,
			end
		])] : []
	])).digest("hex");
	return `hmac-sha256:v1:${identity.deviceId}:${digest}`;
}
async function createRestartSafeChatRequest(params) {
	if (params.goalRequestFingerprint) return { fingerprint: params.goalRequestFingerprint };
	if (!params.eligible || hasRestartUnsafeMessageSemantics(params.message, params.cfg)) return;
	return { fingerprint: await fingerprintRestartSafeChatRequest(params) };
}
function isAdoptedRestartRecoveryClaim(entry, clientRunId) {
	return Boolean(entry?.restartRecoveryDeliveryRunId && entry.restartRecoveryDeliverySourceRunId === clientRunId && !isRetryableUnadoptedChatClaim(entry, clientRunId));
}
function resolveDurableChatClaim(params) {
	const entry = params.entry;
	if (!isAdoptedRestartRecoveryClaim(entry, params.clientRunId) || entry.abortedLastRun !== true) return isAdoptedRestartRecoveryClaim(entry, params.clientRunId) || hasRestartRecoveryTerminalRun(entry, params.clientRunId) ? { kind: "accepted" } : {
		kind: "continue",
		entry
	};
	const recoverySessionError = resolveAgentSessionWorkStartError(params.canonicalSessionKey, entry);
	if (recoverySessionError) return {
		kind: "rejected",
		message: recoverySessionError
	};
	const recoveryRuntime = params.recoveryRuntime;
	if (!recoveryRuntime) return {
		kind: "pending",
		message: "accepted chat turn recovery is waiting for the Gateway runtime; retry"
	};
	return (async () => {
		try {
			const { retryRestartAbortedMainSessionRecovery } = await import("./main-session-restart-recovery-CZnv65GP.mjs");
			await retryRestartAbortedMainSessionRecovery({
				canonicalSessionKey: params.canonicalSessionKey,
				cfg: params.cfg,
				expectedRecoveryRunId: entry.restartRecoveryDeliveryRunId,
				expectedRecoverySourceRunId: entry.restartRecoveryDeliverySourceRunId,
				expectedSessionId: entry.sessionId,
				sessionKey: params.persistedSessionKey,
				storePath: params.storePath,
				gatewayRuntime: recoveryRuntime
			});
		} catch (error) {
			params.warn(String(error));
		}
		const current = params.reloadEntry();
		if (isAdoptedRestartRecoveryClaim(current, params.clientRunId) && current.abortedLastRun === true) return {
			kind: "pending",
			message: "accepted chat turn recovery is still pending; retry"
		};
		if (!isAdoptedRestartRecoveryClaim(current, params.clientRunId) && !hasRestartRecoveryTerminalRun(current, params.clientRunId)) return {
			kind: "rejected",
			message: "accepted chat turn recovery ownership changed; automatic retry stopped to avoid duplicate execution",
			unavailable: true
		};
		return { kind: "accepted" };
	})();
}
function isRestartSafeChatSession(params) {
	const entry = params.entry;
	return Boolean(entry?.sessionId && params.sessionKey !== "global" && entry.abortedLastRun !== true && entry.archivedAt === void 0 && entry.initializationPending !== true && entry.pendingFinalDelivery === void 0 && (entry.agentHarnessId === void 0 || entry.agentHarnessId === "openclaw") && entry.pluginOwnerId === void 0 && entry.spawnedBy === void 0 && entry.subagentRole === void 0 && (entry.spawnDepth ?? 0) === 0 && params.acpMeta == null && entry.cronRunContinuation === void 0 && !isSubagentSessionKey(params.sessionKey) && !isCronSessionKey(params.sessionKey) && !isAcpSessionKey(params.sessionKey) && !isAgentHarnessSessionKey(params.sessionKey) && (params.requestedSessionId === void 0 || params.requestedSessionId === entry.sessionId));
}
function hasRestartUnsafeChatWork(params) {
	if (findRestartRecoveryUnsafeChatAdmissionHook(resolveSessionDispatchKind(params.sessionKey, params.entry)) !== void 0 || resolveProjectedAgentRunProgressState({
		agentId: params.agentId,
		sessionId: params.sessionId,
		sessionKeys: [params.sessionKey]
	}) !== void 0 || listActiveEmbeddedRunSessionIds().includes(params.sessionId) || replyRunRegistry.isActive(params.activeRunScopeKey)) return true;
	for (const runs of [params.context.chatAbortControllers, params.context.chatQueuedTurns]) for (const active of runs?.values() ?? []) if ((active.sessionKey === params.sessionKey || active.sessionId === params.sessionId) && resolveChatRunOwnerAgentId({
		agentId: active.agentId,
		sessionKey: active.sessionKey,
		defaultAgentId: params.agentId
	}) === params.agentId) return true;
	return false;
}
/** Borrow placement facts only while the chat owner revalidates and commits admission. */
async function withRestartSafeChatPlacement(service, sessionId, consume) {
	if (!service.prepareRuntimeRefresh) throw new Error("Worker placement admission reader is unavailable; retry.");
	const facts = await service.prepareRuntimeRefresh(sessionId);
	try {
		await consume({
			sessionId,
			facts
		});
	} finally {
		facts.release();
	}
}
function resolveRestartSafeChatAdmission(params) {
	const request = params.request;
	const entry = params.entry ?? params.initialSessionEntry;
	const placement = params.placement;
	if (placement && placement.state !== "local") return;
	if (!request || !entry || !isRestartSafeChatSession({
		...params,
		entry
	})) return;
	if (!params.initialSessionEntry) {
		const freshnessScope = {
			agentId: params.agentId,
			now: params.now,
			resetOverride: resolveChannelResetConfig({
				sessionCfg: params.cfg.session,
				channel: sessionDeliveryChannel(params.entry)
			}),
			resetType: resolveSessionResetType({ sessionKey: params.sessionKey }),
			sessionCfg: params.cfg.session,
			sessionKey: params.sessionKey,
			storePath: params.storePath
		};
		let freshness;
		if (isIncognitoSessionKey(params.sessionKey)) freshness = resolveSessionEntryResetFreshness(freshnessScope);
		else {
			if (params.lifecycleTimestamps === void 0) throw new Error("Restart-safe chat freshness was not prepared; retry.");
			freshness = resolvePreparedSessionEntryResetFreshness(freshnessScope, entry, params.lifecycleTimestamps);
		}
		if (freshness.state !== "fresh") return;
	}
	if (hasRestartUnsafeChatWork(params)) return;
	const retryableClaim = isRetryableUnadoptedChatClaim(entry, params.clientRunId);
	if (retryableClaim && entry.restartRecoveryDeliveryRequestFingerprint !== request.fingerprint) throw new Error("chat retry does not match its durable admission");
	return {
		requestFingerprint: request.fingerprint,
		...retryableClaim ? { retryExpectedState: buildRestartRecoveryExpectedState(entry) } : entry.restartRecoveryDeliverySourceRunId ? { priorTerminalSourceRunId: entry.restartRecoveryDeliverySourceRunId } : {}
	};
}
function buildRestartSafeChatTranscriptState(params) {
	return {
		...params.admission.retryExpectedState ? { expectedSessionState: params.admission.retryExpectedState } : {},
		sessionLifecyclePatch: {
			restartRecoveryBeforeAgentReplyState: void 0,
			restartRecoveryDeliveryReceiptState: void 0,
			restartRecoveryDeliveryToolCallId: void 0,
			...deriveGatewaySessionLifecycleSnapshot({ event: {
				runId: params.clientRunId,
				ts: params.startedAt,
				data: { phase: "start" }
			} }),
			lifecycleRunId: params.clientRunId,
			lastRunId: void 0,
			restartRecoveryDeliveryContext: void 0,
			restartRecoveryDeliveryRequestFingerprint: params.admission.requestFingerprint,
			restartRecoveryDeliveryRunId: params.clientRunId,
			restartRecoveryDeliverySourceRunId: params.clientRunId,
			restartRecoveryRequesterAccountId: void 0,
			restartRecoveryRequesterSenderId: void 0,
			restartRecoverySameChannelThreadRequired: void 0,
			restartRecoverySourceIngress: params.sourceIngress,
			restartRecoveryOperatorSource: params.admission.retryExpectedState ? params.admission.retryExpectedState.restartRecoveryOperatorSource : params.operatorSource,
			restartRecoverySourceReplyDeliveryMode: void 0,
			...params.admission.priorTerminalSourceRunId ? { restartRecoveryTerminalRunIds: [params.admission.priorTerminalSourceRunId] } : {}
		}
	};
}
async function terminalizeRestartSafeChatAdmission(params) {
	const endedAt = Date.now();
	let terminalized = false;
	params.assertCurrent();
	const persisted = await applySessionEntryTargetOperation(params.target, {
		kind: "restart-safe-terminal",
		runId: params.clientRunId,
		retryable: params.retryable,
		expected: {
			sessionId: params.admittedSessionId,
			lifecycleRevision: params.expectedLifecycleRevision
		},
		patch: {
			...deriveGatewaySessionLifecycleSnapshot({ event: {
				runId: params.clientRunId,
				ts: endedAt,
				data: {
					phase: params.status === "failed" ? "error" : "end",
					startedAt: params.startedAt,
					endedAt,
					aborted: params.status === "killed",
					error: params.error,
					errorKind: params.errorKind
				}
			} }),
			abortedLastRun: params.retryable ? false : params.status === "killed",
			lifecycleRunId: void 0,
			lastRunId: params.clientRunId
		}
	}, {
		requireWriteSuccess: true,
		skipMaintenance: true,
		workerGuard: { assertCurrent: params.assertCurrent },
		onCommitted: () => {
			terminalized = true;
		}
	});
	if (terminalized && persisted && params.status === "failed") await recordGatewaySessionRunFailure({
		target: {
			agentId: params.target.agentId,
			env: params.target.env,
			sessionKey: params.target.target.canonicalKey,
			storePath: params.target.readSource.path,
			sessionId: persisted.sessionId,
			expectedLifecycleRevision: persisted.lifecycleRevision
		},
		runId: params.clientRunId,
		error: params.error,
		errorKind: params.errorKind,
		assertCommitAllowed: () => {
			params.assertCurrent();
			const source = params.target.readSource;
			if (!isIncognitoSessionKey(params.target.target.canonicalKey) && typeof source.databaseIdentity === "string") assertExistingDatabaseIdentity(source.path, `file:${source.databaseIdentity}`, source.databaseBirthtime);
		}
	}).catch((error) => {
		log.warn(`Failed to record restart-safe chat failure notice: ${boundedWorkerError(error)}`);
	});
	return terminalized;
}
//#endregion
//#region src/gateway/server-methods/chat-send-active-leaf.ts
const ACTIVE_LEAF_CHANGED_ERROR_REASON = "active-leaf-changed";
function assertExpectedLeafActive(session, agentId, expectedLeafEntryId, requestedSessionId, options) {
	const activePathRelation = session.entry?.sessionId ? readSessionTranscriptActivePathEntryRelation({
		agentId,
		sessionId: session.entry.sessionId,
		sessionKey: session.canonicalKey,
		sessionEntry: session.entry,
		storePath: session.storePath
	}, expectedLeafEntryId) : expectedLeafEntryId === null ? "exact" : "off-path";
	const matchesRequestedSession = requestedSessionId === void 0 || requestedSessionId === session.entry?.sessionId;
	const matchesActivePath = activePathRelation === "exact" || requestedSessionId !== void 0 && (activePathRelation === "ancestor" || options?.allowEmptyAncestor === true && expectedLeafEntryId === null);
	if (!matchesRequestedSession || !matchesActivePath) throw new Error(ACTIVE_LEAF_CHANGED_ERROR_REASON);
}
//#endregion
//#region src/gateway/server-methods/chat-send-admission-cleanup.ts
/** Own cleanup after chat admission transfers work beyond the request frame. */
function createAdmittedChatSendCleanup(params) {
	let discardPreparedMedia;
	return {
		cleanup: () => {
			params.cleanupAbort();
			params.releaseRetainedWork();
			discardPreparedMedia?.();
			discardPreparedMedia = void 0;
		},
		setDiscardPreparedMedia: (discard) => {
			discardPreparedMedia = discard;
		}
	};
}
function finishAbortedChatSend(params) {
	const endedAt = Date.now();
	const payload = buildAbortedChatSendPayload({
		runId: params.runId,
		stopReason: params.stopReason ?? "rpc",
		endedAt
	});
	setGatewayDedupeEntry({
		dedupe: params.context.dedupe,
		key: `chat:${params.runId}`,
		session: captureAgentJobSession(params.sessionBinding),
		entry: {
			ts: endedAt,
			ok: true,
			payload
		}
	});
	params.cleanup();
	clearAgentRunContext(params.runId, params.lifecycleGeneration);
	params.respond(true, payload, void 0, { runId: params.runId });
}
//#endregion
//#region src/gateway/server-methods/chat-send-goal-retry.ts
async function prepareGoalChatSendRetry({ request, session, context }) {
	if (!request.goalOperation) return;
	const dedupe = context.dedupe.get(`chat:${session.clientRunId}`);
	try {
		return {
			receipt: await lookupSessionGoalOperation({
				sessionKey: session.sessionKey,
				storePath: session.storePath,
				agentId: session.agentId,
				expectedSessionId: session.entry?.sessionId ?? session.backingSessionId ?? session.clientRunId,
				operation: request.goalOperation
			}),
			dedupe
		};
	} catch (error) {
		if (!(error instanceof SessionGoalOperationError)) throw error;
		return {
			receipt: error,
			dedupe
		};
	}
}
//#endregion
//#region src/gateway/server-methods/chat-send-reservation.ts
function createPendingChatSendReservationAccess(params) {
	const { pendingChatSendKey: key, clientRunId: runId } = params.session;
	const read = () => readPreRegisteredRun({
		key,
		entry: params.context.dedupe.get(key),
		keyPrefix: PENDING_CHAT_SEND_DEDUPE_PREFIX
	});
	return {
		read,
		reserve: () => {
			const { context, request, session, attemptId } = params;
			context.dedupe.set(key, {
				ts: session.now,
				ok: true,
				requestIdentity: request.goalOperation?.requestFingerprint ?? request.requestIdentity,
				payload: {
					runId: session.clientRunId,
					attemptId,
					status: "accepted",
					sessionKey: session.sessionKey,
					...session.backingSessionId ? { sessionId: session.backingSessionId } : {},
					...session.rawSessionKey === session.sessionKey ? {} : { sessionKeyAliases: [session.rawSessionKey] },
					...session.selectedAgent.agentId ? { agentId: session.selectedAgent.agentId } : {},
					ownerConnId: normalizeOptionalString(params.client?.connId),
					ownerDeviceId: normalizeOptionalString(params.client?.connect?.device?.id),
					expiresAtMs: resolveChatRunExpiresAtMs({
						now: session.now,
						timeoutMs: session.timeoutMs
					}),
					turnKind: request.turnKind,
					...request.goalOperation ? { goalFingerprint: request.goalOperation.requestFingerprint } : {}
				}
			});
		},
		clear: () => {
			const pending = read();
			if (pending?.runId === runId && normalizeOptionalString(pending.payload.attemptId) === params.attemptId) params.context.dedupe.delete(key);
		}
	};
}
/** A retained request identity is not an ACK; only response-bearing rows may replay. */
function readChatSendDedupeResponse(dedupe, runId) {
	const entry = dedupe.get(`chat:${runId}`);
	return entry?.requestIdentity && entry.ok && entry.payload === void 0 && entry.error === void 0 ? void 0 : entry;
}
/** Consume prepared receipts and current RAM ownership without yielding before reservation. */
function inspectGoalChatSendRetry({ request, session, respond, context, durableClaimAccepted, assertCurrent, prepared }) {
	assertCurrent?.();
	const { clientRunId, pendingChatSendKey } = session;
	if (!request.goalOperation) return { kind: "new" };
	try {
		const receipt = prepared?.receipt;
		if (receipt instanceof SessionGoalOperationError) throw receipt;
		if (receipt) return {
			kind: "replay",
			receipt
		};
		const pending = readPreRegisteredRun({
			key: pendingChatSendKey,
			entry: context.dedupe.get(pendingChatSendKey),
			keyPrefix: PENDING_CHAT_SEND_DEDUPE_PREFIX
		});
		const retainedIdentity = context.dedupe.get(`chat:${clientRunId}`)?.requestIdentity;
		const identityConflict = retainedIdentity !== void 0 && retainedIdentity !== request.goalOperation.requestFingerprint;
		const cachedResponse = readChatSendDedupeResponse(context.dedupe, clientRunId);
		const newlyPublishedResponse = retainedIdentity === request.goalOperation.requestFingerprint && cachedResponse !== void 0 && cachedResponse !== prepared?.dedupe;
		if (!identityConflict && (pending?.payload.goalFingerprint === request.goalOperation.requestFingerprint || newlyPublishedResponse || !pending && !durableClaimAccepted && context.chatAbortControllers.has(clientRunId))) {
			respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, "Goal is being admitted; retry the same request.", { retryable: true }));
			return { kind: "settled" };
		}
		if (identityConflict || pending || durableClaimAccepted || cachedResponse || context.chatRunState.hasAbortMarker(clientRunId) || context.chatAbortControllers.has(clientRunId) || context.chatQueuedTurns?.has(clientRunId)) throw new SessionGoalOperationError("operation-conflict", "Goal operation ID is already used by another request.");
		return { kind: "new" };
	} catch (error) {
		if (!(error instanceof SessionGoalOperationError)) throw error;
		respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, error.message, { details: { reason: `goal-${error.code}` } }));
		return { kind: "settled" };
	}
}
//#endregion
//#region src/gateway/server-methods/chat-send-retry-comparison.ts
/** Submitted bytes compare input; the caller's current owner still decides replay. */
function readChatSendRetryComparison(session) {
	if (!session.entry?.sessionId) return;
	const { agentId, storePath, sessionKey, clientRunId } = session;
	const { sessionId, lifecycleRevision } = session.entry;
	return readSessionSubmittedInput({
		agentId,
		storePath,
		sessionKey,
		sessionId
	}, `${clientRunId}:user`).then((submitted) => {
		return {
			agentId,
			storePath,
			sessionKey,
			sessionId,
			lifecycleRevision,
			clientRunId,
			submitted
		};
	});
}
function compareChatSendSubmittedInput(request, session, comparison) {
	if (!comparison && session.entry?.sessionId || comparison && (comparison.agentId !== session.agentId || comparison.storePath !== session.storePath || comparison.sessionKey !== session.sessionKey || comparison.sessionId !== session.entry?.sessionId || comparison.lifecycleRevision !== session.entry?.lifecycleRevision || comparison.clientRunId !== session.clientRunId)) throw new SessionTranscriptProjectionUnavailableError(session.entry?.sessionId ?? comparison?.sessionId ?? session.clientRunId, "window-changed");
	const submitted = comparison?.submitted;
	if (!submitted) return request.mentions?.length || request.workContext ? "unverifiable" : false;
	const storedMentions = submitted["__openclaw"]?.humanMentions;
	const storedContext = submitted["__openclaw"]?.workContext;
	if (!request.mentions?.length && !storedMentions?.length && !request.workContext && !storedContext) return false;
	return (extractTextFromChatContent(submitted.content, {
		joinWith: "\n",
		normalizeText: (text) => text
	}) ?? "") !== request.rawMessage || !isDeepStrictEqual(storedMentions ?? [], request.mentions ?? []) || !isDeepStrictEqual(storedContext, request.workContext);
}
//#endregion
//#region src/gateway/server-methods/chat-send-session-settings.ts
const SESSION_SETTINGS_CHANGED_ERROR_REASON = "session-settings-changed";
function captureAdmittedChatSendSessionSettings(params) {
	const { entry, expectedPermissionMode, expectedToolOverrides } = params;
	if (expectedPermissionMode !== void 0 && (entry?.permissionMode ?? null) !== expectedPermissionMode || expectedToolOverrides !== void 0 && !sessionToolOverridesEqual(entry?.toolOverrides, expectedToolOverrides)) throw new Error(SESSION_SETTINGS_CHANGED_ERROR_REASON);
	if (!params.commit) return;
	return Object.freeze({
		permissionMode: entry?.permissionMode,
		toolOverrides: normalizeSessionToolOverrides(entry?.toolOverrides)
	});
}
//#endregion
//#region src/gateway/server-methods/chat-send-pre-admission.ts
function respondChatSessionRoutingChanged(respond) {
	respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "session routing changed; review and retry", { details: { reason: SESSION_ROUTING_CHANGED_ERROR_REASON } }));
}
function respondChatSendAdmissionError(error, respond) {
	const reason = error instanceof Error ? error.message : void 0;
	if (reason === "goal-session-busy") {
		respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, "This session still has active or queued work. Wait for it to finish, then retry the Goal.", {
			retryable: true,
			details: { reason: "goal-session-busy" }
		}));
		return;
	}
	if (reason === "session-routing-changed") {
		respondChatSessionRoutingChanged(respond);
		return;
	}
	if (reason === "active-leaf-changed" || reason === "session-settings-changed") {
		respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, reason === "active-leaf-changed" ? "active branch changed; review and retry" : "Session settings changed before send. Retry.", { details: { reason } }));
		return;
	}
	if (isSessionTranscriptProjectionUnavailableError(error)) {
		respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, "session transcript is rebuilding; retry shortly", {
			details: { method: "chat.send" },
			retryable: true,
			retryAfterMs: 250
		}));
		return;
	}
	respond(false, void 0, errorShapeFromError(ErrorCodes.INVALID_REQUEST, error, { message: formatForLog(error) }));
}
function resolveChatSendRequestConflict({ request, session, context }, comparison, ownPendingAttemptId) {
	if (request.goalOperation) return;
	const entries = [context.dedupe.get(`chat:${session.clientRunId}`), context.dedupe.get(session.pendingChatSendKey)];
	const conflict = (unverifiable = false) => errorShape(ErrorCodes.INVALID_REQUEST, unverifiable ? "The previous mention selections cannot be verified. Check the conversation history and use a new message ID to send again." : "This message ID was already used for different input. Check the conversation history and use a new message ID to send again.", { details: { reason: "chat-request-conflict" } });
	if (entries.some((entry) => entry?.requestIdentity !== void 0 && entry.requestIdentity !== request.requestIdentity)) return conflict();
	const sameDurableSource = session.entry?.restartRecoveryDeliverySourceRunId === session.clientRunId;
	const storedFingerprint = sameDurableSource ? session.entry?.restartRecoveryDeliveryRequestFingerprint : void 0;
	if (storedFingerprint !== void 0) return storedFingerprint === session.restartSafeRequest?.fingerprint ? void 0 : conflict();
	if (sameDurableSource && (request.mentions?.length || request.workContext) && !session.restartSafeRequest) return conflict(true);
	const retryEntries = ownPendingAttemptId !== void 0 && readPreRegisteredRun({
		key: session.pendingChatSendKey,
		entry: entries[1],
		keyPrefix: "pending-chat:"
	})?.payload.attemptId === ownPendingAttemptId ? entries.slice(0, 1) : entries;
	if (!comparison && retryEntries.some((entry) => entry?.requestIdentity === request.requestIdentity)) return;
	if (!(retryEntries.some(Boolean) || sameDurableSource || hasRestartRecoveryTerminalRun(session.entry, session.clientRunId) || context.chatRunState.hasAbortMarker(session.clientRunId) || context.chatAbortControllers.has(session.clientRunId) || context.chatQueuedTurns?.has(session.clientRunId))) return;
	const mismatch = compareChatSendSubmittedInput(request, session, comparison);
	return mismatch ? conflict(mismatch === "unverifiable") : void 0;
}
function prepareChatSendRetryComparison(params, ownPendingAttemptId) {
	try {
		resolveChatSendRequestConflict(params, void 0, ownPendingAttemptId);
		return;
	} catch (error) {
		if (!isSessionTranscriptProjectionUnavailableError(error)) throw error;
		return readChatSendRetryComparison(params.session);
	}
}
/** Consume current authority in one synchronous frame after any required worker preparation. */
async function consumeChatSendCurrent(params, consume) {
	const invoke = () => {
		params.assertCurrent?.();
		return consume();
	};
	if (params.withCurrent) return params.withCurrent(invoke);
	if (params.assertCurrentAsync) await params.assertCurrentAsync();
	return invoke();
}
async function respondPreparedChatSendRetry(params) {
	try {
		const pending = prepareChatSendRetryComparison(params);
		const comparison = pending ? await pending : void 0;
		return await consumeChatSendCurrent(params, () => respondChatSendRetry(params, comparison));
	} catch (error) {
		if (!isSessionTranscriptProjectionUnavailableError(error)) throw error;
		respondChatSendAdmissionError(error, params.respond);
		return true;
	}
}
/** Consume prepared comparison and current RAM ownership without yielding before reservation. */
function respondChatSendRetry(params, comparison) {
	params.assertCurrent?.();
	const { session, context, respond } = params;
	const { clientRunId, pendingChatSendKey } = session;
	const conflict = resolveChatSendRequestConflict(params, comparison);
	if (conflict) {
		respond(false, void 0, conflict);
		return true;
	}
	const cached = readChatSendDedupeResponse(context.dedupe, clientRunId);
	if (cached) {
		respond(cached.ok, cached.payload, cached.error, { cached: true });
		return true;
	}
	const abortMarker = context.chatRunState.runs.get(clientRunId)?.abortMarker;
	if (abortMarker !== void 0) {
		const abortedAt = chatAbortMarkerTimestampMs(abortMarker);
		const payload = buildAbortedChatSendPayload({
			runId: clientRunId,
			endedAt: abortedAt
		});
		setGatewayDedupeEntry({
			dedupe: context.dedupe,
			key: `chat:${clientRunId}`,
			entry: {
				ts: abortedAt,
				ok: true,
				payload
			}
		});
		respond(true, payload, void 0, {
			cached: true,
			runId: clientRunId
		});
		return true;
	}
	if (readPreRegisteredRun({
		key: pendingChatSendKey,
		entry: context.dedupe.get(pendingChatSendKey),
		keyPrefix: "pending-chat:"
	}) || context.chatAbortControllers.has(clientRunId) || context.chatQueuedTurns?.has(clientRunId)) {
		respond(true, {
			runId: clientRunId,
			status: "in_flight"
		}, void 0, {
			cached: true,
			runId: clientRunId
		});
		return true;
	}
	return false;
}
/** Settle stop/retry/dedupe cases before reserving lifecycle admission. */
async function runChatSendPreAdmission(params) {
	const { request, session, respond, context, client } = params;
	const { stopCommand } = request;
	const { cfg, entry, sessionKey, rawSessionKey, sessionLoadKey, selectedAgent, clientRunId, sessionLoadOptions, storePath, legacyKey, sessionRoutingChanged } = session;
	const resolveClaim = (currentEntry, warn) => resolveDurableChatClaim({
		canonicalSessionKey: sessionKey,
		cfg,
		clientRunId,
		entry: currentEntry,
		persistedSessionKey: legacyKey ?? sessionKey,
		reloadEntry: () => loadGatewaySessionEntry(sessionLoadKey, sessionLoadOptions).entry,
		storePath,
		recoveryRuntime: context.recoveryRuntime,
		warn
	});
	const warnRecovery = (message) => context.logGateway.warn(`failed to retry durable chat recovery ${clientRunId}: ${message}`);
	const consumeNewDispatchDecision = () => {
		if (sessionRoutingChanged(cfg)) {
			respondChatSessionRoutingChanged(respond);
			return false;
		}
		const archivedSessionError = resolveSessionWorkStartError(sessionKey, entry, {
			allowPendingWorkspace: true,
			providerReviewAcknowledgment: request.providerReviewAcknowledgment,
			runId: clientRunId
		});
		if (archivedSessionError) {
			respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, archivedSessionError));
			return false;
		}
		return true;
	};
	const requiresReconciliation = entry && isMainSessionRecoveryReconciliationCandidate(entry);
	let preparedClaim;
	let initialDecisionCompleted = false;
	let retryChecked = false;
	const consumeInitialDecision = () => {
		if (resolveSendPolicy({
			cfg,
			entry,
			sessionKey,
			channel: sessionDeliveryChannel(entry),
			chatType: entry?.chatType
		}) === "deny") {
			respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "send blocked by session policy"));
			return false;
		}
		if (!stopCommand && !request.goalOperation) {
			try {
				const handled = respondChatSendRetry(params);
				retryChecked = true;
				if (handled) return false;
			} catch (error) {
				if (!isSessionTranscriptProjectionUnavailableError(error)) throw error;
			}
			if (retryChecked && !requiresReconciliation) {
				preparedClaim = resolveClaim(entry, warnRecovery);
				if (preparedClaim instanceof Promise) preparedClaim.catch(() => {});
				else if (preparedClaim.kind === "continue") {
					initialDecisionCompleted = true;
					return consumeNewDispatchDecision();
				}
			}
		}
		return true;
	};
	try {
		if (!(stopCommand ? consumeInitialDecision() : await consumeChatSendCurrent(params, consumeInitialDecision))) return false;
	} catch (error) {
		if (preparedClaim instanceof Promise) await Promise.allSettled([preparedClaim]);
		throw error;
	}
	if (initialDecisionCompleted) return true;
	if (request.goalOperation) {
		const prepared = await prepareGoalChatSendRetry(params);
		const retry = await consumeChatSendCurrent(params, () => inspectGoalChatSendRetry({
			...params,
			prepared
		}));
		if (retry.kind === "settled") return false;
		if (retry.kind === "replay") {
			const claim = await resolveClaim(entry, (message) => context.logGateway.warn(message));
			await consumeChatSendCurrent(params, () => {
				if (claim.kind === "pending" || claim.kind === "rejected") respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, claim.message, { retryable: claim.kind === "pending" }));
				else respond(true, {
					...retry.receipt,
					replayed: true
				}, void 0, {
					cached: true,
					runId: clientRunId
				});
			});
			return false;
		}
	}
	if (stopCommand) {
		if (sessionRoutingChanged(cfg)) {
			respondChatSessionRoutingChanged(respond);
			return false;
		}
		const stopStorePath = session.readSource?.path ?? storePath;
		const guard = {};
		const assertCurrent = () => {
			if (guard.failure) throw guard.failure.error;
			try {
				params.assertCurrent?.();
				if (request.p.queueMode !== "steer" && session.expectedLeafEntryId !== void 0) assertExpectedLeafActive({
					canonicalKey: sessionKey,
					storePath: stopStorePath,
					entry: loadExactSessionEntryCandidates({
						...session.readSource ? { readSource: session.readSource } : {
							storePath: stopStorePath,
							agentId: session.agentId
						},
						sessionKeys: [sessionKey],
						readOnly: true
					})[0]?.entry
				}, session.agentId, session.expectedLeafEntryId, session.requestedSessionId);
			} catch (error) {
				guard.failure = { error };
				throw error;
			}
		};
		let res;
		try {
			assertCurrent();
			res = await abortChatRunsForSessionKeyWithPartials({
				context,
				ops: createChatAbortOps(context),
				sessionKey,
				sessionKeyAliases: sessionKey === rawSessionKey ? void 0 : [rawSessionKey],
				agentId: selectedAgent.agentId,
				sessionId: entry?.sessionId,
				session: {
					ok: true,
					value: {
						cfg,
						storePath: stopStorePath,
						entry,
						canonicalKey: sessionKey,
						agentId: session.agentId
					}
				},
				defaultAgentId: tryResolveSessionCompatibilityOwnerAgentId(cfg, sessionKey),
				abortOrigin: "stop-command",
				stopReason: "stop",
				requester: resolveChatAbortRequester(client),
				assertCurrent,
				cascadeDescendants: true
			});
			if (guard.failure) throw abortedPartialPersistenceError(guard.failure.error, res.warning);
		} catch (error) {
			const admissionError = guard.failure ? guard.failure.error : error;
			if (admissionError instanceof SessionMutationAuthorizationChangedError) throw error instanceof SessionMutationAuthorizationChangedError ? error : admissionError;
			respondChatSendAdmissionError(admissionError, (ok, payload, failure) => {
				respond(ok, payload, failure && error instanceof Error && error.cause === admissionError ? {
					...failure,
					message: error.message
				} : failure);
			});
			return false;
		}
		const error = res.unauthorized ? errorShape(ErrorCodes.INVALID_REQUEST, "unauthorized") : res.error ?? descendantAbortError(res.descendants, "Session");
		if (error) {
			respond(false, void 0, withAbortedPartialPersistenceWarning(error, res.warning));
			return false;
		}
		respond(true, {
			ok: true,
			aborted: res.aborted,
			runIds: res.runIds,
			...res.warning ? { warning: res.warning } : {}
		});
		return false;
	}
	if (!retryChecked && await respondPreparedChatSendRetry(params)) return false;
	let durableEntry = entry;
	if (requiresReconciliation) {
		const { reconcileOrphanedGatewaySessionRecovery } = await import("./session-recovery-service-DRitXQlS.mjs");
		try {
			const recoveryEntry = loadGatewaySessionEntry(sessionLoadKey, sessionLoadOptions).entry;
			if (recoveryEntry) {
				const comparison = await prepareChatSendRetryComparison({
					...params,
					session: {
						...session,
						entry: recoveryEntry
					}
				});
				await reconcileOrphanedGatewaySessionRecovery({
					cfg,
					target: resolveGatewaySessionStoreTarget({
						cfg,
						key: sessionKey,
						agentId: session.agentId
					}),
					entry: recoveryEntry,
					authorizedPluginId: client?.internal?.pluginRuntimeOwnerId,
					commitGuard: () => {
						params.assertCurrent?.();
						if (sessionRoutingChanged(context.getRuntimeConfig())) throw new Error(SESSION_ROUTING_CHANGED_ERROR_REASON);
						const current = loadGatewaySessionEntry(sessionLoadKey, sessionLoadOptions);
						const conflict = resolveChatSendRequestConflict({
							...params,
							session: {
								...session,
								entry: current.entry
							}
						}, comparison);
						if (conflict) throw new Error(conflict.message);
						const workStartError = resolveSessionWorkStartError(sessionKey, current.entry, {
							allowPendingWorkspace: true,
							providerReviewAcknowledgment: request.providerReviewAcknowledgment,
							runId: session.clientRunId,
							expectedSessionId: session.requestedSessionId ?? session.backingSessionId
						});
						if (workStartError) throw new Error(workStartError);
						if (request.p.queueMode !== "steer" && session.expectedLeafEntryId !== void 0) assertExpectedLeafActive(current, session.agentId, session.expectedLeafEntryId, session.requestedSessionId);
						captureAdmittedChatSendSessionSettings({
							commit: false,
							entry: current.entry,
							expectedPermissionMode: request.p.expectedPermissionMode,
							expectedToolOverrides: request.p.expectedToolOverrides
						});
					},
					workerPlacementContext: resolveSessionWorkerPlacementContext(context)
				});
			}
			durableEntry = loadGatewaySessionEntry(sessionLoadKey, sessionLoadOptions).entry;
		} catch (error) {
			if (error instanceof SessionMutationAuthorizationChangedError) throw error;
			respondChatSendAdmissionError(error, respond);
			return false;
		}
		params.assertCurrent?.();
	}
	const durableClaim = await (preparedClaim ?? resolveClaim(durableEntry, warnRecovery));
	const retrySession = {
		...session,
		entry: durableClaim.kind === "continue" ? durableClaim.entry : await withGatewaySessionEntry(sessionLoadKey, sessionLoadOptions, (current) => current.entry, cfg)
	};
	const retryParams = {
		...params,
		session: retrySession
	};
	if (request.goalOperation && await respondPreparedChatSendRetry(retryParams)) return false;
	let comparison;
	if (!request.goalOperation) try {
		const pending = prepareChatSendRetryComparison(retryParams);
		comparison = pending ? await pending : void 0;
	} catch (error) {
		if (!isSessionTranscriptProjectionUnavailableError(error)) throw error;
		respondChatSendAdmissionError(error, respond);
		return false;
	}
	const preparedGoalRetry = durableClaim.kind === "accepted" && request.goalOperation ? await prepareGoalChatSendRetry(params) : void 0;
	return consumeChatSendCurrent(params, () => {
		if (!request.goalOperation && respondChatSendRetry(retryParams, comparison)) return false;
		if (durableClaim.kind === "pending" || durableClaim.kind === "rejected") {
			respond(false, void 0, errorShape(durableClaim.kind === "pending" || durableClaim.unavailable ? ErrorCodes.UNAVAILABLE : ErrorCodes.INVALID_REQUEST, durableClaim.message, { retryable: durableClaim.kind === "pending" }));
			return false;
		}
		if (durableClaim.kind === "accepted") {
			if (request.goalOperation) {
				const retry = inspectGoalChatSendRetry({
					...params,
					durableClaimAccepted: true,
					prepared: preparedGoalRetry
				});
				if (retry.kind === "replay") respond(true, {
					...retry.receipt,
					replayed: true
				}, void 0, {
					cached: true,
					runId: clientRunId
				});
				return false;
			}
			respond(true, {
				runId: clientRunId,
				status: "ok"
			}, void 0, {
				cached: true,
				runId: clientRunId
			});
			return false;
		}
		return consumeNewDispatchDecision();
	});
}
//#endregion
//#region src/gateway/server-methods/chat-send-admission-context.ts
function prepareChatSendAdmissionContext(params) {
	const { request, session, client } = params;
	const { p, explicitOrigin, normalizedAttachments } = request;
	const { cfg, entry, sessionKey, selectedAgent, agentId, clientRunId, resolvedSessionModel } = session;
	return {
		chatSendTraceAttributes: {
			runId: clientRunId,
			sessionKey,
			agentId: selectedAgent.agentId ?? agentId,
			provider: resolvedSessionModel.provider,
			model: resolvedSessionModel.model,
			hasAttachments: normalizedAttachments.length > 0,
			hasExplicitOrigin: explicitOrigin !== void 0,
			hasConnectedClient: client?.connect !== void 0
		},
		originatingRoute: resolveChatSendOriginatingRoute({
			client: request.clientInfo,
			deliver: p.deliver,
			entry,
			explicitOrigin,
			hasConnectedClient: client?.connect !== void 0,
			mainKey: cfg.session?.mainKey,
			sessionKey
		})
	};
}
function assertChatSendSessionTargetOrRespond(params) {
	try {
		params.session.assertSessionTargetCurrent();
		return true;
	} catch (error) {
		params.cleanup();
		respondChatSendAdmissionError(error, params.respond);
		return false;
	}
}
//#endregion
//#region src/gateway/server-methods/chat-send-session-binding.ts
function bindChatSendPreparedSession(params) {
	const { sessionBinding } = params;
	return (binding) => {
		if (binding.sessionKey !== params.sessionKey) return;
		if (params.chatAbortControllers.get(params.clientRunId) !== sessionBinding || params.lifecycleGeneration !== getAgentEventLifecycleGeneration() || !params.admission.isActive() || !isChatAbortControllerEntryAbortable(sessionBinding) || sessionBinding.registrationCleanupRequested || sessionBinding.projectSessionActive === false && !params.progressRefresh || sessionBinding.projectSessionTerminalPending || sessionBinding.projectSessionTerminalPersisted) throw createAbortError("chat session preparation no longer owns its admission");
		adoptExecRequestSession({
			runId: params.clientRunId,
			previousSessionId: sessionBinding.sessionId,
			sessionId: binding.sessionId
		});
		sessionBinding.sessionId = binding.sessionId;
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-session.ts
function chatSendPreparationConfig(cfg, agentId, entry, request, sessionKey) {
	const defaults = cfg.agents?.defaults;
	const agent = resolveAgentEntry(cfg, agentId);
	const selected = resolveSessionModelRef(cfg, entry, agentId);
	const modelRefs = [selected, ...(modelFallbackOverrideFromAvailability(resolveModelFallbackAvailability({
		cfg,
		agentId,
		sessionKey,
		hasSessionModelOverride: Boolean(entry?.modelOverride),
		modelOverrideSource: entry?.modelOverrideSource === "default" ? void 0 : entry?.modelOverrideSource,
		modelSelectionLocked: entry?.modelSelectionLocked
	})) ?? []).flatMap((model) => {
		const parsed = parseModelRef(model, selected.provider);
		return parsed ? [parsed] : [];
	})];
	const providers = Object.fromEntries([...new Set(modelRefs.map(({ provider }) => provider))].map((id) => {
		const provider = findNormalizedProviderValue(cfg.models?.providers, id);
		return [id, provider ? {
			...provider,
			models: provider.models?.filter(({ id: model }) => modelRefs.some((ref) => ref.provider === id && ref.model === model))
		} : void 0];
	}));
	const channels = [...new Set([
		"webchat",
		request?.explicitOrigin?.originatingChannel,
		sessionDeliveryChannel(entry)
	].filter((channel) => Boolean(channel)))];
	return {
		defaultModel: defaults?.model,
		agentModel: agent?.model,
		defaultModels: defaults?.models,
		agentModels: agent?.models,
		defaultModelPolicy: defaults?.modelPolicy,
		agentModelPolicy: agent?.modelPolicy,
		runtime: agent?.runtime,
		models: {
			mode: cfg.models?.mode,
			providers
		},
		auth: cfg.auth,
		plugins: cfg.plugins,
		workspace: agent?.workspace ?? defaults?.workspace,
		agentDir: agent?.agentDir,
		timeoutSeconds: defaults?.timeoutSeconds,
		defaultSandbox: defaults?.sandbox,
		agentSandbox: agent?.sandbox,
		tools: cfg.tools,
		agentTools: agent?.tools,
		channels: {
			defaults: cfg.channels?.defaults,
			selected: Object.fromEntries(channels.map((channel) => [channel, cfg.channels?.[channel]]))
		},
		roles: cfg.gateway?.roles,
		nodeCommands: cfg.gateway?.nodes?.commands,
		commands: cfg.commands,
		sendPolicy: cfg.session?.sendPolicy,
		reset: cfg.session?.reset,
		resetByType: cfg.session?.resetByType,
		resetByChannel: cfg.session?.resetByChannel
	};
}
async function prepareChatSendSessionEntry(params) {
	const { cfg, client, agentId, getRuntimeConfig } = params;
	const creationError = authorizeGatewaySessionCreation({
		cfg,
		client,
		agentId
	});
	if (creationError) throw new Error(creationError.message);
	const creation = await prepareSkillLibrarySessionCreation(client, getRuntimeConfig, resolveOperatorSessionCreation(client));
	const assertSkillSelection = () => assertPreparedSkillLibrarySelection(creation.skillLibrarySelections);
	const createdAt = Date.now();
	const sessionId = randomUUID();
	return {
		entry: {
			...buildSessionCreationStamp({
				...creation,
				sandbox: resolveCreatorSandbox(cfg, creation),
				now: createdAt
			}),
			sessionId,
			lifecycleRevision: randomUUID(),
			updatedAt: createdAt,
			sessionStartedAt: createdAt,
			lastInteractionAt: createdAt,
			chatType: "direct"
		},
		assertSkillSelection
	};
}
async function loadChatSendSessionContext(params) {
	const { request, context } = params;
	const { p, explicitOrigin, normalizedAttachments } = request;
	const rawSessionKey = p.sessionKey;
	if (!rawSessionKey.trim()) return {
		ok: false,
		error: "sessionKey must not be blank"
	};
	const agentIdOverride = normalizeOptionalString(p.agentId);
	const clientRunId = p.idempotencyKey;
	const pendingChatSendKey = pendingChatSendDedupeKey(clientRunId);
	const runtimeConfig = context.getRuntimeConfig();
	const requestedAgent = resolveRequestedSessionAgentId(runtimeConfig, rawSessionKey, agentIdOverride);
	if (!requestedAgent.ok) return {
		ok: false,
		error: requestedAgent.error
	};
	const requestedAgentId = requestedAgent.agentId;
	const sessionLoadKey = resolveChatSendSessionKey(runtimeConfig, rawSessionKey, requestedAgentId);
	const sessionLoadOptions = { agentId: requestedAgentId };
	const assertRoutingCurrent = captureSessionMutationRouting(runtimeConfig);
	const assertConfigCurrent = () => assertRoutingCurrent(context.getRuntimeConfig());
	const sessionLoadStartedAtMs = performance.now();
	const sessionLoadResult = await measureDiagnosticsTimelineSpan("gateway.chat_send.load_session", () => request.stopCommand ? loadGatewaySessionEntry(sessionLoadKey, sessionLoadOptions, runtimeConfig) : withGatewaySessionEntry(sessionLoadKey, sessionLoadOptions, (entry) => entry, runtimeConfig, assertConfigCurrent), {
		phase: "agent-turn",
		attributes: {
			runId: clientRunId,
			hasAttachments: normalizedAttachments.length > 0,
			hasExplicitOrigin: explicitOrigin !== void 0
		}
	});
	assertConfigCurrent();
	const preparationFor = (config) => chatSendPreparationConfig(config, requestedAgentId, sessionLoadResult.entry, request, sessionLoadKey);
	if (!isDeepStrictEqual(preparationFor(runtimeConfig), preparationFor(context.getRuntimeConfig()))) throw new Error("Session preparation changed; retry.");
	const sessionLoadMs = roundedChatSendTimingMs(performance.now() - sessionLoadStartedAtMs);
	const { cfg, agentId, storePath, entry, canonicalKey: sessionKey, legacyKey } = sessionLoadResult;
	const expectedSessionRoutingContract = normalizeOptionalString(p.expectedSessionRoutingContract);
	const expectedLeafEntryId = p.expectedLeafEntryId === null ? null : normalizeOptionalString(p.expectedLeafEntryId);
	const sessionRoutingChanged = (candidateConfig) => expectedSessionRoutingContract !== void 0 && expectedSessionRoutingContract.toLowerCase() !== resolveSessionRoutingContract(candidateConfig);
	return {
		ok: true,
		value: {
			rawSessionKey,
			sessionLoadKey,
			clientRunId,
			pendingChatSendKey,
			sessionLoadOptions,
			sessionLoadMs,
			cfg,
			agentId,
			selectedAgent: requestedAgent,
			...request.explicitOrigin ? { preparationOrigin: request.explicitOrigin } : {},
			storePath,
			...sessionLoadResult.readSource ? { readSource: sessionLoadResult.readSource } : {},
			...sessionLoadResult.capturedReadSource ? { capturedReadSource: sessionLoadResult.capturedReadSource } : {},
			...sessionLoadResult.capturedReadSources ? { capturedReadSources: sessionLoadResult.capturedReadSources } : {},
			entry,
			sessionKey,
			legacyKey,
			sessionRoutingChanged,
			expectedLeafEntryId,
			agentIdOverride,
			requestedAgentId
		}
	};
}
/** Load and validate the session/model facts shared by later admission and dispatch phases. */
async function prepareChatSendSession(params) {
	const loaded = await loadChatSendSessionContext(params);
	if (!loaded.ok) return loaded;
	const loadedValue = loaded.value;
	const { request, client } = params;
	const { p, explicitOrigin, normalizedAttachments, turnKind, rawMessage } = request;
	const { cfg, agentId, sessionKey, entry, legacyKey } = loadedValue;
	if (isIncognitoSessionKey(sessionKey) && !entry) return {
		ok: false,
		error: `Incognito session "${sessionKey}" was not found.`
	};
	const missingHarnessSessionError = resolveMissingAgentHarnessSessionError(sessionKey, entry);
	if (missingHarnessSessionError) return {
		ok: false,
		error: missingHarnessSessionError
	};
	const deletedAgent = prepareDeletedAgentSessionCheck({
		cfg,
		sessionKey,
		entry,
		acpMetadataSessionKey: legacyKey,
		assertCurrent: params.assertCurrent
	});
	const deletedAgentId = deletedAgent instanceof Promise ? await deletedAgent : deletedAgent;
	if (deletedAgent instanceof Promise) params.assertCurrent?.();
	if (deletedAgentId !== null) return {
		ok: false,
		error: `Agent "${deletedAgentId}" no longer exists in configuration`
	};
	const requestedSessionId = normalizeOptionalString(p.sessionId);
	const backingSessionId = entry?.sessionId ?? requestedSessionId;
	if (!entry) {
		const creationError = authorizeGatewaySessionCreation({
			cfg,
			client,
			agentId
		});
		if (creationError) return {
			ok: false,
			error: creationError
		};
	}
	const resolvedSessionModel = resolveSessionModelRef(cfg, entry, agentId);
	const resolvedSessionAuthProvider = resolveProviderIdForAuth(resolvedSessionModel.provider, { config: cfg });
	const timeoutMs = resolveAgentTimeoutMs({
		cfg,
		overrideMs: p.timeoutMs
	});
	const now = Date.now();
	const restartSafeRequest = await createRestartSafeChatRequest({
		goalRequestFingerprint: request.goalOperation?.requestFingerprint,
		cfg,
		eligible: (isBrowserOperatorUiClient(request.clientInfo) || params.isDirectExternalUser === true) && turnKind === "main" && normalizedAttachments.length === 0 && !request.reconnectResumeRequested && explicitOrigin === void 0 && p.deliver !== true && p.thinking === void 0 && p.fastMode === void 0 && p.fastAutoOnSeconds === void 0 && p.timeoutMs === void 0 && request.systemInputProvenance === void 0 && request.systemProvenanceReceipt === void 0 && !request.suppressCommandInterpretation,
		message: rawMessage,
		mentions: p.mentions,
		senderIsOwner: hasGatewayAdminScope(client)
	});
	return {
		ok: true,
		value: {
			...loadedValue,
			requestedSessionId,
			backingSessionId,
			resolvedSessionModel,
			resolvedSessionAuthProvider,
			timeoutMs,
			now,
			restartSafeRequest
		}
	};
}
function qualifyChatSendSession(loaded) {
	const qualified = prepareQualifiedSessionEntryTarget({
		...loaded,
		canonicalKey: loaded.sessionKey,
		requestedKey: loaded.sessionLoadKey,
		storeKey: loaded.legacyKey ?? loaded.sessionKey,
		readSource: loaded.capturedReadSource
	}, loaded.capturedReadSources);
	return {
		...loaded,
		sessionTarget: qualified.target,
		assertSessionTargetCurrent: qualified.assertCurrent,
		releaseSessionTarget: qualified.release,
		activeRunScopeKey: qualified.target.canonicalKey,
		readSource: qualified.target.readSource
	};
}
/** Validate a worker-prepared admission row against the qualified session source. */
function assertCurrentChatSendSession(session, latest) {
	if (session.sessionRoutingChanged(latest.cfg)) throw new Error(SESSION_ROUTING_CHANGED_ERROR_REASON);
	if (latest.agentId !== session.sessionTarget.agentId || (latest.legacyKey ?? latest.canonicalKey) !== session.sessionTarget.storeKey || !isDeepStrictEqual(latest.capturedReadSource, session.sessionTarget.readSource)) throw new Error("Session storage changed while starting work. Retry.");
	session.assertSessionTargetCurrent();
}
function withCurrentChatSendSession(params) {
	const { session } = params;
	const assertRoutingCurrent = captureSessionMutationRouting(session.cfg);
	const preparationRequest = { explicitOrigin: session.preparationOrigin };
	const preparationConfig = chatSendPreparationConfig(session.cfg, session.agentId, session.entry, preparationRequest, session.sessionKey);
	const assertConfigCurrent = () => {
		const currentConfig = params.getRuntimeConfig();
		assertRoutingCurrent(currentConfig);
		if (session.sessionRoutingChanged(currentConfig)) throw new Error(SESSION_ROUTING_CHANGED_ERROR_REASON);
		if (!isDeepStrictEqual(preparationConfig, chatSendPreparationConfig(currentConfig, session.agentId, session.entry, preparationRequest, session.sessionKey))) throw new Error("Session preparation changed; retry.");
	};
	const consume = (latest, membership, assertSourceCurrent) => {
		assertCurrentChatSendSession(session, latest);
		return params.consume(latest, membership, assertSourceCurrent);
	};
	if (isIncognitoSessionKey(session.sessionKey)) return withGatewaySessionEntry(session.sessionLoadKey, {
		...session.sessionLoadOptions,
		includeMembership: params.includeMembership
	}, consume, session.cfg, assertConfigCurrent);
	return withQualifiedGatewaySessionEntry({
		cfg: session.cfg,
		target: session.sessionTarget,
		logicalStorePath: session.storePath,
		includeMembership: params.includeMembership,
		consume,
		assertConfigCurrent
	});
}
/** Refuse before send admission so confirmation can retain the unsent composer. */
async function prepareChatSendNativeRuntimeRestriction(params) {
	const { request, session, client, context } = params;
	const { entry, cfg, agentId, sessionKey, resolvedSessionModel } = session;
	if (request.turnKind !== "main" || request.stopCommand || !entry && session.requestedSessionId || !request.suppressCommandInterpretation && resolveTextCommand(request.inboundMessage, cfg)) return;
	const runtime = resolveEffectiveAgentRuntime({
		cfg,
		agentId,
		sessionKey,
		sessionEntry: entry,
		provider: resolvedSessionModel.provider,
		modelId: resolvedSessionModel.model
	});
	if (runtime === "openclaw") return;
	const harness = getRegisteredAgentHarness(runtime)?.harness;
	if (!harness || harness.executionEnvironment !== "host-only") return;
	const restrictionFor = (config, selectedEntry, model, persistedEntry) => resolveSessionNativeRuntimeRestriction({
		operation: "send",
		cfg: config,
		agentId,
		sessionKey,
		entry: selectedEntry,
		persistedEntry,
		harness,
		provider: model.provider,
		modelId: model.model,
		callerCanConsent: hasGatewayAdminScope(client)
	});
	const creation = resolveOperatorSessionCreation(client);
	const restriction = restrictionFor(cfg, entry ?? buildSessionCreationStamp({
		...creation,
		sandbox: resolveCreatorSandbox(cfg, creation),
		now: session.now
	}), resolvedSessionModel, entry);
	const details = readAgentRuntimeRestrictionErrorDetails(restriction?.details);
	if (entry || !restriction || !hasGatewayAdminScope(client) || !details || details.reason === "sandbox-required" || details.reason === "remote-execution") return restriction;
	const [{ loadReplySessionInitializationSnapshot, commitReplySessionInitialization }, { recordSessionCreated }] = await Promise.all([import("./session-accessor.reset-DvBO4Lnq.mjs"), import("./session-created-BIq2QVB6.mjs")]);
	await (params.assertCurrentAsync ? params.assertCurrentAsync() : params.assertCurrent?.());
	const scope = {
		agentId,
		sessionKey,
		storePath: session.storePath
	};
	const snapshot = await loadReplySessionInitializationSnapshot(scope);
	await (params.assertCurrentAsync ? params.assertCurrentAsync() : params.assertCurrent?.());
	const sessionChanged = () => errorShape(ErrorCodes.INVALID_REQUEST, "Session changed before native confirmation. Retry.");
	if (snapshot.currentEntry) return sessionChanged();
	const prepared = await prepareChatSendSessionEntry({
		cfg,
		client,
		agentId,
		getRuntimeConfig: context.getRuntimeConfig
	});
	const committed = await commitReplySessionInitialization({
		...scope,
		activeSessionKey: sessionKey,
		expectedRevision: snapshot.revision,
		sessionEntry: prepared.entry,
		commitGuard: () => {
			params.assertCurrent?.();
			session.assertSessionTargetCurrent();
			prepared.assertSkillSelection();
			const currentConfig = context.getRuntimeConfig();
			const current = loadGatewaySessionEntry(session.sessionLoadKey, session.sessionLoadOptions);
			const currentCreation = resolveOperatorSessionCreation(client);
			const currentModel = resolveSessionModelRef(currentConfig, void 0, agentId);
			const creationError = authorizeGatewaySessionCreation({
				cfg: currentConfig,
				client,
				agentId
			});
			const currentRestriction = readAgentRuntimeRestrictionErrorDetails(restrictionFor(currentConfig, prepared.entry, currentModel)?.details);
			if (creationError || !hasGatewayAdminScope(client) || current.entry || current.storePath !== session.storePath || current.canonicalKey !== sessionKey || session.sessionRoutingChanged(currentConfig) || currentCreation.actor?.id !== prepared.entry.createdActor?.id || resolveCreatorSandbox(currentConfig, currentCreation) !== prepared.entry.sandbox || currentModel.provider !== resolvedSessionModel.provider || currentModel.model !== resolvedSessionModel.model || currentRestriction?.reason !== details.reason || resolveEffectiveAgentRuntime({
				cfg: currentConfig,
				agentId,
				sessionKey,
				provider: currentModel.provider,
				modelId: currentModel.model
			}) !== runtime) throw new Error(creationError?.message ?? "Native session creation changed before commit.");
		}
	});
	if (!committed.ok) return sessionChanged();
	await recordSessionCreated(cfg, {
		agentId,
		sessionKey,
		entry: committed.sessionEntry
	});
	emitSessionsChanged(context, {
		agentId,
		sessionKey,
		reason: "create"
	});
	return restrictionFor(context.getRuntimeConfig(), committed.sessionEntry, resolvedSessionModel, committed.sessionEntry);
}
//#endregion
//#region src/gateway/server-methods/chat-send-work-admission.ts
/** Preparation returns facts; the caller consumes current retry ownership before reserving. */
function prepareChatSendAdmissionRetry(params) {
	try {
		return prepareChatSendRetryComparison(params)?.catch((error) => ({ error }));
	} catch (error) {
		return { error };
	}
}
function consumeChatSendAdmissionRetry(params, prepared) {
	try {
		if (prepared && "error" in prepared) throw prepared.error;
		if (readPreRegisteredRun({
			key: params.session.pendingChatSendKey,
			entry: params.context.dedupe.get(params.session.pendingChatSendKey),
			keyPrefix: "pending-chat:"
		})?.payload.goalFingerprint) {
			params.respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "Run ID is reserved by a Goal request; use a new ID."));
			return false;
		}
		return !params.request.goalOperation && respondChatSendRetry(params, prepared) ? false : prepared;
	} catch (error) {
		if (error instanceof SessionMutationAuthorizationChangedError) throw error;
		respondChatSendAdmissionError(error, params.respond);
		return false;
	}
}
/** An awaited retry comparison must return to current rows before admission can consume it. */
async function withCurrentChatSendRetry(params, ownPendingAttemptId, consume) {
	const withCurrent = (read) => withCurrentChatSendSession({
		session: params.session,
		getRuntimeConfig: params.context.getRuntimeConfig,
		includeMembership: Boolean(params.withPreparedCurrent),
		consume: (latest, membership, assertSourceCurrent) => {
			const consumeCurrent = () => read(latest);
			if (params.withPreparedCurrent) return params.withPreparedCurrent({
				agentId: latest.agentId,
				storePath: latest.storePath,
				sessionKey: latest.canonicalKey,
				entry: latest.entry,
				readSource: latest.capturedReadSource,
				members: membership.get(latest.legacyKey ?? latest.canonicalKey) ?? []
			}, consumeCurrent, assertSourceCurrent);
			assertSourceCurrent();
			return consumeCurrent();
		}
	});
	const pending = await withCurrent((session) => {
		const comparison = prepareChatSendRetryComparison({
			...params,
			session: {
				...params.session,
				entry: session.entry
			}
		}, ownPendingAttemptId);
		if (comparison) return observeChatSendWork(comparison);
		consume(session, void 0);
	});
	if (pending) {
		const comparison = await pending();
		await withCurrent((session) => consume(session, comparison));
	}
}
function respondChatSendWorkAdmissionFailure(params, error, comparison) {
	if (error instanceof ExpectedProfileMismatchError) throw error;
	const { context, respond, session } = params;
	const { clientRunId } = session;
	try {
		const conflict = resolveChatSendRequestConflict(params, comparison);
		if (conflict) {
			respond(false, void 0, conflict);
			return;
		}
	} catch {}
	const aborted = context.chatRunState.hasAbortMarker(clientRunId) && readChatSendDedupeResponse(context.dedupe, clientRunId);
	if (aborted) {
		respond(aborted.ok, aborted.payload, aborted.error, {
			cached: true,
			runId: clientRunId
		});
		return;
	}
	respondChatSendAdmissionError(error, respond);
}
/** New input is checked only after the chat owner has reconciled prior receipts. */
function admitChatSendUploads({ params, client, context, respond }) {
	try {
		const assertClientUploadAllowed = captureGatewayClientUploadCommitGuard({
			method: "chat.send",
			requestParams: params,
			client,
			context
		});
		assertClientUploadAllowed?.();
		return {
			ok: true,
			assertClientUploadAllowed
		};
	} catch (error) {
		if (!(error instanceof SessionMutationAuthorizationChangedError)) throw error;
		respond(false, void 0, error.error);
		return { ok: false };
	}
}
/** Caller and physical target custody end together when admitted work settles. */
function releaseChatSendCallerAuthority(params) {
	try {
		params.operator.release?.();
	} finally {
		try {
			if (params.request.providerReviewAcknowledgment) retireProviderReviewAcknowledgment(params.request.providerReviewAcknowledgment);
		} finally {
			params.session.releaseSessionTarget();
		}
	}
}
/** Observe started work before the retained read releases; consuming still rethrows its error. */
function observeChatSendWork(work) {
	work.catch(() => {});
	return () => work;
}
/** Interrupt the captured run, or competing admissions, without ever targeting this admission. */
function interruptChatSendWork(params) {
	params.signal.throwIfAborted();
	if (params.target) return interruptReplyRunTarget(params.target, REPLY_RUN_IDLE_SETTLE_TIMEOUT_MS).then(({ settled }) => ({
		interrupted: true,
		settled
	}));
	return params.admission.run(async () => {
		if (!isCompetingSessionWorkAdmissionActive(params.storePath, params.identities)) return {
			interrupted: false,
			settled: true
		};
		return {
			interrupted: true,
			settled: await interruptSessionWorkAdmissions({
				scope: params.storePath,
				identities: params.identities,
				timeoutMs: REPLY_RUN_IDLE_SETTLE_TIMEOUT_MS
			})
		};
	});
}
/** Queued and collected turns share the original session and caller admission until settlement. */
function createChatSendWorkAdmission(params) {
	let references = 1;
	let admittedSource = params.terminal?.target.readSource;
	let admittedLifecycleRevision = params.terminal?.lifecycleRevision;
	let finishPendingInput;
	const releaseAdmission = () => {
		try {
			params.admission.release();
		} finally {
			try {
				params.releaseCallerAuthority?.();
			} finally {
				params.releaseGatewayRootContinuation?.();
			}
		}
	};
	const warnCleanupFailure = (error) => {
		params.logGateway.warn(`Failed to finish pending chat input: ${formatForLog(error)}`);
	};
	const release = () => {
		if (references === 0) return;
		references -= 1;
		if (references !== 0) return;
		let pending = void 0;
		try {
			pending = finishPendingInput?.();
		} catch (error) {
			warnCleanupFailure(error);
		}
		if (pending) pending.then(releaseAdmission, (error) => {
			warnCleanupFailure(error);
			releaseAdmission();
		});
		else releaseAdmission();
	};
	const hold = () => {
		let released = false;
		return () => {
			if (released) return;
			released = true;
			release();
		};
	};
	const retain = () => {
		if (references === 0) throw new Error("cannot retain a released chat work admission");
		references += 1;
		return hold();
	};
	const retainSettlement = (assertOwnerCurrent) => {
		const releaseSettlement = retain();
		let active = true;
		return {
			assertCurrent() {
				if (!active || references === 0) throw new Error("Chat settlement admission was released");
				assertOwnerCurrent();
			},
			release() {
				active = false;
				releaseSettlement();
			}
		};
	};
	const retainTerminalSettlement = () => {
		const terminal = params.terminal;
		if (!terminal || !admittedSource) return;
		return {
			...retainSettlement(() => {
				const registered = terminal.currentRegistration();
				if (!terminal.isActive() || registered && registered !== terminal.sessionBinding) throw new Error("Chat terminal settlement no longer owns its admission");
			}),
			expectedLifecycleRevision: admittedLifecycleRevision,
			target: {
				agentId: terminal.target.agentId,
				storePath: terminal.storePath,
				readSource: admittedSource,
				target: {
					canonicalKey: terminal.target.canonicalKey,
					storeKeys: [...terminal.target.storeKeys]
				}
			}
		};
	};
	return {
		isActive: () => references > 0,
		release: hold(),
		retain,
		async settleTerminal(state) {
			const terminal = params.terminal;
			const settlement = retainTerminalSettlement();
			if (!terminal || !settlement) return false;
			try {
				return await terminalizeRestartSafeChatAdmission({
					...state,
					...settlement,
					admittedSessionId: terminal.admittedSessionId,
					clientRunId: terminal.runId
				});
			} finally {
				settlement.release();
			}
		},
		withInputCommitPublication(run) {
			const terminal = params.terminal;
			if (!terminal) throw new Error("Chat input publication requires its original admission target");
			return withSessionTranscriptSourcePublication({
				agentId: terminal.target.agentId,
				sessionId: terminal.sessionBinding.sessionId,
				sessionKey: terminal.target.storeKey,
				storePath: terminal.target.storePath
			}, (source, committedEntry) => {
				if (admittedSource && (admittedSource.agentId !== source.agentId || admittedSource.path !== source.path || admittedSource.databaseIdentity !== source.databaseIdentity || admittedSource.databaseBirthtime !== source.databaseBirthtime)) throw new Error("Committed chat input changed its admitted physical source");
				admittedSource ??= source;
				admittedLifecycleRevision = committedEntry.lifecycleRevision;
			}, run);
		},
		setPendingInputCleanup: (finish) => {
			finishPendingInput = finish;
		}
	};
}
/** Rechecked inside the session writer barrier before exclusive input is admitted. */
function assertChatSendExclusiveAdmission(request, session) {
	if (!request.goalOperation && !request.providerReviewAcknowledgment) return;
	const { storePath, sessionKey, backingSessionId, activeRunScopeKey } = session;
	if (isCompetingSessionWorkAdmissionActive(storePath, [sessionKey, backingSessionId]) || hasPendingFollowupQueueWork([
		sessionKey,
		backingSessionId,
		activeRunScopeKey
	]) || replyRunRegistry.isActive(activeRunScopeKey)) throw new Error(request.providerReviewAcknowledgment ? "The session still has active work. Review its status before continuing." : "goal-session-busy");
}
/** Goal and initial-session policy are revalidated in the same input writer barrier. */
function createChatSendGoalCommitGuard(params) {
	const { admission, session, client, context, sessionMutationAuthorization, sessionMutationCommitGuard } = params;
	const routingPredicate = admission.initialSessionEntry ? {
		config: structuredClone(context.getRuntimeConfig()),
		key: session.sessionLoadKey,
		agentId: session.sessionLoadOptions.agentId,
		storePath: session.storePath,
		canonicalKey: session.sessionKey
	} : void 0;
	const assertCurrent = () => {
		sessionMutationCommitGuard?.();
		sessionMutationAuthorization?.assertCurrent();
		const currentConfig = context.getRuntimeConfig();
		const initialEntry = admission.initialSessionEntry;
		if (initialEntry) {
			admission.assertInitialSkillSelection?.();
			if (!isDeepStrictEqual(currentConfig, routingPredicate?.config)) throw new Error("Session routing changed before Goal admission; refresh and retry.");
			const creationError = authorizeGatewaySessionCreation({
				cfg: currentConfig,
				client,
				agentId: session.agentId
			});
			if (creationError) throw new SessionMutationAuthorizationChangedError(creationError);
			const creation = resolveOperatorSessionCreation(client);
			if (creation.actor?.id !== initialEntry.createdActor?.id || resolveCreatorSandbox(currentConfig, creation) !== initialEntry.sandbox) throw new Error("Session creation policy changed before Goal admission; retry.");
		}
		if (admission.activeRunAbort.controller.signal.aborted || admission.lifecycleGeneration !== getAgentEventLifecycleGeneration() || session.sessionRoutingChanged(currentConfig)) throw new Error("Goal admission changed before commit; refresh and retry.");
	};
	return {
		assertCurrent,
		routingPredicate
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-admission.ts
/** Reserve the session lifecycle and register the abortable run before attachment work. */
async function admitChatSend(params) {
	const { request, session, respond, context, client } = params;
	const { p, turnKind } = request;
	const requestIdentity = request.goalOperation?.requestFingerprint ?? request.requestIdentity;
	const progressRefresh = isProgressCardRefreshInputProvenance(request.systemInputProvenance);
	const { clientRunId, storePath, entry, sessionKey, selectedAgent, requestedSessionId, backingSessionId, agentId, resolvedSessionModel, resolvedSessionAuthProvider, activeRunScopeKey, timeoutMs, now, restartSafeRequest, expectedLeafEntryId } = session;
	const cachedMeta = {
		cached: true,
		runId: clientRunId
	};
	const assertSessionTargetCurrent = session.assertSessionTargetCurrent;
	const { chatSendTraceAttributes, originatingRoute } = prepareChatSendAdmissionContext(params);
	const lifecycleGeneration = getAgentEventLifecycleGeneration();
	const pendingAttemptId = randomUUID();
	const pendingReservation = createPendingChatSendReservationAccess({
		context,
		client,
		attemptId: pendingAttemptId,
		request,
		session
	});
	const preparedGoalRetry = request.goalOperation ? await prepareGoalChatSendRetry(params) : void 0;
	const pendingRetry = prepareChatSendAdmissionRetry(params);
	const preparedRetry = pendingRetry instanceof Promise ? await pendingRetry : pendingRetry;
	const reserve = () => {
		params.assertCurrent?.();
		assertSessionTargetCurrent();
		const goalRetry = inspectGoalChatSendRetry({
			...params,
			prepared: preparedGoalRetry
		});
		if (goalRetry.kind !== "new") {
			if (goalRetry.kind === "replay") respond(true, {
				...goalRetry.receipt,
				replayed: true
			}, void 0, cachedMeta);
			return;
		}
		const retryComparison = consumeChatSendAdmissionRetry(params, preparedRetry);
		if (retryComparison === false) return;
		const uploadAdmission = admitChatSendUploads({
			params: p,
			client,
			context,
			respond
		});
		if (!uploadAdmission.ok) return;
		params.assertCurrent?.();
		pendingReservation.reserve();
		return {
			retryComparison,
			uploadAdmission
		};
	};
	const reserved = await consumeChatSendCurrent(params, reserve).catch((error) => {
		pendingReservation.clear();
		throw error;
	});
	if (!reserved) return { ok: false };
	let retryComparison = reserved.retryComparison;
	const uploadAdmission = reserved.uploadAdmission;
	const abortPendingChatSend = (stopReason) => writePreRegisteredChatAbort({
		context,
		runId: clientRunId,
		stopReason,
		attemptId: pendingAttemptId,
		requestIdentity
	});
	let admittedSessionId = backingSessionId ?? clientRunId;
	let expectedActiveReplyOperation;
	let gatewayWorkAdmission;
	let admittedRunAbort;
	let restartSafeAdmission;
	let initialSessionEntry;
	let admittedSessionEntry;
	let admittedSessionSettings;
	let assertInitialSkillSelection;
	let messageInjectionTarget;
	let runInterruptTarget;
	let reservationSuperseded = false;
	let supersedingResult;
	let preparedGoalEntry;
	const placementService = context.workerSessionPlacementService;
	const commitChatWorkAdmission = async (acpMeta, preparedPlacement) => {
		if (context.workerSessionPlacementService !== placementService) throw new Error("Worker placement owner changed during chat admission; retry.");
		if (placementService && preparedPlacement?.sessionId !== admittedSessionId) return withRestartSafeChatPlacement(placementService, admittedSessionId, (prepared) => commitChatWorkAdmission(acpMeta, prepared));
		if (request.goalOperation?.action === "start" && !entry && !requestedSessionId && !preparedGoalEntry) preparedGoalEntry = await prepareChatSendSessionEntry({
			cfg: session.cfg,
			client,
			agentId,
			getRuntimeConfig: context.getRuntimeConfig
		});
		let refreshPlacement = false;
		await withCurrentChatSendRetry(params, pendingAttemptId, (latestSession, comparison) => {
			retryComparison = comparison;
			params.assertCurrent?.();
			const retainedRequestConflict = resolveChatSendRequestConflict(params, retryComparison);
			if (retainedRequestConflict) throw new Error(retainedRequestConflict.message);
			if (context.chatRunState.hasAbortMarker(clientRunId)) return;
			const currentReservation = pendingReservation.read();
			if (currentReservation && normalizeOptionalString(currentReservation.payload.attemptId) !== pendingAttemptId) {
				reservationSuperseded = true;
				return;
			}
			if (!currentReservation) {
				const terminalResult = readChatSendDedupeResponse(context.dedupe, clientRunId);
				if (terminalResult || context.chatAbortControllers.has(clientRunId)) {
					reservationSuperseded = true;
					supersedingResult = terminalResult;
					return;
				}
			}
			if (lifecycleGeneration !== getAgentEventLifecycleGeneration()) {
				abortPendingChatSend("restart");
				return;
			}
			if (!currentReservation || !isFutureDateTimestampMs(currentReservation.payload.expiresAtMs, { nowMs: Date.now() })) {
				abortPendingChatSend("timeout");
				return;
			}
			const latestEntry = latestSession.entry;
			admittedSessionEntry = latestEntry;
			const requestConflict = resolveChatSendRequestConflict({
				...params,
				session: {
					...session,
					entry: latestEntry
				}
			}, retryComparison);
			if (requestConflict) throw new Error(requestConflict.message);
			admittedSessionSettings = captureAdmittedChatSendSessionSettings({
				commit: true,
				entry: latestEntry,
				expectedPermissionMode: p.expectedPermissionMode,
				expectedToolOverrides: p.expectedToolOverrides
			});
			assertChatSendExclusiveAdmission(request, session);
			if (entry && !latestEntry) throw new Error(`Session "${sessionKey}" was deleted while starting work. Retry.`);
			messageInjectionTarget = p.queueMode === "steer" ? replyRunRegistry.resolveCurrentMessageInjectionTarget(activeRunScopeKey) : void 0;
			runInterruptTarget = p.queueMode === "interrupt" ? replyRunRegistry.resolveCurrentInterruptTarget(activeRunScopeKey) : void 0;
			if (p.queueMode !== "steer" && expectedLeafEntryId !== void 0) assertExpectedLeafActive(latestSession, agentId, expectedLeafEntryId, requestedSessionId, { allowEmptyAncestor: true });
			if (backingSessionId && latestEntry?.sessionId && latestEntry.sessionId !== backingSessionId) throw new Error(`Session "${sessionKey}" changed while starting work. Retry.`);
			const retryableClaim = isRetryableUnadoptedChatClaim(latestEntry, clientRunId);
			if (latestEntry?.restartRecoveryDeliveryRunId && latestEntry.restartRecoveryDeliverySourceRunId === clientRunId && !retryableClaim || hasRestartRecoveryTerminalRun(latestEntry, clientRunId)) {
				reservationSuperseded = true;
				supersedingResult = {
					ts: Date.now(),
					ok: true,
					payload: {
						runId: clientRunId,
						status: "ok"
					}
				};
				return;
			}
			const archivedError = resolveSessionWorkStartError(sessionKey, latestEntry, {
				allowPendingWorkspace: true,
				providerReviewAcknowledgment: request.providerReviewAcknowledgment,
				runId: clientRunId
			});
			if (archivedError) throw new Error(archivedError);
			admittedSessionId = latestEntry?.sessionId ?? backingSessionId ?? clientRunId;
			expectedActiveReplyOperation = replyRunRegistry.get(activeRunScopeKey);
			if (request.goalOperation?.action === "start" && !latestEntry && !requestedSessionId) {
				const prepared = preparedGoalEntry;
				initialSessionEntry = prepared.entry;
				assertInitialSkillSelection = prepared.assertSkillSelection;
				admittedSessionId = initialSessionEntry.sessionId;
			}
			if (context.workerSessionPlacementService !== placementService) throw new Error("Worker placement owner changed during chat admission; retry.");
			if (placementService && preparedPlacement?.sessionId !== admittedSessionId) {
				refreshPlacement = true;
				return;
			}
			preparedPlacement?.facts.assertCurrent();
			restartSafeAdmission = resolveRestartSafeChatAdmission({
				activeRunScopeKey,
				agentId,
				cfg: latestSession.cfg,
				clientRunId,
				context,
				entry: latestEntry,
				initialSessionEntry,
				lifecycleTimestamps: latestSession.lifecycleTimestamps,
				acpMeta,
				now: Date.now(),
				placement: preparedPlacement?.facts.placement,
				request: restartSafeRequest,
				requestedSessionId,
				sessionId: admittedSessionId,
				sessionKey: latestSession.canonicalKey,
				storePath: latestSession.storePath
			});
			if (request.goalOperation && !restartSafeAdmission) throw new Error("Goal start or resume requires the built-in OpenClaw runtime and an idle local session with recoverable history. This action is unavailable for native Codex and other external runtimes.");
			if (retryableClaim && !restartSafeAdmission) throw new Error("chat retry does not match its durable admission");
			admittedRunAbort = registerChatAbortController({
				chatAbortControllers: context.chatAbortControllers,
				runId: clientRunId,
				sessionId: admittedSessionId,
				sessionKey,
				agentId: selectedAgent.agentId,
				timeoutMs,
				now,
				ownerConnId: normalizeOptionalString(client?.connId),
				ownerDeviceId: normalizeOptionalString(client?.connect?.device?.id),
				providerId: resolvedSessionModel.provider,
				authProviderId: resolvedSessionAuthProvider,
				isAbortable: (active) => isReplyRunAbortableForSignal(active.controller.signal),
				resolveTerminalProducer: (active) => resolveActiveReplyRunOwnerForSignal(active.controller.signal),
				kind: "chat-send",
				turnKind,
				...progressRefresh ? {
					controlUiVisible: false,
					projectSessionActive: false
				} : {},
				lifecycleGeneration
			});
		});
		if (refreshPlacement) return commitChatWorkAdmission(acpMeta);
	};
	let retainedRequestConflict;
	try {
		gatewayWorkAdmission = await beginSessionWorkAdmission({
			scope: storePath,
			isSettling: () => admittedRunAbort?.entry?.terminalOutcomeObserved === true,
			identities: [sessionKey, backingSessionId],
			storeWriterIdentities: [sessionKey, session.sessionTarget.storeKey],
			assertAllowed: () => consumeChatSendCurrent(params, () => {
				assertSessionTargetCurrent();
				assertChatSendExclusiveAdmission(request, session);
			}),
			revalidateAllowed: async () => {
				if (!restartSafeRequest) return commitChatWorkAdmission(null);
				const latest = await withCurrentChatSendSession({
					session,
					getRuntimeConfig: context.getRuntimeConfig,
					includeMembership: false,
					consume: (current) => current
				});
				const [acpMeta] = await readAcpSessionMetaForEntries({
					cfg: latest.cfg,
					entries: [{
						agentId,
						sessionKey: latest.canonicalKey,
						entry: latest.entry
					}]
				});
				return commitChatWorkAdmission(acpMeta ?? null);
			},
			onInterrupt: (reason) => {
				const stopReason = isAgentRunRestartAbortReason(reason) ? "restart" : "rpc";
				if (!admittedRunAbort) {
					if (!context.chatRunState.hasAbortMarker(clientRunId)) abortPendingChatSend(stopReason);
				} else if (!admittedRunAbort.controller.signal.aborted) {
					if (admittedRunAbort.entry) admittedRunAbort.entry.abortStopReason = stopReason;
					admittedRunAbort.controller.abort(reason);
				}
			}
		});
		retainedRequestConflict = await consumeChatSendCurrent(params, () => resolveChatSendRequestConflict(params, retryComparison));
	} catch (err) {
		pendingReservation.clear();
		admittedRunAbort?.cleanup();
		gatewayWorkAdmission?.release();
		respondChatSendWorkAdmissionFailure(params, err, retryComparison);
		return { ok: false };
	}
	if (retainedRequestConflict) {
		pendingReservation.clear();
		admittedRunAbort?.cleanup();
		gatewayWorkAdmission.release();
		respond(false, void 0, retainedRequestConflict);
		return { ok: false };
	}
	if (admittedRunAbort?.registered && !reservationSuperseded && !readChatSendDedupeResponse(context.dedupe, clientRunId)) context.dedupe.set(`chat:${clientRunId}`, {
		ts: Date.now(),
		ok: true,
		requestIdentity
	});
	pendingReservation.clear();
	const activeRunAbort = admittedRunAbort;
	if (reservationSuperseded) {
		gatewayWorkAdmission.release();
		const supersedingCached = supersedingResult ?? readChatSendDedupeResponse(context.dedupe, clientRunId);
		if (supersedingCached) {
			respond(supersedingCached.ok, supersedingCached.payload, supersedingCached.error, cachedMeta);
			return { ok: false };
		}
		respond(true, {
			runId: clientRunId,
			status: "in_flight"
		}, void 0, cachedMeta);
		return { ok: false };
	}
	if (lifecycleGeneration !== getAgentEventLifecycleGeneration()) {
		if (activeRunAbort) {
			if (activeRunAbort.entry) activeRunAbort.entry.abortStopReason = "restart";
			activeRunAbort.controller.abort();
			activeRunAbort.cleanup();
		}
		gatewayWorkAdmission.release();
		if (!readChatSendDedupeResponse(context.dedupe, clientRunId)) abortPendingChatSend(activeRunAbort?.entry?.abortStopReason ?? "restart");
		const aborted = readChatSendDedupeResponse(context.dedupe, clientRunId);
		respond(aborted?.ok ?? true, aborted?.payload, aborted?.error, cachedMeta);
		return { ok: false };
	}
	if (!activeRunAbort) {
		gatewayWorkAdmission.release();
		const aborted = readChatSendDedupeResponse(context.dedupe, clientRunId);
		if (aborted) {
			respond(aborted.ok, aborted.payload, aborted.error, cachedMeta);
			return { ok: false };
		}
		respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, "chat run admission failed"));
		return { ok: false };
	}
	if (!activeRunAbort.registered) {
		gatewayWorkAdmission.release();
		respond(true, {
			runId: clientRunId,
			status: "in_flight"
		}, void 0, cachedMeta);
		return { ok: false };
	}
	const acquiredGatewayWorkAdmission = gatewayWorkAdmission;
	let releaseGatewayRootContinuation = () => {};
	let releaseCallerAuthority;
	let capturedOperator;
	const cleanupPreDispatchAdmission = () => {
		try {
			activeRunAbort.cleanup();
			gatewayWorkAdmission.release();
			releaseGatewayRootContinuation();
		} finally {
			releaseCallerAuthority?.();
			releaseCallerAuthority = void 0;
		}
	};
	let interruptedActiveRun = false;
	let startedWork;
	const startOwnedWork = (work) => {
		const observed = observeChatSendWork(work);
		startedWork = observed;
		return observed;
	};
	try {
		capturedOperator = await retainGatewayOperatorRun({
			...params,
			runId: clientRunId,
			entry: activeRunAbort.entry
		});
		releaseCallerAuthority = () => releaseChatSendCallerAuthority({
			operator: capturedOperator,
			request,
			session
		});
		const consumeCurrent = (consume) => consumeChatSendCurrent(params, () => {
			capturedOperator.authority?.assertCurrent();
			if (!assertChatSendSessionTargetOrRespond({
				session,
				cleanup: cleanupPreDispatchAdmission,
				respond
			})) return;
			return consume();
		});
		if (runInterruptTarget || p.queueMode === "interrupt") {
			const pending = await consumeCurrent(() => ({ interruption: startOwnedWork(interruptChatSendWork({
				target: runInterruptTarget,
				signal: activeRunAbort.controller.signal,
				admission: acquiredGatewayWorkAdmission,
				storePath,
				identities: [
					sessionKey,
					backingSessionId,
					admittedSessionId
				]
			})) }));
			if (!pending) return { ok: false };
			const interruption = await pending.interruption();
			interruptedActiveRun = interruption.interrupted;
			if (!interruption.settled) {
				cleanupPreDispatchAdmission();
				respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, "Previous run is still shutting down. Please try again in a moment.", {
					retryable: true,
					retryAfterMs: 250
				}));
				return { ok: false };
			}
		}
		const pending = await consumeCurrent(() => {
			activeRunAbort.controller.signal.throwIfAborted();
			releaseGatewayRootContinuation = retainGatewayRootWorkAdmissionContinuation() ?? (() => {});
			return { admission: params.onAdmissionOwned ? startOwnedWork(acquiredGatewayWorkAdmission.run(params.onAdmissionOwned)) : void 0 };
		});
		if (!pending) return { ok: false };
		if (pending.admission) {
			if (!await pending.admission()) {
				cleanupPreDispatchAdmission();
				return { ok: false };
			}
			if (!await consumeCurrent(() => true)) return { ok: false };
		}
	} catch (error) {
		if (startedWork) await Promise.allSettled([startedWork()]);
		cleanupPreDispatchAdmission();
		throw error;
	}
	const sessionBinding = activeRunAbort.entry;
	const onSessionPrepared = bindChatSendPreparedSession({
		chatAbortControllers: context.chatAbortControllers,
		clientRunId,
		sessionKey,
		sessionBinding,
		lifecycleGeneration,
		admission: acquiredGatewayWorkAdmission,
		progressRefresh
	});
	const retainedWork = createChatSendWorkAdmission({
		admission: acquiredGatewayWorkAdmission,
		releaseCallerAuthority,
		releaseGatewayRootContinuation,
		logGateway: context.logGateway,
		terminal: {
			target: session.sessionTarget,
			storePath,
			sessionBinding,
			admittedSessionId,
			runId: clientRunId,
			lifecycleRevision: (admittedSessionEntry ?? initialSessionEntry)?.lifecycleRevision,
			isActive: acquiredGatewayWorkAdmission.isActive,
			currentRegistration: () => context.chatAbortControllers.get(clientRunId)
		}
	});
	const { cleanup: cleanupAdmittedRun, setDiscardPreparedMedia } = createAdmittedChatSendCleanup({
		cleanupAbort: activeRunAbort.cleanup,
		releaseRetainedWork: retainedWork.release
	});
	const rejectSessionRoutingChanged = () => {
		cleanupAdmittedRun();
		clearAgentRunContext(clientRunId, lifecycleGeneration);
		respondChatSessionRoutingChanged(respond);
	};
	const finishAborted = () => finishAbortedChatSend({
		context,
		respond,
		runId: clientRunId,
		lifecycleGeneration,
		stopReason: activeRunAbort.entry?.abortStopReason,
		sessionBinding,
		cleanup: cleanupAdmittedRun
	});
	claimAgentRunContext(clientRunId, {
		agentId: selectedAgent.agentId ?? agentId,
		sessionKey,
		sessionId: admittedSessionId,
		lifecycleGeneration,
		...progressCardRefreshRunProjection(request.systemInputProvenance)
	});
	return {
		ok: true,
		value: {
			activeRunAbort,
			operatorAuthority: capturedOperator.authority,
			armOperatorRunCancellation: capturedOperator.armCancellation,
			retireOperatorRunCancellation: capturedOperator.retireCancellation,
			admittedSessionSettings,
			admittedSessionId,
			...expectedActiveReplyOperation ? { expectedActiveReplyOperation } : {},
			sessionBinding,
			onSessionPrepared,
			initialSessionEntry,
			admittedSessionEntry,
			chatSendTraceAttributes,
			assertInitialSkillSelection,
			assertSessionTargetCurrent,
			cleanupAdmittedRun,
			finishAbortedChatSend: finishAborted,
			gatewayWorkAdmission,
			lifecycleGeneration,
			interruptedActiveRun,
			messageInjectionTarget,
			originatingRoute,
			rejectSessionRoutingChanged,
			releaseSourceWorkAdmission: retainedWork.release,
			retainGatewayWorkAdmission: retainedWork.retain,
			settleTerminal: retainedWork.settleTerminal,
			withInputCommitPublication: retainedWork.withInputCommitPublication,
			setPendingInputCleanup: retainedWork.setPendingInputCleanup,
			assertClientUploadAllowed: uploadAdmission.assertClientUploadAllowed,
			assertWorkAdmissionCurrent: () => {
				const queued = context.chatQueuedTurns.get(clientRunId);
				if (!retainedWork.isActive() || !acquiredGatewayWorkAdmission.isActive() || lifecycleGeneration !== getAgentEventLifecycleGeneration() || activeRunAbort.controller.signal.aborted && !(queued?.controller === activeRunAbort.controller && queued.abortable === false)) throw new Error("Chat admission ended or was cancelled; submit a new turn.");
			},
			restartSafeAdmission,
			setDiscardAbandonedPreparedMedia: setDiscardPreparedMedia
		}
	};
}
//#endregion
//#region src/gateway/server-methods/chat-human-mentions.ts
const INVALID_MENTIONS = "Selected mentions no longer match the message. Select the people again.";
function splitsSurrogate(text, offset) {
	const before = text.charCodeAt(offset - 1);
	const after = text.charCodeAt(offset);
	return before >= 55296 && before <= 56319 && after >= 56320 && after <= 57343;
}
/** Normalize raw selected spans against the request boundary's sanitized message. */
function normalizeChatHumanMentions(text, mentions, sanitizedText) {
	if (!mentions?.length) return {
		ok: true,
		value: void 0
	};
	const leadingSpace = sanitizedText.length - sanitizedText.trimStart().length;
	const trimmed = sanitizedText.trim();
	const normalized = [];
	let previousEnd = 0;
	for (const mention of mentions) {
		const token = text.slice(mention.start, mention.end);
		if (mention.start < previousEnd || mention.end > text.length || mention.end <= mention.start + 1 || token.length > 257 || token[0] !== "@" || !token.slice(1).trim() || containsAsciiControlCharacter(token) || splitsSurrogate(text, mention.start) || splitsSurrogate(text, mention.end)) return {
			ok: false,
			error: INVALID_MENTIONS
		};
		const prefix = sanitizeChatSendMessageInput(text.slice(0, mention.start));
		const throughToken = sanitizeChatSendMessageInput(text.slice(0, mention.end));
		if (!prefix.ok || !throughToken.ok || !sanitizedText.startsWith(throughToken.message)) return {
			ok: false,
			error: INVALID_MENTIONS
		};
		const start = prefix.message.length - leadingSpace;
		const end = throughToken.message.length - leadingSpace;
		if (start < 0 || end > trimmed.length || trimmed[start] !== "@") return {
			ok: false,
			error: INVALID_MENTIONS
		};
		normalized.push({
			profileId: mention.profileId,
			start,
			end
		});
		previousEnd = mention.end;
	}
	return {
		ok: true,
		value: normalized
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-request.ts
/** Validate and normalize the wire request before session or lifecycle work begins. */
function normalizeChatSendRequest(params) {
	const chatSendReceivedAtMs = performance.now();
	const reject = (error) => ({
		ok: false,
		error
	});
	const client = params.client;
	const clientInfo = client?.connect?.client;
	const supportsTaskSuggestions = isOperatorUiClient(clientInfo) && params.client?.connect?.scopes?.includes("operator.admin") === true && hasGatewayClientCap(params.client?.connect?.caps, GATEWAY_CLIENT_CAPS.TASK_SUGGESTIONS);
	const controlUiReconnectResume = resolveControlUiReconnectResumeParams(params.params, clientInfo);
	if (!validateChatSendParams(controlUiReconnectResume.params)) return reject(`invalid chat.send params: ${formatValidationErrors(validateChatSendParams.errors)}`);
	const p = controlUiReconnectResume.params;
	const providerReview = params.providerReviewAcknowledgment ? readProviderReviewAcknowledgment(params.providerReviewAcknowledgment) : void 0;
	if (providerReview && (p.sessionId !== providerReview.target.sessionId || p.idempotencyKey !== providerReview.nextRunId || p.message !== providerReview.review.review?.continuation?.message || p.attachments?.length || p.intent || p.queueMode || p.toolBindings || p.workContext || p.systemInputProvenance || p.systemProvenanceReceipt || p.suppressCommandInterpretation !== void 0 || p.thinking !== void 0 || p.fastMode !== void 0 || p.timeoutMs !== void 0)) return reject("Provider continuation no longer matches the reviewed input.");
	const suppressCommandInterpretation = p.suppressCommandInterpretation === true;
	const explicitOriginResult = normalizeExplicitChatSendOrigin({
		originatingChannel: p.originatingChannel,
		originatingTo: p.originatingTo,
		accountId: p.originatingAccountId,
		messageThreadId: p.originatingThreadId
	});
	if (!explicitOriginResult.ok) return explicitOriginResult;
	if ((p.systemInputProvenance || p.systemProvenanceReceipt || suppressCommandInterpretation || explicitOriginResult.value) && !params.trustedSystemInput && !hasGatewayAdminScope(params.client)) return reject(p.systemInputProvenance || p.systemProvenanceReceipt || suppressCommandInterpretation ? "system provenance fields require admin scope" : "originating route fields require admin scope");
	const sanitizedMessageResult = sanitizeChatSendMessageInput(p.message);
	if (!sanitizedMessageResult.ok) return sanitizedMessageResult;
	if (p.intent && (!p.message.trim() || p.message.length > 16e3 || p.idempotencyKey.length > 128 || p.queueMode !== void 0 || p.systemInputProvenance !== void 0 || p.systemProvenanceReceipt !== void 0 || p.suppressCommandInterpretation !== void 0 || sanitizedMessageResult.message !== p.message.normalize("NFC"))) return reject("Goal start requires a nonempty objective of at most 16000 characters, without queue or system-input options.");
	if (p.intent && (explicitOriginResult.value !== void 0 || p.deliver === true || p.toolBindings !== void 0 || p.thinking !== void 0 || p.fastMode !== void 0 || p.fastAutoOnSeconds !== void 0 || p.timeoutMs !== void 0 || controlUiReconnectResume.resumeRequested)) return reject("Goal start uses the session settings and local delivery; per-request runtime or routing overrides are not supported.");
	const systemReceiptResult = normalizeOptionalChatSystemReceipt(p.systemProvenanceReceipt);
	if (!systemReceiptResult.ok) return systemReceiptResult;
	const hasGoalOperation = params.goalResume !== void 0 || p.intent !== void 0;
	const commandInterpretationSuppressed = suppressCommandInterpretation || hasGoalOperation || providerReview !== void 0;
	const inboundMessage = p.intent || providerReview ? p.message : sanitizedMessageResult.message;
	const systemInputProvenance = params.goalResume ? {
		kind: "internal_system",
		sourceTool: "session_goal_resume"
	} : normalizeInputProvenance(p.systemInputProvenance);
	if (!params.trustedSystemInput && isProgressCardRefreshInputProvenance(systemInputProvenance)) return reject("Progress refresh input is reserved for progressCard.refresh.");
	const systemProvenanceReceipt = systemReceiptResult.receipt;
	const stopCommand = !commandInterpretationSuppressed && isAbortRequestText(inboundMessage);
	if (p.toolBindings) {
		if (!client || !isBrowserCopilotClient(clientInfo) || client.pairedClientId !== clientInfo?.id) return reject("run tool bindings require a paired browser copilot");
		if (!hasGatewayClientCap(client.connect.caps, GATEWAY_CLIENT_CAPS.RUN_TOOL_BINDINGS)) return reject("run tool bindings require client capability");
	}
	if (isBrowserCopilotClient(clientInfo) && !stopCommand && (!p.toolBindings || !Object.hasOwn(p.toolBindings, "browser"))) return reject("browser copilot runs require an explicit browser tool binding");
	const turnKind = !commandInterpretationSuppressed && isBtwRequestText(inboundMessage) ? "btw" : "main";
	const normalizedAttachments = normalizeRpcAttachmentsToChatAttachments(p.attachments);
	const rawMessage = hasGoalOperation || providerReview ? inboundMessage : inboundMessage.trim();
	if (!rawMessage && normalizedAttachments.length === 0) return reject("message or attachment required");
	const mentions = normalizeChatHumanMentions(p.message, p.mentions, sanitizedMessageResult.message);
	if (!mentions.ok) return mentions;
	const ordinaryChat = !hasGoalOperation && !stopCommand && turnKind === "main" && !rawMessage.startsWith("/") && !rawMessage.startsWith("!");
	if (mentions.value && (!isBrowserOperatorUiClient(clientInfo) || !client?.authenticatedUserProfile || client.internal?.syntheticClient || client.internal?.senderAttribution || systemInputProvenance || systemProvenanceReceipt || explicitOriginResult.value || suppressCommandInterpretation || !ordinaryChat)) return reject("Human mentions require a signed-in Control UI chat. Remove the selected mentions to use this mode.");
	if (p.workContext && !ordinaryChat) return reject("Working context is only supported for ordinary chat messages.");
	const workContext = p.workContext ? {
		snapshot: captureChatWorkContext(p.workContext),
		text: rawMessage
	} : void 0;
	if (workContext && !workContext.snapshot.page) return reject("Working context requires a nonempty page.");
	const modelMessage = workContext ? [rawMessage, formatChatWorkContext(workContext.snapshot)].filter(Boolean).join("\n\n") : rawMessage;
	const requestIdentity = sha256Hex(JSON.stringify([
		p.message,
		p.mentions?.map(({ profileId, start, end }) => [
			profileId,
			start,
			end
		]) ?? [],
		...workContext ? [workContext.snapshot] : [],
		...providerReview ? [providerReview.review.id, providerReview.target.sessionId] : []
	]));
	const value = {
		chatSendReceivedAtMs,
		clientInfo,
		supportsTaskSuggestions,
		p,
		...params.providerReviewAcknowledgment ? { providerReviewAcknowledgment: params.providerReviewAcknowledgment } : {},
		...params.goalResume ? { goalOperation: params.goalResume } : {},
		explicitOrigin: explicitOriginResult.value,
		inboundMessage: modelMessage,
		...workContext ? { workContext } : {},
		systemInputProvenance,
		systemProvenanceReceipt,
		suppressCommandInterpretation: commandInterpretationSuppressed,
		toolBindings: p.toolBindings,
		stopCommand,
		turnKind,
		normalizedAttachments,
		rawMessage: modelMessage,
		requestIdentity,
		...mentions.value ? { mentions: mentions.value } : {},
		reconnectResumeRequested: controlUiReconnectResume.resumeRequested
	};
	if (p.intent && !params.goalResume) {
		const goalStart = {
			action: "start",
			operationId: p.idempotencyKey,
			issuedAtMs: p.intent.issuedAtMs,
			objective: p.message
		};
		return fingerprintSessionGoalRequest([p, hasGatewayAdminScope(client)]).then((requestFingerprint) => ({
			ok: true,
			value: {
				...value,
				goalOperation: {
					...goalStart,
					requestFingerprint
				}
			}
		}));
	}
	return {
		ok: true,
		value
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-setup.ts
/** Normalize, prepare, and exclusively admit one new chat.send request. */
async function prepareAndAdmitChatSend({ params, respond, context, client, hasCurrentClientAuthority, sessionMutationAuthorization }, onAdmissionOwned, options, diagnostics) {
	const phase = diagnostics?.scope("admission");
	const assertCurrent = sessionMutationAuthorization || hasCurrentClientAuthority ? () => {
		sessionMutationAuthorization?.assertCurrent();
		if (hasCurrentClientAuthority?.() === false) throw new Error("Gateway caller authority is no longer active.");
	} : void 0;
	const withCurrent = sessionMutationAuthorization?.withCurrent;
	const assertCurrentAsync = async () => withCurrent ? withCurrent(() => assertCurrent?.()) : assertCurrent?.();
	const normalization = normalizeChatSendRequest({
		params,
		client,
		...options?.trustedSystemInput ? { trustedSystemInput: true } : {},
		...options?.goalResume ? { goalResume: options.goalResume } : {},
		...options?.providerReviewAcknowledgment ? { providerReviewAcknowledgment: options.providerReviewAcknowledgment } : {}
	});
	const normalizedRequest = normalization instanceof Promise ? await normalization : normalization;
	if (!normalizedRequest.ok) {
		respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, normalizedRequest.error, normalizedRequest.reason ? { details: { reason: normalizedRequest.reason } } : void 0));
		return;
	}
	if (normalizedRequest.value.goalOperation) try {
		assertCurrent?.();
	} catch (error) {
		respondChatSendAdmissionError(error, respond);
		return;
	}
	const loadedSession = await prepareChatSendSession({
		request: normalizedRequest.value,
		context,
		client,
		isDirectExternalUser: options?.isDirectExternalUser,
		assertCurrent
	});
	if (!loadedSession.ok) {
		respond(false, void 0, typeof loadedSession.error === "string" ? errorShape(ErrorCodes.INVALID_REQUEST, loadedSession.error) : loadedSession.error);
		return;
	}
	if (normalizedRequest.value.mentions) {
		const mentions = context.mentionInbox?.validateRecipients(client, loadedSession.value.entry ? {
			sessionKey: loadedSession.value.sessionKey,
			agentId: loadedSession.value.agentId
		} : { agentId: loadedSession.value.agentId }, normalizedRequest.value.mentions.map((mention) => mention.profileId));
		if (!mentions?.ok) {
			respond(false, void 0, mentions?.error ?? errorShape(ErrorCodes.UNAVAILABLE, "Human mentions are unavailable; reconnect and retry."));
			return;
		}
	}
	phase?.mark("authority");
	const preparation = {
		request: normalizedRequest.value,
		session: loadedSession.value,
		respond,
		context,
		client,
		assertCurrent,
		assertCurrentAsync,
		withCurrent
	};
	if (!await runChatSendPreAdmission(preparation)) return;
	let session;
	try {
		session = qualifyChatSendSession(loadedSession.value);
	} catch (error) {
		respondChatSendAdmissionError(error, respond);
		return;
	}
	let admitted;
	try {
		const nativeRestriction = await prepareChatSendNativeRuntimeRestriction({
			...preparation,
			session
		});
		if (nativeRestriction) {
			respond(false, void 0, nativeRestriction);
			return;
		}
		phase?.mark("runAdmission");
		admitted = await admitChatSend({
			...preparation,
			session,
			onAdmissionOwned,
			hasCurrentClientAuthority,
			withPreparedCurrent: sessionMutationAuthorization?.withPreparedCurrent
		});
		if (!admitted.ok) return;
		phase?.finish();
		return {
			request: normalizedRequest.value,
			session,
			admission: admitted.value
		};
	} finally {
		if (!admitted?.ok) session.releaseSessionTarget();
	}
}
//#endregion
//#region src/gateway/server-methods/chat-user-turn-recorder.ts
function createGatewayChatUserTurnController(params) {
	const { admission, request, session } = params;
	const sender = request.goalOperation?.action === "resume" ? void 0 : gatewayClientSenderFields(params.client).sender;
	const senderProfileId = params.client?.authenticatedUserProfile?.profileId;
	const selectedMentions = request.mentions;
	const mentionInbox = params.mentionInbox;
	const sourceId = buildRunUserTurnIdempotencyKey(session.clientRunId);
	const sourceClients = !params.client?.internal?.syntheticClient && (!request.systemInputProvenance || request.systemInputProvenance.kind === "external_user") ? normalizeMessageClientSources([request.clientInfo]) : [];
	const baseInput = {
		...params.transcript,
		...request.goalOperation?.action === "resume" ? { display: false } : {},
		text: request.rawMessage,
		...request.workContext ? { workContext: request.workContext } : {},
		...request.mentions ? { mentions: request.mentions } : {},
		timestamp: session.now,
		idempotencyKey: sourceId,
		...request.p.replyToId ? { replyToId: request.p.replyToId } : {},
		...sender ? { sender } : {},
		...sourceClients.length ? { transport: { clients: sourceClients } } : {},
		...hasGatewayAdminScope(params.client) ? { senderIsOwner: true } : {},
		...request.systemInputProvenance ? { provenance: request.systemInputProvenance } : admission.restartSafeAdmission && params.isDirectExternalUser ? { provenance: { kind: "external_user" } } : {}
	};
	const replyContextFieldsPromise = request.p.replyToId ? resolveChatSendReplyContext({
		replyToId: request.p.replyToId,
		cfg: session.cfg,
		agentId: session.agentId,
		sessionKey: session.sessionKey,
		sessionEntry: session.entry,
		storePath: session.storePath,
		userSenderLabel: request.clientInfo?.displayName,
		warn: params.warn
	}) : void 0;
	let inputPromise = replyContextFieldsPromise ? replyContextFieldsPromise.then((fields) => ({
		...baseInput,
		...fields.ReplyToBody ? { replyToPreview: {
			text: fields.ReplyToBody,
			...fields.ReplyToSender ? { senderLabel: fields.ReplyToSender } : {}
		} } : {}
	})) : Promise.resolve(baseInput);
	let contextFreeCommand = false;
	let mentionCommit;
	const onPersistenceError = (error) => params.warn(`gateway user transcript persistence failed: ${formatForLog(error)}`);
	const recorder = createUserTurnTranscriptRecorder({
		...sender?.id && !request.goalOperation ? { pendingInputRequestFingerprint: sha256Hex(stableStringify([
			{
				...request.p,
				sessionId: admission.sessionBinding.sessionId,
				expectedLeafEntryId: void 0
			},
			sender.identity ?? sender.id,
			hasGatewayAdminScope(params.client)
		])) } : {},
		...request.goalOperation ? { sessionTurnMutation: {
			kind: "goal",
			operation: request.goalOperation,
			runId: session.clientRunId,
			...params.goalCommitGuard
		} } : {},
		input: baseInput,
		resolveInput: () => inputPromise,
		target: () => {
			const target = session.sessionTarget;
			const sessionId = admission.sessionBinding.sessionId;
			return {
				sessionId,
				expectedSessionId: sessionId,
				initialSessionEntry: admission.initialSessionEntry,
				sessionKey: target.storeKey,
				sessionEntry: void 0,
				storePath: target.storePath,
				agentId: session.agentId,
				config: session.cfg
			};
		},
		...admission.restartSafeAdmission ? buildRestartSafeChatTranscriptState({
			admission: admission.restartSafeAdmission,
			clientRunId: session.clientRunId,
			startedAt: params.startedAt,
			sourceIngress: isBrowserOperatorUiClient(request.clientInfo) ? "control-ui" : "internal",
			operatorSource: admission.restartSafeAdmission.retryExpectedState ? void 0 : createRestartRecoveryOperatorSource({
				authority: admission.operatorAuthority,
				entry: admission.admittedSessionEntry ?? admission.initialSessionEntry,
				agentId: session.agentId,
				sessionKey: session.sessionKey,
				sourceRunId: session.clientRunId,
				inputProvenance: request.systemInputProvenance
			})
		}) : {},
		errorContext: "gateway chat user turn transcript",
		assertOriginalInputCommit: composeSessionSourceAssertion([params.assertOriginalInputCommit, admission.operatorAuthority?.assertCurrent]),
		beforeMessageWrite: (event) => {
			const next = runAgentHarnessBeforeMessageWriteHook(event);
			if (event.message.idempotencyKey === sourceId && next?.role === "user" && contextFreeCommand) return {
				...next,
				excludeFromContext: true,
				__openclaw: {
					...asOptionalRecord(Reflect.get(next, "__openclaw")),
					contextFreeCommand: true
				}
			};
			return next;
		},
		onPersistenceError,
		...selectedMentions && senderProfileId && mentionInbox ? { onOriginalInputCommitted: ({ message, anchor }) => {
			const stored = message["__openclaw"]?.humanMentions;
			const text = extractTextFromChatContent(message.content, {
				joinWith: "\n",
				normalizeText: (value) => value
			}) ?? "";
			const retained = selectedMentions.filter((mention) => Array.isArray(stored) && stored.some((value) => {
				const span = asOptionalRecord(value);
				return span?.profileId === mention.profileId && span.start === mention.start && span.end === mention.end && text.slice(mention.start, mention.end) === request.rawMessage.slice(mention.start, mention.end);
			}));
			if (!retained.length) {
				params.warn("Human mentions skipped because the committed text no longer contains the selected tokens.");
				return;
			}
			mentionCommit = mentionInbox.recordCommittedInputAsync({
				sourceId,
				committedSource: {
					generation: anchor.generation,
					sequence: anchor.rawSeq,
					timestamp: message.timestamp
				},
				agentId: anchor.agentId,
				sessionKey: session.sessionKey,
				sessionId: anchor.sessionId,
				messageId: anchor.entryId,
				senderProfileId,
				recipientProfileIds: retained.map((mention) => mention.profileId),
				excerpt: redactSensitiveText(text)
			});
			mentionCommit.catch(onPersistenceError);
		} } : {}
	});
	const persist = async (options) => {
		if (options?.contextFreeCommand === true && !recorder.hasPersisted()) contextFreeCommand = true;
		const persisted = await measureDiagnosticsTimelineSpan("gateway.chat_send.persist_user_transcript", () => recorder.persistFallback(), {
			phase: "agent-turn",
			config: session.cfg,
			attributes: admission.chatSendTraceAttributes
		});
		await mentionCommit;
		return persisted;
	};
	return {
		baseInput,
		persist,
		persistBestEffort: async (options) => {
			return await persist(options).catch(() => void 0);
		},
		recorder,
		replyContextFieldsPromise,
		setInputPromise: (input) => {
			const previousInputPromise = inputPromise;
			inputPromise = Promise.all([previousInputPromise, input]).then(([previous, next]) => ({
				...previous,
				...next
			}));
		}
	};
}
//#endregion
//#region src/gateway/server-methods/chat-send-handler.ts
const mediaDocumentContextLoader = createLazyImportLoader(() => import("./file-context-0xg7vxZe.mjs"));
async function handleChatSendWithOptions(handlerOptions, onAdmissionOwned, externalAuthorityAdmission, options) {
	try {
		var _usingCtx$1 = _usingCtx();
		const { req, respond, context, client, hasCurrentClientAuthority, sessionMutationAuthorization, sessionMutationCommitGuard } = handlerOptions;
		const diagnostics = _usingCtx$1.u(readChatSendDiagnostics(handlerOptions) ?? startChatSendDiagnostics(context.logGateway));
		const isDirectExternalUser = externalAuthorityAdmission !== void 0 && isDirectGatewayUserClient(client);
		const setup = await prepareAndAdmitChatSend(handlerOptions, onAdmissionOwned, {
			...options,
			isDirectExternalUser
		}, diagnostics);
		if (!setup) return;
		const { request, session, admission } = setup;
		const { p, systemInputProvenance, reconnectResumeRequested } = request;
		const { clientRunId, cfg, storePath, entry, sessionKey, sessionRoutingChanged, selectedAgent } = session;
		const { activeRunAbort, admittedSessionId, chatSendTraceAttributes, finishAbortedChatSend, interruptedActiveRun, lifecycleGeneration, messageInjectionTarget, restartSafeAdmission } = admission;
		const phase = diagnostics.scope("attachments");
		const preparedAttachments = await prepareChatSendAttachments({
			...setup,
			client,
			respond,
			context
		});
		if (!preparedAttachments.ok) return;
		const bindPreparedMediaRecorder = bindChatSendPreparedMediaCustody({
			admission,
			attachments: preparedAttachments.value
		});
		const settleInterruptedPreparation = () => {
			if (activeRunAbort.controller.signal.aborted) finishAbortedChatSend();
			else if (sessionRoutingChanged(context.getRuntimeConfig())) admission.rejectSessionRoutingChanged();
			else return false;
			return true;
		};
		if (settleInterruptedPreparation()) return;
		const { imageOrder, prepareAttachmentsMs } = preparedAttachments.value;
		phase?.mark("authority");
		const externalAdmissionParams = {
			runId: clientRunId,
			sessionKey,
			spawnedBy: entry?.spawnedBy,
			client,
			isCurrent: hasCurrentClientAuthority,
			inputProvenance: systemInputProvenance,
			hasExplicitOrigin: request.explicitOrigin !== void 0,
			hasRestoredCronContinuation: entry?.cronRunContinuation !== void 0,
			isIncognitoEntry: entry?.incognito === true,
			isReconnectResume: reconnectResumeRequested,
			isSystemGenerated: request.suppressCommandInterpretation || request.systemProvenanceReceipt !== void 0,
			turnKind: request.turnKind
		};
		const cronCreatorAuthority = externalAuthorityAdmission?.resolve(externalAdmissionParams);
		let dashboardSessionAuthorization;
		const assertDashboardReadCurrent = externalAuthorityAdmission?.allowsDashboardReads(externalAdmissionParams) ? () => {
			admission.assertWorkAdmissionCurrent();
			sessionMutationCommitGuard?.();
			if (client?.invalidated || hasCurrentClientAuthority?.() === false || !externalAuthorityAdmission.allowsDashboardReads(externalAdmissionParams)) throw new Error("Dashboard message read admission is no longer active.");
			if (!dashboardSessionAuthorization) {
				const resolved = resolveSessionMutationAuthorization({
					client,
					context,
					method: "chat.send",
					requestParams: {
						agentId: session.agentId,
						sessionKey
					},
					expectedTarget: {
						agentId: session.agentId,
						sessionKey,
						storePath,
						sessionId: admission.sessionBinding.sessionId
					}
				});
				if (resolved.error) throw new SessionMutationAuthorizationChangedError(resolved.error);
				if (!resolved.authorization) throw new Error("Dashboard session authorization is unavailable.");
				dashboardSessionAuthorization = resolved.authorization;
			}
			dashboardSessionAuthorization.assertCurrent();
		} : void 0;
		const admissionStartedAt = Date.now();
		const terminalizeRestartSafeAdmission = (terminalState) => admission.settleTerminal({
			...terminalState,
			startedAt: admissionStartedAt
		});
		const commitInitialInput = req.method === "sessions.create" && restartSafeAdmission !== void 0 && !restartSafeAdmission.retryExpectedState;
		let inputAdmissionAttempted = false;
		let replyAdmissionTicket;
		let releaseBeforeDispatch = void 0;
		try {
			const assertCustodyLifetimeCurrent = () => {
				admission.assertWorkAdmissionCurrent();
				admission.assertSessionTargetCurrent();
				if (sessionRoutingChanged(context.getRuntimeConfig())) throw new Error("Session routing changed before input admission; refresh and retry.");
			};
			const assertInputAdmissionCurrent = composeSessionSourceAssertion([sessionMutationCommitGuard], (assertSource) => {
				admission.assertClientUploadAllowed?.();
				assertCustodyLifetimeCurrent();
				assertSource();
			});
			assertInputAdmissionCurrent();
			const goalCommitGuard = request.goalOperation ? createChatSendGoalCommitGuard({
				admission,
				session,
				client,
				context,
				sessionMutationAuthorization,
				sessionMutationCommitGuard
			}) : void 0;
			const userTurn = createGatewayChatUserTurnController({
				...setup,
				client,
				transcript: options?.transcript,
				isDirectExternalUser,
				startedAt: admissionStartedAt,
				warn: (message) => context.logGateway.warn(message),
				mentionInbox: context.mentionInbox,
				assertOriginalInputCommit: composeSessionSourceAssertion([assertInputAdmissionCurrent, commitInitialInput ? sessionMutationAuthorization?.assertCurrent : void 0]),
				goalCommitGuard
			});
			const { persist: persistUserTurnTranscript, recorder: userTurnRecorder, replyContextFieldsPromise } = userTurn;
			const persistGatewayUserTurnTranscript = (...args) => admission.withInputCommitPublication(() => persistUserTurnTranscript(...args));
			bindPreparedMediaRecorder(userTurnRecorder);
			phase?.mark("preparation");
			const preparedUserTurn = prepareChatSendUserTurn({
				...setup,
				attachments: preparedAttachments.value,
				client,
				logGateway: context.logGateway,
				getConfig: context.getRuntimeConfig,
				userTurn
			});
			const { ctx, isInternalTextSlashCommandTurn } = preparedUserTurn;
			admission.setPendingInputCleanup(async () => {
				try {
					const pending = userTurnRecorder.getPendingInputMessage?.() && !userTurnRecorder.isPendingInputConsumed?.();
					const disposition = activeRunAbort.controller.signal.aborted && activeRunAbort.entry?.abortStopReason !== "restart" && !isAgentRunRestartAbortReason(activeRunAbort.controller.signal.reason) ? "cancelled" : "interrupted";
					userTurnRecorder.finishPendingInput?.(disposition);
					if (pending && activeRunAbort.controller.signal.aborted) {
						const reason = resolveChatAbortDiagnosticReason(activeRunAbort.controller.signal, activeRunAbort.entry);
						context.logGateway.info(`chat pending input aborted: ${reason} (${disposition})`, {
							runId: clientRunId,
							sessionKey,
							sessionId: admittedSessionId,
							agentId: selectedAgent.agentId,
							disposition,
							reason
						});
					}
					await userTurnRecorder.waitForPendingInputSettlement?.();
				} finally {
					preparedUserTurn.discardUnreferencedMedia(userTurnRecorder.getPendingInputMessage?.()).catch((error) => context.logGateway.warn(`Failed to discard unused chat media: ${String(error)}`));
				}
			});
			phase?.mark("persist");
			let approvedInput;
			if (entry?.sessionId && userTurn.baseInput.display !== false && (!systemInputProvenance || systemInputProvenance.kind === "external_user") && !isInternalTextSlashCommandTurn && !request.goalOperation && !restartSafeAdmission?.retryExpectedState && !commitInitialInput) {
				inputAdmissionAttempted = true;
				const assertCustodyCurrent = () => {
					assertCustodyLifetimeCurrent();
					if (sessionMutationAuthorization?.assertAdmittedInputCurrent) sessionMutationAuthorization.assertAdmittedInputCurrent();
					else {
						sessionMutationCommitGuard?.();
						sessionMutationAuthorization?.assertCurrent();
					}
				};
				let preparationFailure;
				const assertAdmittedCurrent = req.expectedProfileId === void 0 ? assertCustodyCurrent : createMessageInjectionAuthority(() => {
					if (preparationFailure) throw preparationFailure.cause;
					assertCustodyCurrent();
					return true;
				});
				const staged = await userTurnRecorder.stageApproved?.({
					runId: clientRunId,
					authority: sessionMutationAuthorization?.admittedInputAuthority ? withSessionPendingInputAuthorityGuard(sessionMutationAuthorization.admittedInputAuthority, assertCustodyLifetimeCurrent, req.expectedProfileId === void 0 ? void 0 : (cause) => {
						preparationFailure ??= { cause };
						assertAdmittedCurrent();
						throw cause;
					}) : void 0,
					assertCurrent: () => {
						admission.assertClientUploadAllowed?.();
						sessionMutationCommitGuard?.();
						assertCustodyCurrent();
					},
					assertAdmittedCurrent
				});
				if (userTurnRecorder.isPendingInputConsumed?.()) {
					admission.cleanupAdmittedRun();
					clearAgentRunContext(clientRunId, lifecycleGeneration);
					respond(true, {
						runId: clientRunId,
						status: "ok"
					}, void 0, {
						cached: true,
						runId: clientRunId
					});
					return;
				}
				if (!staged) throw new Error("Chat input was not durably admitted; refresh and retry.");
				approvedInput = userTurnRecorder.getPendingInputMessage?.();
				emitSessionsChanged(context, {
					sessionKey,
					agentId: selectedAgent.agentId,
					reason: "send"
				}, { accessChanged: false });
			}
			let goalResult;
			if (restartSafeAdmission) {
				inputAdmissionAttempted ||= commitInitialInput;
				const persistedUserTurn = await persistGatewayUserTurnTranscript();
				if (commitInitialInput) approvedInput = persistedUserTurn?.message;
				const goalOperation = request.goalOperation;
				if (goalOperation) {
					const mutation = persistedUserTurn?.sessionTurnMutationResult;
					goalResult = mutation?.result;
					if (!goalResult) {
						goalResult = await lookupSessionGoalOperation({
							sessionKey,
							storePath,
							agentId: session.agentId,
							expectedSessionId: admittedSessionId,
							operation: goalOperation
						});
						assertInputAdmissionCurrent();
						goalCommitGuard?.assertCurrent();
					}
					if (goalResult && (!persistedUserTurn || mutation?.replayed)) {
						admission.cleanupAdmittedRun();
						clearAgentRunContext(clientRunId, lifecycleGeneration);
						respond(true, {
							...goalResult,
							replayed: true
						}, void 0, {
							cached: true,
							runId: clientRunId
						});
						return;
					}
					if (!goalResult || !persistedUserTurn?.sessionEntry) throw new Error("Goal and its input were not durably admitted.");
					if (admission.initialSessionEntry) await recordSessionCreated(session.cfg, {
						sessionKey,
						agentId: session.agentId,
						entry: persistedUserTurn.sessionEntry
					});
					await publishCommittedSessionGoalChange(context, {
						sessionKey,
						agentId: session.agentId,
						entry: persistedUserTurn.sessionEntry,
						actor: gatewayClientSessionCreator(client),
						summary: `goal ${goalOperation.action}`
					});
				}
				if (!persistedUserTurn || persistedUserTurn.sessionEntry?.restartRecoveryDeliveryRunId !== clientRunId || persistedUserTurn.sessionEntry.restartRecoveryDeliverySourceRunId !== clientRunId) throw new Error("chat turn was not durably admitted");
				if (lifecycleGeneration !== getAgentEventLifecycleGeneration()) {
					if (activeRunAbort.entry) activeRunAbort.entry.abortStopReason = "restart";
					activeRunAbort.controller.abort(createAgentRunRestartAbortError());
				}
				if (activeRunAbort.controller.signal.aborted) {
					if (!await terminalizeRestartSafeAdmission({
						retryable: activeRunAbort.entry?.abortStopReason === "restart",
						status: "killed"
					})) throw new Error("chat admission ownership changed before terminalization");
					finishAbortedChatSend();
					return;
				}
				if (sessionRoutingChanged(context.getRuntimeConfig())) {
					if (!await terminalizeRestartSafeAdmission({
						retryable: true,
						status: "failed"
					})) throw new Error("chat admission ownership changed before terminalization");
					admission.rejectSessionRoutingChanged();
					return;
				}
			}
			if (approvedInput) preparedUserTurn.applyApprovedText(extractTextFromChatContent(approvedInput.content, {
				joinWith: "\n",
				normalizeText: (value) => value
			}) ?? "");
			phase?.mark("preparation");
			if (messageInjectionTarget) invalidateSkillAuthoringForOtherRequester(sessionKey, client?.internal?.syntheticClient ? void 0 : client?.authenticatedUserProfile?.profileId);
			const steerDocumentContext = messageInjectionTarget && !isInternalTextSlashCommandTurn && ctx.media?.length ? await mediaDocumentContextLoader.load().then(async (runtime) => ({
				status: "rendered",
				...await runtime.renderInboundDocumentContext({
					ctx,
					cfg: session.cfg
				})
			})).catch((err) => {
				mediaDocumentContextLoader.clear();
				logVerbose(`steer document render failed, injecting raw content: ${formatErrorMessage(err)}`);
				return { status: "failed" };
			}) : void 0;
			if (settleInterruptedPreparation()) return;
			const beginCapturedMessageInjection = createChatSendMessageInjectionStarter({
				operatorAuthority: admission.operatorAuthority,
				target: messageInjectionTarget,
				abortSignal: activeRunAbort.controller.signal,
				request,
				session,
				admittedSessionSettings: admission.admittedSessionSettings,
				turn: preparedUserTurn,
				imageOrder,
				documentContext: steerDocumentContext,
				userTurnTranscriptRecorder: userTurnRecorder,
				logGateway: context.logGateway,
				assertCurrent: req.expectedProfileId === void 0 && !admission.assertClientUploadAllowed && !isProgressCardRefreshInputProvenance(systemInputProvenance) ? void 0 : assertInputAdmissionCurrent
			});
			const preAckReplyContextPromise = messageInjectionTarget && !isInternalTextSlashCommandTurn ? replyContextFieldsPromise : void 0;
			phase?.mark("replyContext");
			if (preAckReplyContextPromise) {
				applyChatSendReplyContextFields(ctx, await preAckReplyContextPromise);
				if (settleInterruptedPreparation()) return;
			}
			assertInputAdmissionCurrent();
			let messageInjectionAttempt = !p.replyToId || preAckReplyContextPromise ? await beginCapturedMessageInjection() : void 0;
			phase?.mark("runAdmission");
			const preAckInjection = await settleChatSendPreAckMessageInjection({
				attempt: messageInjectionAttempt,
				isAborted: () => activeRunAbort.controller.signal.aborted,
				sessionRoutingChanged: () => sessionRoutingChanged(context.getRuntimeConfig()),
				onAborted: finishAbortedChatSend,
				onSessionRoutingChanged: admission.rejectSessionRoutingChanged
			});
			if (preAckInjection.status === "handled") return;
			messageInjectionAttempt = preAckInjection.attempt;
			phase?.mark("effects");
			const { serverTiming, chatSendTiming, ackReadyEvent } = prepareChatSendAckTiming({
				client,
				request,
				session,
				prepareAttachmentsMs,
				chatSendTraceAttributes
			});
			if (options?.beforeDispatch) {
				assertInputAdmissionCurrent();
				releaseBeforeDispatch = await options.beforeDispatch({
					runId: clientRunId,
					assertCurrent: assertInputAdmissionCurrent,
					assertWorkAdmissionCurrent: () => {
						admission.assertClientUploadAllowed?.();
						admission.assertWorkAdmissionCurrent();
					}
				});
				assertInputAdmissionCurrent();
			}
			context.addChatRun(clientRunId, {
				sessionKey,
				agentId: selectedAgent.agentId,
				clientRunId,
				...chatSendTiming ? { chatSendTiming } : {}
			});
			const receipt = userTurnRecorder.getAdmissionReceipt?.();
			const ackPayload = {
				...goalResult,
				runId: clientRunId,
				status: "started",
				...receipt ? { messageSeq: receipt.activeMessagePosition + 1 } : {},
				...interruptedActiveRun ? { interruptedActiveRun: true } : {},
				...serverTiming ? { serverTiming } : {}
			};
			emitDiagnosticsTimelineEvent(ackReadyEvent(ackPayload.status), { config: cfg });
			assertInputAdmissionCurrent();
			admission.setDiscardAbandonedPreparedMedia(void 0);
			replyAdmissionTicket = reserveReplyAdmissionTicket([ctx.SessionKey, ctx.CommandTargetSessionKey]);
			phase?.mark("response");
			respond(true, ackPayload, void 0, { runId: clientRunId });
			phase?.finish();
			diagnostics.acknowledge();
			context.recordClientActivity?.(client);
			const chatSendAckedAtMs = chatSendTiming?.ackedAtMs ?? performance.now();
			releaseBeforeDispatch = void 0;
			startChatDispatch({
				...setup,
				replyAdmissionTicket,
				diagnostics,
				admissionStartedAt,
				attachments: preparedAttachments.value,
				client,
				context,
				toolsAllow: options?.toolsAllow,
				prepareAssistantTranscriptMessage: options?.prepareAssistantTranscriptMessage,
				prepareSkillLibraryAuthoring: () => prepareGatewaySkillAuthoring({
					client,
					context,
					sessionMutationCommitGuard: () => {
						sessionMutationCommitGuard?.();
						admission.assertWorkAdmissionCurrent();
					}
				}, sessionKey, !options && !systemInputProvenance && !reconnectResumeRequested && request.turnKind === "main"),
				cronCreatorAuthority,
				assertDashboardReadCurrent,
				externalAuthorityAdmission,
				injection: {
					beginCapturedMessageInjection,
					messageInjectionAttempt,
					preAckReplyContextPromise,
					replyContextFieldsPromise
				},
				terminalizeRestartSafeAdmission,
				timing: {
					chatSendAckedAtMs,
					chatSendTiming
				},
				turn: preparedUserTurn,
				userTurn
			});
		} catch (err) {
			releaseBeforeDispatch?.();
			replyAdmissionTicket?.release();
			await handleChatSendSetupError({
				cacheResult: request.goalOperation === void 0 && !inputAdmissionAttempted,
				admission,
				context,
				error: err,
				respond,
				session,
				terminalizeRestartSafeAdmission
			});
		}
	} catch (_) {
		_usingCtx$1.e = _;
	} finally {
		_usingCtx$1.d();
	}
}
async function handleChatSend(options, onAdmissionOwned, externalAuthorityAdmission) {
	await handleChatSendWithOptions(options, onAdmissionOwned, externalAuthorityAdmission);
}
/** The ordinary chat owner retains the exact human-reviewed continuation through settlement. */
async function handleProviderReviewContinuationChat(options, acknowledgment) {
	let admissionOwned = false;
	try {
		await handleChatSendWithOptions(options, async () => {
			admissionOwned = true;
			return true;
		}, void 0, { providerReviewAcknowledgment: acknowledgment });
	} finally {
		if (!admissionOwned) retireProviderReviewAcknowledgment(acknowledgment);
	}
}
/** Operator Resume admits one hidden internal continuation with the Goal transition. */
async function handleSessionGoalResumeChat(options, operation) {
	await handleChatSendWithOptions(options, void 0, void 0, { goalResume: operation });
}
/** Dispatches Gateway-authored system input without widening the public chat-send contract. */
async function handleTrustedInternalChatSend(options, onAdmissionOwned, inputOptions) {
	await handleChatSendWithOptions(options, onAdmissionOwned, void 0, {
		...inputOptions,
		trustedSystemInput: true
	});
}
//#endregion
export { normalizeChatSendRequest as a, handleTrustedInternalChatSend as i, handleProviderReviewContinuationChat as n, scheduleCreatedDashboardSessionTitle as o, handleSessionGoalResumeChat as r, handleChatSend as t };