@ian2018cs/agenthub 0.1.82 → 0.1.83
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/assets/index-B8xBmKbu.css +32 -0
- package/dist/assets/index-BFd2fqw2.js +199 -0
- package/dist/assets/{vendor-icons-DUmFlkZ8.js → vendor-icons-CTLfTCYl.js} +88 -73
- package/dist/index.html +3 -3
- package/package.json +3 -1
- package/server/claude-sdk.js +1 -0
- package/server/database/db.js +98 -1
- package/server/index.js +108 -2
- package/server/routes/cron.js +132 -0
- package/server/services/builtin-tools/FeishuWriter.js +61 -0
- package/server/services/builtin-tools/SessionWriter.js +29 -0
- package/server/services/builtin-tools/WebhookWriter.js +70 -0
- package/server/services/builtin-tools/background-task.js +1 -5
- package/server/services/builtin-tools/cron-scheduler.js +160 -0
- package/server/services/builtin-tools/cron-tool.js +296 -0
- package/server/services/builtin-tools/index.js +30 -1
- package/server/services/feishu/index.js +2 -11
- package/server/services/feishu/lark-client.js +31 -8
- package/server/services/feishu/sdk-bridge.js +20 -16
- package/dist/assets/index-ByqBXYb8.js +0 -197
- package/dist/assets/index-DkNpDSsg.css +0 -32
|
@@ -85,6 +85,11 @@ class FakeSendWriter {
|
|
|
85
85
|
return this.sessionId;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
/** 优先用 chat_id,回退到 feishuOpenId(open_id),LarkClient 会自动识别类型 */
|
|
89
|
+
get _target() {
|
|
90
|
+
return this.chatId || this.feishuOpenId;
|
|
91
|
+
}
|
|
92
|
+
|
|
88
93
|
// ─── 消息路由 ──────────────────────────────────────────────────────────────
|
|
89
94
|
|
|
90
95
|
_handle(data) {
|
|
@@ -146,7 +151,7 @@ class FakeSendWriter {
|
|
|
146
151
|
this.textBuffer.push(block.text);
|
|
147
152
|
} else if (block.type === 'tool_use' && block.name) {
|
|
148
153
|
this.toolNotices.push(`🔧 调用 \`${block.name}\``);
|
|
149
|
-
this.larkClient.
|
|
154
|
+
this.larkClient.sendTextToTarget(this._target, `🔧 正在调用 \`${block.name}\`…`).catch(() => {});
|
|
150
155
|
// 追踪 Write 工具写入的文件路径,完成后按类型发送给用户
|
|
151
156
|
if (block.name === 'Write' && block.input?.file_path) {
|
|
152
157
|
this.writtenFiles.push(block.input.file_path);
|
|
@@ -166,7 +171,7 @@ class FakeSendWriter {
|
|
|
166
171
|
const block = msg.content_block;
|
|
167
172
|
if (block?.type === 'tool_use' && block.name) {
|
|
168
173
|
this.toolNotices.push(`🔧 调用 \`${block.name}\``);
|
|
169
|
-
this.larkClient.
|
|
174
|
+
this.larkClient.sendTextToTarget(this._target, `🔧 正在调用 \`${block.name}\`…`).catch(() => {});
|
|
170
175
|
}
|
|
171
176
|
break;
|
|
172
177
|
}
|
|
@@ -180,7 +185,7 @@ class FakeSendWriter {
|
|
|
180
185
|
case 'tool_use':
|
|
181
186
|
if (msg.name) {
|
|
182
187
|
this.toolNotices.push(`🔧 调用 \`${msg.name}\``);
|
|
183
|
-
this.larkClient.
|
|
188
|
+
this.larkClient.sendTextToTarget(this._target, `🔧 正在调用 \`${msg.name}\`…`).catch(() => {});
|
|
184
189
|
}
|
|
185
190
|
break;
|
|
186
191
|
|
|
@@ -219,14 +224,13 @@ class FakeSendWriter {
|
|
|
219
224
|
|
|
220
225
|
// 直接发送交互卡片(JSON 构建,无需模板 ID)
|
|
221
226
|
const cardContent = buildToolApprovalCardDirect(toolName, input, requestId);
|
|
222
|
-
const cardMsgId = await this.larkClient.sendInteractiveAndGetMsgId(this.
|
|
223
|
-
// 兜底:降级为文本消息
|
|
227
|
+
const cardMsgId = await this.larkClient.sendInteractiveAndGetMsgId(this._target, cardContent).catch(async () => {
|
|
224
228
|
const inputSummary = truncate(
|
|
225
229
|
typeof input === 'object' ? JSON.stringify(input, null, 2) : String(input || ''),
|
|
226
230
|
300
|
|
227
231
|
);
|
|
228
232
|
const text = `🔔 **工具审批请求**\n工具: \`${toolName}\`\n参数:\n\`\`\`\n${inputSummary}\n\`\`\`\n\n回复 **允许** 或 **拒绝**(或 **允许所有** 跳过同类工具询问)`;
|
|
229
|
-
await this.larkClient.
|
|
233
|
+
await this.larkClient.sendTextToTarget(this._target, text).catch(() => {});
|
|
230
234
|
return null;
|
|
231
235
|
});
|
|
232
236
|
this.pendingApprovals.set(this.feishuOpenId, { requestId, cardMessageId: cardMsgId, toolName });
|
|
@@ -237,7 +241,7 @@ class FakeSendWriter {
|
|
|
237
241
|
|
|
238
242
|
// 发送交互卡片(动态 JSON,无需模板 ID)
|
|
239
243
|
const cardContent = buildAskUserQuestionCard(questions, requestId);
|
|
240
|
-
const cardMsgId = await this.larkClient.sendInteractiveAndGetMsgId(this.
|
|
244
|
+
const cardMsgId = await this.larkClient.sendInteractiveAndGetMsgId(this._target, cardContent)
|
|
241
245
|
.catch(async (err) => {
|
|
242
246
|
console.error('[Feishu:sdk-bridge] AskUserQuestion card send error:', err.message);
|
|
243
247
|
// 降级:发送文字说明,用户通过文字回复选项字母
|
|
@@ -257,7 +261,7 @@ class FakeSendWriter {
|
|
|
257
261
|
: '回复选项字母(多选用 + 连接,如 A+B)'
|
|
258
262
|
);
|
|
259
263
|
lines.push('回复"跳过"可跳过此问卷。');
|
|
260
|
-
await this.larkClient.
|
|
264
|
+
await this.larkClient.sendTextToTarget(this._target, lines.join('\n')).catch(() => {});
|
|
261
265
|
return null;
|
|
262
266
|
});
|
|
263
267
|
|
|
@@ -303,7 +307,7 @@ class FakeSendWriter {
|
|
|
303
307
|
const chunks = splitMessage(cleanedText, 4000);
|
|
304
308
|
for (const chunk of chunks) {
|
|
305
309
|
try {
|
|
306
|
-
await this.larkClient.
|
|
310
|
+
await this.larkClient.sendTextToTarget(this._target, chunk);
|
|
307
311
|
console.log('[Feishu:sdk-bridge] sendText OK, chunk.length=', chunk.length);
|
|
308
312
|
} catch (err) {
|
|
309
313
|
console.error('[Feishu:sdk-bridge] sendText FAILED:', err.message, err.stack);
|
|
@@ -343,10 +347,10 @@ class FakeSendWriter {
|
|
|
343
347
|
try {
|
|
344
348
|
const buf = await fs.readFile(resolved);
|
|
345
349
|
if (FakeSendWriter.IMAGE_EXTS.has(ext)) {
|
|
346
|
-
await this.larkClient.sendImageBuffer(this.
|
|
350
|
+
await this.larkClient.sendImageBuffer(this._target, buf);
|
|
347
351
|
console.log(`[Feishu:sdk-bridge] Sent image: ${filename}`);
|
|
348
352
|
} else {
|
|
349
|
-
await this.larkClient.sendFileBuffer(this.
|
|
353
|
+
await this.larkClient.sendFileBuffer(this._target, buf, filename);
|
|
350
354
|
console.log(`[Feishu:sdk-bridge] Sent file: ${filename}`);
|
|
351
355
|
}
|
|
352
356
|
} catch (err) {
|
|
@@ -363,10 +367,10 @@ class FakeSendWriter {
|
|
|
363
367
|
try {
|
|
364
368
|
const buf = await fs.readFile(filePath);
|
|
365
369
|
if (FakeSendWriter.IMAGE_EXTS.has(ext)) {
|
|
366
|
-
await this.larkClient.sendImageBuffer(this.
|
|
370
|
+
await this.larkClient.sendImageBuffer(this._target, buf);
|
|
367
371
|
console.log(`[Feishu:sdk-bridge] Sent tagged image: ${filename}`);
|
|
368
372
|
} else {
|
|
369
|
-
await this.larkClient.sendFileBuffer(this.
|
|
373
|
+
await this.larkClient.sendFileBuffer(this._target, buf, filename);
|
|
370
374
|
console.log(`[Feishu:sdk-bridge] Sent tagged file: ${filename}`);
|
|
371
375
|
}
|
|
372
376
|
} catch (err) {
|
|
@@ -382,7 +386,7 @@ class FakeSendWriter {
|
|
|
382
386
|
async _handleError(errorMsg) {
|
|
383
387
|
// 会话损坏时不发通用错误(由 runQuery 统一处理并重置会话)
|
|
384
388
|
if (this.sessionCorrupted) return;
|
|
385
|
-
await this.larkClient.
|
|
389
|
+
await this.larkClient.sendTextToTarget(this._target, `❌ 出错了:${errorMsg || '未知错误'}`).catch(() => {});
|
|
386
390
|
}
|
|
387
391
|
}
|
|
388
392
|
|
|
@@ -421,7 +425,7 @@ async function runQuery({
|
|
|
421
425
|
const reason = limitStatus.reason === 'daily_limit_exceeded'
|
|
422
426
|
? `每日用量已达上限 ($${limitStatus.limit.toFixed(2)})`
|
|
423
427
|
: `总用量已达上限 ($${limitStatus.limit.toFixed(2)})`;
|
|
424
|
-
await larkClient.
|
|
428
|
+
await larkClient.sendTextToTarget(chatId || feishuOpenId, `⚠️ ${reason},请联系管理员。`);
|
|
425
429
|
return;
|
|
426
430
|
}
|
|
427
431
|
}
|
|
@@ -462,7 +466,7 @@ async function runQuery({
|
|
|
462
466
|
// 会话历史损坏(空 text block):自动清除坏会话,提示用户重发
|
|
463
467
|
if (writer.sessionCorrupted) {
|
|
464
468
|
feishuDb.updateSessionState(feishuOpenId, { claude_session_id: null });
|
|
465
|
-
await larkClient.
|
|
469
|
+
await larkClient.sendTextToTarget(chatId || feishuOpenId,
|
|
466
470
|
'⚠️ 检测到历史会话数据异常,已自动重置会话。请重新发送消息,将以新会话继续。'
|
|
467
471
|
).catch(() => {});
|
|
468
472
|
}
|