import type { GetReplyOptions } from "../../auto-reply/get-reply-options.types.js"; import type { ReplyPayload } from "../../auto-reply/reply-payload.js"; import type { DispatchFromConfigResult } from "../../auto-reply/reply/dispatch-from-config.types.js"; import type { GetReplyFromConfig } from "../../auto-reply/reply/get-reply.types.js"; import type { HistoryEntry } from "../../auto-reply/reply/history.js"; import type { DispatchReplyWithBufferedBlockDispatcher } from "../../auto-reply/reply/provider-dispatcher.types.js"; import type { ReplyDispatcherWithTypingOptions } from "../../auto-reply/reply/reply-dispatcher.js"; import type { ReplyDispatchKind } from "../../auto-reply/reply/reply-dispatcher.types.js"; import type { FinalizedMsgContext, MsgContext } from "../../auto-reply/templating.js"; import type { GroupKeyResolution } from "../../config/sessions/types.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import type { InboundLastRouteUpdate, RecordInboundSession } from "../session.types.js"; export type ChannelTurnAdmission = { kind: "dispatch"; reason?: string; } | { kind: "observeOnly"; reason: string; } | { kind: "handled"; reason: string; } | { kind: "drop"; reason: string; recordHistory?: boolean; }; export type ChannelEventClass = { kind: "message" | "command" | "interaction" | "reaction" | "lifecycle" | "unknown"; canStartAgentTurn: boolean; requiresImmediateAck?: boolean; }; export type NormalizedTurnInput = { id: string; timestamp?: number; rawText: string; textForAgent?: string; textForCommands?: string; raw?: unknown; }; export type SenderFacts = { id: string; name?: string; username?: string; tag?: string; roles?: string[]; isBot?: boolean; isSelf?: boolean; displayLabel?: string; }; export type ConversationFacts = { kind: "direct" | "group" | "channel"; id: string; label?: string; spaceId?: string; parentId?: string; threadId?: string; nativeChannelId?: string; routePeer: { kind: "direct" | "group" | "channel"; id: string; }; }; export type RouteFacts = { agentId: string; accountId?: string; routeSessionKey: string; dispatchSessionKey?: string; persistedSessionKey?: string; parentSessionKey?: string; modelParentSessionKey?: string; mainSessionKey?: string; createIfMissing?: boolean; }; export type ReplyPlanFacts = { to: string; originatingTo: string; nativeChannelId?: string; replyTarget?: string; deliveryTarget?: string; replyToId?: string; replyToIdFull?: string; messageThreadId?: string; threadParentId?: string; sourceReplyDeliveryMode?: "thread" | "reply" | "channel" | "direct" | "none"; }; export type AccessFacts = { dm?: { decision: "allow" | "pairing" | "deny"; reason?: string; allowFrom: string[]; }; group?: { policy: "open" | "allowlist" | "disabled"; routeAllowed: boolean; senderAllowed: boolean; allowFrom: string[]; requireMention: boolean; }; commands?: { useAccessGroups: boolean; allowTextCommands: boolean; authorizers: Array<{ configured: boolean; allowed: boolean; }>; }; mentions?: { canDetectMention: boolean; wasMentioned: boolean; hasAnyMention?: boolean; implicitMentionKinds?: Array<"reply_to_bot" | "bot_thread_participant" | "native">; }; }; export type MessageFacts = { body?: string; rawBody: string; bodyForAgent?: string; commandBody?: string; envelopeFrom: string; senderLabel?: string; preview?: string; inboundHistory?: Array<{ sender: string; body: string; timestamp?: number; }>; }; export type SupplementalContextFacts = { quote?: { id?: string; fullId?: string; body?: string; sender?: string; senderAllowed?: boolean; isExternal?: boolean; isQuote?: boolean; }; forwarded?: { from?: string; fromType?: string; fromId?: string; date?: number; senderAllowed?: boolean; }; thread?: { id?: string; starterBody?: string; historyBody?: string; label?: string; parentSessionKey?: string; modelParentSessionKey?: string; senderAllowed?: boolean; }; untrustedContext?: unknown[]; groupSystemPrompt?: string; }; export type InboundMediaFacts = { path?: string; url?: string; contentType?: string; kind?: "image" | "video" | "audio" | "document" | "unknown"; transcribed?: boolean; }; export type PreflightFacts = { admission?: ChannelTurnAdmission; message?: Partial; media?: InboundMediaFacts[]; supplemental?: SupplementalContextFacts; }; export type ChannelDeliveryInfo = { kind: ReplyDispatchKind; }; export type ChannelDeliveryResult = { messageIds?: string[]; threadId?: string; replyToId?: string; visibleReplySent?: boolean; }; export type ChannelTurnDeliveryAdapter = { deliver: (payload: ReplyPayload, info: ChannelDeliveryInfo) => Promise; onError?: (err: unknown, info: { kind: string; }) => void; }; export type ChannelTurnRecordOptions = { groupResolution?: GroupKeyResolution | null; createIfMissing?: boolean; updateLastRoute?: InboundLastRouteUpdate; onRecordError?: (err: unknown) => void; trackSessionMetaTask?: (task: Promise) => void; }; export type ChannelTurnHistoryFinalizeOptions = { isGroup?: boolean; historyKey?: string; historyMap?: Map; limit?: number; }; export type ChannelTurnDispatcherOptions = Omit; export type AssembledChannelTurn = { cfg: OpenClawConfig; channel: string; accountId?: string; agentId: string; routeSessionKey: string; storePath: string; ctxPayload: FinalizedMsgContext; recordInboundSession: RecordInboundSession; dispatchReplyWithBufferedBlockDispatcher: DispatchReplyWithBufferedBlockDispatcher; delivery: ChannelTurnDeliveryAdapter; dispatcherOptions?: ChannelTurnDispatcherOptions; replyOptions?: Omit; replyResolver?: GetReplyFromConfig; record?: ChannelTurnRecordOptions; history?: ChannelTurnHistoryFinalizeOptions; admission?: Extract; log?: (event: ChannelTurnLogEvent) => void; messageId?: string; }; export type PreparedChannelTurn = { channel: string; accountId?: string; routeSessionKey: string; storePath: string; ctxPayload: FinalizedMsgContext; recordInboundSession: RecordInboundSession; record?: ChannelTurnRecordOptions; history?: ChannelTurnHistoryFinalizeOptions; onPreDispatchFailure?: (err: unknown) => void | Promise; runDispatch: () => Promise; observeOnlyDispatchResult?: TDispatchResult; admission?: Extract; log?: (event: ChannelTurnLogEvent) => void; messageId?: string; }; export type ChannelTurnResolved = (AssembledChannelTurn & { admission?: Extract; }) | (PreparedChannelTurn & { admission?: Extract; }); export type ChannelTurnStage = "ingest" | "classify" | "preflight" | "resolve" | "authorize" | "assemble" | "record" | "dispatch" | "finalize"; export type ChannelTurnLogEvent = { stage: ChannelTurnStage; event: "start" | "done" | "drop" | "handled" | "error"; channel: string; accountId?: string; messageId?: string; sessionKey?: string; admission?: ChannelTurnAdmission["kind"]; reason?: string; error?: unknown; }; export type ChannelTurnResult = DispatchedChannelTurnResult | { admission: ChannelTurnAdmission; dispatched: false; ctxPayload?: MsgContext; routeSessionKey?: string; }; export type DispatchedChannelTurnResult = { admission: Extract; dispatched: true; ctxPayload: MsgContext; routeSessionKey: string; dispatchResult: TDispatchResult; }; export type ChannelTurnAdapter = { ingest: (raw: TRaw) => Promise | NormalizedTurnInput | null; classify?: (input: NormalizedTurnInput) => Promise | ChannelEventClass; preflight?: (input: NormalizedTurnInput, eventClass: ChannelEventClass) => Promise | PreflightFacts | ChannelTurnAdmission | null | undefined; resolveTurn: (input: NormalizedTurnInput, eventClass: ChannelEventClass, preflight: PreflightFacts) => Promise> | ChannelTurnResolved; onFinalize?: (result: ChannelTurnResult) => Promise | void; }; export type RunChannelTurnParams = { channel: string; accountId?: string; raw: TRaw; adapter: ChannelTurnAdapter; log?: (event: ChannelTurnLogEvent) => void; }; export type RunResolvedChannelTurnParams = { channel: string; accountId?: string; raw: TRaw; input: NormalizedTurnInput | ((raw: TRaw) => Promise | NormalizedTurnInput | null); resolveTurn: (input: NormalizedTurnInput, eventClass: ChannelEventClass, preflight: PreflightFacts) => Promise> | ChannelTurnResolved; log?: (event: ChannelTurnLogEvent) => void; };