import { type PromptQueueState } from "#channel/prompt-queue.js"; import type { UserContent } from "ai"; import type { ChannelRespondOptions, ChannelSendOptions } from "#channel/channel-operations.js"; import type { SessionAuthContext, TurnPolicy } from "#channel/types.js"; import type { InputResolution } from "#protocol/message.js"; import type { InputRequest } from "#shared/input.js"; import { type InputResponse, type StrictInputResponses } from "#shared/input.js"; import type { ActionEvent, Adapter, ChatConfig, SerializedThread, Thread, WebhookOptions } from "#compiled/chat/index.js"; import { Chat } from "#compiled/chat/index.js"; import { type Channel, type ChannelEvents, type ChannelContinuationOps, type Session } from "#public/definitions/channel.js"; type ChatSdkAdapters = Record; /** Durable Chat SDK thread state plus default-handler streaming bookkeeping. */ export interface ChatSdkChannelState extends Record, PromptQueueState { thread: SerializedThread | null; /** Message id of the in-flight streamed assistant post (edit fallback). */ anchorMessageId?: string | null; /** * Whether `adapter.editMessage` works for this session. Set to `false` once * an edit throws {@link isNotImplemented}, which disables streaming edits for * the rest of the session. */ editSupported?: boolean; /** Epoch ms of the last streaming edit, used to throttle edits. */ lastEditAtMs?: number | null; /** Buffered first line of a tool-call message, surfaced as typing status. */ pendingToolCallMessage?: string | null; /** Authorization status messages, keyed by connection name. */ pendingAuthMessageIds?: Record; /** * The Chat SDK user behind each principal that sent a message, so a sign-in * reaches them privately. `null` once more than one person sent as it. */ usersByPrincipal?: Record; /** Posted input request cards, keyed by message id, until eve resolves every request on them. */ pendingInputCards?: Record; streamStepIndex?: number | null; } /** One posted card's requests and the resolutions eve has reported for them so far. */ export interface ChatSdkPendingInputCard { readonly requests: readonly InputRequest[]; readonly resolved: Readonly>; } /** * Thread selector accepted by `chatSdkChannel().receive`. Pass a serialized * Chat SDK thread when possible; `threadId` plus `adapterName` is supported for * proactive sends that only have a provider-native thread id. */ export interface ChatSdkReceiveTarget { readonly adapterName?: string; readonly thread?: SerializedThread; readonly threadId?: string; } /** * Channel-owned metadata exposed to eve instrumentation. */ export interface ChatSdkInstrumentationMetadata extends Record { readonly adapterName: string | null; readonly channelId: string | null; readonly isDM: boolean | null; readonly threadId: string | null; } /** * Per-session context passed to `chatSdkChannel({ events })` handlers. `thread` * is rebuilt from persisted channel state using the configured Chat SDK * adapter, so default handlers can post back to the originating chat thread. */ export interface ChatSdkChannelContext { readonly bot: Chat; readonly thread: Thread | null; state: ChatSdkChannelState; /** Whether streamed deltas are delivered via a post+edit fallback. */ readonly streaming: boolean; /** Minimum interval between streaming edits, in ms. */ readonly streamingEditIntervalMs: number; } /** Event-handler context for `chatSdkChannel`, including continuation routing. */ export interface ChatSdkEventContext extends ChatSdkChannelContext, ChannelContinuationOps { } /** * Per-event handlers for `chatSdkChannel({ events })`. Each supplied handler * replaces the built-in default for that event. */ export type ChatSdkChannelEvents = ChannelEvents>; /** Selects the Chat SDK thread that owns the eve continuation token. */ interface ChatSdkThreadOptions { readonly auth?: SessionAuthContext | null; readonly thread: SerializedThread | Thread | string; /** * Required when `thread` is a string that does not include the Chat SDK * adapter prefix. Prefer passing the `Thread` object from the Chat SDK handler * when possible. */ readonly adapterName?: string; } /** * Options for `bridge.send`: channel send options plus the thread. The thread * determines the eve continuation token and persisted channel state. */ export interface ChatSdkSendOptions extends ChatSdkThreadOptions, Omit { /** * Controls how this input interacts with an active eve turn on the same * thread. Defaults to the channel's `turnPolicy`, then `"steer"`. */ readonly turnPolicy?: TurnPolicy; } /** Options for `bridge.respond`: channel respond options plus the thread. */ export interface ChatSdkRespondOptions extends ChatSdkThreadOptions, Omit { } /** * Configuration for {@link chatSdkChannel}. It accepts normal Chat SDK * `ChatConfig` fields, plus eve route and event settings. */ export interface ChatSdkChannelConfig extends Omit, "adapters"> { /** Map of Chat SDK adapter name to adapter instance. */ readonly adapters: TAdapters; /** * Base route for generated adapter webhooks. Defaults to `/eve/v1`, so an * adapter named `slack` mounts at `/eve/v1/slack`. */ readonly route?: string; /** * Per-adapter route overrides. Use when a provider requires a fixed webhook * URL or when migrating an existing endpoint without changing provider * settings. */ readonly routes?: Partial, string>>; /** Policy for accepted messages that arrive while a turn is active. */ readonly turnPolicy?: TurnPolicy; /** Extra Chat SDK webhook options. eve owns `waitUntil`. */ readonly webhook?: Omit; /** Optional eve event handlers. Supplied handlers replace built-in defaults. */ readonly events?: ChatSdkChannelEvents; /** * Prefix for default eve HITL button action ids. Change this if your Chat SDK * app already uses the `eve_input:` prefix. */ readonly inputActionPrefix?: string; /** * Auth resolver for default HITL button clicks. Defaults to `null`; provide a * resolver when continued sessions should keep user or tenant auth. */ readonly resolveInputAuth?: (event: ActionEvent) => SessionAuthContext | null | Promise; /** * Whether the default handlers stream assistant output by posting an initial * message and editing it as deltas arrive. Defaults to `true`. Set to `false` * for adapters that only deliver a single message per turn (e.g. email), so * replies post once on completion. */ readonly streaming?: boolean; /** * Minimum interval between streaming edits, in ms. Defaults to `1000`. Only * used when `streaming` is enabled and the adapter supports editing. */ readonly streamingEditIntervalMs?: number; } /** Concrete channel value returned on `bridge.channel`. */ export interface ChatSdkChannel extends Channel { } /** * Return value of {@link chatSdkChannel}. Export `channel` from * `agent/channels/.ts`, then register handlers on `bot` and call `send` * from those handlers to hand work to eve. */ export interface ChatSdkChannelBridge { readonly bot: Chat; readonly channel: ChatSdkChannel; /** * Starts or resumes an eve session from inside a Chat SDK webhook handler. * Use `channel.receive(...)` for proactive sends that are not handling an * inbound Chat SDK webhook. */ send(message: string | UserContent, options: ChatSdkSendOptions): Promise; /** * Answers pending input requests on the thread's session from inside a Chat * SDK webhook handler. Never creates a session. */ respond(inputResponses: StrictInputResponses, options: ChatSdkRespondOptions): Promise; } /** * Creates an eve channel backed by one Chat SDK runtime and its adapters. * * @example * ```ts * import { createSlackAdapter } from "@chat-adapter/slack"; * import { createMemoryState } from "@chat-adapter/state-memory"; * import { chatSdkChannel } from "eve/channels/chat-sdk"; * * export const { bot, channel, send } = chatSdkChannel({ * userName: "acme", * adapters: { slack: createSlackAdapter() }, * state: createMemoryState(), * }); * * bot.onNewMention(async (thread, message) => { * await send(message.text, { thread }); * }); * ``` */ export declare function chatSdkChannel(config: ChatSdkChannelConfig): ChatSdkChannelBridge; export {};