@clowder-ai/connector-feishu 0.0.0-stage → 0.1.0-alpha.5
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.en.md +54 -0
- package/README.md +25 -2
- package/assets/icon.svg +3 -0
- package/dist/FeishuAdapter.d.ts +250 -0
- package/dist/FeishuAdapter.d.ts.map +1 -0
- package/dist/FeishuAdapter.js +845 -0
- package/dist/FeishuAdapter.js.map +1 -0
- package/dist/FeishuQrBindClient.d.ts +23 -0
- package/dist/FeishuQrBindClient.d.ts.map +1 -0
- package/dist/FeishuQrBindClient.js +97 -0
- package/dist/FeishuQrBindClient.js.map +1 -0
- package/dist/FeishuTokenManager.d.ts +15 -0
- package/dist/FeishuTokenManager.d.ts.map +1 -0
- package/dist/FeishuTokenManager.js +35 -0
- package/dist/FeishuTokenManager.js.map +1 -0
- package/dist/command-ingress.d.ts +10 -0
- package/dist/command-ingress.d.ts.map +1 -0
- package/dist/command-ingress.js +15 -0
- package/dist/command-ingress.js.map +1 -0
- package/dist/execution-status.d.ts +27 -0
- package/dist/execution-status.d.ts.map +1 -0
- package/dist/execution-status.js +48 -0
- package/dist/execution-status.js.map +1 -0
- package/dist/feishu-card-formatter.d.ts +18 -0
- package/dist/feishu-card-formatter.d.ts.map +1 -0
- package/dist/feishu-card-formatter.js +58 -0
- package/dist/feishu-card-formatter.js.map +1 -0
- package/dist/inbound-download.d.ts +13 -0
- package/dist/inbound-download.d.ts.map +1 -0
- package/dist/inbound-download.js +70 -0
- package/dist/inbound-download.js.map +1 -0
- package/dist/inbound-media-source.d.ts +25 -0
- package/dist/inbound-media-source.d.ts.map +1 -0
- package/dist/inbound-media-source.js +111 -0
- package/dist/inbound-media-source.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle-action.d.ts +30 -0
- package/dist/lifecycle-action.d.ts.map +1 -0
- package/dist/lifecycle-action.js +457 -0
- package/dist/lifecycle-action.js.map +1 -0
- package/dist/materialize-media.d.ts +7 -0
- package/dist/materialize-media.d.ts.map +1 -0
- package/dist/materialize-media.js +35 -0
- package/dist/materialize-media.js.map +1 -0
- package/dist/media-notice.d.ts +6 -0
- package/dist/media-notice.d.ts.map +1 -0
- package/dist/media-notice.js +50 -0
- package/dist/media-notice.js.map +1 -0
- package/dist/plugin-entrypoint.d.ts +9 -0
- package/dist/plugin-entrypoint.d.ts.map +1 -0
- package/dist/plugin-entrypoint.js +347 -0
- package/dist/plugin-entrypoint.js.map +1 -0
- package/dist/reply-sender-map.d.ts +10 -0
- package/dist/reply-sender-map.d.ts.map +1 -0
- package/dist/reply-sender-map.js +123 -0
- package/dist/reply-sender-map.js.map +1 -0
- package/dist/runtime.d.ts +190 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +580 -0
- package/dist/runtime.js.map +1 -0
- package/dist/settings.d.ts +20 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +35 -0
- package/dist/settings.js.map +1 -0
- package/dist/thread-mappings.d.ts +46 -0
- package/dist/thread-mappings.d.ts.map +1 -0
- package/dist/thread-mappings.js +62 -0
- package/dist/thread-mappings.js.map +1 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/npm-shrinkwrap.json +979 -0
- package/package.json +58 -4
- package/plugin.yaml +118 -0
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import * as lark from '@larksuiteoapi/node-sdk';
|
|
2
|
+
import { FeishuAdapter, } from './FeishuAdapter.js';
|
|
3
|
+
import { FeishuTokenManager } from './FeishuTokenManager.js';
|
|
4
|
+
const WS_START_TIMEOUT_MS = 30_000;
|
|
5
|
+
const WS_CONNECT_POLL_MS = 250;
|
|
6
|
+
/** WebSocket.OPEN — the lark SDK's own liveness truth (es/index.js isOpen). */
|
|
7
|
+
const WS_READY_STATE_OPEN = 1;
|
|
8
|
+
function terminateWsInstance(ws) {
|
|
9
|
+
if (ws === null || ws === undefined || typeof ws !== 'object')
|
|
10
|
+
return;
|
|
11
|
+
const socket = ws;
|
|
12
|
+
socket.removeAllListeners?.();
|
|
13
|
+
socket.terminate?.();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* F2/F3: the lark WSClient cannot cancel a connection that is still
|
|
17
|
+
* handshaking — `close()` only touches the socket registered after 'open',
|
|
18
|
+
* so a stop() landing pre-open would leave an authenticated socket that
|
|
19
|
+
* starts pingLoop and self-reconnects forever (an orphan nobody can kill).
|
|
20
|
+
*
|
|
21
|
+
* This facade makes teardown deterministic:
|
|
22
|
+
* - `close()` terminates the current socket AND installs a birth guard that
|
|
23
|
+
* terminates any socket the SDK opens afterwards, plus a pingLoop no-op so
|
|
24
|
+
* a late 'open' cannot restart the ping timer.
|
|
25
|
+
* - `start()` does not settle until the SDK has registered an open socket
|
|
26
|
+
* (lark `WSClient.start()` resolves in the same tick it kicks off
|
|
27
|
+
* `reConnect(true)`, so without this the runtime would report `running`
|
|
28
|
+
* before anything is connected), or aborts on stop/timeout/SDK give-up.
|
|
29
|
+
* - after `start()` settles, the open socket's 'close' event drives the
|
|
30
|
+
* optional `onClose` hook (suppressed when `close()` initiated it), so the
|
|
31
|
+
* runtime can drop out of 'running' and schedule a reconnect instead of
|
|
32
|
+
* reporting a dead connection as live.
|
|
33
|
+
*
|
|
34
|
+
* `autoReconnect: false` is deliberate: SDK-owned reconnection was the F2
|
|
35
|
+
* revival mechanism. Reconnect supervision belongs to the Host lifecycle.
|
|
36
|
+
*/
|
|
37
|
+
export class PausableLarkWsClient {
|
|
38
|
+
inner;
|
|
39
|
+
hooks;
|
|
40
|
+
stopped = false;
|
|
41
|
+
constructor(appId, appSecret, inner, hooks = {}) {
|
|
42
|
+
this.inner = inner ?? new lark.WSClient({
|
|
43
|
+
appId,
|
|
44
|
+
appSecret,
|
|
45
|
+
loggerLevel: lark.LoggerLevel.info,
|
|
46
|
+
autoReconnect: false,
|
|
47
|
+
});
|
|
48
|
+
this.hooks = hooks;
|
|
49
|
+
}
|
|
50
|
+
async start(options) {
|
|
51
|
+
await this.inner.start(options);
|
|
52
|
+
const deadline = Date.now() + WS_START_TIMEOUT_MS;
|
|
53
|
+
for (;;) {
|
|
54
|
+
if (this.stopped)
|
|
55
|
+
throw new Error('Feishu WSClient stopped during connect');
|
|
56
|
+
const socket = this.inner.wsConfig.getWSInstance();
|
|
57
|
+
if (socket !== null) {
|
|
58
|
+
// H1: registration is not liveness. The lark SDK's own isOpen checks
|
|
59
|
+
// use readyState === OPEN (es/index.js ~85475); with autoReconnect off
|
|
60
|
+
// a closed socket stays registered (the close handler returns before
|
|
61
|
+
// setWSInstance(null)), so a bare `!== null` accepts a corpse and
|
|
62
|
+
// reports 'running' over a dead socket with no recovery. Refusing here
|
|
63
|
+
// routes the failure into the runtime's supervised reconnect instead.
|
|
64
|
+
if (socket.readyState === WS_READY_STATE_OPEN) {
|
|
65
|
+
this.watchSocketClose(socket);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`Feishu WSClient registered a socket that is not OPEN (readyState=${String(socket.readyState)}); refusing to treat a dead socket as connected`);
|
|
69
|
+
}
|
|
70
|
+
// Fail fast when the SDK has already given up: with autoReconnect off a
|
|
71
|
+
// failed handshake logs 'connect failed' and returns in about a second,
|
|
72
|
+
// clearing isConnecting long before the 30s deadline. Without this the
|
|
73
|
+
// start loop would spin the full timeout on every bad-credential boot.
|
|
74
|
+
if (this.inner.isConnecting === false) {
|
|
75
|
+
throw new Error('Feishu WSClient aborted the connection attempt before a socket opened');
|
|
76
|
+
}
|
|
77
|
+
if (Date.now() >= deadline) {
|
|
78
|
+
throw new Error(`Feishu WSClient start timed out after ${WS_START_TIMEOUT_MS}ms`);
|
|
79
|
+
}
|
|
80
|
+
await new Promise((resolve) => setTimeout(resolve, WS_CONNECT_POLL_MS));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
watchSocketClose(socket) {
|
|
84
|
+
// The socket was readyState === OPEN when accepted in start()'s poll loop
|
|
85
|
+
// (same tick, no I/O in between), so only the asynchronous 'close' path
|
|
86
|
+
// matters here; a synchronous CLOSING/CLOSED check at attach time can no
|
|
87
|
+
// longer trigger and would fire while the runtime is still 'starting',
|
|
88
|
+
// where the hook's signal gets dropped (H1).
|
|
89
|
+
const emitter = socket;
|
|
90
|
+
if (typeof emitter !== 'object' || emitter === null || typeof emitter.on !== 'function')
|
|
91
|
+
return;
|
|
92
|
+
emitter.on('close', () => {
|
|
93
|
+
if (this.stopped)
|
|
94
|
+
return; // close() terminates the socket itself
|
|
95
|
+
this.hooks.onClose?.();
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
close() {
|
|
99
|
+
if (this.stopped)
|
|
100
|
+
return;
|
|
101
|
+
this.stopped = true;
|
|
102
|
+
const wsConfig = this.inner.wsConfig;
|
|
103
|
+
const originalSet = wsConfig.setWSInstance.bind(wsConfig);
|
|
104
|
+
wsConfig.setWSInstance = (ws) => {
|
|
105
|
+
if (ws === null || ws === undefined) {
|
|
106
|
+
originalSet(ws);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Socket born after stop: kill before the SDK registers/uses it.
|
|
110
|
+
terminateWsInstance(ws);
|
|
111
|
+
};
|
|
112
|
+
// A late 'open' would otherwise start the ping timer again.
|
|
113
|
+
this.inner.pingLoop = () => undefined;
|
|
114
|
+
terminateWsInstance(wsConfig.getWSInstance());
|
|
115
|
+
this.inner.close({ force: true });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function trimValue(value) {
|
|
119
|
+
return value.trim();
|
|
120
|
+
}
|
|
121
|
+
function hasCredentials(config) {
|
|
122
|
+
return config.appId.length > 0 && config.appSecret.length > 0;
|
|
123
|
+
}
|
|
124
|
+
function parseMentions(value) {
|
|
125
|
+
if (value === undefined || value.trim() === '')
|
|
126
|
+
return undefined;
|
|
127
|
+
let candidate;
|
|
128
|
+
try {
|
|
129
|
+
candidate = JSON.parse(value);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
throw new TypeError('groupBotMentionsJson must be valid JSON');
|
|
133
|
+
}
|
|
134
|
+
if (candidate === null || typeof candidate !== 'object' || Array.isArray(candidate)) {
|
|
135
|
+
throw new TypeError('groupBotMentionsJson must be an object');
|
|
136
|
+
}
|
|
137
|
+
const result = {};
|
|
138
|
+
for (const [rawAlias, rawTarget] of Object.entries(candidate)) {
|
|
139
|
+
const alias = rawAlias.trim();
|
|
140
|
+
if (alias.length === 0 || rawTarget === null || typeof rawTarget !== 'object' || Array.isArray(rawTarget)) {
|
|
141
|
+
throw new TypeError('groupBotMentionsJson entries must contain an alias and target object');
|
|
142
|
+
}
|
|
143
|
+
const target = rawTarget;
|
|
144
|
+
if (typeof target.openId !== 'string' || target.openId.trim() === '') {
|
|
145
|
+
throw new TypeError(`groupBotMentionsJson.${alias}.openId must be non-empty`);
|
|
146
|
+
}
|
|
147
|
+
result[alias] = {
|
|
148
|
+
openId: target.openId.trim(),
|
|
149
|
+
...(typeof target.displayName === 'string' && target.displayName.trim() !== ''
|
|
150
|
+
? { displayName: target.displayName.trim() } : {}),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
export function requireFeishuWebhookInput(candidate) {
|
|
156
|
+
if (candidate === null || typeof candidate !== 'object' || Array.isArray(candidate)) {
|
|
157
|
+
throw new TypeError('feishu webhook input must be an object');
|
|
158
|
+
}
|
|
159
|
+
return { body: candidate.body };
|
|
160
|
+
}
|
|
161
|
+
async function providerMessage(adapter, message) {
|
|
162
|
+
let senderName = message.senderName;
|
|
163
|
+
let chatName = message.chatName;
|
|
164
|
+
if (message.chatType === 'group') {
|
|
165
|
+
senderName ??= await adapter.resolveSenderName(message.senderId).catch(() => undefined);
|
|
166
|
+
senderName ??= await adapter.resolveSenderNameFromChat(message.senderId, message.chatId).catch(() => undefined);
|
|
167
|
+
chatName ??= await adapter.resolveChatName(message.chatId).catch(() => undefined);
|
|
168
|
+
}
|
|
169
|
+
const attachments = message.attachments?.map(attachment => ({
|
|
170
|
+
type: attachment.type,
|
|
171
|
+
platformKey: attachment.feishuKey,
|
|
172
|
+
...(attachment.fileName === undefined ? {} : { fileName: attachment.fileName }),
|
|
173
|
+
...(attachment.duration === undefined ? {} : { duration: attachment.duration }),
|
|
174
|
+
}));
|
|
175
|
+
const sender = message.chatType === 'group' && message.senderId !== 'unknown'
|
|
176
|
+
? { id: message.senderId, ...(senderName === undefined ? {} : { name: senderName }) }
|
|
177
|
+
: undefined;
|
|
178
|
+
return {
|
|
179
|
+
externalConversationId: message.chatId,
|
|
180
|
+
providerMessageId: message.messageId,
|
|
181
|
+
...(message.senderId === 'unknown' || message.senderId.trim() === '' ? {} : { externalSenderId: message.senderId }),
|
|
182
|
+
text: message.text,
|
|
183
|
+
...(attachments === undefined ? {} : { attachments }),
|
|
184
|
+
...(sender === undefined ? {} : { sender }),
|
|
185
|
+
conversation: {
|
|
186
|
+
type: message.chatType === 'group' ? 'group' : 'direct',
|
|
187
|
+
...(chatName === undefined ? {} : { title: chatName }),
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
async function cardMessage(adapter, action) {
|
|
192
|
+
const value = action.actionValue;
|
|
193
|
+
const command = typeof value.cmd === 'string' && value.cmd.startsWith('/')
|
|
194
|
+
? `${value.cmd}${typeof value.args === 'string' && value.args ? ` ${value.args}` : ''}`
|
|
195
|
+
: action.option?.startsWith('/') ? action.option : undefined;
|
|
196
|
+
const chatType = action.chatType ?? await adapter.resolveChatType(action.chatId);
|
|
197
|
+
if (chatType === undefined)
|
|
198
|
+
return null;
|
|
199
|
+
return {
|
|
200
|
+
externalConversationId: action.chatId,
|
|
201
|
+
providerMessageId: action.eventId,
|
|
202
|
+
...(action.senderId === 'unknown' || action.senderId.trim() === '' ? {} : { externalSenderId: action.senderId }),
|
|
203
|
+
text: command ?? JSON.stringify(action.actionValue),
|
|
204
|
+
...(command === undefined || action.senderId === '' ? {} : { sender: { id: action.senderId } }),
|
|
205
|
+
conversation: { type: chatType === 'group' ? 'group' : 'direct' },
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
export function createFeishuConnectorRuntime(options) {
|
|
209
|
+
// Credentials may arrive only later via the feishu_qr_login operation — empty
|
|
210
|
+
// values mean the runtime starts healthy and idle (no ingress) until connect().
|
|
211
|
+
let current = {
|
|
212
|
+
appId: trimValue(options.config.appId),
|
|
213
|
+
appSecret: trimValue(options.config.appSecret),
|
|
214
|
+
connectionMode: options.config.connectionMode,
|
|
215
|
+
...(options.config.verificationToken === undefined ? {} : { verificationToken: options.config.verificationToken }),
|
|
216
|
+
...(options.config.groupBotMentionsJson === undefined ? {} : { groupBotMentionsJson: options.config.groupBotMentionsJson }),
|
|
217
|
+
};
|
|
218
|
+
const createAdapter = options.createAdapter ?? ((id, secret, logger, value) => new FeishuAdapter(id, secret, logger, value));
|
|
219
|
+
const buildAdapterOptions = () => {
|
|
220
|
+
const groupBotMentions = parseMentions(current.groupBotMentionsJson);
|
|
221
|
+
return {
|
|
222
|
+
...(current.verificationToken === undefined ? {} : { verificationToken: current.verificationToken }),
|
|
223
|
+
...(groupBotMentions === undefined ? {} : { groupBotMentions }),
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
let outbound = hasCredentials(current)
|
|
227
|
+
? createAdapter(current.appId, current.appSecret, options.logger, buildAdapterOptions())
|
|
228
|
+
: undefined;
|
|
229
|
+
let tokenManager;
|
|
230
|
+
const buildTokenManager = () => (new FeishuTokenManager({ appId: current.appId, appSecret: current.appSecret, ...(options.fetchFn === undefined ? {} : { fetchFn: options.fetchFn }) }));
|
|
231
|
+
if (outbound !== undefined) {
|
|
232
|
+
tokenManager = buildTokenManager();
|
|
233
|
+
outbound._injectTokenManager?.(tokenManager);
|
|
234
|
+
}
|
|
235
|
+
const requireOutbound = () => {
|
|
236
|
+
if (outbound === undefined) {
|
|
237
|
+
throw new Error('Feishu connector is not configured — complete QR authorization (feishu_qr_login) first');
|
|
238
|
+
}
|
|
239
|
+
return outbound;
|
|
240
|
+
};
|
|
241
|
+
let state = 'idle';
|
|
242
|
+
let ingressEpoch = 0;
|
|
243
|
+
const isCurrent = (epoch) => epoch === ingressEpoch && state !== 'stopped';
|
|
244
|
+
let armed = false;
|
|
245
|
+
let startPromise;
|
|
246
|
+
let stopPromise;
|
|
247
|
+
let wsClient;
|
|
248
|
+
let identityAbort;
|
|
249
|
+
const identityTasks = new Set();
|
|
250
|
+
let reconnectTimer;
|
|
251
|
+
const reconnectBaseDelayMs = options.reconnectDelayMs ?? 5_000;
|
|
252
|
+
const reconnectMaxDelayMs = options.reconnectMaxDelayMs ?? 60_000;
|
|
253
|
+
// Backoff, not a fixed interval: each consecutive failed supervise attempt
|
|
254
|
+
// doubles the delay (capped), so a persistently dead endpoint is retried
|
|
255
|
+
// ~70x/hour instead of ~700x, and each retry no longer hammers a fresh
|
|
256
|
+
// tenant_access_token at a constant cadence. Reset on every transition into
|
|
257
|
+
// 'running'.
|
|
258
|
+
let reconnectAttempts = 0;
|
|
259
|
+
const nextBackoffMs = () => {
|
|
260
|
+
const exponential = Math.min(reconnectBaseDelayMs * 2 ** reconnectAttempts, reconnectMaxDelayMs);
|
|
261
|
+
reconnectAttempts += 1;
|
|
262
|
+
// ±20% jitter keeps simultaneous connectors from lock-stepping the Host.
|
|
263
|
+
return Math.round(exponential * (0.8 + Math.random() * 0.4));
|
|
264
|
+
};
|
|
265
|
+
// Both return the real delivery outcome so callers can derive their
|
|
266
|
+
// reported state from it instead of asserting success independently (G3):
|
|
267
|
+
// a message dropped by the state recheck must never be reported 'processed'.
|
|
268
|
+
const routeEvent = async (message, webhookEventId) => {
|
|
269
|
+
if (state !== 'running')
|
|
270
|
+
return false;
|
|
271
|
+
const hostMessage = await providerMessage(requireOutbound(), message);
|
|
272
|
+
// Group chats await name-resolution round-trips above; stop() landing in
|
|
273
|
+
// that window must not still deliver (TOCTOU recheck after the await).
|
|
274
|
+
if (state !== 'running')
|
|
275
|
+
return false;
|
|
276
|
+
// The webhook transport has a provider delivery ID distinct from the IM
|
|
277
|
+
// message ID. Replays of that delivery must carry the same Host source key.
|
|
278
|
+
await options.host.deliver(webhookEventId === undefined
|
|
279
|
+
? hostMessage : { ...hostMessage, providerMessageId: webhookEventId });
|
|
280
|
+
return true;
|
|
281
|
+
};
|
|
282
|
+
const routeCard = async (action) => {
|
|
283
|
+
if (state !== 'running')
|
|
284
|
+
return 'not_running';
|
|
285
|
+
const message = await cardMessage(requireOutbound(), action);
|
|
286
|
+
if (message === null)
|
|
287
|
+
return 'chat_type_unknown';
|
|
288
|
+
if (state !== 'running')
|
|
289
|
+
return 'not_running';
|
|
290
|
+
await options.host.deliver(message);
|
|
291
|
+
return 'delivered';
|
|
292
|
+
};
|
|
293
|
+
const startIngress = async () => {
|
|
294
|
+
const adapter = requireOutbound();
|
|
295
|
+
const manager = tokenManager ?? buildTokenManager();
|
|
296
|
+
tokenManager = manager;
|
|
297
|
+
// Identity discovery is optional, but its I/O still belongs to this
|
|
298
|
+
// ingress generation. Retiring it must not access a revoked Host logger
|
|
299
|
+
// or publish an old identity into an adapter after disconnect/reconfigure.
|
|
300
|
+
identityAbort?.abort();
|
|
301
|
+
const cancellation = new AbortController();
|
|
302
|
+
identityAbort = cancellation;
|
|
303
|
+
const signal = AbortSignal.any([cancellation.signal, AbortSignal.timeout(30_000)]);
|
|
304
|
+
const identityTask = manager.getTenantAccessToken(signal).then(async (token) => {
|
|
305
|
+
signal.throwIfAborted();
|
|
306
|
+
const response = await (options.fetchFn ?? globalThis.fetch)('https://open.feishu.cn/open-apis/bot/v3/info', {
|
|
307
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
308
|
+
signal,
|
|
309
|
+
});
|
|
310
|
+
signal.throwIfAborted();
|
|
311
|
+
if (!response.ok)
|
|
312
|
+
return;
|
|
313
|
+
const data = await response.json();
|
|
314
|
+
signal.throwIfAborted();
|
|
315
|
+
if (data.bot?.open_id)
|
|
316
|
+
adapter.setBotOpenId(data.bot.open_id);
|
|
317
|
+
}).catch(error => {
|
|
318
|
+
if (!cancellation.signal.aborted) {
|
|
319
|
+
options.logger.warn({ error }, '[FeishuRuntime] Bot identity resolution failed');
|
|
320
|
+
}
|
|
321
|
+
}).finally(() => { identityTasks.delete(identityTask); });
|
|
322
|
+
identityTasks.add(identityTask);
|
|
323
|
+
if (current.connectionMode !== 'websocket')
|
|
324
|
+
return;
|
|
325
|
+
const dispatcher = new lark.EventDispatcher({}).register({
|
|
326
|
+
'im.message.receive_v1': async (data) => {
|
|
327
|
+
const parsed = adapter.parseEvent({ header: { event_type: 'im.message.receive_v1' }, event: data });
|
|
328
|
+
if (parsed !== null)
|
|
329
|
+
await routeEvent(parsed);
|
|
330
|
+
},
|
|
331
|
+
'card.action.trigger': async (data) => {
|
|
332
|
+
const parsed = adapter.parseCardAction({
|
|
333
|
+
header: { event_type: 'card.action.trigger', event_id: data.event_id }, event: data,
|
|
334
|
+
});
|
|
335
|
+
if (parsed !== null)
|
|
336
|
+
await routeCard(parsed);
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
const createWs = options.createWsClient ?? ((value) => (new PausableLarkWsClient(value.appId, value.appSecret, undefined, { onClose: value.onClose })));
|
|
340
|
+
const client = createWs({ appId: current.appId, appSecret: current.appSecret, onClose: () => handleUnexpectedClose(client) });
|
|
341
|
+
wsClient = client;
|
|
342
|
+
// PausableLarkWsClient.start() settles only once the socket is really
|
|
343
|
+
// open (or stop/timeout/SDK give-up aborts it), so no outer timer needed.
|
|
344
|
+
// On rejection the client must be torn down here: an un-closed client
|
|
345
|
+
// keeps its registered socket, ping loop and close hook alive — the F2
|
|
346
|
+
// orphan the facade exists to prevent, now on the routine failure path
|
|
347
|
+
// (H1 made start() throw for dead sockets instead of accepting them).
|
|
348
|
+
try {
|
|
349
|
+
await client.start({ eventDispatcher: dispatcher });
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
client.close({ force: true });
|
|
353
|
+
if (wsClient === client)
|
|
354
|
+
wsClient = undefined;
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
// G1: the only trustworthy signal of a dead ingress is the socket's own
|
|
359
|
+
// 'close' event (the lark SDK leaves a dead socket registered when
|
|
360
|
+
// autoReconnect is off, so polling its registry would report 'alive').
|
|
361
|
+
// B3: the callback carries its originating client and only the CURRENT
|
|
362
|
+
// client may tear the connection down — a leaked/orphaned client's late
|
|
363
|
+
// close must not kill a healthy successor.
|
|
364
|
+
const handleUnexpectedClose = (caller) => {
|
|
365
|
+
if (wsClient !== caller)
|
|
366
|
+
return; // orphan close: not our connection
|
|
367
|
+
// PausableLarkWsClient suppresses the callback for stop-initiated closes
|
|
368
|
+
// via its stopped guard, so reaching here means an unexpected drop.
|
|
369
|
+
if (state !== 'running')
|
|
370
|
+
return;
|
|
371
|
+
identityAbort?.abort();
|
|
372
|
+
const dead = wsClient;
|
|
373
|
+
wsClient = undefined;
|
|
374
|
+
state = 'idle'; // no live inbound during reconnect; webhooks derive skipped
|
|
375
|
+
startPromise = undefined;
|
|
376
|
+
dead?.close({ force: true });
|
|
377
|
+
scheduleReconnect('ingress socket closed unexpectedly');
|
|
378
|
+
};
|
|
379
|
+
const scheduleReconnect = (reason) => {
|
|
380
|
+
if (state === 'stopped' || reconnectTimer !== undefined)
|
|
381
|
+
return;
|
|
382
|
+
const delayMs = nextBackoffMs();
|
|
383
|
+
options.logger.error(`[FeishuRuntime] ${reason}; reconnecting in ${delayMs}ms`);
|
|
384
|
+
reconnectTimer = setTimeout(() => {
|
|
385
|
+
reconnectTimer = undefined;
|
|
386
|
+
if (state !== 'idle')
|
|
387
|
+
return; // stop() or a fresh start() superseded it
|
|
388
|
+
state = 'starting';
|
|
389
|
+
const epoch = ingressEpoch;
|
|
390
|
+
startPromise = startIngress()
|
|
391
|
+
.then(() => {
|
|
392
|
+
if (isCurrent(epoch)) {
|
|
393
|
+
reconnectAttempts = 0;
|
|
394
|
+
state = 'running';
|
|
395
|
+
options.logger.info('[FeishuRuntime] Provider ingress started');
|
|
396
|
+
}
|
|
397
|
+
})
|
|
398
|
+
.catch((error) => {
|
|
399
|
+
// Timer-context rejection: never rethrow (unhandled rejection);
|
|
400
|
+
// log and reschedule the backoff instead.
|
|
401
|
+
if (!isCurrent(epoch))
|
|
402
|
+
return;
|
|
403
|
+
state = 'idle';
|
|
404
|
+
startPromise = undefined;
|
|
405
|
+
options.logger.error({ error }, '[FeishuRuntime] Reconnect attempt failed');
|
|
406
|
+
scheduleReconnect('reconnect attempt failed');
|
|
407
|
+
});
|
|
408
|
+
}, delayMs);
|
|
409
|
+
};
|
|
410
|
+
const stopIngress = () => {
|
|
411
|
+
ingressEpoch += 1;
|
|
412
|
+
identityAbort?.abort();
|
|
413
|
+
if (reconnectTimer !== undefined) {
|
|
414
|
+
clearTimeout(reconnectTimer);
|
|
415
|
+
reconnectTimer = undefined;
|
|
416
|
+
}
|
|
417
|
+
wsClient?.close({ force: true });
|
|
418
|
+
wsClient = undefined;
|
|
419
|
+
// Join even providers that settle cancellation asynchronously. The Host
|
|
420
|
+
// may revoke the context as soon as stop() resolves.
|
|
421
|
+
return Promise.all([...identityTasks]).then(() => undefined);
|
|
422
|
+
};
|
|
423
|
+
return {
|
|
424
|
+
get outbound() {
|
|
425
|
+
return requireOutbound();
|
|
426
|
+
},
|
|
427
|
+
start() {
|
|
428
|
+
if (state === 'stopped')
|
|
429
|
+
return Promise.reject(new Error('Feishu connector runtime has been stopped'));
|
|
430
|
+
if (startPromise !== undefined)
|
|
431
|
+
return startPromise;
|
|
432
|
+
armed = true;
|
|
433
|
+
if (outbound === undefined) {
|
|
434
|
+
// Armed but idle: no ingress until connect() supplies credentials.
|
|
435
|
+
startPromise = Promise.resolve();
|
|
436
|
+
return startPromise;
|
|
437
|
+
}
|
|
438
|
+
state = 'starting';
|
|
439
|
+
const epoch = ingressEpoch;
|
|
440
|
+
startPromise = startIngress()
|
|
441
|
+
.then(() => {
|
|
442
|
+
if (isCurrent(epoch)) {
|
|
443
|
+
reconnectAttempts = 0;
|
|
444
|
+
state = 'running';
|
|
445
|
+
options.logger.info('[FeishuRuntime] Provider ingress started');
|
|
446
|
+
}
|
|
447
|
+
})
|
|
448
|
+
.catch((error) => {
|
|
449
|
+
// stop() aborts the in-flight start on purpose — that is not a start
|
|
450
|
+
// failure and must not surface as an unhandled rejection.
|
|
451
|
+
if (!isCurrent(epoch))
|
|
452
|
+
return;
|
|
453
|
+
state = 'idle';
|
|
454
|
+
startPromise = undefined;
|
|
455
|
+
throw error;
|
|
456
|
+
});
|
|
457
|
+
return startPromise;
|
|
458
|
+
},
|
|
459
|
+
async connect(next) {
|
|
460
|
+
const appId = trimValue(next.appId);
|
|
461
|
+
const appSecret = trimValue(next.appSecret);
|
|
462
|
+
if (appId.length === 0 || appSecret.length === 0) {
|
|
463
|
+
throw new TypeError('appId and appSecret must be non-empty values');
|
|
464
|
+
}
|
|
465
|
+
if (state === 'stopped')
|
|
466
|
+
throw new Error('Feishu connector runtime has been stopped');
|
|
467
|
+
// Tear down the previous ingress before rebuilding: a live socket or a
|
|
468
|
+
// pending reconnect timer from the old credentials must not survive.
|
|
469
|
+
state = 'idle';
|
|
470
|
+
const draining = stopIngress();
|
|
471
|
+
const epoch = ingressEpoch;
|
|
472
|
+
await draining;
|
|
473
|
+
if (!isCurrent(epoch))
|
|
474
|
+
return;
|
|
475
|
+
current = { ...current, appId, appSecret, connectionMode: next.connectionMode };
|
|
476
|
+
outbound = createAdapter(appId, appSecret, options.logger, buildAdapterOptions());
|
|
477
|
+
tokenManager = buildTokenManager();
|
|
478
|
+
outbound._injectTokenManager?.(tokenManager);
|
|
479
|
+
state = 'idle';
|
|
480
|
+
startPromise = undefined;
|
|
481
|
+
if (!armed)
|
|
482
|
+
return;
|
|
483
|
+
state = 'starting';
|
|
484
|
+
startPromise = startIngress()
|
|
485
|
+
.then(() => {
|
|
486
|
+
if (isCurrent(epoch)) {
|
|
487
|
+
reconnectAttempts = 0;
|
|
488
|
+
state = 'running';
|
|
489
|
+
options.logger.info('[FeishuRuntime] Provider ingress started');
|
|
490
|
+
}
|
|
491
|
+
})
|
|
492
|
+
.catch((error) => {
|
|
493
|
+
if (!isCurrent(epoch))
|
|
494
|
+
return;
|
|
495
|
+
state = 'idle';
|
|
496
|
+
startPromise = undefined;
|
|
497
|
+
throw error;
|
|
498
|
+
});
|
|
499
|
+
return startPromise;
|
|
500
|
+
},
|
|
501
|
+
async disconnect() {
|
|
502
|
+
if (state === 'stopped')
|
|
503
|
+
return;
|
|
504
|
+
// Close the in-process ingress AND drop the configured adapter/token
|
|
505
|
+
// manager: the operation targetValues clear appId/appSecret, so any
|
|
506
|
+
// retained outbound would keep sending with credentials the owner just
|
|
507
|
+
// disconnected (the Host write-back does not restart the plugin).
|
|
508
|
+
state = 'idle';
|
|
509
|
+
const draining = stopIngress();
|
|
510
|
+
const epoch = ingressEpoch;
|
|
511
|
+
await draining;
|
|
512
|
+
if (!isCurrent(epoch))
|
|
513
|
+
return;
|
|
514
|
+
outbound = undefined;
|
|
515
|
+
tokenManager = undefined;
|
|
516
|
+
state = 'idle';
|
|
517
|
+
startPromise = undefined;
|
|
518
|
+
},
|
|
519
|
+
isConnected() {
|
|
520
|
+
return state === 'running';
|
|
521
|
+
},
|
|
522
|
+
status() {
|
|
523
|
+
const verificationToken = current.verificationToken;
|
|
524
|
+
return {
|
|
525
|
+
connectionMode: current.connectionMode,
|
|
526
|
+
hasVerificationToken: typeof verificationToken === 'string' && verificationToken.trim() !== '',
|
|
527
|
+
connected: state === 'running',
|
|
528
|
+
};
|
|
529
|
+
},
|
|
530
|
+
stop() {
|
|
531
|
+
if (stopPromise !== undefined)
|
|
532
|
+
return stopPromise;
|
|
533
|
+
armed = false;
|
|
534
|
+
state = 'stopped';
|
|
535
|
+
stopPromise = stopIngress();
|
|
536
|
+
return stopPromise;
|
|
537
|
+
},
|
|
538
|
+
async handleWebhook(candidate) {
|
|
539
|
+
if (state === 'stopped')
|
|
540
|
+
throw new Error('Feishu connector runtime has been stopped');
|
|
541
|
+
if (current.connectionMode === 'websocket')
|
|
542
|
+
return { kind: 'skipped', reason: 'websocket_mode' };
|
|
543
|
+
if (outbound === undefined)
|
|
544
|
+
return { kind: 'error', status: 503, message: 'feishu connector is not configured' };
|
|
545
|
+
const adapter = outbound;
|
|
546
|
+
const { body } = requireFeishuWebhookInput(candidate);
|
|
547
|
+
const challenge = adapter.isVerificationChallenge(body);
|
|
548
|
+
if (challenge !== null)
|
|
549
|
+
return { kind: 'challenge', response: challenge };
|
|
550
|
+
if (!adapter.verifyEventToken(body))
|
|
551
|
+
return { kind: 'error', status: 403, message: 'Invalid verification token' };
|
|
552
|
+
// Events arriving before start() completed (state idle/starting) are not
|
|
553
|
+
// delivered; report them honestly instead of dropping silently and
|
|
554
|
+
// claiming they were processed.
|
|
555
|
+
if (state !== 'running')
|
|
556
|
+
return { kind: 'skipped', reason: 'not_running' };
|
|
557
|
+
const action = adapter.parseCardAction(body);
|
|
558
|
+
if (action !== null) {
|
|
559
|
+
const routed = await routeCard(action);
|
|
560
|
+
if (routed === 'delivered')
|
|
561
|
+
return { kind: 'processed', messageId: 'card-action' };
|
|
562
|
+
// 'not_running' covers the guard killing the route mid-flight; only a
|
|
563
|
+
// completed route with an unresolvable chat type is chat_type_unknown.
|
|
564
|
+
return { kind: 'skipped', reason: routed === 'not_running' ? 'not_running' : 'chat_type_unknown' };
|
|
565
|
+
}
|
|
566
|
+
const parsed = adapter.parseEvent(body);
|
|
567
|
+
if (parsed === null)
|
|
568
|
+
return { kind: 'skipped', reason: 'unsupported_event' };
|
|
569
|
+
const header = body !== null && typeof body === 'object' && !Array.isArray(body)
|
|
570
|
+
? body.header : undefined;
|
|
571
|
+
const eventId = header !== null && typeof header === 'object' && !Array.isArray(header)
|
|
572
|
+
? header.event_id : undefined;
|
|
573
|
+
const stableEventId = typeof eventId === 'string' && eventId.length > 0 ? eventId : undefined;
|
|
574
|
+
return await routeEvent(parsed, stableEventId)
|
|
575
|
+
? { kind: 'processed', messageId: stableEventId ?? parsed.messageId }
|
|
576
|
+
: { kind: 'skipped', reason: 'not_running' };
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { definePluginModule } from '@clowder-ai/plugin-sdk';
|
|
2
|
+
import type { ModulePluginHostShape } from '@clowder-ai/plugin-sdk';
|
|
3
|
+
import type { FeishuQrBindClient } from './FeishuQrBindClient.js';
|
|
4
|
+
export type SettingsHost = Pick<ModulePluginHostShape, 'config' | 'secrets' | 'storage' | 'log'>;
|
|
5
|
+
interface SettingsCall {
|
|
6
|
+
readonly signal?: AbortSignal;
|
|
7
|
+
assertCurrent(): void | Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface SettingsDefinition {
|
|
10
|
+
readonly actions: Readonly<Record<string, (params: unknown, action?: unknown, call?: SettingsCall) => Promise<unknown>>>;
|
|
11
|
+
dispose?(): void | Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface SettingsEntrypoint {
|
|
14
|
+
create(manifest: unknown): ReturnType<ReturnType<typeof definePluginModule>['create']> & {
|
|
15
|
+
settings(host: SettingsHost): SettingsDefinition;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare function createFeishuSettings(host: SettingsHost, client: FeishuQrBindClient): SettingsDefinition;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;AACjG,UAAU,YAAY;IAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,aAAa,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAAE;AAEhG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACzH,OAAO,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AACD,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,QAAQ,EAAE,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG;QAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,kBAAkB,CAAA;KAAE,CAAC;CAC/I;AAID,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CA0BvG"}
|