@wu529778790/open-im 1.4.2-beta.2 → 1.5.1-beta.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/dist/dingtalk/message-sender.js +37 -18
- package/package.json +1 -1
|
@@ -12,7 +12,6 @@ const STATUS_ICONS = {
|
|
|
12
12
|
done: '✅',
|
|
13
13
|
error: '❌',
|
|
14
14
|
};
|
|
15
|
-
const streamingMessages = new Set();
|
|
16
15
|
function generateMessageId() {
|
|
17
16
|
return `${Date.now()}-${randomBytes(6).toString('hex')}`;
|
|
18
17
|
}
|
|
@@ -31,32 +30,52 @@ function formatMessage(content, status, note, toolId = 'claude') {
|
|
|
31
30
|
text += `\n\n─────────\n${note}`;
|
|
32
31
|
return text;
|
|
33
32
|
}
|
|
33
|
+
async function sendTextWithRetry(chatId, text, retries = 1) {
|
|
34
|
+
let lastError;
|
|
35
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
36
|
+
try {
|
|
37
|
+
await sendText(chatId, text);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
lastError = err;
|
|
42
|
+
if (attempt < retries) {
|
|
43
|
+
log.warn(`DingTalk send failed, retrying (${attempt + 1}/${retries}):`, err);
|
|
44
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
throw lastError;
|
|
49
|
+
}
|
|
34
50
|
export async function sendThinkingMessage(chatId, _replyToMessageId, toolId = 'claude') {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
// 钉钉 sessionWebhook 回复不支持像 Telegram/飞书那样稳定编辑原消息。
|
|
52
|
+
// 为避免 “thinking -> streaming -> final” 连发多条,这里只生成一个本地 messageId,
|
|
53
|
+
// 实际消息延迟到 sendFinalMessages/sendTextReply 阶段再发送。
|
|
54
|
+
void chatId;
|
|
55
|
+
void toolId;
|
|
56
|
+
return generateMessageId();
|
|
39
57
|
}
|
|
40
58
|
export async function updateMessage(chatId, messageId, content, status, note, toolId = 'claude') {
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
// 钉钉第一版不发送中间更新,避免用户看到多条状态消息。
|
|
60
|
+
void chatId;
|
|
61
|
+
void messageId;
|
|
62
|
+
void content;
|
|
63
|
+
void status;
|
|
64
|
+
void note;
|
|
65
|
+
void toolId;
|
|
47
66
|
}
|
|
48
67
|
export async function sendFinalMessages(chatId, messageId, fullContent, note, toolId = 'claude') {
|
|
49
|
-
|
|
68
|
+
void messageId;
|
|
50
69
|
const parts = splitLongContent(fullContent, MAX_WEWORK_MESSAGE_LENGTH);
|
|
51
70
|
for (let i = 0; i < parts.length; i++) {
|
|
52
71
|
const partNote = parts.length > 1
|
|
53
72
|
? `${i === parts.length - 1 ? note + '\n' : ''}(续 ${i + 1}/${parts.length})`.trim()
|
|
54
73
|
: note;
|
|
55
|
-
await
|
|
74
|
+
await sendTextWithRetry(chatId, formatMessage(parts[i], 'done', partNote, toolId));
|
|
56
75
|
}
|
|
57
76
|
}
|
|
58
77
|
export async function sendTextReply(chatId, text, _threadCtx) {
|
|
59
|
-
await
|
|
78
|
+
await sendTextWithRetry(chatId, text);
|
|
60
79
|
log.info(`Text reply sent to DingTalk chat ${chatId}`);
|
|
61
80
|
}
|
|
62
81
|
export async function sendProactiveTextReply(chatId, text) {
|
|
@@ -76,7 +95,7 @@ ${toolInput.length > 300 ? toolInput.slice(0, 300) + '...' : toolInput}
|
|
|
76
95
|
/deny - 拒绝
|
|
77
96
|
|
|
78
97
|
请求 ID: ${requestId.slice(-8)}`;
|
|
79
|
-
await
|
|
98
|
+
await sendTextWithRetry(chatId, message);
|
|
80
99
|
}
|
|
81
100
|
export async function sendModeCard(chatId, _userId, currentMode) {
|
|
82
101
|
const { MODE_LABELS } = await import('../permission-mode/types.js');
|
|
@@ -89,13 +108,13 @@ export async function sendModeCard(chatId, _userId, currentMode) {
|
|
|
89
108
|
/mode accept-edits - 自动批准编辑
|
|
90
109
|
/mode plan - 仅分析
|
|
91
110
|
/mode yolo - 跳过所有权限`;
|
|
92
|
-
await
|
|
111
|
+
await sendTextWithRetry(chatId, message);
|
|
93
112
|
}
|
|
94
113
|
export async function sendDirectorySelection(chatId, currentDir, userId) {
|
|
95
114
|
const directories = listDirectories(currentDir);
|
|
96
115
|
const dirName = basename(currentDir) || currentDir;
|
|
97
116
|
if (directories.length === 0) {
|
|
98
|
-
await
|
|
117
|
+
await sendTextWithRetry(chatId, `📁 当前目录: ${dirName}\n\n没有可访问的子目录`);
|
|
99
118
|
return;
|
|
100
119
|
}
|
|
101
120
|
const keyboard = buildDirectoryKeyboard(directories, userId);
|
|
@@ -103,7 +122,7 @@ export async function sendDirectorySelection(chatId, currentDir, userId) {
|
|
|
103
122
|
.flat()
|
|
104
123
|
.map((item) => item.text)
|
|
105
124
|
.join('\n');
|
|
106
|
-
await
|
|
125
|
+
await sendTextWithRetry(chatId, `📁 当前目录: ${dirName}\n\n可用目录:\n${entries}\n\n请使用 /cd <路径> 切换目录`);
|
|
107
126
|
}
|
|
108
127
|
export function startTypingLoop(_chatId) {
|
|
109
128
|
return () => { };
|