larkcc 0.4.0 → 0.6.0
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 +61 -12
- package/README.md +188 -27
- package/dist/agent.d.ts +2 -1
- package/dist/agent.js +189 -38
- package/dist/agent.js.map +1 -1
- package/dist/app.js +14 -5
- package/dist/app.js.map +1 -1
- package/dist/cardkit.d.ts +125 -0
- package/dist/cardkit.js +448 -0
- package/dist/cardkit.js.map +1 -0
- package/dist/config.d.ts +23 -3
- package/dist/config.js +43 -47
- package/dist/config.js.map +1 -1
- package/dist/feishu.d.ts +50 -4
- package/dist/feishu.js +287 -97
- package/dist/feishu.js.map +1 -1
- package/dist/format/builder.d.ts +126 -37
- package/dist/format/builder.js +276 -116
- package/dist/format/builder.js.map +1 -1
- package/dist/format/card-optimize.d.ts +42 -0
- package/dist/format/card-optimize.js +74 -0
- package/dist/format/card-optimize.js.map +1 -0
- package/dist/format/constants.d.ts +80 -9
- package/dist/format/constants.js +140 -53
- package/dist/format/constants.js.map +1 -1
- package/dist/format/document.d.ts +4 -2
- package/dist/format/document.js +57 -35
- package/dist/format/document.js.map +1 -1
- package/dist/format/duration.d.ts +24 -0
- package/dist/format/duration.js +72 -0
- package/dist/format/duration.js.map +1 -0
- package/dist/format/guide.d.ts +19 -0
- package/dist/format/guide.js +201 -0
- package/dist/format/guide.js.map +1 -0
- package/dist/format/image-resolver.d.ts +31 -0
- package/dist/format/image-resolver.js +202 -0
- package/dist/format/image-resolver.js.map +1 -0
- package/dist/format/index.d.ts +8 -3
- package/dist/format/index.js +8 -2
- package/dist/format/index.js.map +1 -1
- package/dist/format/parser.d.ts +16 -0
- package/dist/format/parser.js +26 -12
- package/dist/format/parser.js.map +1 -1
- package/dist/format/sanitize.d.ts +3 -0
- package/dist/format/sanitize.js +16 -7
- package/dist/format/sanitize.js.map +1 -1
- package/dist/format/thinking.d.ts +29 -0
- package/dist/format/thinking.js +50 -0
- package/dist/format/thinking.js.map +1 -0
- package/dist/resources/format-guide.md +109 -0
- package/dist/streaming.d.ts +83 -0
- package/dist/streaming.js +301 -0
- package/dist/streaming.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -4
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/feishu.d.ts
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import * as lark from "@larksuiteoapi/node-sdk";
|
|
2
2
|
import { OverflowConfig, CardTableConfig } from "./config.js";
|
|
3
3
|
import { DocumentMeta } from "./format/index.js";
|
|
4
|
+
export declare function registerDocument(docId: string, profile: string): void;
|
|
4
5
|
export declare function createLarkClient(appId: string, appSecret: string): lark.Client;
|
|
5
6
|
export declare function createWSClient(appId: string, appSecret: string): lark.WSClient;
|
|
6
7
|
export declare function sendText(client: lark.Client, chatId: string, text: string): Promise<string>;
|
|
7
8
|
export declare function replyText(client: lark.Client, chatId: string, rootMsgId: string, text: string): Promise<string>;
|
|
8
9
|
export declare function updateText(client: lark.Client, msgId: string, text: string): Promise<void>;
|
|
9
|
-
export
|
|
10
|
-
|
|
10
|
+
export interface ReplyFinalOptions {
|
|
11
|
+
/** 底部元数据(耗时、token 等),仅追加到卡片 */
|
|
12
|
+
metadata?: string;
|
|
13
|
+
/** 思考内容,显示在可折叠区域 */
|
|
14
|
+
thinking?: string;
|
|
15
|
+
/** 卡片标题 */
|
|
16
|
+
cardTitle?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function replyFinalCard(client: lark.Client, chatId: string, rootMsgId: string, markdown: string, context?: ReplyContext, options?: ReplyFinalOptions): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* 准备溢出文档所需的上下文(标题、原始消息、元信息)
|
|
21
|
+
*/
|
|
22
|
+
export declare function prepareOverflowContext(client: lark.Client, rootMsgId: string, context: ReplyContext): Promise<{
|
|
23
|
+
token: string;
|
|
24
|
+
title: string;
|
|
25
|
+
originalMessage: string;
|
|
26
|
+
meta: DocumentMeta;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function sendToolCard(client: lark.Client, chatId: string, rootMsgId: string, label: string, detail: string, status?: "running" | "done" | "error", toolName?: string): Promise<string>;
|
|
11
29
|
export declare function updateToolCard(client: lark.Client, msgId: string, label: string, detail: string, _resultPreview: string): Promise<void>;
|
|
12
30
|
export declare function downloadImage(client: lark.Client, messageId: string, imageKey: string): Promise<{
|
|
13
31
|
base64: string;
|
|
@@ -24,7 +42,25 @@ export interface DownloadedFile {
|
|
|
24
42
|
* 下载飞书消息中的文件到本地临时目录
|
|
25
43
|
*/
|
|
26
44
|
export declare function downloadFile(client: lark.Client, messageId: string, fileKey: string, tempDir: string, filename: string): Promise<DownloadedFile | null>;
|
|
27
|
-
interface
|
|
45
|
+
export interface CardBuildOptions {
|
|
46
|
+
/** 思考内容(完整),显示在可折叠区域 */
|
|
47
|
+
thinking?: string;
|
|
48
|
+
/** 思考进行中指示器(流式中间态) */
|
|
49
|
+
thinkingInProgress?: boolean;
|
|
50
|
+
/** 思考耗时(毫秒) */
|
|
51
|
+
reasoningElapsedMs?: number;
|
|
52
|
+
/** 卡片标题,为空则不显示 header */
|
|
53
|
+
cardTitle?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 构建飞书卡片 JSON
|
|
57
|
+
*
|
|
58
|
+
* 支持可选的思考过程折叠区域:
|
|
59
|
+
* - thinkingInProgress: 流式中间态,显示"💭 思考中..."提示
|
|
60
|
+
* - thinking: 完成态,显示可折叠的思考过程
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildMarkdownCard(markdown: string, warnings?: string[], options?: CardBuildOptions): any;
|
|
63
|
+
export interface ReplyContext {
|
|
28
64
|
profile: string;
|
|
29
65
|
cwd: string;
|
|
30
66
|
sessionId: string;
|
|
@@ -37,9 +73,19 @@ interface ReplyContext {
|
|
|
37
73
|
}
|
|
38
74
|
/**
|
|
39
75
|
* 创建云文档并写入内容(在应用云空间)
|
|
76
|
+
*
|
|
77
|
+
* 写入流程(严格保序):
|
|
78
|
+
* - 简单块:分批通过 children API 写入
|
|
79
|
+
* - 表格/高亮块:通过 descendants API 写入
|
|
80
|
+
* - 保持原始文档顺序
|
|
40
81
|
*/
|
|
41
82
|
export declare function createOverflowDocument(token: string, title: string, markdown: string, originalMessage: string, meta: DocumentMeta): Promise<{
|
|
42
83
|
docUrl: string;
|
|
43
84
|
docId: string;
|
|
85
|
+
warnings: string[];
|
|
44
86
|
}>;
|
|
45
|
-
|
|
87
|
+
/**
|
|
88
|
+
* 使缓存的 token 失效,下次调用 getTenantAccessToken 时强制刷新
|
|
89
|
+
*/
|
|
90
|
+
export declare function invalidateTokenCache(): void;
|
|
91
|
+
export declare function getTenantAccessToken(appId: string, appSecret: string): Promise<string>;
|
package/dist/feishu.js
CHANGED
|
@@ -2,7 +2,8 @@ import * as lark from "@larksuiteoapi/node-sdk";
|
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import * as os from "os";
|
|
5
|
-
import { sanitizeContent, formatWarnings, markdownToBlocks, countTables } from "./format/index.js";
|
|
5
|
+
import { sanitizeContent, formatWarnings, markdownToBlocks, countTables, optimizeForCard, BlockType } from "./format/index.js";
|
|
6
|
+
import { buildThinkingPanel } from "./format/duration.js";
|
|
6
7
|
const DOC_REGISTRY_DIR = path.join(os.homedir(), ".larkcc");
|
|
7
8
|
function getDocRegistryPath(profile) {
|
|
8
9
|
if (!profile || profile === "default") {
|
|
@@ -29,7 +30,7 @@ function saveDocRegistry(profile, records) {
|
|
|
29
30
|
const filePath = getDocRegistryPath(profile);
|
|
30
31
|
fs.writeFileSync(filePath, JSON.stringify(records, null, 2), "utf8");
|
|
31
32
|
}
|
|
32
|
-
function registerDocument(docId, profile) {
|
|
33
|
+
export function registerDocument(docId, profile) {
|
|
33
34
|
const records = loadDocRegistry(profile);
|
|
34
35
|
records.push({
|
|
35
36
|
id: docId,
|
|
@@ -88,7 +89,6 @@ export async function updateText(client, msgId, text) {
|
|
|
88
89
|
// 最终回复卡片,超长分段发送,卡片失败 fallback 到普通文本
|
|
89
90
|
const CHUNK_SIZE = 2800;
|
|
90
91
|
const DEFAULT_MAX_TABLES_PER_CARD = 5;
|
|
91
|
-
const DEFAULT_MAX_TABLES_SPLIT = 10;
|
|
92
92
|
function splitMarkdown(text, size) {
|
|
93
93
|
if (text.length <= size)
|
|
94
94
|
return [text];
|
|
@@ -183,62 +183,56 @@ function splitMarkdownByTables(markdown, maxTables) {
|
|
|
183
183
|
flushChunk();
|
|
184
184
|
return chunks;
|
|
185
185
|
}
|
|
186
|
-
export async function replyFinalCard(client, chatId, rootMsgId, markdown, context) {
|
|
186
|
+
export async function replyFinalCard(client, chatId, rootMsgId, markdown, context, options) {
|
|
187
187
|
const threshold = context?.overflow.mode === "document"
|
|
188
188
|
? context.overflow.document.threshold
|
|
189
189
|
: context?.overflow.chunk.threshold ?? CHUNK_SIZE;
|
|
190
|
-
// 统计表格数量
|
|
191
190
|
const tableCount = countTables(markdown);
|
|
192
191
|
const maxTablesPerCard = context?.card_table?.max_tables_per_card ?? DEFAULT_MAX_TABLES_PER_CARD;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
192
|
+
// 表格数量超过卡片承载能力
|
|
193
|
+
if (tableCount > maxTablesPerCard) {
|
|
194
|
+
if (context?.overflow.mode === "document" && markdown.length > threshold) {
|
|
195
|
+
// 表格多 + 内容长 → 文档(文档比分片更适合承载大量表格+长文本)
|
|
197
196
|
await replyWithDocument(client, chatId, rootMsgId, markdown, context);
|
|
198
197
|
}
|
|
199
198
|
else {
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
const content = chunks.length > 1
|
|
205
|
-
? `**(${i + 1}/${chunks.length})**\n${chunks[i]}`
|
|
206
|
-
: chunks[i];
|
|
207
|
-
await sendMessageChunk(client, rootMsgId, content);
|
|
199
|
+
// 表格多 + 内容短 → 按表格拆分为多个卡片
|
|
200
|
+
const chunks = splitMarkdownByTables(markdown, maxTablesPerCard);
|
|
201
|
+
for (const chunk of chunks) {
|
|
202
|
+
await sendMessageChunk(client, rootMsgId, chunk);
|
|
208
203
|
}
|
|
209
204
|
}
|
|
210
205
|
return;
|
|
211
206
|
}
|
|
212
|
-
// 表格数量需要拆分发送
|
|
213
|
-
if (tableCount > maxTablesPerCard) {
|
|
214
|
-
const chunks = splitMarkdownByTables(markdown, maxTablesPerCard);
|
|
215
|
-
for (const chunk of chunks) {
|
|
216
|
-
await sendMessageChunk(client, rootMsgId, chunk);
|
|
217
|
-
}
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
207
|
// 不超限,直接发送
|
|
221
208
|
if (markdown.length <= threshold) {
|
|
222
|
-
|
|
209
|
+
const finalContent = options?.metadata
|
|
210
|
+
? `${markdown}\n\n---\n${options.metadata}`
|
|
211
|
+
: markdown;
|
|
212
|
+
await sendMessageChunk(client, rootMsgId, finalContent, options?.thinking, options?.cardTitle);
|
|
223
213
|
return;
|
|
224
214
|
}
|
|
225
215
|
// 超限处理
|
|
226
216
|
if (context?.overflow.mode === "document") {
|
|
227
|
-
//
|
|
217
|
+
// 文档模式:不追加 metadata 和 thinking
|
|
228
218
|
await replyWithDocument(client, chatId, rootMsgId, markdown, context);
|
|
229
219
|
}
|
|
230
220
|
else {
|
|
231
|
-
// 分片发送
|
|
232
221
|
const chunks = splitMarkdown(markdown, context?.overflow.chunk.threshold ?? CHUNK_SIZE);
|
|
233
222
|
for (let i = 0; i < chunks.length; i++) {
|
|
223
|
+
const isLast = i === chunks.length - 1;
|
|
234
224
|
const content = chunks.length > 1
|
|
235
225
|
? `**(${i + 1}/${chunks.length})**\n${chunks[i]}`
|
|
236
226
|
: chunks[i];
|
|
237
|
-
|
|
227
|
+
// 仅在最后一个 chunk 追加 metadata 和 thinking
|
|
228
|
+
const finalContent = isLast && options?.metadata
|
|
229
|
+
? `${content}\n\n---\n${options.metadata}`
|
|
230
|
+
: content;
|
|
231
|
+
await sendMessageChunk(client, rootMsgId, finalContent, isLast ? options?.thinking : undefined, isLast ? options?.cardTitle : undefined);
|
|
238
232
|
}
|
|
239
233
|
}
|
|
240
234
|
}
|
|
241
|
-
async function sendMessageChunk(client, rootMsgId, content) {
|
|
235
|
+
async function sendMessageChunk(client, rootMsgId, content, thinking, cardTitle) {
|
|
242
236
|
// 过滤 blob URL 和外部图片
|
|
243
237
|
const { content: sanitizedContent, warnings } = sanitizeContent(content);
|
|
244
238
|
// 追加警告消息
|
|
@@ -247,7 +241,8 @@ async function sendMessageChunk(client, rootMsgId, content) {
|
|
|
247
241
|
finalContent += formatWarnings(warnings);
|
|
248
242
|
}
|
|
249
243
|
try {
|
|
250
|
-
const
|
|
244
|
+
const optimizedContent = optimizeForCard(finalContent);
|
|
245
|
+
const card = buildMarkdownCard(optimizedContent, [], { thinking, cardTitle });
|
|
251
246
|
await client.im.message.reply({
|
|
252
247
|
path: { message_id: rootMsgId },
|
|
253
248
|
data: { content: JSON.stringify(card), msg_type: "interactive", reply_in_thread: false },
|
|
@@ -261,54 +256,61 @@ async function sendMessageChunk(client, rootMsgId, content) {
|
|
|
261
256
|
});
|
|
262
257
|
}
|
|
263
258
|
}
|
|
264
|
-
|
|
259
|
+
/**
|
|
260
|
+
* 准备溢出文档所需的上下文(标题、原始消息、元信息)
|
|
261
|
+
*/
|
|
262
|
+
export async function prepareOverflowContext(client, rootMsgId, context) {
|
|
263
|
+
// 仅当缓存 token 剩余不足 10 分钟时才刷新,避免不必要的 HTTP 调用
|
|
264
|
+
if (cachedToken && cachedToken.expiresAt - Date.now() < 600_000) {
|
|
265
|
+
cachedToken = null;
|
|
266
|
+
}
|
|
267
|
+
const token = await getTenantAccessToken(context.appId, context.appSecret);
|
|
268
|
+
const now = new Date();
|
|
269
|
+
const datetime = now.toISOString().replace("T", " ").slice(0, 19);
|
|
270
|
+
const title = context.overflow.document.title_template
|
|
271
|
+
.replace("{profile}", context.profile)
|
|
272
|
+
.replace("{cwd}", context.cwd)
|
|
273
|
+
.replace("{session_id}", context.sessionId ?? "")
|
|
274
|
+
.replace("{datetime}", datetime)
|
|
275
|
+
.replace("{date}", datetime.slice(0, 10));
|
|
276
|
+
let originalMessage = "";
|
|
265
277
|
try {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
.
|
|
273
|
-
.replace("{cwd}", context.cwd)
|
|
274
|
-
.replace("{session_id}", context.sessionId ?? "")
|
|
275
|
-
.replace("{datetime}", datetime)
|
|
276
|
-
.replace("{date}", datetime.slice(0, 10));
|
|
277
|
-
// 获取用户原始消息内容
|
|
278
|
-
let originalMessage = "";
|
|
279
|
-
try {
|
|
280
|
-
const msgRes = await client.im.message.get({
|
|
281
|
-
path: { message_id: rootMsgId },
|
|
282
|
-
});
|
|
283
|
-
const msgData = msgRes.data;
|
|
284
|
-
// 提取消息文本内容
|
|
285
|
-
if (msgData?.items?.[0]?.body?.content) {
|
|
286
|
-
const content = JSON.parse(msgData.items[0].body.content);
|
|
287
|
-
originalMessage = content.text || "";
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
catch {
|
|
291
|
-
// 获取失败时忽略
|
|
278
|
+
const msgRes = await client.im.message.get({
|
|
279
|
+
path: { message_id: rootMsgId },
|
|
280
|
+
});
|
|
281
|
+
const msgData = msgRes.data;
|
|
282
|
+
if (msgData?.items?.[0]?.body?.content) {
|
|
283
|
+
const content = JSON.parse(msgData.items[0].body.content);
|
|
284
|
+
originalMessage = content.text || "";
|
|
292
285
|
}
|
|
286
|
+
}
|
|
287
|
+
catch { /* ignore */ }
|
|
288
|
+
const meta = {
|
|
289
|
+
cwd: context.cwd,
|
|
290
|
+
profile: context.profile,
|
|
291
|
+
sessionId: context.sessionId ?? "",
|
|
292
|
+
datetime,
|
|
293
|
+
};
|
|
294
|
+
return { token, title, originalMessage, meta };
|
|
295
|
+
}
|
|
296
|
+
async function replyWithDocument(client, chatId, rootMsgId, markdown, context) {
|
|
297
|
+
try {
|
|
298
|
+
const { token, title, originalMessage, meta } = await prepareOverflowContext(client, rootMsgId, context);
|
|
293
299
|
// 清理旧文档(如果启用)
|
|
294
300
|
let cleanupResult = null;
|
|
295
301
|
const cleanupConfig = context.overflow.document.cleanup;
|
|
296
302
|
if (cleanupConfig?.enabled) {
|
|
297
303
|
cleanupResult = await cleanupOldDocuments(token, cleanupConfig.max_docs, context.profile);
|
|
298
304
|
}
|
|
299
|
-
// 构建文档元信息
|
|
300
|
-
const meta = {
|
|
301
|
-
cwd: context.cwd,
|
|
302
|
-
profile: context.profile,
|
|
303
|
-
sessionId: context.sessionId ?? "",
|
|
304
|
-
datetime: datetime,
|
|
305
|
-
};
|
|
306
305
|
// 创建文档(在应用云空间)
|
|
307
|
-
const { docUrl, docId } = await createOverflowDocument(token, title, markdown, originalMessage, meta);
|
|
306
|
+
const { docUrl, docId, warnings: docWarnings } = await createOverflowDocument(token, title, markdown, originalMessage, meta);
|
|
308
307
|
// 注册新文档到本地记录
|
|
309
308
|
registerDocument(docId, context.profile);
|
|
310
309
|
// 构建回复消息
|
|
311
310
|
let replyMsg = `📝 内容较长,已写入云文档:${docUrl}`;
|
|
311
|
+
if (docWarnings.length > 0) {
|
|
312
|
+
replyMsg += `\n⚠️ ${docWarnings.join(";")}`;
|
|
313
|
+
}
|
|
312
314
|
if (cleanupConfig?.notify && cleanupResult && (cleanupResult.deleted > 0 || cleanupResult.failed > 0)) {
|
|
313
315
|
if (cleanupResult.failed > 0) {
|
|
314
316
|
replyMsg += `\n🗑️ 已清理 ${cleanupResult.deleted} 个旧文档,${cleanupResult.failed} 个删除失败`;
|
|
@@ -331,15 +333,29 @@ async function replyWithDocument(client, chatId, rootMsgId, markdown, context) {
|
|
|
331
333
|
}
|
|
332
334
|
}
|
|
333
335
|
}
|
|
334
|
-
|
|
336
|
+
// 按工具名匹配的状态词
|
|
337
|
+
const TOOL_STATUS_WORDS = {
|
|
338
|
+
Read: ["📖 Reading...", "📖 Scanning..."],
|
|
339
|
+
Write: ["📝 Writing...", "📝 Creating..."],
|
|
340
|
+
Edit: ["✏️ Editing...", "✏️ Modifying..."],
|
|
341
|
+
Bash: ["⚡ Running...", "⚡ Executing..."],
|
|
342
|
+
Glob: ["📂 Finding files...", "📂 Scanning..."],
|
|
343
|
+
Grep: ["🔍 Searching...", "🔍 Analyzing..."],
|
|
344
|
+
LS: ["📁 Listing...", "📁 Browsing..."],
|
|
345
|
+
};
|
|
346
|
+
export async function sendToolCard(client, chatId, rootMsgId, label, detail, status = "running", toolName) {
|
|
335
347
|
const DEFAULT_STATUS = {
|
|
336
|
-
running: "⏳
|
|
348
|
+
running: "⏳ Processing...",
|
|
337
349
|
done: "✅ 完成",
|
|
338
350
|
error: "❌ 失败",
|
|
339
351
|
};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
352
|
+
let statusIcon = DEFAULT_STATUS[status];
|
|
353
|
+
if (status === "running" && toolName) {
|
|
354
|
+
const words = TOOL_STATUS_WORDS[toolName];
|
|
355
|
+
if (words?.length) {
|
|
356
|
+
statusIcon = words[Math.floor(Math.random() * words.length)];
|
|
357
|
+
}
|
|
358
|
+
}
|
|
343
359
|
const content = `${label}\n\`${detail}\`\n${statusIcon}`;
|
|
344
360
|
const card = buildMarkdownCard(content);
|
|
345
361
|
const res = await client.im.message.reply({
|
|
@@ -482,16 +498,42 @@ export async function downloadFile(client, messageId, fileKey, tempDir, filename
|
|
|
482
498
|
return null;
|
|
483
499
|
}
|
|
484
500
|
}
|
|
485
|
-
|
|
486
|
-
|
|
501
|
+
/**
|
|
502
|
+
* 构建飞书卡片 JSON
|
|
503
|
+
*
|
|
504
|
+
* 支持可选的思考过程折叠区域:
|
|
505
|
+
* - thinkingInProgress: 流式中间态,显示"💭 思考中..."提示
|
|
506
|
+
* - thinking: 完成态,显示可折叠的思考过程
|
|
507
|
+
*/
|
|
508
|
+
export function buildMarkdownCard(markdown, warnings = [], options) {
|
|
487
509
|
let content = markdown;
|
|
488
510
|
if (warnings.length > 0) {
|
|
489
511
|
content += formatWarnings(warnings);
|
|
490
512
|
}
|
|
491
|
-
|
|
513
|
+
const elements = [];
|
|
514
|
+
// 思考过程区域
|
|
515
|
+
if (options?.thinkingInProgress) {
|
|
516
|
+
elements.push({ tag: "markdown", content: "💭 思考中..." });
|
|
517
|
+
}
|
|
518
|
+
else if (options?.thinking) {
|
|
519
|
+
elements.push(...buildThinkingPanel({
|
|
520
|
+
thinking: options.thinking,
|
|
521
|
+
reasoningElapsedMs: options.reasoningElapsedMs,
|
|
522
|
+
}));
|
|
523
|
+
}
|
|
524
|
+
elements.push({ tag: "markdown", content });
|
|
525
|
+
const card = {
|
|
492
526
|
schema: "2.0",
|
|
493
|
-
|
|
527
|
+
config: { wide_screen_mode: true },
|
|
528
|
+
body: { elements },
|
|
494
529
|
};
|
|
530
|
+
if (options?.cardTitle) {
|
|
531
|
+
card.header = {
|
|
532
|
+
title: { tag: "plain_text", content: options.cardTitle },
|
|
533
|
+
template: "blue",
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
return card;
|
|
495
537
|
}
|
|
496
538
|
/**
|
|
497
539
|
* 安全解析 JSON 响应
|
|
@@ -510,10 +552,15 @@ async function safeJsonParse(res, context) {
|
|
|
510
552
|
}
|
|
511
553
|
/**
|
|
512
554
|
* 创建云文档并写入内容(在应用云空间)
|
|
555
|
+
*
|
|
556
|
+
* 写入流程(严格保序):
|
|
557
|
+
* - 简单块:分批通过 children API 写入
|
|
558
|
+
* - 表格/高亮块:通过 descendants API 写入
|
|
559
|
+
* - 保持原始文档顺序
|
|
513
560
|
*/
|
|
514
561
|
export async function createOverflowDocument(token, title, markdown, originalMessage, meta) {
|
|
515
|
-
// 1. 将 markdown
|
|
516
|
-
const {
|
|
562
|
+
// 1. 将 markdown 转换为文档块
|
|
563
|
+
const { items } = markdownToBlocks(markdown, originalMessage, meta);
|
|
517
564
|
// 2. 创建文档(不指定 folder_token,创建在应用云空间)
|
|
518
565
|
const createRes = await fetch("https://open.feishu.cn/open-apis/docx/v1/documents", {
|
|
519
566
|
method: "POST",
|
|
@@ -528,40 +575,183 @@ export async function createOverflowDocument(token, title, markdown, originalMes
|
|
|
528
575
|
if (!docId) {
|
|
529
576
|
throw new Error("Failed to create document");
|
|
530
577
|
}
|
|
531
|
-
// 3.
|
|
578
|
+
// 3. 严格保序写入(带容错)
|
|
532
579
|
const BATCH_SIZE = 50;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
580
|
+
let simpleBatch = [];
|
|
581
|
+
let isFirstBatch = true;
|
|
582
|
+
let batchIndex = 0;
|
|
583
|
+
const writeWarnings = [];
|
|
584
|
+
const flushSimpleBatch = async () => {
|
|
585
|
+
if (simpleBatch.length === 0)
|
|
586
|
+
return;
|
|
587
|
+
batchIndex++;
|
|
588
|
+
const index = isFirstBatch ? 0 : -1;
|
|
589
|
+
const batchTypes = simpleBatch.map(b => b.block_type);
|
|
590
|
+
try {
|
|
591
|
+
await batchCreateBlocks(token, docId, simpleBatch, index);
|
|
592
|
+
isFirstBatch = false;
|
|
593
|
+
}
|
|
594
|
+
catch (error) {
|
|
595
|
+
const errMsg = `Batch ${batchIndex} 写入失败(${simpleBatch.length} 个块),已跳过`;
|
|
596
|
+
console.error(`[DOC] ${errMsg}:`, error);
|
|
597
|
+
console.error(`[DOC] Block types: [${batchTypes.join(", ")}]`);
|
|
598
|
+
writeWarnings.push(errMsg);
|
|
599
|
+
// 不抛出,继续后续处理
|
|
600
|
+
}
|
|
601
|
+
finally {
|
|
602
|
+
simpleBatch = [];
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
for (let i = 0; i < items.length; i++) {
|
|
606
|
+
const item = items[i];
|
|
607
|
+
switch (item.type) {
|
|
608
|
+
case "simple":
|
|
609
|
+
simpleBatch.push(item.block);
|
|
610
|
+
if (simpleBatch.length >= BATCH_SIZE) {
|
|
611
|
+
await flushSimpleBatch();
|
|
612
|
+
}
|
|
613
|
+
break;
|
|
614
|
+
case "table":
|
|
615
|
+
await flushSimpleBatch();
|
|
616
|
+
try {
|
|
617
|
+
await createTableDescendants(token, docId, item.data);
|
|
618
|
+
}
|
|
619
|
+
catch (error) {
|
|
620
|
+
console.error(`[DOC] Table descendants failed at item ${i}:`, error);
|
|
621
|
+
// 降级为代码块:包含原始 Markdown 保留可读性
|
|
622
|
+
const tableInfo = item.data.tableBlock.table.property;
|
|
623
|
+
const rawMd = item.data.rawMarkdown ?? "";
|
|
624
|
+
writeWarnings.push(`表格渲染失败(${tableInfo.row_size}行 × ${tableInfo.column_size}列)`);
|
|
625
|
+
const fallbackContent = rawMd
|
|
626
|
+
? `⚠️ 表格渲染失败(${tableInfo.row_size}行 × ${tableInfo.column_size}列),原始内容:\n${rawMd}`
|
|
627
|
+
: `⚠️ 表格渲染失败(${tableInfo.row_size}行 × ${tableInfo.column_size}列)`;
|
|
628
|
+
simpleBatch.push({
|
|
629
|
+
block_type: BlockType.CODE,
|
|
630
|
+
code: {
|
|
631
|
+
style: { language: 1, wrap: true },
|
|
632
|
+
elements: [{
|
|
633
|
+
text_run: { content: fallbackContent },
|
|
634
|
+
}],
|
|
635
|
+
},
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
break;
|
|
639
|
+
case "callout":
|
|
640
|
+
await flushSimpleBatch();
|
|
641
|
+
try {
|
|
642
|
+
await createCalloutDescendants(token, docId, item.data);
|
|
643
|
+
}
|
|
644
|
+
catch (error) {
|
|
645
|
+
console.error(`[DOC] Callout descendants failed at item ${i}:`, error);
|
|
646
|
+
writeWarnings.push("高亮块渲染失败");
|
|
647
|
+
// 降级为普通引用块
|
|
648
|
+
const calloutTexts = item.data.contentDescendants
|
|
649
|
+
.map(d => d.text?.elements?.map(e => e.text_run?.content ?? "").join("") ?? "")
|
|
650
|
+
.filter(Boolean);
|
|
651
|
+
simpleBatch.push({
|
|
652
|
+
block_type: BlockType.QUOTE,
|
|
653
|
+
quote: { elements: [{ text_run: { content: calloutTexts.join("\n") } }] },
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
break;
|
|
551
657
|
}
|
|
552
658
|
}
|
|
659
|
+
// 写入剩余的简单块
|
|
660
|
+
await flushSimpleBatch();
|
|
553
661
|
// 返回文档链接和 ID
|
|
554
662
|
return {
|
|
555
663
|
docUrl: `https://feishu.cn/docx/${docId}`,
|
|
556
664
|
docId,
|
|
665
|
+
warnings: writeWarnings,
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* 批量创建文档块(children API)
|
|
670
|
+
*/
|
|
671
|
+
async function batchCreateBlocks(token, docId, children, index) {
|
|
672
|
+
const url = `https://open.feishu.cn/open-apis/docx/v1/documents/${docId}/blocks/${docId}/children`;
|
|
673
|
+
const res = await fetch(url, {
|
|
674
|
+
method: "POST",
|
|
675
|
+
headers: {
|
|
676
|
+
"Authorization": `Bearer ${token}`,
|
|
677
|
+
"Content-Type": "application/json",
|
|
678
|
+
},
|
|
679
|
+
body: JSON.stringify({ children, index }),
|
|
680
|
+
});
|
|
681
|
+
const data = await safeJsonParse(res, "Batch create blocks");
|
|
682
|
+
if (data.code !== 0) {
|
|
683
|
+
console.error(`[DOC] API error response:`, JSON.stringify(data, null, 2));
|
|
684
|
+
throw new Error(`Write content failed (${data.code}): ${data.msg}`);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* 通过 Descendants API 创建表格
|
|
689
|
+
* 一次性创建 table + table_cell + cell text blocks
|
|
690
|
+
*/
|
|
691
|
+
async function createTableDescendants(token, docId, table) {
|
|
692
|
+
const url = `https://open.feishu.cn/open-apis/docx/v1/documents/${docId}/blocks/${docId}/descendants`;
|
|
693
|
+
const body = {
|
|
694
|
+
children_id: [docId],
|
|
695
|
+
descendants: [
|
|
696
|
+
table.tableBlock,
|
|
697
|
+
...table.cellDescendants,
|
|
698
|
+
],
|
|
699
|
+
};
|
|
700
|
+
const res = await fetch(url, {
|
|
701
|
+
method: "POST",
|
|
702
|
+
headers: {
|
|
703
|
+
"Authorization": `Bearer ${token}`,
|
|
704
|
+
"Content-Type": "application/json",
|
|
705
|
+
},
|
|
706
|
+
body: JSON.stringify(body),
|
|
707
|
+
});
|
|
708
|
+
const data = await safeJsonParse(res, "Create table descendants");
|
|
709
|
+
if (data.code !== 0) {
|
|
710
|
+
console.error(`[DOC] Table API error response:`, JSON.stringify(data, null, 2));
|
|
711
|
+
console.error(`[DOC] Table payload (truncated):`, JSON.stringify(table.tableBlock, null, 2).slice(0, 500));
|
|
712
|
+
throw new Error(`Create table failed (${data.code}): ${data.msg}`);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* 通过 Descendants API 创建高亮块
|
|
717
|
+
* 一次性创建 callout + content text blocks
|
|
718
|
+
*/
|
|
719
|
+
async function createCalloutDescendants(token, docId, callout) {
|
|
720
|
+
const url = `https://open.feishu.cn/open-apis/docx/v1/documents/${docId}/blocks/${docId}/descendants`;
|
|
721
|
+
const body = {
|
|
722
|
+
children_id: [docId],
|
|
723
|
+
descendants: [
|
|
724
|
+
callout.calloutBlock,
|
|
725
|
+
...callout.contentDescendants,
|
|
726
|
+
],
|
|
557
727
|
};
|
|
728
|
+
const res = await fetch(url, {
|
|
729
|
+
method: "POST",
|
|
730
|
+
headers: {
|
|
731
|
+
"Authorization": `Bearer ${token}`,
|
|
732
|
+
"Content-Type": "application/json",
|
|
733
|
+
},
|
|
734
|
+
body: JSON.stringify(body),
|
|
735
|
+
});
|
|
736
|
+
const data = await safeJsonParse(res, "Create callout descendants");
|
|
737
|
+
if (data.code !== 0) {
|
|
738
|
+
console.error(`[DOC] Callout API error response:`, JSON.stringify(data, null, 2));
|
|
739
|
+
console.error(`[DOC] Callout payload:`, JSON.stringify(callout.calloutBlock, null, 2).slice(0, 500));
|
|
740
|
+
throw new Error(`Create callout failed (${data.code}): ${data.msg}`);
|
|
741
|
+
}
|
|
558
742
|
}
|
|
559
743
|
/**
|
|
560
744
|
* 获取 tenant_access_token
|
|
561
745
|
* 直接使用 appId 和 appSecret 获取
|
|
562
746
|
*/
|
|
563
747
|
let cachedToken = null;
|
|
564
|
-
|
|
748
|
+
/**
|
|
749
|
+
* 使缓存的 token 失效,下次调用 getTenantAccessToken 时强制刷新
|
|
750
|
+
*/
|
|
751
|
+
export function invalidateTokenCache() {
|
|
752
|
+
cachedToken = null;
|
|
753
|
+
}
|
|
754
|
+
export async function getTenantAccessToken(appId, appSecret) {
|
|
565
755
|
// 检查缓存
|
|
566
756
|
if (cachedToken && cachedToken.expiresAt > Date.now()) {
|
|
567
757
|
return cachedToken.token;
|