@excitedjs/feishu-transport 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/contract/access-store.d.ts +23 -0
- package/dist/contract/access-store.d.ts.map +1 -0
- package/dist/contract/access-store.js +16 -0
- package/dist/contract/access-store.js.map +1 -0
- package/dist/contract/outbound.d.ts +39 -0
- package/dist/contract/outbound.d.ts.map +1 -0
- package/dist/contract/outbound.js +16 -0
- package/dist/contract/outbound.js.map +1 -0
- package/dist/contract/types.d.ts +86 -0
- package/dist/contract/types.d.ts.map +1 -0
- package/dist/contract/types.js +10 -0
- package/dist/contract/types.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +10 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +14 -0
- package/dist/json.js.map +1 -0
- package/dist/parse/comment.d.ts +41 -0
- package/dist/parse/comment.d.ts.map +1 -0
- package/dist/parse/comment.js +51 -0
- package/dist/parse/comment.js.map +1 -0
- package/dist/parse/content.d.ts +42 -0
- package/dist/parse/content.d.ts.map +1 -0
- package/dist/parse/content.js +208 -0
- package/dist/parse/content.js.map +1 -0
- package/dist/policy/gate.d.ts +105 -0
- package/dist/policy/gate.d.ts.map +1 -0
- package/dist/policy/gate.js +276 -0
- package/dist/policy/gate.js.map +1 -0
- package/dist/policy/pairing.d.ts +12 -0
- package/dist/policy/pairing.d.ts.map +1 -0
- package/dist/policy/pairing.js +15 -0
- package/dist/policy/pairing.js.map +1 -0
- package/dist/render/render.d.ts +186 -0
- package/dist/render/render.d.ts.map +1 -0
- package/dist/render/render.js +630 -0
- package/dist/render/render.js.map +1 -0
- package/dist/transport/connection.d.ts +25 -0
- package/dist/transport/connection.d.ts.map +1 -0
- package/dist/transport/connection.js +42 -0
- package/dist/transport/connection.js.map +1 -0
- package/dist/transport/feishu.d.ts +222 -0
- package/dist/transport/feishu.d.ts.map +1 -0
- package/dist/transport/feishu.js +431 -0
- package/dist/transport/feishu.js.map +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure log-line builders for the Feishu WebSocket connection lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* `createFeishuTransport` wires the SDK's connection callbacks to these, so a
|
|
5
|
+
* dropped or failed connection is always surfaced on the host's stderr instead
|
|
6
|
+
* of disappearing into the SDK's reconnect loop. The wording lives here — pure
|
|
7
|
+
* and free of any SDK dependency — so it is unit-testable. Ported verbatim from
|
|
8
|
+
* claudemux.
|
|
9
|
+
*/
|
|
10
|
+
/** The connection dropped and the SDK has begun a reconnect cycle. */
|
|
11
|
+
export declare function reconnectingLogLine(): string;
|
|
12
|
+
/** The reconnect cycle restored the connection. */
|
|
13
|
+
export declare function reconnectedLogLine(): string;
|
|
14
|
+
/**
|
|
15
|
+
* The SDK reported a connection error and stopped — a non-recoverable error,
|
|
16
|
+
* or an exhausted retry budget. The channel needs a restart to reconnect.
|
|
17
|
+
*/
|
|
18
|
+
export declare function connectionErrorLogLine(err: unknown): string;
|
|
19
|
+
/**
|
|
20
|
+
* The initial connection never came up within the startup grace window.
|
|
21
|
+
* `sdkGaveUp` is true when the SDK has already stopped retrying on its own,
|
|
22
|
+
* false when it is still looping and the channel is the one stopping it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function startupTimeoutLogLine(graceMs: number, sdkGaveUp: boolean): string;
|
|
25
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/transport/connection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,sEAAsE;AACtE,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,mDAAmD;AACnD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CASjF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure log-line builders for the Feishu WebSocket connection lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* `createFeishuTransport` wires the SDK's connection callbacks to these, so a
|
|
5
|
+
* dropped or failed connection is always surfaced on the host's stderr instead
|
|
6
|
+
* of disappearing into the SDK's reconnect loop. The wording lives here — pure
|
|
7
|
+
* and free of any SDK dependency — so it is unit-testable. Ported verbatim from
|
|
8
|
+
* claudemux.
|
|
9
|
+
*/
|
|
10
|
+
/** Extract a human-readable detail from an unknown thrown value. */
|
|
11
|
+
function detail(err) {
|
|
12
|
+
return err instanceof Error ? err.message : String(err);
|
|
13
|
+
}
|
|
14
|
+
/** The connection dropped and the SDK has begun a reconnect cycle. */
|
|
15
|
+
export function reconnectingLogLine() {
|
|
16
|
+
return 'Feishu connection lost — the SDK is reconnecting.';
|
|
17
|
+
}
|
|
18
|
+
/** The reconnect cycle restored the connection. */
|
|
19
|
+
export function reconnectedLogLine() {
|
|
20
|
+
return 'Feishu connection re-established.';
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The SDK reported a connection error and stopped — a non-recoverable error,
|
|
24
|
+
* or an exhausted retry budget. The channel needs a restart to reconnect.
|
|
25
|
+
*/
|
|
26
|
+
export function connectionErrorLogLine(err) {
|
|
27
|
+
return `Feishu connection failed and the SDK stopped retrying: ${detail(err)}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The initial connection never came up within the startup grace window.
|
|
31
|
+
* `sdkGaveUp` is true when the SDK has already stopped retrying on its own,
|
|
32
|
+
* false when it is still looping and the channel is the one stopping it.
|
|
33
|
+
*/
|
|
34
|
+
export function startupTimeoutLogLine(graceMs, sdkGaveUp) {
|
|
35
|
+
const secs = Math.round(graceMs / 1000);
|
|
36
|
+
const tail = sdkGaveUp
|
|
37
|
+
? 'the SDK has stopped retrying'
|
|
38
|
+
: 'stopping the connection attempt so it does not retry in a tight loop';
|
|
39
|
+
return (`Feishu connection did not come up within ${secs}s of startup; ${tail}. ` +
|
|
40
|
+
'Inbound events will not arrive until the channel is restarted.');
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/transport/connection.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,oEAAoE;AACpE,SAAS,MAAM,CAAC,GAAY;IAC1B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AACzD,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,mBAAmB;IACjC,OAAO,mDAAmD,CAAA;AAC5D,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,kBAAkB;IAChC,OAAO,mCAAmC,CAAA;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAY;IACjD,OAAO,0DAA0D,MAAM,CAAC,GAAG,CAAC,EAAE,CAAA;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAe,EAAE,SAAkB;IACvE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IACvC,MAAM,IAAI,GAAG,SAAS;QACpB,CAAC,CAAC,8BAA8B;QAChC,CAAC,CAAC,sEAAsE,CAAA;IAC1E,OAAO,CACL,4CAA4C,IAAI,iBAAiB,IAAI,IAAI;QACzE,gEAAgE,CACjE,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Feishu platform boundary — the only module in the workspace that imports
|
|
3
|
+
* the Feishu SDK.
|
|
4
|
+
*
|
|
5
|
+
* Everything that talks to Feishu — the inbound long-lived WebSocket and the
|
|
6
|
+
* outbound message API — sits behind the `FeishuTransport` interface. A host
|
|
7
|
+
* depends only on that interface, so its wiring can be exercised against an
|
|
8
|
+
* injected fake with no live connection.
|
|
9
|
+
*
|
|
10
|
+
* The transport is event-type agnostic. `start` is handed a route table mapping
|
|
11
|
+
* each Feishu event_type to a callback and registers every entry with the SDK's
|
|
12
|
+
* event dispatcher; decoding a specific event's payload is the job of that
|
|
13
|
+
* event's handler (see `../parse`), not this module. Adding a new event type to
|
|
14
|
+
* a host therefore never touches this file.
|
|
15
|
+
*
|
|
16
|
+
* Cross-process single-instance election is intentionally **not** here. dreamux
|
|
17
|
+
* gives each dispatcher its own bot identity (election is moot), and claudemux
|
|
18
|
+
* wraps this transport with its own elected-transport layer. Core opens the
|
|
19
|
+
* inbound WebSocket directly; whether exactly one process may do so is the
|
|
20
|
+
* host's concern, layered on top. (claudemux#155 §二 / dreamux#25 §7.2.)
|
|
21
|
+
*
|
|
22
|
+
* Ported from claudemux's `feishu-channel/src/feishu.ts` (the source of truth),
|
|
23
|
+
* with the instance-lock removed, `sendText` upgraded to the structured
|
|
24
|
+
* `send(OutboundTarget, …)` contract, and `botOpenId` renamed to `selfId`.
|
|
25
|
+
*/
|
|
26
|
+
import * as lark from '@larksuiteoapi/node-sdk';
|
|
27
|
+
import type { OutboundTarget } from '../contract/outbound.js';
|
|
28
|
+
/** Outcome of an outbound send. */
|
|
29
|
+
export interface FeishuSendResult {
|
|
30
|
+
/**
|
|
31
|
+
* message_ids of every card the send produced, in order. A Markdown body
|
|
32
|
+
* that fits one card produces one entry; a longer body that the renderer
|
|
33
|
+
* split over several cards produces several. Empty when Feishu omitted the
|
|
34
|
+
* message_ids.
|
|
35
|
+
*/
|
|
36
|
+
messageIds: string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build the `content` string for a Feishu plain-text message — the legacy
|
|
40
|
+
* `msg_type: 'text'` payload, used by `editText`'s fallback path so an edit
|
|
41
|
+
* on a message that was sent before this channel switched to interactive
|
|
42
|
+
* cards still works.
|
|
43
|
+
*/
|
|
44
|
+
export declare function textMessageContent(text: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Safe ceiling for the serialised card `content` string. Stays a few hundred
|
|
47
|
+
* bytes below the documented 30 KB request-body limit so HTTP headers and the
|
|
48
|
+
* `{ params, data: { receive_id, msg_type, content } }` envelope still fit.
|
|
49
|
+
*/
|
|
50
|
+
export declare const FEISHU_CARD_CONTENT_SAFE_BYTES: number;
|
|
51
|
+
/** One reply within a fetched document-comment thread. */
|
|
52
|
+
export interface FeishuDocCommentReply {
|
|
53
|
+
/** reply_id of this reply; `''` when Feishu omitted it. */
|
|
54
|
+
replyId: string;
|
|
55
|
+
/** open_id of the reply's author. */
|
|
56
|
+
authorId: string;
|
|
57
|
+
/** Raw Feishu rich-content elements of the reply body, rendered by the handler. */
|
|
58
|
+
elements: unknown[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A document comment and its reply thread, fetched to enrich a comment event.
|
|
62
|
+
*
|
|
63
|
+
* The `drive.notice.comment_add_v1` payload carries only the comment's ids, so
|
|
64
|
+
* the comment text is fetched separately — this is the fetched result.
|
|
65
|
+
*/
|
|
66
|
+
export interface FeishuDocComment {
|
|
67
|
+
/** False for a comment anchored to a text selection; `quote` then holds it. */
|
|
68
|
+
isWhole: boolean;
|
|
69
|
+
/** The selected text a local-selection comment is anchored to; `''` otherwise. */
|
|
70
|
+
quote: string;
|
|
71
|
+
/** The comment's replies, oldest first. */
|
|
72
|
+
replies: FeishuDocCommentReply[];
|
|
73
|
+
}
|
|
74
|
+
/** A document's human-readable identity, fetched to render a comment event. */
|
|
75
|
+
export interface FeishuDocMeta {
|
|
76
|
+
/** Document title. */
|
|
77
|
+
title: string;
|
|
78
|
+
/** Browser URL of the document. */
|
|
79
|
+
url: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* One comment as `drive.v1.fileComment.batchQuery` returns it — only the
|
|
83
|
+
* fields the channel reads. The SDK's response type carries more; this is the
|
|
84
|
+
* structural subset `commentFromBatchQuery` decodes, and the shape a unit
|
|
85
|
+
* test builds a fixture against.
|
|
86
|
+
*/
|
|
87
|
+
interface RawCommentItem {
|
|
88
|
+
comment_id?: string;
|
|
89
|
+
is_whole?: boolean;
|
|
90
|
+
quote?: string;
|
|
91
|
+
reply_list?: {
|
|
92
|
+
replies?: Array<{
|
|
93
|
+
reply_id?: string;
|
|
94
|
+
user_id?: string;
|
|
95
|
+
content?: {
|
|
96
|
+
elements?: unknown[];
|
|
97
|
+
};
|
|
98
|
+
}>;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Pick the comment with `commentId` out of a `fileComment.batchQuery` response
|
|
103
|
+
* and shape it into a `FeishuDocComment`. Returns `null` when the response
|
|
104
|
+
* carried no such comment. Pure: no I/O, never throws — exported so the decode
|
|
105
|
+
* is unit-tested without a live Feishu connection.
|
|
106
|
+
*/
|
|
107
|
+
export declare function commentFromBatchQuery(items: RawCommentItem[], commentId: string): FeishuDocComment | null;
|
|
108
|
+
/**
|
|
109
|
+
* A single inbound-event route handler. Receives the raw event payload exactly
|
|
110
|
+
* as the Feishu SDK delivered it; decoding it is the handler's job (`../parse`).
|
|
111
|
+
*
|
|
112
|
+
* Deferred-ACK invariant (claudemux#155 §七.3 / dreamux#25 §7.3): the Feishu SDK
|
|
113
|
+
* sends the platform ACK frame only **after** this promise resolves. The
|
|
114
|
+
* returned promise MUST therefore resolve only once the message is durable in
|
|
115
|
+
* the host (dreamux: the SQLite `enqueueInbound` INSERT; claudemux: the inbox
|
|
116
|
+
* tmp+rename). Returning before durability — or returning a non-promise — would
|
|
117
|
+
* ACK an unpersisted message and lose it on a crash. The type is
|
|
118
|
+
* `=> Promise<void>`, not `=> void | Promise<void>`, precisely to keep that
|
|
119
|
+
* gate from being bypassed by a synchronous handler.
|
|
120
|
+
*/
|
|
121
|
+
export type RouteHandler = (raw: unknown) => Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Inbound event routes: Feishu event_type → handler. A host builds this from
|
|
124
|
+
* its event registry; the transport registers every entry with the SDK's event
|
|
125
|
+
* dispatcher.
|
|
126
|
+
*/
|
|
127
|
+
export type InboundRoutes = Record<string, RouteHandler>;
|
|
128
|
+
/**
|
|
129
|
+
* The platform boundary a host depends on. The real implementation
|
|
130
|
+
* (`createFeishuTransport`) wraps the Feishu SDK; tests inject a fake so the
|
|
131
|
+
* inbound and outbound wiring runs without a live Feishu connection.
|
|
132
|
+
*/
|
|
133
|
+
export interface FeishuTransport {
|
|
134
|
+
/** The app id this transport was created with. */
|
|
135
|
+
readonly appId: string;
|
|
136
|
+
/**
|
|
137
|
+
* open_id of the bot itself, for group mention-gating. `undefined` until
|
|
138
|
+
* `start` has resolved it (and stays `undefined` if resolution failed).
|
|
139
|
+
*/
|
|
140
|
+
readonly selfId: string | undefined;
|
|
141
|
+
/**
|
|
142
|
+
* Open the inbound WebSocket and dispatch every subscribed event_type through
|
|
143
|
+
* `routes`. Core opens the connection directly — single-instance election, if
|
|
144
|
+
* a deployment needs it, is layered on top by the host. **Rejects** if the
|
|
145
|
+
* connection does not come up within the startup grace window, so a host can
|
|
146
|
+
* fail a dispatcher loudly instead of registering a silently-dark bot.
|
|
147
|
+
*/
|
|
148
|
+
start(routes: InboundRoutes): Promise<void>;
|
|
149
|
+
/**
|
|
150
|
+
* Send a text message to the target chat. Routed by `chat_id`, never by a
|
|
151
|
+
* message_id, so a forged reply target cannot redirect the message into an
|
|
152
|
+
* unrelated conversation.
|
|
153
|
+
*
|
|
154
|
+
* PR1 reads only `target.chatId` (behavior-identical to the old
|
|
155
|
+
* `sendText(chatId, text)`). Honoring `target.replyToMessageId` (reply-threading
|
|
156
|
+
* via `im.message.reply`) and `target.mentionUserIds` (auto @-back) lands in
|
|
157
|
+
* dreamux#25 PR2 (gap ④), with its own tests; `target.conversationKey` is a
|
|
158
|
+
* channel-layer routing hint the transport never reads.
|
|
159
|
+
*/
|
|
160
|
+
send(target: OutboundTarget, text: string): Promise<FeishuSendResult>;
|
|
161
|
+
/**
|
|
162
|
+
* Add an emoji reaction to a message and return the reaction_id Feishu
|
|
163
|
+
* assigned. That id is what `removeReaction` needs to take the same reaction
|
|
164
|
+
* back off; Feishu can omit it, in which case an empty string is returned.
|
|
165
|
+
*/
|
|
166
|
+
addReaction(messageId: string, emoji: string): Promise<string>;
|
|
167
|
+
/**
|
|
168
|
+
* Remove a reaction from a message, identified by the reaction_id that
|
|
169
|
+
* `addReaction` returned. Feishu only lets the app that added a reaction
|
|
170
|
+
* remove it, so this is always paired with a prior `addReaction` from the
|
|
171
|
+
* same channel.
|
|
172
|
+
*/
|
|
173
|
+
removeReaction(messageId: string, reactionId: string): Promise<void>;
|
|
174
|
+
/** Replace the text of a message the bot previously sent. */
|
|
175
|
+
editText(messageId: string, text: string): Promise<void>;
|
|
176
|
+
/**
|
|
177
|
+
* Fetch one document comment and its reply thread. The comment-add event
|
|
178
|
+
* payload carries no comment text, so the doc-comment handler calls this to
|
|
179
|
+
* fill it in. Best-effort: returns `null` for a file type with no comment
|
|
180
|
+
* API or on any API failure, and never throws — a failure degrades the
|
|
181
|
+
* notification rather than dropping the event.
|
|
182
|
+
*/
|
|
183
|
+
fetchDocComment(fileToken: string, fileType: string, commentId: string): Promise<FeishuDocComment | null>;
|
|
184
|
+
/**
|
|
185
|
+
* Fetch a document's title and URL, so a comment notification names the
|
|
186
|
+
* document a human would recognize. Best-effort: returns `null` for a file
|
|
187
|
+
* type with no metadata API or on any API failure, and never throws.
|
|
188
|
+
*/
|
|
189
|
+
fetchDocMeta(fileToken: string, fileType: string): Promise<FeishuDocMeta | null>;
|
|
190
|
+
/** Close the connection and release every resource it holds. */
|
|
191
|
+
close(): Promise<void>;
|
|
192
|
+
}
|
|
193
|
+
/** Feishu self-built-app credentials. */
|
|
194
|
+
export interface FeishuCredentials {
|
|
195
|
+
appId: string;
|
|
196
|
+
appSecret: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Optional knobs for `createFeishuTransport`. The `client` seam lets unit
|
|
200
|
+
* tests inject a stub of just the SDK methods this module touches, so the
|
|
201
|
+
* outbound paths (`send`, `editText`, the doc-comment fetchers) are covered
|
|
202
|
+
* without a live Feishu app.
|
|
203
|
+
*/
|
|
204
|
+
export interface FeishuTransportOptions {
|
|
205
|
+
/**
|
|
206
|
+
* SDK client to use for outbound API calls. Default: a fresh `lark.Client`
|
|
207
|
+
* built from `creds`. Tests pass a stub; production never sets this.
|
|
208
|
+
*/
|
|
209
|
+
client?: lark.Client;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* The real Feishu transport, wrapping the official SDK.
|
|
213
|
+
*
|
|
214
|
+
* Inbound: a `WSClient` opens a long-lived WebSocket and an `EventDispatcher`
|
|
215
|
+
* routes every subscribed event_type to its callback. Outbound: a `Client`
|
|
216
|
+
* calls the `im` message API; it manages the `tenant_access_token` internally.
|
|
217
|
+
* The outbound paths are unit-tested through the `client` seam in
|
|
218
|
+
* `FeishuTransportOptions`; inbound still needs a live Feishu connection.
|
|
219
|
+
*/
|
|
220
|
+
export declare function createFeishuTransport(creds: FeishuCredentials, options?: FeishuTransportOptions): FeishuTransport;
|
|
221
|
+
export {};
|
|
222
|
+
//# sourceMappingURL=feishu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feishu.d.ts","sourceRoot":"","sources":["../../src/transport/feishu.ts"],"names":[],"mappings":"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"}
|