Skip to content

Commit 9756b13

Browse files
committed
chore: update code
1 parent c0541a8 commit 9756b13

11 files changed

Lines changed: 372 additions & 363 deletions

File tree

src/claude.ts

Lines changed: 256 additions & 257 deletions
Large diffs are not rendered by default.

src/client/cardkit.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
import * as lark from "@larksuiteoapi/node-sdk";
2222
import { optimizeForCard, truncateSafely } from "../format/card-optimize.js";
2323
import { stripThinking } from "../format/thinking.js";
24+
import { replyMessage } from "./lark.js";
2425
import { STREAMING_TRUNCATE, FlushController } from "./flush.js";
2526
import type { FlushControllerOptions } from "./flush.js";
2627
import { buildCard, markdown, hr, buildThinkingPanel, buildToolPanels, buildHeader, buildFooterElement, buildStatsTags } from "../card/index.js";
2728
import type { ToolResultEntry } from "../card/index.js";
28-
import { replyFinalCard, prepareOverflowContext, createOverflowDocument, registerDocument, cleanupOldDocuments } from "./index.js";
29-
import type { ReplyContext, CompletionOptions } from "./index.js";
29+
import { replyFinalCard, prepareOverflowContext } from "./message.js";
30+
import type { ReplyContext, CompletionOptions } from "./message.js";
31+
import { createAndRegisterOverflowDoc, cleanupOldDocuments } from "./document.js";
3032
import { countTables } from "../format/index.js";
3133

