@larksuite/openclaw-lark 2026.4.1 → 2026.4.7

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.
Files changed (43) hide show
  1. package/index.js +25 -6
  2. package/package.json +1 -1
  3. package/src/card/builder.d.ts +29 -7
  4. package/src/card/builder.js +241 -29
  5. package/src/card/reasoning-utils.d.ts +14 -0
  6. package/src/card/reasoning-utils.js +64 -0
  7. package/src/card/reply-dispatcher-types.d.ts +12 -15
  8. package/src/card/reply-dispatcher-types.js +1 -0
  9. package/src/card/reply-dispatcher.js +63 -11
  10. package/src/card/streaming-card-controller.d.ts +15 -0
  11. package/src/card/streaming-card-controller.js +188 -65
  12. package/src/card/tool-use-config.d.ts +26 -0
  13. package/src/card/tool-use-config.js +76 -0
  14. package/src/card/tool-use-display.d.ts +29 -0
  15. package/src/card/tool-use-display.js +438 -0
  16. package/src/card/tool-use-trace-store.d.ts +51 -0
  17. package/src/card/tool-use-trace-store.js +271 -0
  18. package/src/channel/event-handlers.d.ts +1 -0
  19. package/src/channel/event-handlers.js +51 -0
  20. package/src/channel/monitor.js +2 -0
  21. package/src/core/comment-target.d.ts +65 -0
  22. package/src/core/comment-target.js +100 -0
  23. package/src/core/config-schema.d.ts +9 -0
  24. package/src/core/config-schema.js +5 -0
  25. package/src/core/tool-scopes.d.ts +1 -1
  26. package/src/core/tool-scopes.js +7 -0
  27. package/src/messaging/inbound/comment-context.d.ts +82 -0
  28. package/src/messaging/inbound/comment-context.js +353 -0
  29. package/src/messaging/inbound/comment-handler.d.ts +30 -0
  30. package/src/messaging/inbound/comment-handler.js +269 -0
  31. package/src/messaging/inbound/dispatch-commands.js +23 -2
  32. package/src/messaging/inbound/dispatch-context.js +19 -7
  33. package/src/messaging/inbound/dispatch.js +87 -8
  34. package/src/messaging/outbound/deliver.d.ts +29 -0
  35. package/src/messaging/outbound/deliver.js +94 -0
  36. package/src/messaging/outbound/outbound.js +19 -0
  37. package/src/messaging/types.d.ts +63 -0
  38. package/src/tools/oapi/drive/doc-comments.js +93 -24
  39. package/src/tools/oapi/index.js +1 -0
  40. package/src/tools/oapi/task/index.d.ts +1 -0
  41. package/src/tools/oapi/task/index.js +3 -1
  42. package/src/tools/oapi/task/section.d.ts +17 -0
  43. package/src/tools/oapi/task/section.js +285 -0
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
4
+ * SPDX-License-Identifier: MIT
5
+ *
6
+ * feishu_task_section tool -- Manage Feishu task sections.
7
+ *
8
+ * P0 Actions: create, get, list, patch, tasks
9
+ *
10
+ * Uses the Feishu Task v2 API:
11
+ * - create: POST /open-apis/task/v2/sections
12
+ * - get: GET /open-apis/task/v2/sections/:section_guid
13
+ * - patch: PATCH /open-apis/task/v2/sections/:section_guid
14
+ * - list: GET /open-apis/task/v2/sections
15
+ * - tasks: GET /open-apis/task/v2/sections/:section_guid/tasks
16
+ */
17
+ /* eslint-disable @typescript-eslint/no-explicit-any */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.registerFeishuTaskSectionTool = registerFeishuTaskSectionTool;
20
+ const typebox_1 = require("@sinclair/typebox");
21
+ const helpers_1 = require("../helpers.js");
22
+ // ---------------------------------------------------------------------------
23
+ // Schema
24
+ // ---------------------------------------------------------------------------
25
+ const FeishuTaskSectionSchema = typebox_1.Type.Union([
26
+ // CREATE
27
+ typebox_1.Type.Object({
28
+ action: typebox_1.Type.Literal('create'),
29
+ name: typebox_1.Type.String({
30
+ description: '自定义分组名。不允许为空,最大100个utf8字符。',
31
+ }),
32
+ resource_type: (0, helpers_1.StringEnum)(['tasklist', 'my_tasks']),
33
+ resource_id: typebox_1.Type.Optional(typebox_1.Type.String({
34
+ description: '自定义分组要归属的资源id。当resource_type为"tasklist"时这里需要填写清单的GUID;当resource_type为"my_tasks"时,无需填写。',
35
+ })),
36
+ insert_before: typebox_1.Type.Optional(typebox_1.Type.String({
37
+ description: '要将新分组插入到自定义分分组的前面的目标分组的guid。',
38
+ })),
39
+ insert_after: typebox_1.Type.Optional(typebox_1.Type.String({
40
+ description: '要将新分组插入到自定义分分组的后面的目标分组的guid。',
41
+ })),
42
+ user_id_type: typebox_1.Type.Optional((0, helpers_1.StringEnum)(['open_id', 'union_id', 'user_id'])),
43
+ }),
44
+ // GET
45
+ typebox_1.Type.Object({
46
+ action: typebox_1.Type.Literal('get'),
47
+ section_guid: typebox_1.Type.String({
48
+ description: '要获取的自定义分组GUID',
49
+ }),
50
+ user_id_type: typebox_1.Type.Optional((0, helpers_1.StringEnum)(['open_id', 'union_id', 'user_id'])),
51
+ }),
52
+ // PATCH
53
+ typebox_1.Type.Object({
54
+ action: typebox_1.Type.Literal('patch'),
55
+ section_guid: typebox_1.Type.String({
56
+ description: '要更新的自定义分组GUID',
57
+ }),
58
+ name: typebox_1.Type.Optional(typebox_1.Type.String({
59
+ description: '自定义字段名字',
60
+ })),
61
+ insert_before: typebox_1.Type.Optional(typebox_1.Type.String({
62
+ description: '要让当前自定义分组放到某个自定义分组前面的secion_guid,用于改变当前自定义分组的位置。',
63
+ })),
64
+ insert_after: typebox_1.Type.Optional(typebox_1.Type.String({
65
+ description: '要让当前自定义分组放到某个自定义分组后面的secion_guid,用于改变当前自定义分组的位置。',
66
+ })),
67
+ user_id_type: typebox_1.Type.Optional((0, helpers_1.StringEnum)(['open_id', 'union_id', 'user_id'])),
68
+ }),
69
+ // LIST
70
+ typebox_1.Type.Object({
71
+ action: typebox_1.Type.Literal('list'),
72
+ resource_type: (0, helpers_1.StringEnum)(['tasklist', 'my_tasks']),
73
+ resource_id: typebox_1.Type.Optional(typebox_1.Type.String({
74
+ description: '如resource_type为"tasklist",这里需要填写要列取自定义分组的清单的GUID。',
75
+ })),
76
+ page_size: typebox_1.Type.Optional(typebox_1.Type.Number({
77
+ description: '分页大小',
78
+ })),
79
+ page_token: typebox_1.Type.Optional(typebox_1.Type.String({
80
+ description: '分页标记',
81
+ })),
82
+ user_id_type: typebox_1.Type.Optional((0, helpers_1.StringEnum)(['open_id', 'union_id', 'user_id'])),
83
+ }),
84
+ // TASKS
85
+ typebox_1.Type.Object({
86
+ action: typebox_1.Type.Literal('tasks'),
87
+ section_guid: typebox_1.Type.String({
88
+ description: '要获取任务的自定义分组全局唯一ID',
89
+ }),
90
+ page_size: typebox_1.Type.Optional(typebox_1.Type.Number({
91
+ description: '分页大小',
92
+ })),
93
+ page_token: typebox_1.Type.Optional(typebox_1.Type.String({
94
+ description: '分页标记',
95
+ })),
96
+ completed: typebox_1.Type.Optional(typebox_1.Type.Boolean({
97
+ description: '按照任务状态过滤,如果不填写则表示不按完成状态过滤',
98
+ })),
99
+ created_from: typebox_1.Type.Optional(typebox_1.Type.String({
100
+ description: '按照创建时间筛选的起始时间(支持 ISO 8601 或毫秒时间戳)',
101
+ })),
102
+ created_to: typebox_1.Type.Optional(typebox_1.Type.String({
103
+ description: '按照创建时间筛选的结束时间(支持 ISO 8601 或毫秒时间戳)',
104
+ })),
105
+ user_id_type: typebox_1.Type.Optional((0, helpers_1.StringEnum)(['open_id', 'union_id', 'user_id'])),
106
+ }),
107
+ ]);
108
+ // ---------------------------------------------------------------------------
109
+ // Registration
110
+ // ---------------------------------------------------------------------------
111
+ function registerFeishuTaskSectionTool(api) {
112
+ if (!api.config)
113
+ return;
114
+ const cfg = api.config;
115
+ const { toolClient, log } = (0, helpers_1.createToolContext)(api, 'feishu_task_section');
116
+ (0, helpers_1.registerTool)(api, {
117
+ name: 'feishu_task_section',
118
+ label: 'Feishu Task Section Management',
119
+ description: '【以用户身份】飞书任务自定义分组管理工具。用于创建、查询、更新自定义分组,以及列出分组内的任务。Actions: create(创建分组), get(获取分组详情), patch(更新分组), list(获取分组列表), tasks(获取分组任务列表)。',
120
+ parameters: FeishuTaskSectionSchema,
121
+ async execute(_toolCallId, params) {
122
+ const p = params;
123
+ try {
124
+ const client = toolClient();
125
+ switch (p.action) {
126
+ // -----------------------------------------------------------------
127
+ // CREATE SECTION
128
+ // -----------------------------------------------------------------
129
+ case 'create': {
130
+ log.info(`create: name=${p.name}, resource_type=${p.resource_type}`);
131
+ const data = {
132
+ name: p.name,
133
+ resource_type: p.resource_type,
134
+ };
135
+ if (p.resource_id)
136
+ data.resource_id = p.resource_id;
137
+ if (p.insert_before)
138
+ data.insert_before = p.insert_before;
139
+ if (p.insert_after)
140
+ data.insert_after = p.insert_after;
141
+ const res = await client.invoke('feishu_task_section.create', (sdk, opts) => sdk.task.v2.section.create({
142
+ data,
143
+ params: {
144
+ user_id_type: (p.user_id_type || 'open_id'),
145
+ },
146
+ }, opts), { as: 'user' });
147
+ (0, helpers_1.assertLarkOk)(res);
148
+ log.info(`create: section created: section_guid=${res.data?.section?.guid}`);
149
+ return (0, helpers_1.json)({
150
+ section: res.data?.section,
151
+ });
152
+ }
153
+ // -----------------------------------------------------------------
154
+ // GET SECTION
155
+ // -----------------------------------------------------------------
156
+ case 'get': {
157
+ log.info(`get: section_guid=${p.section_guid}`);
158
+ const res = await client.invoke('feishu_task_section.get', (sdk, opts) => sdk.task.v2.section.get({
159
+ path: { section_guid: p.section_guid },
160
+ params: {
161
+ user_id_type: (p.user_id_type || 'open_id'),
162
+ },
163
+ }, opts), { as: 'user' });
164
+ (0, helpers_1.assertLarkOk)(res);
165
+ log.info(`get: retrieved section ${p.section_guid}`);
166
+ return (0, helpers_1.json)({
167
+ section: res.data?.section,
168
+ });
169
+ }
170
+ // -----------------------------------------------------------------
171
+ // PATCH SECTION
172
+ // -----------------------------------------------------------------
173
+ case 'patch': {
174
+ log.info(`patch: section_guid=${p.section_guid}`);
175
+ const sectionData = {};
176
+ const updateFields = [];
177
+ if (p.name !== undefined) {
178
+ sectionData.name = p.name;
179
+ updateFields.push('name');
180
+ }
181
+ if (p.insert_before !== undefined) {
182
+ sectionData.insert_before = p.insert_before;
183
+ updateFields.push('insert_before');
184
+ }
185
+ if (p.insert_after !== undefined) {
186
+ sectionData.insert_after = p.insert_after;
187
+ updateFields.push('insert_after');
188
+ }
189
+ if (updateFields.length === 0) {
190
+ return (0, helpers_1.json)({
191
+ error: 'No fields to update',
192
+ });
193
+ }
194
+ const res = await client.invoke('feishu_task_section.patch', (sdk, opts) => sdk.task.v2.section.patch({
195
+ path: { section_guid: p.section_guid },
196
+ data: {
197
+ section: sectionData,
198
+ update_fields: updateFields,
199
+ },
200
+ params: {
201
+ user_id_type: (p.user_id_type || 'open_id'),
202
+ },
203
+ }, opts), { as: 'user' });
204
+ (0, helpers_1.assertLarkOk)(res);
205
+ log.info(`patch: section ${p.section_guid} updated`);
206
+ return (0, helpers_1.json)({
207
+ section: res.data?.section,
208
+ });
209
+ }
210
+ // -----------------------------------------------------------------
211
+ // LIST SECTIONS
212
+ // -----------------------------------------------------------------
213
+ case 'list': {
214
+ log.info(`list: resource_type=${p.resource_type}, page_size=${p.page_size ?? 50}`);
215
+ const paramsData = {
216
+ resource_type: p.resource_type,
217
+ user_id_type: (p.user_id_type || 'open_id'),
218
+ };
219
+ if (p.resource_id)
220
+ paramsData.resource_id = p.resource_id;
221
+ if (p.page_size !== undefined)
222
+ paramsData.page_size = p.page_size;
223
+ if (p.page_token !== undefined)
224
+ paramsData.page_token = p.page_token;
225
+ const res = await client.invoke('feishu_task_section.list', (sdk, opts) => sdk.task.v2.section.list({
226
+ params: paramsData,
227
+ }, opts), { as: 'user' });
228
+ (0, helpers_1.assertLarkOk)(res);
229
+ const data = res.data;
230
+ log.info(`list: returned ${data?.items?.length ?? 0} sections`);
231
+ return (0, helpers_1.json)({
232
+ sections: data?.items,
233
+ has_more: data?.has_more ?? false,
234
+ page_token: data?.page_token,
235
+ });
236
+ }
237
+ // -----------------------------------------------------------------
238
+ // TASKS IN SECTION
239
+ // -----------------------------------------------------------------
240
+ case 'tasks': {
241
+ log.info(`tasks: section_guid=${p.section_guid}`);
242
+ const paramsData = {
243
+ user_id_type: (p.user_id_type || 'open_id'),
244
+ };
245
+ if (p.page_size !== undefined)
246
+ paramsData.page_size = p.page_size;
247
+ if (p.page_token !== undefined)
248
+ paramsData.page_token = p.page_token;
249
+ if (p.completed !== undefined)
250
+ paramsData.completed = p.completed;
251
+ if (p.created_from) {
252
+ const ts = (0, helpers_1.parseTimeToTimestampMs)(p.created_from);
253
+ if (ts)
254
+ paramsData.created_from = ts;
255
+ else
256
+ paramsData.created_from = p.created_from;
257
+ }
258
+ if (p.created_to) {
259
+ const ts = (0, helpers_1.parseTimeToTimestampMs)(p.created_to);
260
+ if (ts)
261
+ paramsData.created_to = ts;
262
+ else
263
+ paramsData.created_to = p.created_to;
264
+ }
265
+ const res = await client.invoke('feishu_task_section.tasks', (sdk, opts) => sdk.task.v2.section.tasks({
266
+ path: { section_guid: p.section_guid },
267
+ params: paramsData,
268
+ }, opts), { as: 'user' });
269
+ (0, helpers_1.assertLarkOk)(res);
270
+ const data = res.data;
271
+ log.info(`tasks: returned ${data?.items?.length ?? 0} tasks`);
272
+ return (0, helpers_1.json)({
273
+ tasks: data?.items,
274
+ has_more: data?.has_more ?? false,
275
+ page_token: data?.page_token,
276
+ });
277
+ }
278
+ }
279
+ }
280
+ catch (err) {
281
+ return await (0, helpers_1.handleInvokeErrorWithAutoAuth)(err, cfg);
282
+ }
283
+ },
284
+ }, { name: 'feishu_task_section' });
285
+ }