import type { MessageRef, MessageContent, MessageContext, MessageEditContext, ActionContext, ModalSubmitContext, ModalDefinition, PlatformCapabilities, PlatformFileRef, DownloadedFile, Destination, PostMessageOpts, FileUploadOpts, ActionElement } from './types.js'; import type { OutputStream, OpenOutputStreamOpts } from './output-stream.js'; export interface PlatformAdapter { readonly name: string; readonly capabilities: PlatformCapabilities; start(): Promise; stop(): Promise; onMessage(handler: (ctx: MessageContext) => Promise): void; onMessageEdit(handler: (ctx: MessageEditContext) => Promise): void; onAction(actionId: string, handler: (ctx: ActionContext) => Promise): void; onModalSubmit(callbackId: string, handler: (ctx: ModalSubmitContext) => Promise): void; postMessage(destination: Destination, content: MessageContent, opts?: PostMessageOpts): Promise; updateMessage(ref: MessageRef, content: MessageContent): Promise; deleteMessage(ref: MessageRef): Promise; postInteractive(destination: Destination, content: MessageContent & { actions: ActionElement[]; }, opts?: PostMessageOpts): Promise; openModal(triggerId: string, modal: ModalDefinition): Promise; markQueued(ref: MessageRef): Promise; uploadFile(destination: Destination, filePath: string, opts?: FileUploadOpts): Promise; downloadFile(fileRef: PlatformFileRef, destDir: string): Promise; getPermalink(ref: MessageRef): Promise; /** Open a new OutputStream for streaming agent output to the given destination. */ openOutputStream(destination: Destination, opts?: OpenOutputStreamOpts): OutputStream; /** Register a conduit (channel/chat) for project-report destinations. */ bindProjectConduit(projectId: string, conduitHint: string): Promise; /** Remove a conduit registration. */ unbindProjectConduit(projectId: string): Promise; /** Get all registered project→conduit mappings. */ getProjectConduits(): Promise>; /** Inverse lookup: given an inbound conduit (e.g., a Slack channel id), return * the project it is currently bound to, or null if unbound. Used by the * orchestration layer to attach inbound messages to their project. */ resolveInboundProject(conduit: string): Promise; /** True if the given (prefixed) conduit belongs to this adapter. Used by * CompositeAdapter to route outbound operations to the right sub-adapter when * multiple platforms are online simultaneously. Each adapter owns a conduit * namespace by prefix: Slack `slack:`, Feishu `feishu:`, TUI `tui-`/`tui:`. */ ownsConduit(conduit: string): boolean; }