import * as lark from '@larksuiteoapi/node-sdk'; import type { Readable } from 'node:stream'; import { type OutboundTarget } from './outbound-message.js'; import { type TransportLogger } from './diagnostics.js'; import { type FeishuMessageReader, type FeishuMessageReadRequest, type FeishuMessageReadResponse } from './message-read.js'; import { type FeishuDocCommentRequest, type FeishuDocCommentText } from './doc-comment.js'; import { type FeishuCotClient } from './cot.js'; import { type FeishuAppOwnerIdentity } from './identity.js'; export { FEISHU_APP_OWNER_TYPE_ENTERPRISE_MEMBER, type FeishuAppOwnerIdentity, } from './identity.js'; export type { FeishuMessageReadItem, FeishuMessageReadRequest, FeishuMessageReadResponse, FeishuMessageReader, } from './message-read.js'; export type { FeishuCommentAnchor, FeishuCommentSegment, FeishuDocCommentRequest, FeishuDocCommentText, } from './doc-comment.js'; /** One sent message and where the platform placed it. */ export interface FeishuSentMessage { readonly messageId: string; readonly chatId: string; readonly threadId: string | undefined; } export interface FeishuSendResult { /** One entry per message part sent, in order. Empty if Feishu omitted ids. */ readonly messages: readonly FeishuSentMessage[]; } export interface FeishuSendOptions { signal?: AbortSignal; } /** * A chat's effective conversation format. `topic` means new conversations are * topics — a native topic group, or an ordinary group switched to thread * message format. `group` means plain chat message format. The raw platform * fields that establish this (`chat_mode`, `group_message_type`) never leave * this transport. */ export type FeishuChatMode = 'p2p' | 'group' | 'topic'; /** * What a metadata read actually established. * * A caller uses this read as a permission proof, and the three answers it used * to collapse into `null` are not one fact: a token Feishu reports in * `failed_list` proves this app cannot see the document, a type the metadata * API does not take proves only that, and a request that failed proves nothing * at all — so it is not an answer here, it is a rejected promise. */ export type FeishuDocMetaResult = { readonly kind: 'visible'; } | { readonly kind: 'invisible'; } | { readonly kind: 'unsupported_type'; }; /** The document a wiki node points at. */ export interface FeishuWikiNode { objToken: string; objType: string; } export type FeishuMessageResourceType = 'file' | 'image'; export interface FeishuMessageResourceRequest { messageId: string; fileKey: string; type: FeishuMessageResourceType; } export interface FeishuMessageResourceResponse { stream: Readable; headers: Record; } export interface FeishuMessageResourceFetcher { fetchMessageResource(request: FeishuMessageResourceRequest): Promise; } export type RouteHandler = (raw: unknown) => Promise; export type InboundRoutes = Record; export interface FeishuTransport { readonly appId: string; readonly selfId: string | undefined; readonly selfName: string | undefined; start(routes: InboundRoutes): Promise; send(target: OutboundTarget, text: string, options?: FeishuSendOptions): Promise; sendCard(target: OutboundTarget, card: unknown, options?: FeishuSendOptions): Promise; /** * Optional capability for custom transports; callers must fail safe when absent. * * The result is the chat's effective conversation format, not its raw * `chat_mode`: `topic` covers both a native topic group (`chat_mode=topic`) * and an ordinary group currently using thread message format * (`chat_mode=group`, `group_message_type=thread`). A custom transport * reports effective format through this same capability. */ getChatMode?(chatId: string): Promise; /** Optional best-effort lookup of a chat's current Feishu name. */ resolveChatName?(chatId: string): Promise; addReaction(messageId: string, emoji: string): Promise; /** Repaint an already-sent card in place, by message id. */ editCard(messageId: string, card: unknown): Promise; fetchDocMeta(fileToken: string, fileType: string): Promise; /** * The text of the one comment a request names, or `null` when the thread * Feishu returns does not hold it. Every `null` means the same thing to a * caller — there is no text to show — so it is one value and not a * discriminated result. */ fetchDocCommentText(request: FeishuDocCommentRequest): Promise; /** * The document a wiki node holds, or `null` when this app cannot see that * node. A wiki URL names the node, while every comment API — and the * comment event itself — names the object inside it. */ resolveWikiNode(token: string): Promise; fetchMessageResource(request: FeishuMessageResourceRequest): Promise; readMessage?(request: FeishuMessageReadRequest): Promise; /** * The message a topic's replies hang under, asked of the platform by topic * id, or `undefined` when the topic lists no message. Optional like the * other reads: callers must fail safe when a custom transport lacks it. */ readThreadRoot?(threadId: string): Promise; /** Optional best-effort contact lookup for an accepted human sender. */ resolveUserName?(openId: string): Promise; /** * Optional COT (chain-of-thought) message operations. Absent on a custom or * older transport; callers must treat absence as "no COT surface" and keep * working without one. */ readonly cot?: FeishuCotClient; resolveAppOwner(): Promise; close(): Promise; } export interface FeishuCredentials { appId: string; appSecret: string; } export interface FeishuTransportOptions { client?: lark.Client; logger?: TransportLogger | undefined; } export declare function createFeishuTransport(creds: FeishuCredentials, options?: FeishuTransportOptions): FeishuTransport & FeishuMessageReader; //# sourceMappingURL=feishu.d.ts.map