@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
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const KEY_PREFIX = 'reply-sender:';
|
|
2
|
+
const ENTRY_TTL_MS = 24 * 60 * 60 * 1000;
|
|
3
|
+
const SWEEP_EVERY_RECORDS = 50;
|
|
4
|
+
const ENTRY_CAP = 2000;
|
|
5
|
+
function object(value) {
|
|
6
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function errorName(error) {
|
|
9
|
+
return error instanceof Error ? error.name : 'unknown';
|
|
10
|
+
}
|
|
11
|
+
function parseEntry(value) {
|
|
12
|
+
if (typeof value !== 'string')
|
|
13
|
+
return undefined;
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = JSON.parse(value);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
if (!object(parsed) || parsed.version !== 1 || typeof parsed.storedAt !== 'number')
|
|
22
|
+
return undefined;
|
|
23
|
+
const candidate = parsed.sender;
|
|
24
|
+
if (!object(candidate) || typeof candidate.id !== 'string' || candidate.id.length === 0)
|
|
25
|
+
return undefined;
|
|
26
|
+
return {
|
|
27
|
+
version: 1,
|
|
28
|
+
storedAt: parsed.storedAt,
|
|
29
|
+
sender: {
|
|
30
|
+
id: candidate.id,
|
|
31
|
+
...(typeof candidate.name === 'string' ? { name: candidate.name } : {}),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function createReplySenderMap(context) {
|
|
36
|
+
let recordedSinceSweep = 0;
|
|
37
|
+
let sweepInFlight = false;
|
|
38
|
+
const sweep = async () => {
|
|
39
|
+
let listed;
|
|
40
|
+
try {
|
|
41
|
+
listed = await context.storage.list();
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
context.log('warn', 'Connector reply-sender mapping sweep failed', { errorName: errorName(error) });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
const live = [];
|
|
49
|
+
for (const [key, item] of Object.entries(listed)) {
|
|
50
|
+
if (!key.startsWith(KEY_PREFIX))
|
|
51
|
+
continue;
|
|
52
|
+
const entry = parseEntry(item?.value);
|
|
53
|
+
if (entry === undefined || entry.storedAt + ENTRY_TTL_MS < now) {
|
|
54
|
+
await context.storage.delete(key).catch(() => undefined);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
live.push({ key, storedAt: entry.storedAt });
|
|
58
|
+
}
|
|
59
|
+
live.sort((a, b) => a.storedAt - b.storedAt);
|
|
60
|
+
let overflow = live.length - (ENTRY_CAP - 1);
|
|
61
|
+
for (let index = 0; overflow > 0 && index < live.length; index += 1, overflow -= 1) {
|
|
62
|
+
await context.storage.delete(live[index].key).catch(() => undefined);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
// Sweep single-flight in the background: recording stays on the inbound
|
|
66
|
+
// hot path and overlapping bursts never stack sweeps. sweep() already
|
|
67
|
+
// swallows and logs its own storage failures. context.log is intentionally
|
|
68
|
+
// NOT used here: log() runs assertActive() and throws
|
|
69
|
+
// FeatureContextRevokedError after stop/revoke, so a sweep racing feature
|
|
70
|
+
// shutdown would turn into an unhandled rejection; console.warn is the
|
|
71
|
+
// reviewer-sanctioned exception that stays callable past revocation.
|
|
72
|
+
const sweepInBackground = () => {
|
|
73
|
+
if (sweepInFlight)
|
|
74
|
+
return;
|
|
75
|
+
sweepInFlight = true;
|
|
76
|
+
void sweep()
|
|
77
|
+
.catch((error) => {
|
|
78
|
+
console.warn('Connector reply-sender mapping sweep failed', { errorName: errorName(error) });
|
|
79
|
+
})
|
|
80
|
+
.finally(() => {
|
|
81
|
+
sweepInFlight = false;
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
async record(hostMessageId, replySender) {
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
try {
|
|
88
|
+
await context.storage.set(`${KEY_PREFIX}${hostMessageId}`, JSON.stringify({ version: 1, sender: replySender, storedAt: now }));
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
context.log('warn', 'Connector reply-sender mapping record failed', { errorName: errorName(error) });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
recordedSinceSweep += 1;
|
|
95
|
+
if (recordedSinceSweep < SWEEP_EVERY_RECORDS)
|
|
96
|
+
return;
|
|
97
|
+
recordedSinceSweep = 0;
|
|
98
|
+
sweepInBackground();
|
|
99
|
+
},
|
|
100
|
+
async resolve(hostMessageId) {
|
|
101
|
+
if (hostMessageId === undefined)
|
|
102
|
+
return undefined;
|
|
103
|
+
const key = `${KEY_PREFIX}${hostMessageId}`;
|
|
104
|
+
let stored;
|
|
105
|
+
try {
|
|
106
|
+
stored = await context.storage.get(key);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
context.log('warn', 'Connector reply-sender mapping lookup failed', { errorName: errorName(error) });
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
const entry = parseEntry(stored?.value);
|
|
113
|
+
if (entry === undefined)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (entry.storedAt + ENTRY_TTL_MS < Date.now()) {
|
|
116
|
+
await context.storage.delete(key).catch(() => undefined);
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
return entry.sender;
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=reply-sender-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply-sender-map.js","sourceRoot":"","sources":["../src/reply-sender-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import * as lark from '@larksuiteoapi/node-sdk';
|
|
2
|
+
import { FeishuAdapter, type FeishuAdapterOptions } from './FeishuAdapter.js';
|
|
3
|
+
import { FeishuTokenManager } from './FeishuTokenManager.js';
|
|
4
|
+
import type { ConnectorLogger } from './types.js';
|
|
5
|
+
export interface FeishuRuntimeConfig {
|
|
6
|
+
readonly appId: string;
|
|
7
|
+
readonly appSecret: string;
|
|
8
|
+
readonly connectionMode: 'webhook' | 'websocket';
|
|
9
|
+
readonly verificationToken?: string;
|
|
10
|
+
readonly groupBotMentionsJson?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface FeishuWebhookInput {
|
|
13
|
+
readonly body?: unknown;
|
|
14
|
+
}
|
|
15
|
+
export type FeishuWebhookResult = Readonly<{
|
|
16
|
+
kind: 'challenge';
|
|
17
|
+
response: Readonly<{
|
|
18
|
+
challenge: string;
|
|
19
|
+
}>;
|
|
20
|
+
}> | Readonly<{
|
|
21
|
+
kind: 'processed';
|
|
22
|
+
messageId: string;
|
|
23
|
+
}> | Readonly<{
|
|
24
|
+
kind: 'skipped';
|
|
25
|
+
reason: string;
|
|
26
|
+
}> | Readonly<{
|
|
27
|
+
kind: 'error';
|
|
28
|
+
status: number;
|
|
29
|
+
message: string;
|
|
30
|
+
}>;
|
|
31
|
+
export interface FeishuHostInboundMessage {
|
|
32
|
+
readonly externalConversationId: string;
|
|
33
|
+
readonly providerMessageId: string;
|
|
34
|
+
/** Provider sender identity for admission; independent of group reply attribution. */
|
|
35
|
+
readonly externalSenderId?: string;
|
|
36
|
+
readonly text: string;
|
|
37
|
+
readonly attachments?: readonly Readonly<{
|
|
38
|
+
type: 'image' | 'file' | 'audio';
|
|
39
|
+
platformKey: string;
|
|
40
|
+
fileName?: string;
|
|
41
|
+
duration?: number;
|
|
42
|
+
}>[];
|
|
43
|
+
readonly sender?: Readonly<{
|
|
44
|
+
id: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
}>;
|
|
47
|
+
readonly conversation: Readonly<{
|
|
48
|
+
type: 'direct' | 'group';
|
|
49
|
+
title?: string;
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
52
|
+
export interface FeishuRuntimeHost {
|
|
53
|
+
deliver(message: FeishuHostInboundMessage): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
export interface FeishuRuntimeAdapter {
|
|
56
|
+
readonly connectorId: string;
|
|
57
|
+
isVerificationChallenge: FeishuAdapter['isVerificationChallenge'];
|
|
58
|
+
verifyEventToken: FeishuAdapter['verifyEventToken'];
|
|
59
|
+
parseEvent: FeishuAdapter['parseEvent'];
|
|
60
|
+
parseCardAction: FeishuAdapter['parseCardAction'];
|
|
61
|
+
resolveSenderName: FeishuAdapter['resolveSenderName'];
|
|
62
|
+
resolveSenderNameFromChat: FeishuAdapter['resolveSenderNameFromChat'];
|
|
63
|
+
resolveChatName: FeishuAdapter['resolveChatName'];
|
|
64
|
+
resolveChatType: FeishuAdapter['resolveChatType'];
|
|
65
|
+
setBotOpenId: FeishuAdapter['setBotOpenId'];
|
|
66
|
+
sendFormattedReply: FeishuAdapter['sendFormattedReply'];
|
|
67
|
+
sendMedia: FeishuAdapter['sendMedia'];
|
|
68
|
+
sendReply: FeishuAdapter['sendReply'];
|
|
69
|
+
_injectTokenManager?(manager: FeishuTokenManager): void;
|
|
70
|
+
}
|
|
71
|
+
interface FeishuWsClient {
|
|
72
|
+
start(options: {
|
|
73
|
+
eventDispatcher: lark.EventDispatcher;
|
|
74
|
+
}): Promise<void>;
|
|
75
|
+
close(options?: {
|
|
76
|
+
force?: boolean;
|
|
77
|
+
}): void;
|
|
78
|
+
}
|
|
79
|
+
/** SDK internals the teardown guard needs (verified against @larksuiteoapi/node-sdk 1.59.0). */
|
|
80
|
+
interface LarkWsInternals {
|
|
81
|
+
start(options: {
|
|
82
|
+
eventDispatcher: lark.EventDispatcher;
|
|
83
|
+
}): Promise<void>;
|
|
84
|
+
close(options?: {
|
|
85
|
+
force?: boolean;
|
|
86
|
+
}): void;
|
|
87
|
+
pingLoop(): void;
|
|
88
|
+
/**
|
|
89
|
+
* Instance flag the SDK sets true while a connect attempt is in flight and
|
|
90
|
+
* false once it settles (es/index.js reConnect finally, ~line 85412). With
|
|
91
|
+
* `autoReconnect: false` a failed attempt logs 'connect failed' and returns
|
|
92
|
+
* without touching the registered socket, so this flag is the observable
|
|
93
|
+
* termination signal for fail-fast start.
|
|
94
|
+
*/
|
|
95
|
+
isConnecting?: boolean;
|
|
96
|
+
wsConfig: {
|
|
97
|
+
getWSInstance(): unknown;
|
|
98
|
+
setWSInstance(ws: unknown): void;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export interface PausableLarkWsClientHooks {
|
|
102
|
+
/**
|
|
103
|
+
* Invoked when the open socket emits 'close' without a stop() in flight.
|
|
104
|
+
* The lark SDK cannot be trusted to surface this itself: with
|
|
105
|
+
* `autoReconnect: false` its close handler returns before clearing the
|
|
106
|
+
* registered socket (es/index.js ~85422), leaving a dead socket in the
|
|
107
|
+
* registry with no callback. Reconnect supervision therefore lives here.
|
|
108
|
+
*/
|
|
109
|
+
readonly onClose?: () => void;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* F2/F3: the lark WSClient cannot cancel a connection that is still
|
|
113
|
+
* handshaking — `close()` only touches the socket registered after 'open',
|
|
114
|
+
* so a stop() landing pre-open would leave an authenticated socket that
|
|
115
|
+
* starts pingLoop and self-reconnects forever (an orphan nobody can kill).
|
|
116
|
+
*
|
|
117
|
+
* This facade makes teardown deterministic:
|
|
118
|
+
* - `close()` terminates the current socket AND installs a birth guard that
|
|
119
|
+
* terminates any socket the SDK opens afterwards, plus a pingLoop no-op so
|
|
120
|
+
* a late 'open' cannot restart the ping timer.
|
|
121
|
+
* - `start()` does not settle until the SDK has registered an open socket
|
|
122
|
+
* (lark `WSClient.start()` resolves in the same tick it kicks off
|
|
123
|
+
* `reConnect(true)`, so without this the runtime would report `running`
|
|
124
|
+
* before anything is connected), or aborts on stop/timeout/SDK give-up.
|
|
125
|
+
* - after `start()` settles, the open socket's 'close' event drives the
|
|
126
|
+
* optional `onClose` hook (suppressed when `close()` initiated it), so the
|
|
127
|
+
* runtime can drop out of 'running' and schedule a reconnect instead of
|
|
128
|
+
* reporting a dead connection as live.
|
|
129
|
+
*
|
|
130
|
+
* `autoReconnect: false` is deliberate: SDK-owned reconnection was the F2
|
|
131
|
+
* revival mechanism. Reconnect supervision belongs to the Host lifecycle.
|
|
132
|
+
*/
|
|
133
|
+
export declare class PausableLarkWsClient implements FeishuWsClient {
|
|
134
|
+
private readonly inner;
|
|
135
|
+
private readonly hooks;
|
|
136
|
+
private stopped;
|
|
137
|
+
constructor(appId: string, appSecret: string, inner?: LarkWsInternals, hooks?: PausableLarkWsClientHooks);
|
|
138
|
+
start(options: {
|
|
139
|
+
eventDispatcher: lark.EventDispatcher;
|
|
140
|
+
}): Promise<void>;
|
|
141
|
+
private watchSocketClose;
|
|
142
|
+
close(): void;
|
|
143
|
+
}
|
|
144
|
+
export interface FeishuConnectorRuntime<Adapter extends FeishuRuntimeAdapter = FeishuAdapter> {
|
|
145
|
+
readonly outbound: Adapter;
|
|
146
|
+
start(): Promise<void>;
|
|
147
|
+
stop(): Promise<void>;
|
|
148
|
+
handleWebhook(input: FeishuWebhookInput): Promise<FeishuWebhookResult>;
|
|
149
|
+
/** Rebuild the provider connection in-process with new credentials and start ingress. */
|
|
150
|
+
connect(config: Readonly<{
|
|
151
|
+
appId: string;
|
|
152
|
+
appSecret: string;
|
|
153
|
+
connectionMode: 'webhook' | 'websocket';
|
|
154
|
+
}>): Promise<void>;
|
|
155
|
+
/** Close the in-process ingress (WebSocket/reconnect timers); configuration values untouched. */
|
|
156
|
+
disconnect(): Promise<void>;
|
|
157
|
+
/** True when the provider ingress is live (webhook mode armed counts as connected once started). */
|
|
158
|
+
isConnected(): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Live connection facts for the `feishu.test` operation. The activation-time
|
|
161
|
+
* config/secrets snapshot goes stale once `connect()` adopts QR credentials
|
|
162
|
+
* in-process, so readiness must be derived from runtime state only.
|
|
163
|
+
*/
|
|
164
|
+
status(): {
|
|
165
|
+
connectionMode: 'webhook' | 'websocket';
|
|
166
|
+
hasVerificationToken: boolean;
|
|
167
|
+
connected: boolean;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export interface FeishuConnectorRuntimeOptions<Adapter extends FeishuRuntimeAdapter = FeishuAdapter> {
|
|
171
|
+
readonly config: FeishuRuntimeConfig;
|
|
172
|
+
readonly host: FeishuRuntimeHost;
|
|
173
|
+
readonly logger: ConnectorLogger;
|
|
174
|
+
readonly fetchFn?: typeof fetch;
|
|
175
|
+
readonly createAdapter?: (appId: string, appSecret: string, logger: ConnectorLogger, options: FeishuAdapterOptions) => Adapter;
|
|
176
|
+
readonly createWsClient?: (config: Readonly<{
|
|
177
|
+
appId: string;
|
|
178
|
+
appSecret: string;
|
|
179
|
+
/** Unexpected-close notification; see PausableLarkWsClientHooks. */
|
|
180
|
+
onClose?: () => void;
|
|
181
|
+
}>) => FeishuWsClient;
|
|
182
|
+
/** Base delay of the reconnect backoff (default 5s); doubles per attempt. */
|
|
183
|
+
readonly reconnectDelayMs?: number;
|
|
184
|
+
/** Cap of the reconnect backoff (default 60s). */
|
|
185
|
+
readonly reconnectMaxDelayMs?: number;
|
|
186
|
+
}
|
|
187
|
+
export declare function requireFeishuWebhookInput(candidate: unknown): FeishuWebhookInput;
|
|
188
|
+
export declare function createFeishuConnectorRuntime<Adapter extends FeishuRuntimeAdapter = FeishuAdapter>(options: FeishuConnectorRuntimeOptions<Adapter>): FeishuConnectorRuntime<Adapter>;
|
|
189
|
+
export {};
|
|
190
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|