cc-lark 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +47 -0
- package/.github/workflows/release.yml +47 -0
- package/.github/workflows/sync-upstream.yml +127 -0
- package/.prettierrc.json +7 -0
- package/README.md +214 -0
- package/dist/core/api-error.d.ts +193 -0
- package/dist/core/api-error.d.ts.map +1 -0
- package/dist/core/api-error.js +263 -0
- package/dist/core/api-error.js.map +1 -0
- package/dist/core/auth-errors.d.ts +13 -0
- package/dist/core/auth-errors.d.ts.map +1 -0
- package/dist/core/auth-errors.js +14 -0
- package/dist/core/auth-errors.js.map +1 -0
- package/dist/core/config.d.ts +60 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +115 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/device-flow.d.ts +80 -0
- package/dist/core/device-flow.d.ts.map +1 -0
- package/dist/core/device-flow.js +231 -0
- package/dist/core/device-flow.js.map +1 -0
- package/dist/core/index.d.ts +16 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +16 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lark-client.d.ts +136 -0
- package/dist/core/lark-client.d.ts.map +1 -0
- package/dist/core/lark-client.js +315 -0
- package/dist/core/lark-client.js.map +1 -0
- package/dist/core/token-store.d.ts +67 -0
- package/dist/core/token-store.d.ts.map +1 -0
- package/dist/core/token-store.js +215 -0
- package/dist/core/token-store.js.map +1 -0
- package/dist/core/types.d.ts +286 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +11 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/uat-client.d.ts +64 -0
- package/dist/core/uat-client.d.ts.map +1 -0
- package/dist/core/uat-client.js +227 -0
- package/dist/core/uat-client.js.map +1 -0
- package/dist/core/version.d.ts +26 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +50 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/bitable/app.d.ts +20 -0
- package/dist/tools/bitable/app.d.ts.map +1 -0
- package/dist/tools/bitable/app.js +301 -0
- package/dist/tools/bitable/app.js.map +1 -0
- package/dist/tools/bitable/field.d.ts +19 -0
- package/dist/tools/bitable/field.d.ts.map +1 -0
- package/dist/tools/bitable/field.js +315 -0
- package/dist/tools/bitable/field.js.map +1 -0
- package/dist/tools/bitable/index.d.ts +21 -0
- package/dist/tools/bitable/index.d.ts.map +1 -0
- package/dist/tools/bitable/index.js +39 -0
- package/dist/tools/bitable/index.js.map +1 -0
- package/dist/tools/bitable/record.d.ts +22 -0
- package/dist/tools/bitable/record.d.ts.map +1 -0
- package/dist/tools/bitable/record.js +434 -0
- package/dist/tools/bitable/record.js.map +1 -0
- package/dist/tools/bitable/table.d.ts +21 -0
- package/dist/tools/bitable/table.d.ts.map +1 -0
- package/dist/tools/bitable/table.js +361 -0
- package/dist/tools/bitable/table.js.map +1 -0
- package/dist/tools/calendar/calendar.d.ts +18 -0
- package/dist/tools/calendar/calendar.d.ts.map +1 -0
- package/dist/tools/calendar/calendar.js +192 -0
- package/dist/tools/calendar/calendar.js.map +1 -0
- package/dist/tools/calendar/event.d.ts +20 -0
- package/dist/tools/calendar/event.d.ts.map +1 -0
- package/dist/tools/calendar/event.js +465 -0
- package/dist/tools/calendar/event.js.map +1 -0
- package/dist/tools/calendar/index.d.ts +19 -0
- package/dist/tools/calendar/index.d.ts.map +1 -0
- package/dist/tools/calendar/index.js +37 -0
- package/dist/tools/calendar/index.js.map +1 -0
- package/dist/tools/chat/chat.d.ts +11 -0
- package/dist/tools/chat/chat.d.ts.map +1 -0
- package/dist/tools/chat/chat.js +106 -0
- package/dist/tools/chat/chat.js.map +1 -0
- package/dist/tools/chat/index.d.ts +11 -0
- package/dist/tools/chat/index.d.ts.map +1 -0
- package/dist/tools/chat/index.js +20 -0
- package/dist/tools/chat/index.js.map +1 -0
- package/dist/tools/chat/members.d.ts +9 -0
- package/dist/tools/chat/members.d.ts.map +1 -0
- package/dist/tools/chat/members.js +80 -0
- package/dist/tools/chat/members.js.map +1 -0
- package/dist/tools/common/get-user.d.ts +11 -0
- package/dist/tools/common/get-user.d.ts.map +1 -0
- package/dist/tools/common/get-user.js +112 -0
- package/dist/tools/common/get-user.js.map +1 -0
- package/dist/tools/common/index.d.ts +11 -0
- package/dist/tools/common/index.d.ts.map +1 -0
- package/dist/tools/common/index.js +20 -0
- package/dist/tools/common/index.js.map +1 -0
- package/dist/tools/common/search-user.d.ts +9 -0
- package/dist/tools/common/search-user.d.ts.map +1 -0
- package/dist/tools/common/search-user.js +88 -0
- package/dist/tools/common/search-user.js.map +1 -0
- package/dist/tools/doc/create.d.ts +17 -0
- package/dist/tools/doc/create.d.ts.map +1 -0
- package/dist/tools/doc/create.js +159 -0
- package/dist/tools/doc/create.js.map +1 -0
- package/dist/tools/doc/fetch.d.ts +17 -0
- package/dist/tools/doc/fetch.d.ts.map +1 -0
- package/dist/tools/doc/fetch.js +123 -0
- package/dist/tools/doc/fetch.js.map +1 -0
- package/dist/tools/doc/index.d.ts +21 -0
- package/dist/tools/doc/index.d.ts.map +1 -0
- package/dist/tools/doc/index.js +33 -0
- package/dist/tools/doc/index.js.map +1 -0
- package/dist/tools/doc/shared.d.ts +69 -0
- package/dist/tools/doc/shared.d.ts.map +1 -0
- package/dist/tools/doc/shared.js +172 -0
- package/dist/tools/doc/shared.js.map +1 -0
- package/dist/tools/doc/update.d.ts +25 -0
- package/dist/tools/doc/update.d.ts.map +1 -0
- package/dist/tools/doc/update.js +208 -0
- package/dist/tools/doc/update.js.map +1 -0
- package/dist/tools/drive/file.d.ts +13 -0
- package/dist/tools/drive/file.d.ts.map +1 -0
- package/dist/tools/drive/file.js +212 -0
- package/dist/tools/drive/file.js.map +1 -0
- package/dist/tools/drive/index.d.ts +12 -0
- package/dist/tools/drive/index.d.ts.map +1 -0
- package/dist/tools/drive/index.js +25 -0
- package/dist/tools/drive/index.js.map +1 -0
- package/dist/tools/im/format-messages.d.ts +99 -0
- package/dist/tools/im/format-messages.d.ts.map +1 -0
- package/dist/tools/im/format-messages.js +277 -0
- package/dist/tools/im/format-messages.js.map +1 -0
- package/dist/tools/im/helpers.d.ts +53 -0
- package/dist/tools/im/helpers.d.ts.map +1 -0
- package/dist/tools/im/helpers.js +85 -0
- package/dist/tools/im/helpers.js.map +1 -0
- package/dist/tools/im/index.d.ts +25 -0
- package/dist/tools/im/index.d.ts.map +1 -0
- package/dist/tools/im/index.js +44 -0
- package/dist/tools/im/index.js.map +1 -0
- package/dist/tools/im/message-read.d.ts +19 -0
- package/dist/tools/im/message-read.d.ts.map +1 -0
- package/dist/tools/im/message-read.js +526 -0
- package/dist/tools/im/message-read.js.map +1 -0
- package/dist/tools/im/message.d.ts +22 -0
- package/dist/tools/im/message.d.ts.map +1 -0
- package/dist/tools/im/message.js +233 -0
- package/dist/tools/im/message.js.map +1 -0
- package/dist/tools/im/resource.d.ts +19 -0
- package/dist/tools/im/resource.d.ts.map +1 -0
- package/dist/tools/im/resource.js +185 -0
- package/dist/tools/im/resource.js.map +1 -0
- package/dist/tools/im/time-utils.d.ts +70 -0
- package/dist/tools/im/time-utils.d.ts.map +1 -0
- package/dist/tools/im/time-utils.js +277 -0
- package/dist/tools/im/time-utils.js.map +1 -0
- package/dist/tools/index.d.ts +85 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +135 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/oauth.d.ts +15 -0
- package/dist/tools/oauth.d.ts.map +1 -0
- package/dist/tools/oauth.js +379 -0
- package/dist/tools/oauth.js.map +1 -0
- package/dist/tools/search/doc-search.d.ts +9 -0
- package/dist/tools/search/doc-search.d.ts.map +1 -0
- package/dist/tools/search/doc-search.js +219 -0
- package/dist/tools/search/doc-search.js.map +1 -0
- package/dist/tools/search/index.d.ts +11 -0
- package/dist/tools/search/index.d.ts.map +1 -0
- package/dist/tools/search/index.js +18 -0
- package/dist/tools/search/index.js.map +1 -0
- package/dist/tools/sheets/index.d.ts +11 -0
- package/dist/tools/sheets/index.d.ts.map +1 -0
- package/dist/tools/sheets/index.js +18 -0
- package/dist/tools/sheets/index.js.map +1 -0
- package/dist/tools/sheets/sheet.d.ts +11 -0
- package/dist/tools/sheets/sheet.d.ts.map +1 -0
- package/dist/tools/sheets/sheet.js +332 -0
- package/dist/tools/sheets/sheet.js.map +1 -0
- package/dist/tools/task/index.d.ts +12 -0
- package/dist/tools/task/index.d.ts.map +1 -0
- package/dist/tools/task/index.js +30 -0
- package/dist/tools/task/index.js.map +1 -0
- package/dist/tools/task/task.d.ts +13 -0
- package/dist/tools/task/task.d.ts.map +1 -0
- package/dist/tools/task/task.js +225 -0
- package/dist/tools/task/task.js.map +1 -0
- package/dist/tools/task/tasklist.d.ts +13 -0
- package/dist/tools/task/tasklist.d.ts.map +1 -0
- package/dist/tools/task/tasklist.js +206 -0
- package/dist/tools/task/tasklist.js.map +1 -0
- package/dist/tools/wiki/index.d.ts +11 -0
- package/dist/tools/wiki/index.d.ts.map +1 -0
- package/dist/tools/wiki/index.js +20 -0
- package/dist/tools/wiki/index.js.map +1 -0
- package/dist/tools/wiki/node.d.ts +11 -0
- package/dist/tools/wiki/node.d.ts.map +1 -0
- package/dist/tools/wiki/node.js +112 -0
- package/dist/tools/wiki/node.js.map +1 -0
- package/dist/tools/wiki/space.d.ts +11 -0
- package/dist/tools/wiki/space.d.ts.map +1 -0
- package/dist/tools/wiki/space.js +125 -0
- package/dist/tools/wiki/space.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +101 -0
- package/dist/utils/logger.js.map +1 -0
- package/eslint.config.js +13 -0
- package/package.json +54 -0
- package/skills/feishu-bitable/SKILL.md +248 -0
- package/skills/feishu-bitable/references/examples.md +813 -0
- package/skills/feishu-bitable/references/field-properties.md +763 -0
- package/skills/feishu-bitable/references/record-values.md +911 -0
- package/skills/feishu-calendar/SKILL.md +244 -0
- package/skills/feishu-channel-rules/SKILL.md +18 -0
- package/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
- package/skills/feishu-create-doc/SKILL.md +719 -0
- package/skills/feishu-fetch-doc/SKILL.md +93 -0
- package/skills/feishu-im-read/SKILL.md +163 -0
- package/skills/feishu-task/SKILL.md +293 -0
- package/skills/feishu-troubleshoot/SKILL.md +70 -0
- package/skills/feishu-update-doc/SKILL.md +285 -0
- package/src/core/api-error.ts +342 -0
- package/src/core/auth-errors.ts +27 -0
- package/src/core/config.ts +134 -0
- package/src/core/device-flow.ts +314 -0
- package/src/core/index.ts +16 -0
- package/src/core/lark-client.ts +391 -0
- package/src/core/token-store.ts +249 -0
- package/src/core/types.ts +302 -0
- package/src/core/uat-client.ts +298 -0
- package/src/core/version.ts +53 -0
- package/src/index.ts +138 -0
- package/src/tools/bitable/app.ts +390 -0
- package/src/tools/bitable/field.ts +406 -0
- package/src/tools/bitable/index.ts +43 -0
- package/src/tools/bitable/record.ts +559 -0
- package/src/tools/bitable/table.ts +472 -0
- package/src/tools/calendar/calendar.ts +254 -0
- package/src/tools/calendar/event.ts +606 -0
- package/src/tools/calendar/index.ts +41 -0
- package/src/tools/chat/chat.ts +127 -0
- package/src/tools/chat/index.ts +24 -0
- package/src/tools/chat/members.ts +93 -0
- package/src/tools/common/get-user.ts +127 -0
- package/src/tools/common/index.ts +24 -0
- package/src/tools/common/search-user.ts +99 -0
- package/src/tools/doc/create.ts +184 -0
- package/src/tools/doc/fetch.ts +149 -0
- package/src/tools/doc/index.ts +38 -0
- package/src/tools/doc/shared.ts +228 -0
- package/src/tools/doc/update.ts +240 -0
- package/src/tools/drive/file.ts +265 -0
- package/src/tools/drive/index.ts +29 -0
- package/src/tools/im/format-messages.ts +391 -0
- package/src/tools/im/helpers.ts +109 -0
- package/src/tools/im/index.ts +49 -0
- package/src/tools/im/message-read.ts +676 -0
- package/src/tools/im/message.ts +303 -0
- package/src/tools/im/resource.ts +225 -0
- package/src/tools/im/time-utils.ts +347 -0
- package/src/tools/index.ts +205 -0
- package/src/tools/oauth.ts +460 -0
- package/src/tools/search/doc-search.ts +250 -0
- package/src/tools/search/index.ts +22 -0
- package/src/tools/sheets/index.ts +22 -0
- package/src/tools/sheets/sheet.ts +382 -0
- package/src/tools/task/index.ts +34 -0
- package/src/tools/task/task.ts +265 -0
- package/src/tools/task/tasklist.ts +262 -0
- package/src/tools/wiki/index.ts +24 -0
- package/src/tools/wiki/node.ts +131 -0
- package/src/tools/wiki/space.ts +152 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/logger.ts +132 -0
- package/tests/core/config.test.ts +238 -0
- package/tests/core/device-flow.test.ts +490 -0
- package/tests/core/lark-client.test.ts +378 -0
- package/tests/core/token-store.test.ts +438 -0
- package/tests/index.test.ts +360 -0
- package/tests/tools/doc/create.test.ts +224 -0
- package/tests/tools/doc/fetch.test.ts +182 -0
- package/tests/tools/doc/shared.test.ts +183 -0
- package/tests/tools/doc/update.test.ts +330 -0
- package/tests/tools/im/format-messages.test.ts +184 -0
- package/tests/tools/im/time-utils.test.ts +178 -0
- package/tests/utils/logger.test.ts +140 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* feishu_im_message tool - Send/reply IM messages with user identity.
|
|
6
|
+
*
|
|
7
|
+
* Actions: send, reply
|
|
8
|
+
*
|
|
9
|
+
* Uses Feishu IM API:
|
|
10
|
+
* - send: POST /open-apis/im/v1/messages?receive_id_type=...
|
|
11
|
+
* - reply: POST /open-apis/im/v1/messages/:message_id/reply
|
|
12
|
+
*
|
|
13
|
+
* All calls use user access token (UAT) - requires OAuth authorization.
|
|
14
|
+
*
|
|
15
|
+
* Adapted from openclaw-lark for MCP Server architecture.
|
|
16
|
+
*/
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import { getValidAccessToken, NeedAuthorizationError } from '../../core/uat-client.js';
|
|
19
|
+
import { assertLarkOk } from '../../core/api-error.js';
|
|
20
|
+
import { json, jsonError } from './helpers.js';
|
|
21
|
+
import { logger } from '../../utils/logger.js';
|
|
22
|
+
const log = logger('tools:im:message');
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Input schemas (raw shape for ZodRawShapeCompat)
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const msgTypeEnum = z.enum([
|
|
27
|
+
'text',
|
|
28
|
+
'post',
|
|
29
|
+
'image',
|
|
30
|
+
'file',
|
|
31
|
+
'audio',
|
|
32
|
+
'media',
|
|
33
|
+
'interactive',
|
|
34
|
+
'share_chat',
|
|
35
|
+
'share_user',
|
|
36
|
+
]);
|
|
37
|
+
// We use separate tools for send and reply to avoid discriminated union issues
|
|
38
|
+
const sendMessageSchema = {
|
|
39
|
+
action: z.literal('send').describe('Send a message'),
|
|
40
|
+
receive_id_type: z.enum(['open_id', 'chat_id']).describe('Recipient ID type: open_id (private chat, ou_xxx) or chat_id (group chat, oc_xxx)'),
|
|
41
|
+
receive_id: z.string().describe("Recipient ID corresponding to receive_id_type. Use 'ou_xxx' for open_id, 'oc_xxx' for chat_id"),
|
|
42
|
+
msg_type: msgTypeEnum.describe('Message type: text (plain text), post (rich text), image, file, interactive (card), share_chat (group card), share_user (user card), etc.'),
|
|
43
|
+
content: z.string().describe('Message content (JSON string), format depends on msg_type. ' +
|
|
44
|
+
'Examples: text -> \'{"text":"Hello"}\', ' +
|
|
45
|
+
'image -> \'{"image_key":"img_xxx"}\', ' +
|
|
46
|
+
'share_chat -> \'{"chat_id":"oc_xxx"}\', ' +
|
|
47
|
+
'post -> \'{"zh_cn":{"title":"Title","content":[[{"tag":"text","text":"Body"}]]}}\''),
|
|
48
|
+
uuid: z.string().optional().describe('Idempotent unique identifier. Same uuid will only send one message within 1 hour for deduplication.'),
|
|
49
|
+
};
|
|
50
|
+
const replyMessageSchema = {
|
|
51
|
+
action: z.literal('reply').describe('Reply to a message'),
|
|
52
|
+
message_id: z.string().describe('Message ID to reply to (om_xxx format)'),
|
|
53
|
+
msg_type: msgTypeEnum.describe('Message type: text (plain text), post (rich text), image, interactive (card), etc.'),
|
|
54
|
+
content: z.string().describe('Reply message content (JSON string), same format as send content'),
|
|
55
|
+
reply_in_thread: z.boolean().optional().describe('Whether to reply in thread. true = message appears in the thread, false (default) = appears in main chat flow'),
|
|
56
|
+
uuid: z.string().optional().describe('Idempotent unique identifier'),
|
|
57
|
+
};
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Tool registration
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
/**
|
|
62
|
+
* Register the feishu_im_message tool for sending messages.
|
|
63
|
+
*/
|
|
64
|
+
export function registerImMessageTool(registry) {
|
|
65
|
+
// Register send message tool
|
|
66
|
+
registry.register({
|
|
67
|
+
name: 'feishu_im_send_message',
|
|
68
|
+
description: [
|
|
69
|
+
'Send an IM message with user identity.',
|
|
70
|
+
'',
|
|
71
|
+
'Usage:',
|
|
72
|
+
'- Use receive_id_type=open_id for private chat (provide user open_id)',
|
|
73
|
+
'- Use receive_id_type=chat_id for group chat (provide chat_id)',
|
|
74
|
+
'',
|
|
75
|
+
'Message types:',
|
|
76
|
+
'- text: Plain text. Content: \'{"text":"message"}\'',
|
|
77
|
+
'- post: Rich text. Content: \'{"zh_cn":{"title":"Title","content":[[{"tag":"text","text":"text"}]]}}\'',
|
|
78
|
+
'- image: Image. Content: \'{"image_key":"img_xxx"}\'',
|
|
79
|
+
'- file: File. Content: \'{"file_key":"file_xxx"}\'',
|
|
80
|
+
'- interactive: Interactive card.',
|
|
81
|
+
'',
|
|
82
|
+
'IMPORTANT: This tool sends messages as the authenticated user.',
|
|
83
|
+
'Before calling, confirm with the user: 1) Who to send to, 2) Message content.',
|
|
84
|
+
'',
|
|
85
|
+
'Requires OAuth authorization (use feishu_oauth tool with action="authorize" first).',
|
|
86
|
+
].join('\n'),
|
|
87
|
+
inputSchema: sendMessageSchema,
|
|
88
|
+
handler: async (args, context) => {
|
|
89
|
+
return handleSend(args, context);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
// Register reply message tool
|
|
93
|
+
registry.register({
|
|
94
|
+
name: 'feishu_im_reply_message',
|
|
95
|
+
description: [
|
|
96
|
+
'Reply to an IM message with user identity.',
|
|
97
|
+
'',
|
|
98
|
+
'Usage:',
|
|
99
|
+
'- Use message_id (om_xxx) to specify which message to reply to',
|
|
100
|
+
'- Use reply_in_thread=true to create a thread reply',
|
|
101
|
+
'',
|
|
102
|
+
'Message types:',
|
|
103
|
+
'- text: Plain text. Content: \'{"text":"message"}\'',
|
|
104
|
+
'- post: Rich text. Content: \'{"zh_cn":{"title":"Title","content":[[{"tag":"text","text":"text"}]]}}\'',
|
|
105
|
+
'- image: Image. Content: \'{"image_key":"img_xxx"}\'',
|
|
106
|
+
'',
|
|
107
|
+
'Requires OAuth authorization (use feishu_oauth tool with action="authorize" first).',
|
|
108
|
+
].join('\n'),
|
|
109
|
+
inputSchema: replyMessageSchema,
|
|
110
|
+
handler: async (args, context) => {
|
|
111
|
+
return handleReply(args, context);
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
log.debug('feishu_im_message tools registered');
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Handler
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
async function handleSend(args, context) {
|
|
120
|
+
const p = args;
|
|
121
|
+
const { larkClient, config } = context;
|
|
122
|
+
if (!larkClient) {
|
|
123
|
+
return jsonError('LarkClient not initialized. Check FEISHU_APP_ID and FEISHU_APP_SECRET.');
|
|
124
|
+
}
|
|
125
|
+
const { appId, appSecret, brand } = config;
|
|
126
|
+
if (!appId || !appSecret) {
|
|
127
|
+
return jsonError('Missing FEISHU_APP_ID or FEISHU_APP_SECRET.');
|
|
128
|
+
}
|
|
129
|
+
// Get the first stored user token
|
|
130
|
+
const { listStoredTokens } = await import('../../core/token-store.js');
|
|
131
|
+
const tokens = await listStoredTokens(appId);
|
|
132
|
+
if (tokens.length === 0) {
|
|
133
|
+
return jsonError('No user authorization found. Please use the feishu_oauth tool with action="authorize" to authorize a user first.');
|
|
134
|
+
}
|
|
135
|
+
const userOpenId = tokens[0].userOpenId;
|
|
136
|
+
try {
|
|
137
|
+
const accessToken = await getValidAccessToken({
|
|
138
|
+
userOpenId,
|
|
139
|
+
appId,
|
|
140
|
+
appSecret,
|
|
141
|
+
domain: brand ?? 'feishu',
|
|
142
|
+
});
|
|
143
|
+
log.info('Sending message', {
|
|
144
|
+
receive_id_type: p.receive_id_type,
|
|
145
|
+
receive_id: p.receive_id,
|
|
146
|
+
msg_type: p.msg_type,
|
|
147
|
+
});
|
|
148
|
+
const Lark = await import('@larksuiteoapi/node-sdk');
|
|
149
|
+
const opts = Lark.withUserAccessToken(accessToken);
|
|
150
|
+
const res = await larkClient.sdk.im.v1.message.create({
|
|
151
|
+
params: { receive_id_type: p.receive_id_type },
|
|
152
|
+
data: {
|
|
153
|
+
receive_id: p.receive_id,
|
|
154
|
+
msg_type: p.msg_type,
|
|
155
|
+
content: p.content,
|
|
156
|
+
uuid: p.uuid,
|
|
157
|
+
},
|
|
158
|
+
}, opts);
|
|
159
|
+
assertLarkOk(res);
|
|
160
|
+
const data = res.data;
|
|
161
|
+
log.info('Message sent', { message_id: data?.message_id });
|
|
162
|
+
return json({
|
|
163
|
+
message_id: data?.message_id,
|
|
164
|
+
chat_id: data?.chat_id,
|
|
165
|
+
create_time: data?.create_time,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
if (err instanceof NeedAuthorizationError) {
|
|
170
|
+
return jsonError(`User authorization required or expired. Please use feishu_oauth tool with action="authorize" to re-authorize.`, { userOpenId });
|
|
171
|
+
}
|
|
172
|
+
log.error('Send message failed', { error: err instanceof Error ? err.message : String(err) });
|
|
173
|
+
return jsonError(err instanceof Error ? err.message : String(err));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function handleReply(args, context) {
|
|
177
|
+
const p = args;
|
|
178
|
+
const { larkClient, config } = context;
|
|
179
|
+
if (!larkClient) {
|
|
180
|
+
return jsonError('LarkClient not initialized. Check FEISHU_APP_ID or FEISHU_APP_SECRET.');
|
|
181
|
+
}
|
|
182
|
+
const { appId, appSecret, brand } = config;
|
|
183
|
+
if (!appId || !appSecret) {
|
|
184
|
+
return jsonError('Missing FEISHU_APP_ID or FEISHU_APP_SECRET.');
|
|
185
|
+
}
|
|
186
|
+
// Get the first stored user token
|
|
187
|
+
const { listStoredTokens } = await import('../../core/token-store.js');
|
|
188
|
+
const tokens = await listStoredTokens(appId);
|
|
189
|
+
if (tokens.length === 0) {
|
|
190
|
+
return jsonError('No user authorization found. Please use the feishu_oauth tool with action="authorize" to authorize a user first.');
|
|
191
|
+
}
|
|
192
|
+
const userOpenId = tokens[0].userOpenId;
|
|
193
|
+
try {
|
|
194
|
+
const accessToken = await getValidAccessToken({
|
|
195
|
+
userOpenId,
|
|
196
|
+
appId,
|
|
197
|
+
appSecret,
|
|
198
|
+
domain: brand ?? 'feishu',
|
|
199
|
+
});
|
|
200
|
+
log.info('Replying to message', {
|
|
201
|
+
message_id: p.message_id,
|
|
202
|
+
msg_type: p.msg_type,
|
|
203
|
+
reply_in_thread: p.reply_in_thread ?? false,
|
|
204
|
+
});
|
|
205
|
+
const Lark = await import('@larksuiteoapi/node-sdk');
|
|
206
|
+
const opts = Lark.withUserAccessToken(accessToken);
|
|
207
|
+
const res = await larkClient.sdk.im.v1.message.reply({
|
|
208
|
+
path: { message_id: p.message_id },
|
|
209
|
+
data: {
|
|
210
|
+
content: p.content,
|
|
211
|
+
msg_type: p.msg_type,
|
|
212
|
+
reply_in_thread: p.reply_in_thread,
|
|
213
|
+
uuid: p.uuid,
|
|
214
|
+
},
|
|
215
|
+
}, opts);
|
|
216
|
+
assertLarkOk(res);
|
|
217
|
+
const data = res.data;
|
|
218
|
+
log.info('Reply sent', { message_id: data?.message_id });
|
|
219
|
+
return json({
|
|
220
|
+
message_id: data?.message_id,
|
|
221
|
+
chat_id: data?.chat_id,
|
|
222
|
+
create_time: data?.create_time,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
if (err instanceof NeedAuthorizationError) {
|
|
227
|
+
return jsonError(`User authorization required or expired. Please use feishu_oauth tool with action="authorize" to re-authorize.`, { userOpenId });
|
|
228
|
+
}
|
|
229
|
+
log.error('Reply message failed', { error: err instanceof Error ? err.message : String(err) });
|
|
230
|
+
return jsonError(err instanceof Error ? err.message : String(err));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../../src/tools/im/message.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* feishu_im_fetch_resource tool - Download IM message attachments with user identity.
|
|
6
|
+
*
|
|
7
|
+
* Uses Feishu API:
|
|
8
|
+
* - im.v1.messageResource.get: GET /open-apis/im/v1/messages/:message_id/resources/:file_key
|
|
9
|
+
*
|
|
10
|
+
* All calls use user access token (UAT) - requires OAuth authorization.
|
|
11
|
+
*
|
|
12
|
+
* Adapted from openclaw-lark for MCP Server architecture.
|
|
13
|
+
*/
|
|
14
|
+
import type { ToolRegistry } from '../index.js';
|
|
15
|
+
/**
|
|
16
|
+
* Register the feishu_im_fetch_resource tool.
|
|
17
|
+
*/
|
|
18
|
+
export declare function registerImFetchResourceTool(registry: ToolRegistry): void;
|
|
19
|
+
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../../src/tools/im/resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA8EhD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CA4HxE"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* feishu_im_fetch_resource tool - Download IM message attachments with user identity.
|
|
6
|
+
*
|
|
7
|
+
* Uses Feishu API:
|
|
8
|
+
* - im.v1.messageResource.get: GET /open-apis/im/v1/messages/:message_id/resources/:file_key
|
|
9
|
+
*
|
|
10
|
+
* All calls use user access token (UAT) - requires OAuth authorization.
|
|
11
|
+
*
|
|
12
|
+
* Adapted from openclaw-lark for MCP Server architecture.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
16
|
+
import { dirname } from 'node:path';
|
|
17
|
+
import { tmpdir } from 'node:os';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
import { getValidAccessToken, NeedAuthorizationError } from '../../core/uat-client.js';
|
|
20
|
+
import { json, jsonError } from './helpers.js';
|
|
21
|
+
import { logger } from '../../utils/logger.js';
|
|
22
|
+
const log = logger('tools:im:resource');
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// MIME type mapping
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
const MIME_TO_EXT = {
|
|
27
|
+
// Images
|
|
28
|
+
'image/png': '.png',
|
|
29
|
+
'image/jpeg': '.jpg',
|
|
30
|
+
'image/jpg': '.jpg',
|
|
31
|
+
'image/gif': '.gif',
|
|
32
|
+
'image/webp': '.webp',
|
|
33
|
+
'image/svg+xml': '.svg',
|
|
34
|
+
'image/bmp': '.bmp',
|
|
35
|
+
'image/tiff': '.tiff',
|
|
36
|
+
// Videos
|
|
37
|
+
'video/mp4': '.mp4',
|
|
38
|
+
'video/mpeg': '.mpeg',
|
|
39
|
+
'video/quicktime': '.mov',
|
|
40
|
+
'video/x-msvideo': '.avi',
|
|
41
|
+
'video/webm': '.webm',
|
|
42
|
+
// Audio
|
|
43
|
+
'audio/mpeg': '.mp3',
|
|
44
|
+
'audio/wav': '.wav',
|
|
45
|
+
'audio/ogg': '.ogg',
|
|
46
|
+
'audio/mp4': '.m4a',
|
|
47
|
+
// Documents
|
|
48
|
+
'application/pdf': '.pdf',
|
|
49
|
+
'application/msword': '.doc',
|
|
50
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
|
|
51
|
+
'application/vnd.ms-excel': '.xls',
|
|
52
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',
|
|
53
|
+
'application/vnd.ms-powerpoint': '.ppt',
|
|
54
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation': '.pptx',
|
|
55
|
+
// Others
|
|
56
|
+
'application/zip': '.zip',
|
|
57
|
+
'application/x-rar-compressed': '.rar',
|
|
58
|
+
'text/plain': '.txt',
|
|
59
|
+
'application/json': '.json',
|
|
60
|
+
};
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Input schema (raw shape for ZodRawShapeCompat)
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
const fetchResourceShape = {
|
|
65
|
+
message_id: z.string().describe('Message ID (om_xxx format), obtained from message events or message list'),
|
|
66
|
+
file_key: z.string().describe('Resource key from message body. For images use image_key (img_xxx), for files use file_key (file_xxx)'),
|
|
67
|
+
type: z.enum(['image', 'file']).describe('Resource type: image (image in image message) or file (file/audio/video in file message)'),
|
|
68
|
+
};
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Temp file helper
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
function buildRandomTempFilePath(options = {}) {
|
|
73
|
+
const { prefix = 'resource', extension } = options;
|
|
74
|
+
const randomId = Math.random().toString(36).substring(2, 10);
|
|
75
|
+
const timestamp = Date.now();
|
|
76
|
+
const baseName = `${prefix}-${timestamp}-${randomId}`;
|
|
77
|
+
return join(tmpdir(), 'cc-lark', extension ? `${baseName}${extension}` : baseName);
|
|
78
|
+
}
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Tool registration
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
/**
|
|
83
|
+
* Register the feishu_im_fetch_resource tool.
|
|
84
|
+
*/
|
|
85
|
+
export function registerImFetchResourceTool(registry) {
|
|
86
|
+
registry.register({
|
|
87
|
+
name: 'feishu_im_fetch_resource',
|
|
88
|
+
description: [
|
|
89
|
+
'Download IM message file/image attachments to local file with user identity.',
|
|
90
|
+
'',
|
|
91
|
+
'Usage:',
|
|
92
|
+
'- Use message_id from message list or search results',
|
|
93
|
+
'- Use file_key from message content (image_key for images, file_key for files)',
|
|
94
|
+
'- Use type="image" for images, type="file" for files/audio/video',
|
|
95
|
+
'',
|
|
96
|
+
'The downloaded file is saved to the system temp directory.',
|
|
97
|
+
'Returns: message_id, file_key, type, size_bytes, content_type, saved_path',
|
|
98
|
+
'',
|
|
99
|
+
'Limitations:',
|
|
100
|
+
'- File size limit: 100MB',
|
|
101
|
+
'- Does not support stickers, merge-forward messages, or card resources',
|
|
102
|
+
'',
|
|
103
|
+
'Requires OAuth authorization (use feishu_oauth tool with action="authorize" first).',
|
|
104
|
+
].join('\n'),
|
|
105
|
+
inputSchema: fetchResourceShape,
|
|
106
|
+
handler: async (args, context) => {
|
|
107
|
+
const p = args;
|
|
108
|
+
if (!context.larkClient) {
|
|
109
|
+
return jsonError('LarkClient not initialized. Check FEISHU_APP_ID and FEISHU_APP_SECRET.');
|
|
110
|
+
}
|
|
111
|
+
const { appId, appSecret, brand } = context.config;
|
|
112
|
+
if (!appId || !appSecret) {
|
|
113
|
+
return jsonError('Missing FEISHU_APP_ID or FEISHU_APP_SECRET.');
|
|
114
|
+
}
|
|
115
|
+
// Get the first stored user token
|
|
116
|
+
const { listStoredTokens } = await import('../../core/token-store.js');
|
|
117
|
+
const tokens = await listStoredTokens(appId);
|
|
118
|
+
if (tokens.length === 0) {
|
|
119
|
+
return jsonError('No user authorization found. Please use the feishu_oauth tool with action="authorize" to authorize a user first.');
|
|
120
|
+
}
|
|
121
|
+
const userOpenId = tokens[0].userOpenId;
|
|
122
|
+
try {
|
|
123
|
+
const accessToken = await getValidAccessToken({
|
|
124
|
+
userOpenId,
|
|
125
|
+
appId,
|
|
126
|
+
appSecret,
|
|
127
|
+
domain: brand ?? 'feishu',
|
|
128
|
+
});
|
|
129
|
+
log.info('fetch_resource: downloading', {
|
|
130
|
+
message_id: p.message_id,
|
|
131
|
+
file_key: p.file_key,
|
|
132
|
+
type: p.type,
|
|
133
|
+
});
|
|
134
|
+
const Lark = await import('@larksuiteoapi/node-sdk');
|
|
135
|
+
const opts = Lark.withUserAccessToken(accessToken);
|
|
136
|
+
// Download the resource
|
|
137
|
+
const res = await context.larkClient.sdk.im.v1.messageResource.get({
|
|
138
|
+
params: { type: p.type },
|
|
139
|
+
path: { message_id: p.message_id, file_key: p.file_key },
|
|
140
|
+
}, opts);
|
|
141
|
+
// Response is a binary stream, use getReadableStream()
|
|
142
|
+
const stream = res.getReadableStream();
|
|
143
|
+
const chunks = [];
|
|
144
|
+
for await (const chunk of stream) {
|
|
145
|
+
chunks.push(chunk);
|
|
146
|
+
}
|
|
147
|
+
const buffer = Buffer.concat(chunks);
|
|
148
|
+
log.info(`fetch_resource: downloaded ${buffer.length} bytes`);
|
|
149
|
+
// Get Content-Type from response headers
|
|
150
|
+
const contentType = res.headers?.['content-type'] || '';
|
|
151
|
+
log.info(`fetch_resource: content-type=${contentType}`);
|
|
152
|
+
// Infer extension from Content-Type
|
|
153
|
+
const mimeType = contentType ? contentType.split(';')[0].trim() : '';
|
|
154
|
+
const mimeExt = mimeType ? MIME_TO_EXT[mimeType] : undefined;
|
|
155
|
+
const finalPath = buildRandomTempFilePath({
|
|
156
|
+
prefix: 'im-resource',
|
|
157
|
+
extension: mimeExt,
|
|
158
|
+
});
|
|
159
|
+
log.info(`fetch_resource: saving to ${finalPath}`);
|
|
160
|
+
// Ensure parent directory exists
|
|
161
|
+
await mkdir(dirname(finalPath), { recursive: true });
|
|
162
|
+
// Write file
|
|
163
|
+
await writeFile(finalPath, buffer);
|
|
164
|
+
log.info(`fetch_resource: saved to ${finalPath}`);
|
|
165
|
+
return json({
|
|
166
|
+
message_id: p.message_id,
|
|
167
|
+
file_key: p.file_key,
|
|
168
|
+
type: p.type,
|
|
169
|
+
size_bytes: buffer.length,
|
|
170
|
+
content_type: contentType,
|
|
171
|
+
saved_path: finalPath,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
if (err instanceof NeedAuthorizationError) {
|
|
176
|
+
return jsonError(`User authorization required or expired. Please use feishu_oauth tool with action="authorize" to re-authorize.`, { userOpenId });
|
|
177
|
+
}
|
|
178
|
+
log.error('fetch_resource failed', { error: err instanceof Error ? err.message : String(err) });
|
|
179
|
+
return jsonError(err instanceof Error ? err.message : String(err));
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
log.debug('feishu_im_fetch_resource tool registered');
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.js","sourceRoot":"","sources":["../../../src/tools/im/resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*
|
|
5
|
+
* Time utilities for IM tools.
|
|
6
|
+
*
|
|
7
|
+
* Provides time range parsing and ISO 8601 conversion utilities.
|
|
8
|
+
* Adapted from openclaw-lark for MCP Server architecture.
|
|
9
|
+
*/
|
|
10
|
+
/** Convert Unix seconds (number) to ISO 8601 Beijing time */
|
|
11
|
+
export declare function secondsToDateTime(seconds: number): string;
|
|
12
|
+
/** Convert Unix seconds (string) to ISO 8601 Beijing time */
|
|
13
|
+
export declare function secondsStringToDateTime(seconds: string): string;
|
|
14
|
+
/** Convert Unix milliseconds (number) to ISO 8601 Beijing time */
|
|
15
|
+
export declare function millisToDateTime(millis: number): string;
|
|
16
|
+
/** Convert Unix milliseconds (string) to ISO 8601 Beijing time */
|
|
17
|
+
export declare function millisStringToDateTime(millis: string): string;
|
|
18
|
+
/** Convert ISO 8601 to Unix seconds (number) */
|
|
19
|
+
export declare function dateTimeToSeconds(datetime: string): number;
|
|
20
|
+
/** Convert ISO 8601 to Unix seconds (string) */
|
|
21
|
+
export declare function dateTimeToSecondsString(datetime: string): string;
|
|
22
|
+
/** Convert ISO 8601 to Unix milliseconds (number) */
|
|
23
|
+
export declare function dateTimeToMillis(datetime: string): number;
|
|
24
|
+
/** ISO 8601 time range */
|
|
25
|
+
export interface TimeRange {
|
|
26
|
+
start: string;
|
|
27
|
+
end: string;
|
|
28
|
+
}
|
|
29
|
+
/** Unix timestamp time range (seconds) */
|
|
30
|
+
export interface TimeRangeSeconds {
|
|
31
|
+
start: string;
|
|
32
|
+
end: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Parse a time range identifier to ISO 8601 string pair.
|
|
36
|
+
*
|
|
37
|
+
* Supported formats:
|
|
38
|
+
* - `today` / `yesterday` / `day_before_yesterday`
|
|
39
|
+
* - `this_week` / `last_week` / `this_month` / `last_month`
|
|
40
|
+
* - `last_{N}_{unit}` — unit: minutes / hours / days
|
|
41
|
+
*
|
|
42
|
+
* All calculations are based on Beijing time (UTC+8).
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseTimeRange(input: string): TimeRange;
|
|
45
|
+
/**
|
|
46
|
+
* Parse a time range identifier to Unix seconds string pair.
|
|
47
|
+
* This is for SDK API calls that require Unix timestamps.
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseTimeRangeToSeconds(input: string): TimeRangeSeconds;
|
|
50
|
+
/**
|
|
51
|
+
* Parse a time string to Unix timestamp (seconds).
|
|
52
|
+
*
|
|
53
|
+
* Supports:
|
|
54
|
+
* 1. ISO 8601 / RFC 3339 with timezone: "2024-01-01T00:00:00+08:00"
|
|
55
|
+
* 2. Formats without timezone (defaults to Beijing time UTC+8):
|
|
56
|
+
* - "2026-02-25 14:30"
|
|
57
|
+
* - "2026-02-25 14:30:00"
|
|
58
|
+
* - "2026-02-25T14:30:00"
|
|
59
|
+
*
|
|
60
|
+
* Returns null if parsing fails.
|
|
61
|
+
*/
|
|
62
|
+
export declare function parseTimeToTimestamp(input: string): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* Convert a Unix timestamp (seconds or milliseconds) to ISO 8601 string
|
|
65
|
+
* in Asia/Shanghai timezone.
|
|
66
|
+
*
|
|
67
|
+
* Auto-detects seconds vs milliseconds based on magnitude.
|
|
68
|
+
*/
|
|
69
|
+
export declare function unixTimestampToISO8601(raw: string | number | undefined): string | null;
|
|
70
|
+
//# sourceMappingURL=time-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-utils.d.ts","sourceRoot":"","sources":["../../../src/tools/im/time-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAwBH,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,6DAA6D;AAC7D,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AAMD,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,kEAAkE;AAClE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7D;AAMD,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED,gDAAgD;AAChD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,qDAAqD;AACrD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQzD;AAMD,0BAA0B;AAC1B,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,0CAA0C;AAC1C,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CA6FvD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAMvE;AA6CD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA0CjE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAqBtF"}
|