3234
// ── 常量 ──────────────────────────────────────────────────
@@ -386,12 +388,9 @@ export class CardKitController {
386388
* 通过 IM 消息 API 发送卡片到聊天
387389
*/
388390
private async sendCardMessage(): Promise<void> {
389-
await (this.client.im.message as any).reply({
390-
path: { message_id: this.rootMsgId },
391-
data: {
392-
content: JSON.stringify({ type: "card", data: { card_id: this.cardId } }),
393-
msg_type: "interactive",
394-
},
391+
await replyMessage(this.client, this.rootMsgId, {
392+
content: JSON.stringify({ type: "card", data: { card_id: this.cardId } }),
393+
msgType: "interactive",
395394
});
396395
}
397396

@@ -458,9 +457,7 @@ export class CardKitController {
458457
this.client, this.rootMsgId, this.context,
459458
);
460459

461-
const { docUrl, docId } = await createOverflowDocument(token, title, rawContent, originalMessage, meta);
462-
463-
registerDocument(docId, this.context.profile);
460+
const { docUrl, docId } = await createAndRegisterOverflowDoc(token, title, rawContent, originalMessage, meta, this.context.profile);
464461

465462
let cardContent = `📝 内容较长,已写入云文档:[${title}](${docUrl})`;
466463

src/client/document.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ export function registerDocument(docId: string, profile: string): void {
4545
saveDocRegistry(profile, records);
4646
}
4747

48+
/** 创建 overflow 文档并注册到本地 */
49+
export async function createAndRegisterOverflowDoc(
50+
token: string,
51+
title: string,
52+
markdown: string,
53+
originalMessage: string,
54+
meta: import("../format/index.js").DocumentMeta,
55+
profile: string,
56+
) {
57+
const result = await createOverflowDocument(token, title, markdown, originalMessage, meta);
58+
registerDocument(result.docId, profile);
59+
return result;
60+
}
61+
4862
function getOldestDocuments(profile: string, keepCount: number): DocumentRecord[] {
4963
const records = loadDocRegistry(profile);
5064
const sortedDocs = [...records].sort((a, b) => a.createdAt - b.createdAt);

src/client/flush.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,7 @@ export class FlushController {
151151

152152
// ── 流式卡片接口 ──────────────────────────────────────────────
153153

154-
import type { CompletionOptions } from "./index.js";
155-
156-
/** @deprecated Import CompletionOptions from "./index.js" instead */
157-
export type CompleteOptions = CompletionOptions;
154+
import type { CompletionOptions } from "./message.js";
158155

159156
export interface IStreamingCard {
160157
append(text: string): Promise<void>;

src/client/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ export {
1515
} from "./message.js";
1616
export type { ReplyContext, ReplyFinalOptions, CompletionOptions } from "./message.js";
1717

18-
// 卡片构建(re-export from card/ directory)
19-
export { buildMarkdownCard } from "../card/index.js";
20-
export type { CardBuildOptions } from "../card/index.js";
21-
2218
// 下载
2319
export { downloadImage, downloadFile } from "./download.js";
2420
export type { DownloadedFile } from "./download.js";

src/client/lark.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,56 @@ export function checkTokenExpiry(): void {
7474
cachedToken = null;
7575
}
7676
}
77+
78+
// ── 类型安全的 SDK wrapper ─────────────────────────────────────
79+
80+
/** SDK 类型缺失 reply_in_thread,用 wrapper 补齐 */
81+
interface ReplyOptions {
82+
content: string;
83+
msgType: string;
84+
replyInThread?: boolean;
85+
}
86+
87+
export async function replyMessage(
88+
client: lark.Client,
89+
msgId: string,
90+
options: ReplyOptions,
91+
): Promise<{ messageId: string }> {
92+
const res = await (client.im.message as any).reply({
93+
path: { message_id: msgId },
94+
data: {
95+
content: options.content,
96+
msg_type: options.msgType,
97+
reply_in_thread: options.replyInThread ?? false,
98+
},
99+
});
100+
return { messageId: res?.data?.message_id ?? "" };
101+
}
102+
103+
export async function patchMessage(
104+
client: lark.Client,
105+
msgId: string,
106+
content: string,
107+
): Promise<void> {
108+
await client.im.message.patch({
109+
path: { message_id: msgId },
110+
data: { content },
111+
});
112+
}
113+
114+
export async function sendMessage(
115+
client: lark.Client,
116+
chatId: string,
117+
content: string,
118+
msgType: string,
119+
): Promise<{ messageId: string }> {
120+
const res = await client.im.message.create({
121+
params: { receive_id_type: "chat_id" },
122+
data: {
123+
receive_id: chatId,
124+
msg_type: msgType,
125+
content,
126+
},
127+
});
128+
return { messageId: (res.data as any)?.message_id ?? "" };
129+
}

src/client/message.ts

Lines changed: 25 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import * as lark from "@larksuiteoapi/node-sdk";
22
import { OverflowConfig, CardTableConfig } from "../config.js";
33
import { sanitizeContent, formatWarnings, countTables, optimizeForCard } from "../format/index.js";
4-
import { buildCard, buildSimpleCard, buildMarkdownCard, buildThinkingPanel, collapsiblePanel, markdown, hr, buildHeader, buildFooterElement, buildStatsTags } from "../card/index.js";
4+
import { buildCard, buildMarkdownCard, buildThinkingPanel, collapsiblePanel, markdown, hr, buildHeader, buildFooterElement, buildStatsTags } from "../card/index.js";
55
import type { CardBuildOptions } from "../card/index.js";
6-
import { getTenantAccessToken, checkTokenExpiry } from "./lark.js";
7-
import { createOverflowDocument, registerDocument, cleanupOldDocuments } from "./document.js";
6+
import { getTenantAccessToken, checkTokenExpiry, replyMessage, patchMessage, sendMessage } from "./lark.js";
7+
import { createAndRegisterOverflowDoc, cleanupOldDocuments } from "./document.js";
88
import type { DocumentMeta } from "../format/index.js";
99

1010
// ── 共享类型 ──────────────────────────────────────────────────
@@ -67,11 +67,11 @@ export async function replyText(
6767
text: string
6868
): Promise<string> {
6969
const card = buildMarkdownCard(text);
70-
const res = await (client.im.message as any).reply({
71-
path: { message_id: rootMsgId },
72-
data: { content: JSON.stringify(card), msg_type: "interactive", reply_in_thread: false },
70+
const { messageId } = await replyMessage(client, rootMsgId, {
71+
content: JSON.stringify(card),
72+
msgType: "interactive",
7373
});
74-
return res.data?.message_id ?? "";
74+
return messageId;
7575
}
7676

7777
export async function updateText(
@@ -250,14 +250,14 @@ async function sendMessageChunk(
250250
try {
251251
const optimizedContent = optimizeForCard(finalContent);
252252
const card = buildMarkdownCard(optimizedContent, [], { thinking, cardTitle });
253-
await (client.im.message as any).reply({
254-
path: { message_id: rootMsgId },
255-
data: { content: JSON.stringify(card), msg_type: "interactive", reply_in_thread: false },
253+
await replyMessage(client, rootMsgId, {
254+
content: JSON.stringify(card),
255+
msgType: "interactive",
256256
});
257257
} catch {
258-
await (client.im.message as any).reply({
259-
path: { message_id: rootMsgId },
260-
data: { content: JSON.stringify({ text: finalContent }), msg_type: "text", reply_in_thread: false },
258+
await replyMessage(client, rootMsgId, {
259+
content: JSON.stringify({ text: finalContent }),
260+
msgType: "text",
261261
});
262262
}
263263
}
@@ -314,10 +314,7 @@ async function patchOrCreateCard(
314314
if (waitingMsgId) {
315315
try {
316316
const card = buildMarkdownCard(content);
317-
await (client.im.message as any).patch({
318-
path: { message_id: waitingMsgId },
319-
data: { content: JSON.stringify(card) },
320-
});
317+
await patchMessage(client, waitingMsgId, JSON.stringify(card));
321318
return true;
322319
} catch {}
323320
}
@@ -339,11 +336,11 @@ async function replyWithDocument(
339336
let waitingMsgId: string | undefined;
340337
try {
341338
const waitingCard = buildMarkdownCard("📝 内容较长,正在写入云文档...");
342-
const waitRes = await (client.im.message as any).reply({
343-
path: { message_id: rootMsgId },
344-
data: { content: JSON.stringify(waitingCard), msg_type: "interactive", reply_in_thread: false },
339+
const { messageId: waitId } = await replyMessage(client, rootMsgId, {
340+
content: JSON.stringify(waitingCard),
341+
msgType: "interactive",
345342
});
346-
waitingMsgId = waitRes?.data?.message_id;
343+
waitingMsgId = waitId || undefined;
347344
} catch {}
348345

349346
try {
@@ -352,9 +349,7 @@ async function replyWithDocument(
352349
const cleanupConfig = context.overflow.document.cleanup;
353350
await cleanupOldDocuments(token, cleanupConfig.max_docs, context.profile);
354351

355-
const { docUrl, docId, warnings: docWarnings } = await createOverflowDocument(token, title, markdown, originalMessage, meta);
356-
357-
registerDocument(docId, context.profile);
352+
const { docUrl, docId, warnings: docWarnings } = await createAndRegisterOverflowDoc(token, title, markdown, originalMessage, meta, context.profile);
358353

359354
let replyMsg = `📝 内容较长,已写入云文档:${docUrl}`;
360355
if (docWarnings.length > 0) {
@@ -386,10 +381,7 @@ async function replyWithDocument(
386381

387382
if (waitingMsgId) {
388383
try {
389-
await (client.im.message as any).patch({
390-
path: { message_id: waitingMsgId },
391-
data: { content: JSON.stringify(docCard) },
392-
});
384+
await patchMessage(client, waitingMsgId, JSON.stringify(docCard));
393385
return;
394386
} catch {}
395387
}
@@ -444,11 +436,11 @@ export async function sendToolCard(
444436

445437
const content = `${label}\n\`${detail}\`\n${statusIcon}`;
446438
const card = buildMarkdownCard(content);
447-
const res = await (client.im.message as any).reply({
448-
path: { message_id: rootMsgId },
449-
data: { content: JSON.stringify(card), msg_type: "interactive", reply_in_thread: false },
439+
const { messageId } = await replyMessage(client, rootMsgId, {
440+
content: JSON.stringify(card),
441+
msgType: "interactive",
450442
});
451-
return res.data?.message_id ?? "";
443+
return messageId;
452444
}
453445

454446
export async function updateToolCard(
@@ -483,38 +475,4 @@ export async function updateToolCard(
483475
}
484476

485477
// ── 卡片构建 ─────────────────────────────────────────────────
486-
// buildMarkdownCard 已迁移至 ../card/card.ts,通过 barrel re-export 使用
487-
488-
// ── 发送辅助 ─────────────────────────────────────────────────
489-
490-
export async function sendMarkdownCardMessage(
491-
client: lark.Client,
492-
chatId: string,
493-
content: string,
494-
options?: {
495-
rootMsgId?: string;
496-
reply?: boolean;
497-
},
498-
): Promise<void> {
499-
const { content: sanitizedContent, warnings } = sanitizeContent(content);
500-
const card = buildSimpleCard(sanitizedContent, warnings);
501-
502-
if (options?.reply && options.rootMsgId) {
503-
await client.im.message.reply({
504-
path: { message_id: options.rootMsgId },
505-
data: {
506-
msg_type: "interactive",
507-
content: JSON.stringify(card),
508-
},
509-
});
510-
} else {
511-
await client.im.message.create({
512-
params: { receive_id_type: "chat_id" },
513-
data: {
514-
receive_id: chatId,
515-
msg_type: "interactive",
516-
content: JSON.stringify(card),
517-
},
518-
});
519-
}
520-
}
478+
// buildMarkdownCard 已迁移至 ../card/compose.ts,通过 barrel re-export 使用

src/client/task-panel-ctrl.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import * as lark from "@larksuiteoapi/node-sdk";
99
import { buildTaskPanelCard } from "../card/index.js";
1010
import type { TaskPanelStatus, TaskPanelCardOptions } from "../card/index.js";
11+
import { replyMessage, patchMessage } from "./lark.js";
1112
import { logger } from "../logger.js";
1213

1314
// Re-export types for consumers
@@ -23,11 +24,11 @@ export async function sendTaskCard(
2324
headerIconImgKey?: string,
2425
): Promise<string> {
2526
const card = buildTaskPanelCard({ description, status: "running", headerIconImgKey });
26-
const res = await (client.im.message as any).reply({
27-
path: { message_id: rootMsgId },
28-
data: { content: JSON.stringify(card), msg_type: "interactive", reply_in_thread: false },
27+
const { messageId } = await replyMessage(client, rootMsgId, {
28+
content: JSON.stringify(card),
29+
msgType: "interactive",
2930
});
30-
return res.data?.message_id ?? "";
31+
return messageId;
3132
}
3233

3334
export async function updateTaskCard(

src/client/update.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import { optimizeForCard, truncateSafely } from "../format/card-optimize.js";
1212
import { parseThinking, stripThinking } from "../format/thinking.js";
1313
import { STREAMING_TRUNCATE, FlushController } from "./flush.js";
1414
import type { IStreamingCard } from "./flush.js";
15+
import { replyMessage } from "./lark.js";
1516
import type { StreamingConfig } from "../config.js";
16-
import type { ReplyContext, CompletionOptions, CardBuildOptions } from "./index.js";
17-
import { replyFinalCard, buildMarkdownCard } from "./index.js";
18-
import { buildCard, markdown } from "../card/index.js";
17+
import type { ReplyContext, CompletionOptions } from "./message.js";
18+
import { replyFinalCard } from "./message.js";
19+
import { buildCard, markdown, buildMarkdownCard } from "../card/index.js";
20+
import type { CardBuildOptions } from "../card/index.js";
1921

2022
const TRUNCATE_LIMIT = STREAMING_TRUNCATE;
2123

@@ -78,15 +80,11 @@ class UpdateStreamingCard implements IStreamingCard {
7880
template: "blue",
7981
};
8082
}
81-
const res = await (this.client.im.message as any).reply({
82-
path: { message_id: this.rootMsgId },
83-
data: {
84-
content: JSON.stringify(card),
85-
msg_type: "interactive",
86-
reply_in_thread: false,
87-
},
83+
const res = await replyMessage(this.client, this.rootMsgId, {
84+
content: JSON.stringify(card),
85+
msgType: "interactive",
8886
});
89-
this.msgId = res.data?.message_id ?? null;
87+
this.msgId = res.messageId || null;
9088

9189
if (this.msgId) {
9290
this.flushCtrl.start();

src/format/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,3 @@ export { optimizeForCard, truncateSafely } from "./card-optimize.js";
5858
// Thinking 解析
5959
export { parseThinking, stripThinking } from "./thinking.js";
6060
export type { ThinkingResult } from "./thinking.js";
61-
62-
// 图片解析(已迁移至 ../feishu/image-resolver.ts)
63-
export { resolveImages } from "../client/image-resolver.js";
64-
export type { ImageResolveResult } from "../client/image-resolver.js";

0 commit comments

Comments
 (0)