@zhin.js/adapter-lark 6.0.3 → 6.0.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/CHANGELOG.md +79 -0
- package/adapters/lark.js +2 -2
- package/adapters/lark.ts +2 -2
- package/lib/endpoint.js +27 -29
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/lark-agent-deps.d.ts +2 -2
- package/lib/lark-agent-deps.js +7 -7
- package/lib/platform-permit.d.ts +2 -3
- package/lib/platform-permit.js +3 -11
- package/lib/protocol.d.ts +3 -3
- package/lib/protocol.js +5 -5
- package/package.json +17 -16
- package/plugin.js +6 -3
- package/schema.json +41 -5
- package/src/endpoint.ts +28 -30
- package/src/index.ts +0 -1
- package/src/lark-agent-deps.ts +8 -8
- package/src/platform-permit.ts +4 -8
- package/src/protocol.ts +7 -7
- /package/commands/endpoint/add/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/add/{[name].ts → [id].ts} +0 -0
- /package/commands/endpoint/remove/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/remove/{[name].ts → [id].ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,84 @@
|
|
|
1
1
|
# @zhin.js/adapter-lark
|
|
2
2
|
|
|
3
|
+
## 6.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
|
|
8
|
+
|
|
9
|
+
All adapter platform-permit checkers now accept PermissionSubject
|
|
10
|
+
(duck-typed from Message/CommandSession) instead of Message directly.
|
|
11
|
+
registerPlatformPermitChecker is replaced by host.registerPlatform in
|
|
12
|
+
the adapter plugin setup. activity-feedback service updated for new
|
|
13
|
+
PermissionHost integration.
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [6f9c366]
|
|
16
|
+
- Updated dependencies [373a56b]
|
|
17
|
+
- Updated dependencies [0de46a8]
|
|
18
|
+
- Updated dependencies [c106ecc]
|
|
19
|
+
- Updated dependencies [ca92e03]
|
|
20
|
+
- Updated dependencies [b0f37ae]
|
|
21
|
+
- Updated dependencies [ba08a2f]
|
|
22
|
+
- Updated dependencies [b08f7fe]
|
|
23
|
+
- Updated dependencies [daffd4c]
|
|
24
|
+
- Updated dependencies [36c7400]
|
|
25
|
+
- Updated dependencies [a9fa72e]
|
|
26
|
+
- Updated dependencies [c8de3ef]
|
|
27
|
+
- Updated dependencies [60f0fc8]
|
|
28
|
+
- Updated dependencies [574c990]
|
|
29
|
+
- Updated dependencies [d096f16]
|
|
30
|
+
- Updated dependencies [3f29623]
|
|
31
|
+
- Updated dependencies [2916852]
|
|
32
|
+
- Updated dependencies [d047869]
|
|
33
|
+
- Updated dependencies [162fa34]
|
|
34
|
+
- Updated dependencies [e62561e]
|
|
35
|
+
- Updated dependencies [3eeeb46]
|
|
36
|
+
- Updated dependencies [85d0f82]
|
|
37
|
+
- Updated dependencies [61bfc1c]
|
|
38
|
+
- Updated dependencies [04bad47]
|
|
39
|
+
- Updated dependencies [e40b048]
|
|
40
|
+
- Updated dependencies [5a5b1bb]
|
|
41
|
+
- Updated dependencies [f1708c3]
|
|
42
|
+
- Updated dependencies [d254a81]
|
|
43
|
+
- Updated dependencies [7123c47]
|
|
44
|
+
- Updated dependencies [05befc1]
|
|
45
|
+
- Updated dependencies [0663b6a]
|
|
46
|
+
- Updated dependencies [f28f9b3]
|
|
47
|
+
- Updated dependencies [9f340f7]
|
|
48
|
+
- Updated dependencies [e53444f]
|
|
49
|
+
- Updated dependencies [5eedd26]
|
|
50
|
+
- Updated dependencies [92b0dd7]
|
|
51
|
+
- Updated dependencies [f919b6f]
|
|
52
|
+
- Updated dependencies [098e411]
|
|
53
|
+
- Updated dependencies [e1b7c01]
|
|
54
|
+
- Updated dependencies [9b94f87]
|
|
55
|
+
- Updated dependencies [a7df753]
|
|
56
|
+
- @zhin.js/agent@1.1.5
|
|
57
|
+
- @zhin.js/host-http@1.0.8
|
|
58
|
+
- @zhin.js/permission@1.0.1
|
|
59
|
+
- @zhin.js/im-contract@1.0.3
|
|
60
|
+
- @zhin.js/adapter@1.1.7
|
|
61
|
+
- @zhin.js/plugin-runtime@1.1.5
|
|
62
|
+
- @zhin.js/command@1.0.9
|
|
63
|
+
- @zhin.js/core@1.5.4
|
|
64
|
+
- zhin.js@6.0.4
|
|
65
|
+
|
|
66
|
+
## 6.0.4
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- f8c7a54: fix: im
|
|
71
|
+
- Updated dependencies [f8c7a54]
|
|
72
|
+
- @zhin.js/logger@1.0.76
|
|
73
|
+
- @zhin.js/host-http@1.0.7
|
|
74
|
+
- @zhin.js/adapter@1.1.6
|
|
75
|
+
- @zhin.js/agent@1.1.4
|
|
76
|
+
- @zhin.js/command@1.0.8
|
|
77
|
+
- @zhin.js/core@1.5.3
|
|
78
|
+
- @zhin.js/im-contract@1.0.2
|
|
79
|
+
- @zhin.js/plugin-runtime@1.1.4
|
|
80
|
+
- zhin.js@6.0.3
|
|
81
|
+
|
|
3
82
|
## 6.0.3
|
|
4
83
|
|
|
5
84
|
### Patch Changes
|
package/adapters/lark.js
CHANGED
|
@@ -21,8 +21,8 @@ export default defineAdapter({
|
|
|
21
21
|
create(context) {
|
|
22
22
|
const config = resolveLarkConfig(context.config);
|
|
23
23
|
// 注册到插件运行时状态(lark.endpoint list 的"运行中"数据源)
|
|
24
|
-
context.use(larkRuntimeStateToken).endpoints.set(config.
|
|
25
|
-
|
|
24
|
+
context.use(larkRuntimeStateToken).endpoints.set(config.id, {
|
|
25
|
+
id: config.id,
|
|
26
26
|
mode: 'webhook',
|
|
27
27
|
});
|
|
28
28
|
return new LarkEndpoint({
|
package/adapters/lark.ts
CHANGED
|
@@ -26,8 +26,8 @@ export default defineAdapter<LarkAdapterConfig>({
|
|
|
26
26
|
create(context) {
|
|
27
27
|
const config = resolveLarkConfig(context.config);
|
|
28
28
|
// 注册到插件运行时状态(lark.endpoint list 的"运行中"数据源)
|
|
29
|
-
context.use(larkRuntimeStateToken).endpoints.set(config.
|
|
30
|
-
|
|
29
|
+
context.use(larkRuntimeStateToken).endpoints.set(config.id, {
|
|
30
|
+
id: config.id,
|
|
31
31
|
mode: 'webhook',
|
|
32
32
|
});
|
|
33
33
|
return new LarkEndpoint({
|
package/lib/endpoint.js
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { readFile } from 'node:fs/promises';
|
|
5
5
|
import { basename } from 'node:path';
|
|
6
|
-
import { formatCompact,
|
|
6
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
7
7
|
import { registerLarkAgentEndpoint } from './lark-agent-deps.js';
|
|
8
8
|
import { buildImageUploadForm, readOutboundImageMedia, resolveMediaBinary, } from './media-upload.js';
|
|
9
9
|
import { formatInboundContent, formatOutboundBody, generateMessageId, larkInboundConversation, resolveChatType, resolveSender, } from './protocol.js';
|
|
10
10
|
import { registerLarkWebhookRoutes } from './webhook.js';
|
|
11
|
-
const logger = getLogger('lark');
|
|
12
11
|
/** 出站 HTTP 调用统一 30s 超时。 */
|
|
13
12
|
const OUTBOUND_TIMEOUT_MS = 30_000;
|
|
14
13
|
export class LarkEndpoint {
|
|
14
|
+
#logger;
|
|
15
15
|
#options;
|
|
16
16
|
#fetch;
|
|
17
17
|
/**
|
|
@@ -45,6 +45,7 @@ export class LarkEndpoint {
|
|
|
45
45
|
#started = false;
|
|
46
46
|
#unregisterAgent;
|
|
47
47
|
constructor(options) {
|
|
48
|
+
this.#logger = getAdapterLogger('lark', options.config.id);
|
|
48
49
|
this.#options = options;
|
|
49
50
|
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
50
51
|
}
|
|
@@ -62,25 +63,25 @@ export class LarkEndpoint {
|
|
|
62
63
|
try {
|
|
63
64
|
if (!this.#options.config.encryptKey && !this.#options.config.verificationToken) {
|
|
64
65
|
// encryptKey / verificationToken 都未配置时 webhook 完全无鉴权,任何人可伪造事件
|
|
65
|
-
logger.warn(formatCompact({
|
|
66
|
-
endpoint: this.#options.config.
|
|
66
|
+
this.#logger.warn(formatCompact({
|
|
67
|
+
endpoint: this.#options.config.id,
|
|
67
68
|
op: 'webhook',
|
|
68
69
|
ok: false,
|
|
69
70
|
error: 'neither encryptKey nor verificationToken configured; webhook is unauthenticated',
|
|
70
71
|
}));
|
|
71
72
|
}
|
|
72
73
|
await this.#refreshAccessToken();
|
|
73
|
-
this.#unregisterAgent = registerLarkAgentEndpoint(this.#options.config.
|
|
74
|
+
this.#unregisterAgent = registerLarkAgentEndpoint(this.#options.config.id, this);
|
|
74
75
|
this.#routeReleases.push(...registerLarkWebhookRoutes(this.#options.http, this));
|
|
75
|
-
logger.debug(formatCompact({
|
|
76
|
-
endpoint: this.#options.config.
|
|
76
|
+
this.#logger.debug(formatCompact({
|
|
77
|
+
endpoint: this.#options.config.id,
|
|
77
78
|
op: 'webhook',
|
|
78
79
|
path: this.#options.config.webhookPath,
|
|
79
80
|
}));
|
|
80
81
|
}
|
|
81
82
|
catch (error) {
|
|
82
83
|
await this.stop();
|
|
83
|
-
logger.error('Failed to connect Lark endpoint:', error);
|
|
84
|
+
this.#logger.error('Failed to connect Lark endpoint:', error);
|
|
84
85
|
throw error;
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -97,7 +98,7 @@ export class LarkEndpoint {
|
|
|
97
98
|
this.#unregisterAgent?.();
|
|
98
99
|
this.#unregisterAgent = undefined;
|
|
99
100
|
this.#started = false;
|
|
100
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
101
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
101
102
|
}
|
|
102
103
|
async send({ conversation, payload }) {
|
|
103
104
|
const materialized = await this.#materializeOutboundMedia(payload);
|
|
@@ -115,10 +116,7 @@ export class LarkEndpoint {
|
|
|
115
116
|
throw new Error(`Failed to send message: ${data.msg}`);
|
|
116
117
|
}
|
|
117
118
|
const messageId = data.data?.message_id || `${Date.now()}`;
|
|
118
|
-
logger.debug(formatCompact({
|
|
119
|
-
op: 'send',
|
|
120
|
-
endpoint: this.#options.config.name,
|
|
121
|
-
to: conversation.id,
|
|
119
|
+
this.#logger.debug(formatCompact({ op: 'send', to: conversation.id,
|
|
122
120
|
id: messageId,
|
|
123
121
|
}));
|
|
124
122
|
return messageId;
|
|
@@ -177,7 +175,7 @@ export class LarkEndpoint {
|
|
|
177
175
|
throw new Error(`Image upload failed: ${data.msg}`);
|
|
178
176
|
}
|
|
179
177
|
catch (error) {
|
|
180
|
-
logger.error('Failed to upload image:', error);
|
|
178
|
+
this.#logger.error('Failed to upload image:', error);
|
|
181
179
|
return null;
|
|
182
180
|
}
|
|
183
181
|
}
|
|
@@ -190,14 +188,14 @@ export class LarkEndpoint {
|
|
|
190
188
|
conversation,
|
|
191
189
|
message: { conversation, id: generateMessageId(msg) },
|
|
192
190
|
content: formatInboundContent(msg),
|
|
193
|
-
sender: resolveSender(msg),
|
|
191
|
+
sender: { id: resolveSender(msg) },
|
|
192
|
+
endpointId: this.#options.config.id,
|
|
194
193
|
metadata: Object.freeze({
|
|
195
194
|
messageType: msg.message_type,
|
|
196
195
|
chatType: resolveChatType(msg.chat_id, msg.chat_type),
|
|
197
|
-
endpoint: this.#options.config.name,
|
|
198
196
|
}),
|
|
199
197
|
}).catch((err) => {
|
|
200
|
-
logger.warn(formatCompact({
|
|
198
|
+
this.#logger.warn(formatCompact({
|
|
201
199
|
op: 'lark_gateway_receive_failed',
|
|
202
200
|
conversation: conversation.id,
|
|
203
201
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -213,7 +211,7 @@ export class LarkEndpoint {
|
|
|
213
211
|
return data.data?.user ?? null;
|
|
214
212
|
}
|
|
215
213
|
catch (error) {
|
|
216
|
-
logger.error('Failed to get user info:', error);
|
|
214
|
+
this.#logger.error('Failed to get user info:', error);
|
|
217
215
|
return null;
|
|
218
216
|
}
|
|
219
217
|
}
|
|
@@ -223,7 +221,7 @@ export class LarkEndpoint {
|
|
|
223
221
|
return data.data ?? null;
|
|
224
222
|
}
|
|
225
223
|
catch (error) {
|
|
226
|
-
logger.error('Failed to get chat info:', error);
|
|
224
|
+
this.#logger.error('Failed to get chat info:', error);
|
|
227
225
|
return null;
|
|
228
226
|
}
|
|
229
227
|
}
|
|
@@ -247,7 +245,7 @@ export class LarkEndpoint {
|
|
|
247
245
|
throw new Error(`Upload failed: ${data.msg}`);
|
|
248
246
|
}
|
|
249
247
|
catch (error) {
|
|
250
|
-
logger.error('Failed to upload file:', error);
|
|
248
|
+
this.#logger.error('Failed to upload file:', error);
|
|
251
249
|
return null;
|
|
252
250
|
}
|
|
253
251
|
}
|
|
@@ -266,7 +264,7 @@ export class LarkEndpoint {
|
|
|
266
264
|
throw new Error(`Failed to create chat: ${data.msg}`);
|
|
267
265
|
}
|
|
268
266
|
catch (error) {
|
|
269
|
-
logger.error('Failed to create chat:', error);
|
|
267
|
+
this.#logger.error('Failed to create chat:', error);
|
|
270
268
|
return null;
|
|
271
269
|
}
|
|
272
270
|
}
|
|
@@ -281,7 +279,7 @@ export class LarkEndpoint {
|
|
|
281
279
|
throw new Error(`Failed to update chat: ${data.msg}`);
|
|
282
280
|
}
|
|
283
281
|
catch (error) {
|
|
284
|
-
logger.error('Failed to update chat:', error);
|
|
282
|
+
this.#logger.error('Failed to update chat:', error);
|
|
285
283
|
return false;
|
|
286
284
|
}
|
|
287
285
|
}
|
|
@@ -296,7 +294,7 @@ export class LarkEndpoint {
|
|
|
296
294
|
throw new Error(`Failed to add members: ${data.msg}`);
|
|
297
295
|
}
|
|
298
296
|
catch (error) {
|
|
299
|
-
logger.error('Failed to add chat members:', error);
|
|
297
|
+
this.#logger.error('Failed to add chat members:', error);
|
|
300
298
|
return false;
|
|
301
299
|
}
|
|
302
300
|
}
|
|
@@ -311,7 +309,7 @@ export class LarkEndpoint {
|
|
|
311
309
|
throw new Error(`Failed to remove members: ${data.msg}`);
|
|
312
310
|
}
|
|
313
311
|
catch (error) {
|
|
314
|
-
logger.error('Failed to remove chat members:', error);
|
|
312
|
+
this.#logger.error('Failed to remove chat members:', error);
|
|
315
313
|
return false;
|
|
316
314
|
}
|
|
317
315
|
}
|
|
@@ -323,7 +321,7 @@ export class LarkEndpoint {
|
|
|
323
321
|
throw new Error(`Failed to get members: ${data.msg}`);
|
|
324
322
|
}
|
|
325
323
|
catch (error) {
|
|
326
|
-
logger.error('Failed to get chat members:', error);
|
|
324
|
+
this.#logger.error('Failed to get chat members:', error);
|
|
327
325
|
return [];
|
|
328
326
|
}
|
|
329
327
|
}
|
|
@@ -335,7 +333,7 @@ export class LarkEndpoint {
|
|
|
335
333
|
throw new Error(`Failed to dissolve chat: ${data.msg}`);
|
|
336
334
|
}
|
|
337
335
|
catch (error) {
|
|
338
|
-
logger.error('Failed to dissolve chat:', error);
|
|
336
|
+
this.#logger.error('Failed to dissolve chat:', error);
|
|
339
337
|
return false;
|
|
340
338
|
}
|
|
341
339
|
}
|
|
@@ -350,7 +348,7 @@ export class LarkEndpoint {
|
|
|
350
348
|
throw new Error(`Failed to set managers: ${data.msg}`);
|
|
351
349
|
}
|
|
352
350
|
catch (error) {
|
|
353
|
-
logger.error('Failed to set chat managers:', error);
|
|
351
|
+
this.#logger.error('Failed to set chat managers:', error);
|
|
354
352
|
return false;
|
|
355
353
|
}
|
|
356
354
|
}
|
|
@@ -365,7 +363,7 @@ export class LarkEndpoint {
|
|
|
365
363
|
throw new Error(`Failed to remove managers: ${data.msg}`);
|
|
366
364
|
}
|
|
367
365
|
catch (error) {
|
|
368
|
-
logger.error('Failed to remove chat managers:', error);
|
|
366
|
+
this.#logger.error('Failed to remove chat managers:', error);
|
|
369
367
|
return false;
|
|
370
368
|
}
|
|
371
369
|
}
|
|
@@ -450,7 +448,7 @@ export class LarkEndpoint {
|
|
|
450
448
|
expires_in: data.expire ?? 7200,
|
|
451
449
|
timestamp: Date.now(),
|
|
452
450
|
};
|
|
453
|
-
logger.debug('Access token refreshed successfully');
|
|
451
|
+
this.#logger.debug('Access token refreshed successfully');
|
|
454
452
|
return;
|
|
455
453
|
}
|
|
456
454
|
throw new Error(`Failed to get access token: ${data.msg} (${data.code})`);
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { formatInboundContent, formatOutboundBody, generateMessageId, headerValue, larkInboundConversation, normalizeWebhookPath, readTextBody, resolveChatType, resolveLarkConfig, resolveSender, verifySignature, type AccessToken, type LarkAdapterConfig, type LarkApiResponse, type LarkEventBody, type LarkMessage, type LarkSendBody, type LarkWireSegment, type ResolvedLarkConfig, } from './protocol.js';
|
|
2
2
|
export { getLarkAgentDeps, registerLarkAgentEndpoint, setLarkAgentDeps, type LarkAgentDeps, type LarkAgentEndpoint, } from './lark-agent-deps.js';
|
|
3
|
-
export { checkLarkPlatformPermit, larkGroupPermitResolver, normalizeLarkSenderForPermit, platformPermit,
|
|
3
|
+
export { checkLarkPlatformPermit, larkGroupPermitResolver, normalizeLarkSenderForPermit, platformPermit, } from './platform-permit.js';
|
|
4
4
|
export { LarkEndpoint, type LarkEndpointOptions, type LarkFetch, } from './endpoint.js';
|
|
5
5
|
export { buildImageUploadForm, readOutboundImageMedia, resolveMediaBinary, type MediaBinary, } from './media-upload.js';
|
|
6
6
|
export { registerLarkWebhookRoutes, handleLarkWebhookRequest, type LarkWebhookHandler, } from './webhook.js';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { formatInboundContent, formatOutboundBody, generateMessageId, headerValue, larkInboundConversation, normalizeWebhookPath, readTextBody, resolveChatType, resolveLarkConfig, resolveSender, verifySignature, } from './protocol.js';
|
|
2
2
|
export { getLarkAgentDeps, registerLarkAgentEndpoint, setLarkAgentDeps, } from './lark-agent-deps.js';
|
|
3
|
-
export { checkLarkPlatformPermit, larkGroupPermitResolver, normalizeLarkSenderForPermit, platformPermit,
|
|
3
|
+
export { checkLarkPlatformPermit, larkGroupPermitResolver, normalizeLarkSenderForPermit, platformPermit, } from './platform-permit.js';
|
|
4
4
|
export { LarkEndpoint, } from './endpoint.js';
|
|
5
5
|
export { buildImageUploadForm, readOutboundImageMedia, resolveMediaBinary, } from './media-upload.js';
|
|
6
6
|
export { registerLarkWebhookRoutes, handleLarkWebhookRequest, } from './webhook.js';
|
package/lib/lark-agent-deps.d.ts
CHANGED
|
@@ -19,9 +19,9 @@ export interface LarkAgentEndpoint {
|
|
|
19
19
|
removeChatManagers(chatId: string, userIds: string[]): Promise<boolean>;
|
|
20
20
|
}
|
|
21
21
|
export interface LarkAgentDeps {
|
|
22
|
-
getEndpoint: (
|
|
22
|
+
getEndpoint: (endpointKey: string) => LarkAgentEndpoint;
|
|
23
23
|
}
|
|
24
|
-
export declare function registerLarkAgentEndpoint(
|
|
24
|
+
export declare function registerLarkAgentEndpoint(endpointKey: string, endpoint: LarkAgentEndpoint): () => void;
|
|
25
25
|
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
26
26
|
export declare function setLarkAgentDeps(deps: LarkAgentDeps | null): void;
|
|
27
27
|
export declare function getLarkAgentDeps(): LarkAgentDeps;
|
package/lib/lark-agent-deps.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const endpoints = new Map();
|
|
6
6
|
let override = null;
|
|
7
|
-
export function registerLarkAgentEndpoint(
|
|
8
|
-
endpoints.set(
|
|
7
|
+
export function registerLarkAgentEndpoint(endpointKey, endpoint) {
|
|
8
|
+
endpoints.set(endpointKey, endpoint);
|
|
9
9
|
return () => {
|
|
10
|
-
if (endpoints.get(
|
|
11
|
-
endpoints.delete(
|
|
10
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
11
|
+
endpoints.delete(endpointKey);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -20,10 +20,10 @@ export function getLarkAgentDeps() {
|
|
|
20
20
|
if (override)
|
|
21
21
|
return override;
|
|
22
22
|
return {
|
|
23
|
-
getEndpoint(
|
|
24
|
-
const endpoint = endpoints.get(
|
|
23
|
+
getEndpoint(endpointKey) {
|
|
24
|
+
const endpoint = endpoints.get(endpointKey);
|
|
25
25
|
if (!endpoint)
|
|
26
|
-
throw new Error(`Endpoint ${
|
|
26
|
+
throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
27
27
|
return endpoint;
|
|
28
28
|
},
|
|
29
29
|
};
|
package/lib/platform-permit.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 飞书 Lark platform permit
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
5
|
export declare function platformPermit(perm: string): string;
|
|
6
6
|
export declare function larkGroupPermitResolver(logicalPerm: string): string;
|
|
7
7
|
export declare function normalizeLarkSenderForPermit(input: {
|
|
@@ -11,5 +11,4 @@ export declare function normalizeLarkSenderForPermit(input: {
|
|
|
11
11
|
role?: string;
|
|
12
12
|
permissions?: string[];
|
|
13
13
|
};
|
|
14
|
-
export declare function checkLarkPlatformPermit(perm: string,
|
|
15
|
-
export declare function registerLarkPlatformPermitChecker(): () => void;
|
|
14
|
+
export declare function checkLarkPlatformPermit(perm: string, subject: PermissionSubject): boolean;
|
package/lib/platform-permit.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 飞书 Lark platform permit
|
|
3
|
-
*/
|
|
4
|
-
import { registerPlatformPermitChecker } from '@zhin.js/core';
|
|
5
1
|
const ADAPTER = 'lark';
|
|
6
2
|
export function platformPermit(perm) {
|
|
7
3
|
return `platform(${ADAPTER},${perm})`;
|
|
@@ -22,10 +18,9 @@ export function normalizeLarkSenderForPermit(input) {
|
|
|
22
18
|
}
|
|
23
19
|
return { role: 'member', permissions: [] };
|
|
24
20
|
}
|
|
25
|
-
export function checkLarkPlatformPermit(perm,
|
|
26
|
-
const
|
|
27
|
-
const permissions = sender
|
|
28
|
-
const role = sender.role;
|
|
21
|
+
export function checkLarkPlatformPermit(perm, subject) {
|
|
22
|
+
const role = subject.sender?.role?.[0];
|
|
23
|
+
const permissions = subject.sender?.permissions ?? [];
|
|
29
24
|
const has = (t) => permissions.includes(t);
|
|
30
25
|
switch (perm) {
|
|
31
26
|
case 'chat_owner':
|
|
@@ -38,6 +33,3 @@ export function checkLarkPlatformPermit(perm, message) {
|
|
|
38
33
|
return false;
|
|
39
34
|
}
|
|
40
35
|
}
|
|
41
|
-
export function registerLarkPlatformPermitChecker() {
|
|
42
|
-
return registerPlatformPermitChecker(ADAPTER, checkLarkPlatformPermit);
|
|
43
|
-
}
|
package/lib/protocol.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { IncomingMessage } from 'node:http';
|
|
|
6
6
|
import type { ConversationRef } from '@zhin.js/im-contract';
|
|
7
7
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
8
8
|
export interface LarkAdapterConfig {
|
|
9
|
-
readonly
|
|
9
|
+
readonly id?: string;
|
|
10
10
|
readonly appId?: string;
|
|
11
11
|
readonly appSecret?: string;
|
|
12
12
|
readonly encryptKey?: string;
|
|
@@ -21,7 +21,7 @@ export interface LarkAdapterConfig {
|
|
|
21
21
|
}
|
|
22
22
|
export interface ResolvedLarkConfig {
|
|
23
23
|
readonly context: 'lark';
|
|
24
|
-
readonly
|
|
24
|
+
readonly id: string;
|
|
25
25
|
readonly appId: string;
|
|
26
26
|
readonly appSecret: string;
|
|
27
27
|
readonly encryptKey?: string;
|
|
@@ -102,7 +102,7 @@ export declare function resolveChatType(chatId?: string, chatType?: string): 'gr
|
|
|
102
102
|
* p2p 单聊映射为 private;id 一律为平台 chat_id。Lark 无 guild/频道容器,
|
|
103
103
|
* 不产生 `parent`。
|
|
104
104
|
*/
|
|
105
|
-
export declare function larkInboundConversation(
|
|
105
|
+
export declare function larkInboundConversation(endpointKey: string, msg: LarkMessage): ConversationRef;
|
|
106
106
|
export declare function resolveSender(msg: LarkMessage): string;
|
|
107
107
|
export declare function generateMessageId(msg: LarkMessage): string;
|
|
108
108
|
/** Build inbound text for MessageGateway.receive. */
|
package/lib/protocol.js
CHANGED
|
@@ -14,8 +14,8 @@ export function resolveLarkConfig(config = {}) {
|
|
|
14
14
|
throw new TypeError('Lark adapter requires appId + appSecret (plugins.<key> or endpoints with context: lark)');
|
|
15
15
|
}
|
|
16
16
|
const isFeishu = config.isFeishu ?? entry?.isFeishu ?? true;
|
|
17
|
-
const
|
|
18
|
-
|| (typeof entry?.
|
|
17
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
18
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
19
19
|
|| process.env.LARK_BOT_NAME
|
|
20
20
|
|| 'lark-bot';
|
|
21
21
|
const webhookPath = normalizeWebhookPath(config.webhookPath ?? entry?.webhookPath ?? '/lark/webhook');
|
|
@@ -27,7 +27,7 @@ export function resolveLarkConfig(config = {}) {
|
|
|
27
27
|
const verificationToken = config.verificationToken ?? entry?.verificationToken;
|
|
28
28
|
return {
|
|
29
29
|
context: 'lark',
|
|
30
|
-
|
|
30
|
+
id,
|
|
31
31
|
appId,
|
|
32
32
|
appSecret,
|
|
33
33
|
...(encryptKey ? { encryptKey } : {}),
|
|
@@ -54,9 +54,9 @@ export function resolveChatType(chatId, chatType) {
|
|
|
54
54
|
* p2p 单聊映射为 private;id 一律为平台 chat_id。Lark 无 guild/频道容器,
|
|
55
55
|
* 不产生 `parent`。
|
|
56
56
|
*/
|
|
57
|
-
export function larkInboundConversation(
|
|
57
|
+
export function larkInboundConversation(endpointKey, msg) {
|
|
58
58
|
return {
|
|
59
|
-
endpoint: { id:
|
|
59
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
60
60
|
kind: resolveChatType(msg.chat_id, msg.chat_type),
|
|
61
61
|
id: msg.chat_id || 'unknown',
|
|
62
62
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-lark",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.5",
|
|
4
4
|
"description": "Zhin.js Lark/Feishu (飞书) adapter for Plugin Runtime (HTTP webhook)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -34,22 +34,23 @@
|
|
|
34
34
|
"directory": "plugins/adapters/lark"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@zhin.js/adapter": "1.1.
|
|
38
|
-
"@zhin.js/command": "1.0.
|
|
39
|
-
"@zhin.js/core": "1.5.
|
|
40
|
-
"@zhin.js/host-http": "1.0.
|
|
41
|
-
"@zhin.js/im-contract": "1.0.
|
|
42
|
-
"@zhin.js/logger": "1.0.
|
|
43
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
37
|
+
"@zhin.js/adapter": "1.1.7",
|
|
38
|
+
"@zhin.js/command": "1.0.9",
|
|
39
|
+
"@zhin.js/core": "1.5.4",
|
|
40
|
+
"@zhin.js/host-http": "1.0.8",
|
|
41
|
+
"@zhin.js/im-contract": "1.0.3",
|
|
42
|
+
"@zhin.js/logger": "1.0.76",
|
|
43
|
+
"@zhin.js/plugin-runtime": "1.1.5"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"zod": "^4.0.0",
|
|
47
|
-
"@zhin.js/adapter": "1.1.
|
|
48
|
-
"@zhin.js/agent": "1.1.
|
|
49
|
-
"@zhin.js/core": "1.5.
|
|
50
|
-
"@zhin.js/host-http": "1.0.
|
|
51
|
-
"@zhin.js/
|
|
52
|
-
"zhin.js": "
|
|
47
|
+
"@zhin.js/adapter": "1.1.7",
|
|
48
|
+
"@zhin.js/agent": "1.1.5",
|
|
49
|
+
"@zhin.js/core": "1.5.4",
|
|
50
|
+
"@zhin.js/host-http": "1.0.8",
|
|
51
|
+
"@zhin.js/permission": "1.0.1",
|
|
52
|
+
"@zhin.js/plugin-runtime": "1.1.5",
|
|
53
|
+
"zhin.js": "6.0.4"
|
|
53
54
|
},
|
|
54
55
|
"peerDependenciesMeta": {
|
|
55
56
|
"zhin.js": {
|
|
@@ -67,8 +68,8 @@
|
|
|
67
68
|
"typescript": "^6.0.3",
|
|
68
69
|
"vitest": "^4.1.10",
|
|
69
70
|
"zod": "^4.4.3",
|
|
70
|
-
"@zhin.js/agent": "1.1.
|
|
71
|
-
"zhin.js": "6.0.
|
|
71
|
+
"@zhin.js/agent": "1.1.5",
|
|
72
|
+
"zhin.js": "6.0.4"
|
|
72
73
|
},
|
|
73
74
|
"files": [
|
|
74
75
|
"adapters",
|
package/plugin.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { createEndpointRuntimeState } from '@zhin.js/adapter';
|
|
3
3
|
import { definePlugin } from '@zhin.js/plugin-runtime';
|
|
4
|
-
import {
|
|
4
|
+
import { permissionHostToken } from '@zhin.js/permission';
|
|
5
|
+
import { checkLarkPlatformPermit } from "./lib/platform-permit.js";
|
|
5
6
|
import { larkRuntimeStateToken } from "./lib/lark-runtime-state.js";
|
|
6
7
|
export default definePlugin({
|
|
7
8
|
name: 'lark',
|
|
@@ -9,8 +10,10 @@ export default definePlugin({
|
|
|
9
10
|
displayName: 'Lark/Feishu (飞书) Adapter',
|
|
10
11
|
},
|
|
11
12
|
setup(context) {
|
|
12
|
-
// 运行中 endpoint 注册表(lark.endpoint list 的"运行中"数据源)
|
|
13
13
|
context.resources.provide(larkRuntimeStateToken, createEndpointRuntimeState());
|
|
14
|
-
|
|
14
|
+
if (context.resources.has(permissionHostToken)) {
|
|
15
|
+
const host = context.resources.use(permissionHostToken);
|
|
16
|
+
return host.registerPlatform('lark', checkLarkPlatformPermit);
|
|
17
|
+
}
|
|
15
18
|
},
|
|
16
19
|
});
|
package/schema.json
CHANGED
|
@@ -14,16 +14,48 @@
|
|
|
14
14
|
"type": "boolean",
|
|
15
15
|
"default": true
|
|
16
16
|
},
|
|
17
|
+
"master": {
|
|
18
|
+
"type": [
|
|
19
|
+
"string",
|
|
20
|
+
"number"
|
|
21
|
+
],
|
|
22
|
+
"description": "框架 master(Lark/Feishu open_id or user_id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
23
|
+
},
|
|
24
|
+
"trusted": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": [
|
|
28
|
+
"string",
|
|
29
|
+
"number"
|
|
30
|
+
],
|
|
31
|
+
"description": "Trusted Lark/Feishu open_id or user_id"
|
|
32
|
+
},
|
|
33
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
34
|
+
},
|
|
17
35
|
"endpoints": {
|
|
18
36
|
"type": "array",
|
|
19
|
-
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(
|
|
37
|
+
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
20
38
|
"items": {
|
|
21
39
|
"type": "object",
|
|
22
40
|
"additionalProperties": true,
|
|
23
41
|
"properties": {
|
|
24
|
-
"
|
|
25
|
-
"type":
|
|
26
|
-
|
|
42
|
+
"master": {
|
|
43
|
+
"type": [
|
|
44
|
+
"string",
|
|
45
|
+
"number"
|
|
46
|
+
],
|
|
47
|
+
"description": "本 endpoint 的框架 master(Lark/Feishu open_id or user_id);覆盖顶层 master"
|
|
48
|
+
},
|
|
49
|
+
"trusted": {
|
|
50
|
+
"type": "array",
|
|
51
|
+
"items": {
|
|
52
|
+
"type": [
|
|
53
|
+
"string",
|
|
54
|
+
"number"
|
|
55
|
+
],
|
|
56
|
+
"description": "Trusted Lark/Feishu open_id or user_id"
|
|
57
|
+
},
|
|
58
|
+
"description": "本 endpoint 的 trusted 列表"
|
|
27
59
|
},
|
|
28
60
|
"appId": {
|
|
29
61
|
"type": "string",
|
|
@@ -40,10 +72,14 @@
|
|
|
40
72
|
"verificationToken": {
|
|
41
73
|
"type": "string",
|
|
42
74
|
"description": "Lark verification token"
|
|
75
|
+
},
|
|
76
|
+
"id": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "Lark bot name"
|
|
43
79
|
}
|
|
44
80
|
},
|
|
45
81
|
"required": [
|
|
46
|
-
"
|
|
82
|
+
"id",
|
|
47
83
|
"appId",
|
|
48
84
|
"appSecret"
|
|
49
85
|
]
|
package/src/endpoint.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { basename } from 'node:path';
|
|
|
6
6
|
import type { EndpointGroup, EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
|
|
7
7
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
8
8
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
9
|
-
import { formatCompact,
|
|
9
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
10
10
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
11
11
|
import { registerLarkAgentEndpoint } from './lark-agent-deps.js';
|
|
12
12
|
import {
|
|
@@ -28,8 +28,6 @@ import {
|
|
|
28
28
|
} from './protocol.js';
|
|
29
29
|
import { registerLarkWebhookRoutes } from './webhook.js';
|
|
30
30
|
|
|
31
|
-
const logger = getLogger('lark');
|
|
32
|
-
|
|
33
31
|
/** 出站 HTTP 调用统一 30s 超时。 */
|
|
34
32
|
const OUTBOUND_TIMEOUT_MS = 30_000;
|
|
35
33
|
|
|
@@ -57,6 +55,8 @@ export interface LarkEndpointOptions {
|
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
export class LarkEndpoint implements EndpointInstance {
|
|
58
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
59
|
+
|
|
60
60
|
readonly #options: LarkEndpointOptions;
|
|
61
61
|
readonly #fetch: LarkFetch;
|
|
62
62
|
/**
|
|
@@ -93,6 +93,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
93
93
|
#unregisterAgent?: () => void;
|
|
94
94
|
|
|
95
95
|
constructor(options: LarkEndpointOptions) {
|
|
96
|
+
this.#logger = getAdapterLogger('lark', options.config.id);
|
|
96
97
|
this.#options = options;
|
|
97
98
|
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
98
99
|
}
|
|
@@ -112,24 +113,24 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
112
113
|
try {
|
|
113
114
|
if (!this.#options.config.encryptKey && !this.#options.config.verificationToken) {
|
|
114
115
|
// encryptKey / verificationToken 都未配置时 webhook 完全无鉴权,任何人可伪造事件
|
|
115
|
-
logger.warn(formatCompact({
|
|
116
|
-
endpoint: this.#options.config.
|
|
116
|
+
this.#logger.warn(formatCompact({
|
|
117
|
+
endpoint: this.#options.config.id,
|
|
117
118
|
op: 'webhook',
|
|
118
119
|
ok: false,
|
|
119
120
|
error: 'neither encryptKey nor verificationToken configured; webhook is unauthenticated',
|
|
120
121
|
}));
|
|
121
122
|
}
|
|
122
123
|
await this.#refreshAccessToken();
|
|
123
|
-
this.#unregisterAgent = registerLarkAgentEndpoint(this.#options.config.
|
|
124
|
+
this.#unregisterAgent = registerLarkAgentEndpoint(this.#options.config.id, this);
|
|
124
125
|
this.#routeReleases.push(...registerLarkWebhookRoutes(this.#options.http, this));
|
|
125
|
-
logger.debug(formatCompact({
|
|
126
|
-
endpoint: this.#options.config.
|
|
126
|
+
this.#logger.debug(formatCompact({
|
|
127
|
+
endpoint: this.#options.config.id,
|
|
127
128
|
op: 'webhook',
|
|
128
129
|
path: this.#options.config.webhookPath,
|
|
129
130
|
}));
|
|
130
131
|
} catch (error) {
|
|
131
132
|
await this.stop();
|
|
132
|
-
logger.error('Failed to connect Lark endpoint:', error);
|
|
133
|
+
this.#logger.error('Failed to connect Lark endpoint:', error);
|
|
133
134
|
throw error;
|
|
134
135
|
}
|
|
135
136
|
}
|
|
@@ -148,7 +149,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
148
149
|
this.#unregisterAgent?.();
|
|
149
150
|
this.#unregisterAgent = undefined;
|
|
150
151
|
this.#started = false;
|
|
151
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
152
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -167,10 +168,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
167
168
|
throw new Error(`Failed to send message: ${data.msg}`);
|
|
168
169
|
}
|
|
169
170
|
const messageId = (data.data?.message_id as string) || `${Date.now()}`;
|
|
170
|
-
logger.debug(formatCompact({
|
|
171
|
-
op: 'send',
|
|
172
|
-
endpoint: this.#options.config.name,
|
|
173
|
-
to: conversation.id,
|
|
171
|
+
this.#logger.debug(formatCompact({ op: 'send', to: conversation.id,
|
|
174
172
|
id: messageId,
|
|
175
173
|
}));
|
|
176
174
|
return messageId;
|
|
@@ -226,7 +224,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
226
224
|
}
|
|
227
225
|
throw new Error(`Image upload failed: ${data.msg}`);
|
|
228
226
|
} catch (error) {
|
|
229
|
-
logger.error('Failed to upload image:', error);
|
|
227
|
+
this.#logger.error('Failed to upload image:', error);
|
|
230
228
|
return null;
|
|
231
229
|
}
|
|
232
230
|
}
|
|
@@ -239,14 +237,14 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
239
237
|
conversation,
|
|
240
238
|
message: { conversation, id: generateMessageId(msg) },
|
|
241
239
|
content: formatInboundContent(msg),
|
|
242
|
-
sender: resolveSender(msg),
|
|
240
|
+
sender: { id: resolveSender(msg) },
|
|
241
|
+
endpointId: this.#options.config.id,
|
|
243
242
|
metadata: Object.freeze({
|
|
244
243
|
messageType: msg.message_type,
|
|
245
244
|
chatType: resolveChatType(msg.chat_id, msg.chat_type),
|
|
246
|
-
endpoint: this.#options.config.name,
|
|
247
245
|
}),
|
|
248
246
|
}).catch((err) => {
|
|
249
|
-
logger.warn(formatCompact({
|
|
247
|
+
this.#logger.warn(formatCompact({
|
|
250
248
|
op: 'lark_gateway_receive_failed',
|
|
251
249
|
conversation: conversation.id,
|
|
252
250
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -265,7 +263,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
265
263
|
});
|
|
266
264
|
return data.data?.user ?? null;
|
|
267
265
|
} catch (error) {
|
|
268
|
-
logger.error('Failed to get user info:', error);
|
|
266
|
+
this.#logger.error('Failed to get user info:', error);
|
|
269
267
|
return null;
|
|
270
268
|
}
|
|
271
269
|
}
|
|
@@ -275,7 +273,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
275
273
|
const data = await this.#request(`/im/v1/chats/${chatId}`, { method: 'GET' });
|
|
276
274
|
return data.data ?? null;
|
|
277
275
|
} catch (error) {
|
|
278
|
-
logger.error('Failed to get chat info:', error);
|
|
276
|
+
this.#logger.error('Failed to get chat info:', error);
|
|
279
277
|
return null;
|
|
280
278
|
}
|
|
281
279
|
}
|
|
@@ -302,7 +300,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
302
300
|
}
|
|
303
301
|
throw new Error(`Upload failed: ${data.msg}`);
|
|
304
302
|
} catch (error) {
|
|
305
|
-
logger.error('Failed to upload file:', error);
|
|
303
|
+
this.#logger.error('Failed to upload file:', error);
|
|
306
304
|
return null;
|
|
307
305
|
}
|
|
308
306
|
}
|
|
@@ -324,7 +322,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
324
322
|
if (data.code === 0) return (data.data?.chat_id as string) || null;
|
|
325
323
|
throw new Error(`Failed to create chat: ${data.msg}`);
|
|
326
324
|
} catch (error) {
|
|
327
|
-
logger.error('Failed to create chat:', error);
|
|
325
|
+
this.#logger.error('Failed to create chat:', error);
|
|
328
326
|
return null;
|
|
329
327
|
}
|
|
330
328
|
}
|
|
@@ -341,7 +339,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
341
339
|
if (data.code === 0) return true;
|
|
342
340
|
throw new Error(`Failed to update chat: ${data.msg}`);
|
|
343
341
|
} catch (error) {
|
|
344
|
-
logger.error('Failed to update chat:', error);
|
|
342
|
+
this.#logger.error('Failed to update chat:', error);
|
|
345
343
|
return false;
|
|
346
344
|
}
|
|
347
345
|
}
|
|
@@ -355,7 +353,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
355
353
|
if (data.code === 0) return true;
|
|
356
354
|
throw new Error(`Failed to add members: ${data.msg}`);
|
|
357
355
|
} catch (error) {
|
|
358
|
-
logger.error('Failed to add chat members:', error);
|
|
356
|
+
this.#logger.error('Failed to add chat members:', error);
|
|
359
357
|
return false;
|
|
360
358
|
}
|
|
361
359
|
}
|
|
@@ -369,7 +367,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
369
367
|
if (data.code === 0) return true;
|
|
370
368
|
throw new Error(`Failed to remove members: ${data.msg}`);
|
|
371
369
|
} catch (error) {
|
|
372
|
-
logger.error('Failed to remove chat members:', error);
|
|
370
|
+
this.#logger.error('Failed to remove chat members:', error);
|
|
373
371
|
return false;
|
|
374
372
|
}
|
|
375
373
|
}
|
|
@@ -380,7 +378,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
380
378
|
if (data.code === 0) return (data.data?.items as unknown[]) || [];
|
|
381
379
|
throw new Error(`Failed to get members: ${data.msg}`);
|
|
382
380
|
} catch (error) {
|
|
383
|
-
logger.error('Failed to get chat members:', error);
|
|
381
|
+
this.#logger.error('Failed to get chat members:', error);
|
|
384
382
|
return [];
|
|
385
383
|
}
|
|
386
384
|
}
|
|
@@ -391,7 +389,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
391
389
|
if (data.code === 0) return true;
|
|
392
390
|
throw new Error(`Failed to dissolve chat: ${data.msg}`);
|
|
393
391
|
} catch (error) {
|
|
394
|
-
logger.error('Failed to dissolve chat:', error);
|
|
392
|
+
this.#logger.error('Failed to dissolve chat:', error);
|
|
395
393
|
return false;
|
|
396
394
|
}
|
|
397
395
|
}
|
|
@@ -405,7 +403,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
405
403
|
if (data.code === 0) return true;
|
|
406
404
|
throw new Error(`Failed to set managers: ${data.msg}`);
|
|
407
405
|
} catch (error) {
|
|
408
|
-
logger.error('Failed to set chat managers:', error);
|
|
406
|
+
this.#logger.error('Failed to set chat managers:', error);
|
|
409
407
|
return false;
|
|
410
408
|
}
|
|
411
409
|
}
|
|
@@ -419,7 +417,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
419
417
|
if (data.code === 0) return true;
|
|
420
418
|
throw new Error(`Failed to remove managers: ${data.msg}`);
|
|
421
419
|
} catch (error) {
|
|
422
|
-
logger.error('Failed to remove chat managers:', error);
|
|
420
|
+
this.#logger.error('Failed to remove chat managers:', error);
|
|
423
421
|
return false;
|
|
424
422
|
}
|
|
425
423
|
}
|
|
@@ -524,7 +522,7 @@ export class LarkEndpoint implements EndpointInstance {
|
|
|
524
522
|
expires_in: data.expire ?? 7200,
|
|
525
523
|
timestamp: Date.now(),
|
|
526
524
|
};
|
|
527
|
-
logger.debug('Access token refreshed successfully');
|
|
525
|
+
this.#logger.debug('Access token refreshed successfully');
|
|
528
526
|
return;
|
|
529
527
|
}
|
|
530
528
|
throw new Error(`Failed to get access token: ${data.msg} (${data.code})`);
|
package/src/index.ts
CHANGED
package/src/lark-agent-deps.ts
CHANGED
|
@@ -27,20 +27,20 @@ export interface LarkAgentEndpoint {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export interface LarkAgentDeps {
|
|
30
|
-
getEndpoint: (
|
|
30
|
+
getEndpoint: (endpointKey: string) => LarkAgentEndpoint;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const endpoints = new Map<string, LarkAgentEndpoint>();
|
|
34
34
|
let override: LarkAgentDeps | null = null;
|
|
35
35
|
|
|
36
36
|
export function registerLarkAgentEndpoint(
|
|
37
|
-
|
|
37
|
+
endpointKey: string,
|
|
38
38
|
endpoint: LarkAgentEndpoint,
|
|
39
39
|
): () => void {
|
|
40
|
-
endpoints.set(
|
|
40
|
+
endpoints.set(endpointKey, endpoint);
|
|
41
41
|
return () => {
|
|
42
|
-
if (endpoints.get(
|
|
43
|
-
endpoints.delete(
|
|
42
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
43
|
+
endpoints.delete(endpointKey);
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
}
|
|
@@ -53,9 +53,9 @@ export function setLarkAgentDeps(deps: LarkAgentDeps | null): void {
|
|
|
53
53
|
export function getLarkAgentDeps(): LarkAgentDeps {
|
|
54
54
|
if (override) return override;
|
|
55
55
|
return {
|
|
56
|
-
getEndpoint(
|
|
57
|
-
const endpoint = endpoints.get(
|
|
58
|
-
if (!endpoint) throw new Error(`Endpoint ${
|
|
56
|
+
getEndpoint(endpointKey) {
|
|
57
|
+
const endpoint = endpoints.get(endpointKey);
|
|
58
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
59
59
|
return endpoint;
|
|
60
60
|
},
|
|
61
61
|
};
|
package/src/platform-permit.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 飞书 Lark platform permit
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
5
|
|
|
6
6
|
const ADAPTER = 'lark';
|
|
7
7
|
|
|
@@ -31,10 +31,9 @@ export function normalizeLarkSenderForPermit(input: {
|
|
|
31
31
|
return { role: 'member', permissions: [] };
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export function checkLarkPlatformPermit(perm: string,
|
|
35
|
-
const
|
|
36
|
-
const permissions = sender
|
|
37
|
-
const role = sender.role;
|
|
34
|
+
export function checkLarkPlatformPermit(perm: string, subject: PermissionSubject): boolean {
|
|
35
|
+
const role = subject.sender?.role?.[0];
|
|
36
|
+
const permissions = subject.sender?.permissions ?? [];
|
|
38
37
|
const has = (t: string) => permissions.includes(t);
|
|
39
38
|
|
|
40
39
|
switch (perm) {
|
|
@@ -49,6 +48,3 @@ export function checkLarkPlatformPermit(perm: string, message: Message<any>): bo
|
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
export function registerLarkPlatformPermitChecker(): () => void {
|
|
53
|
-
return registerPlatformPermitChecker(ADAPTER, checkLarkPlatformPermit);
|
|
54
|
-
}
|
package/src/protocol.ts
CHANGED
|
@@ -13,7 +13,7 @@ const logger = getLogger('lark');
|
|
|
13
13
|
|
|
14
14
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
15
15
|
export interface LarkAdapterConfig {
|
|
16
|
-
readonly
|
|
16
|
+
readonly id?: string;
|
|
17
17
|
readonly appId?: string;
|
|
18
18
|
readonly appSecret?: string;
|
|
19
19
|
readonly encryptKey?: string;
|
|
@@ -29,7 +29,7 @@ export interface LarkAdapterConfig {
|
|
|
29
29
|
|
|
30
30
|
export interface ResolvedLarkConfig {
|
|
31
31
|
readonly context: 'lark';
|
|
32
|
-
readonly
|
|
32
|
+
readonly id: string;
|
|
33
33
|
readonly appId: string;
|
|
34
34
|
readonly appSecret: string;
|
|
35
35
|
readonly encryptKey?: string;
|
|
@@ -119,8 +119,8 @@ export function resolveLarkConfig(config: LarkAdapterConfig = {}): ResolvedLarkC
|
|
|
119
119
|
);
|
|
120
120
|
}
|
|
121
121
|
const isFeishu = config.isFeishu ?? entry?.isFeishu ?? true;
|
|
122
|
-
const
|
|
123
|
-
|| (typeof entry?.
|
|
122
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
123
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
124
124
|
|| process.env.LARK_BOT_NAME
|
|
125
125
|
|| 'lark-bot';
|
|
126
126
|
const webhookPath = normalizeWebhookPath(
|
|
@@ -136,7 +136,7 @@ export function resolveLarkConfig(config: LarkAdapterConfig = {}): ResolvedLarkC
|
|
|
136
136
|
const verificationToken = config.verificationToken ?? entry?.verificationToken;
|
|
137
137
|
return {
|
|
138
138
|
context: 'lark',
|
|
139
|
-
|
|
139
|
+
id,
|
|
140
140
|
appId,
|
|
141
141
|
appSecret,
|
|
142
142
|
...(encryptKey ? { encryptKey } : {}),
|
|
@@ -164,9 +164,9 @@ export function resolveChatType(chatId?: string, chatType?: string): 'group' | '
|
|
|
164
164
|
* p2p 单聊映射为 private;id 一律为平台 chat_id。Lark 无 guild/频道容器,
|
|
165
165
|
* 不产生 `parent`。
|
|
166
166
|
*/
|
|
167
|
-
export function larkInboundConversation(
|
|
167
|
+
export function larkInboundConversation(endpointKey: string, msg: LarkMessage): ConversationRef {
|
|
168
168
|
return {
|
|
169
|
-
endpoint: { id:
|
|
169
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
170
170
|
kind: resolveChatType(msg.chat_id, msg.chat_type),
|
|
171
171
|
id: msg.chat_id || 'unknown',
|
|
172
172
|
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|