dsh-agent-toolkit 0.2.2 → 0.2.3
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/lib/client.js +100 -92
- package/lib/client.js.map +1 -1
- package/lib/index.js +92 -74
- package/lib/index.js.map +1 -1
- package/package.json +7 -1
package/lib/index.js
CHANGED
|
@@ -2266,20 +2266,23 @@ const feishuChannel = {
|
|
|
2266
2266
|
appSecret: bot.secret
|
|
2267
2267
|
}));
|
|
2268
2268
|
const dedup = new MessageDedup();
|
|
2269
|
-
const dispatcher = new lark.EventDispatcher({}).register({
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2269
|
+
const dispatcher = new lark.EventDispatcher({}).register({
|
|
2270
|
+
"im.message.message_read_v1": async () => void 0,
|
|
2271
|
+
"im.message.receive_v1": async (data) => {
|
|
2272
|
+
const parsed = parseMessageEvent(data);
|
|
2273
|
+
if (parsed === null || !dedup.check(parsed.messageId)) return;
|
|
2274
|
+
const reply = new FeishuReplyHandle(api, parsed.chatId, tunables, log);
|
|
2275
|
+
io.onMessage({
|
|
2276
|
+
botId: bot.record.id,
|
|
2277
|
+
chatId: parsed.chatId,
|
|
2278
|
+
userId: parsed.userId,
|
|
2279
|
+
messageId: parsed.messageId,
|
|
2280
|
+
text: parsed.text,
|
|
2281
|
+
reply,
|
|
2282
|
+
ackProcessing: makeAck(api, parsed.messageId, tunables.processingReactionEmoji)
|
|
2283
|
+
});
|
|
2284
|
+
}
|
|
2285
|
+
});
|
|
2283
2286
|
const ws = new lark.WSClient({
|
|
2284
2287
|
appId,
|
|
2285
2288
|
appSecret: bot.secret,
|
|
@@ -2342,66 +2345,6 @@ const projectBotDomain = defineDomain({
|
|
|
2342
2345
|
function bindingKey(botId, chatId) {
|
|
2343
2346
|
return `${botId}:${chatId}`;
|
|
2344
2347
|
}
|
|
2345
|
-
//#endregion
|
|
2346
|
-
//#region src/channels/inbound.ts
|
|
2347
|
-
/** 入站:指令分流 → 路由 → 单 in-flight 准入 → 表情回复 → followup 投递。 */
|
|
2348
|
-
var Inbound = class {
|
|
2349
|
-
deps;
|
|
2350
|
-
constructor(deps) {
|
|
2351
|
-
this.deps = deps;
|
|
2352
|
-
}
|
|
2353
|
-
onMessage(msg) {
|
|
2354
|
-
this.handle(msg).catch(async (error) => {
|
|
2355
|
-
this.deps.onError(`[project-bot] 入站处理失败:${error instanceof Error ? error.message : String(error)}`);
|
|
2356
|
-
await msg.reply.notice("处理失败,请稍后再试").catch(() => void 0);
|
|
2357
|
-
});
|
|
2358
|
-
}
|
|
2359
|
-
async handle(msg) {
|
|
2360
|
-
const bot = this.deps.bots.get(msg.botId);
|
|
2361
|
-
if (bot === void 0) return;
|
|
2362
|
-
const directive = parseDirective(msg.text);
|
|
2363
|
-
if (directive === "new") {
|
|
2364
|
-
await this.deps.router.reset(bot, msg.chatId, msg.reply);
|
|
2365
|
-
await msg.reply.notice("已开启新会话");
|
|
2366
|
-
return;
|
|
2367
|
-
}
|
|
2368
|
-
if (directive === "stop") {
|
|
2369
|
-
const rt = this.deps.router.lookup(bot.id, msg.chatId);
|
|
2370
|
-
if (rt?.inflight !== void 0) {
|
|
2371
|
-
rt.agent.cancel();
|
|
2372
|
-
await msg.reply.notice("已请求停止当前任务");
|
|
2373
|
-
} else await msg.reply.notice("当前没有进行中的任务");
|
|
2374
|
-
return;
|
|
2375
|
-
}
|
|
2376
|
-
if (directive === "status") {
|
|
2377
|
-
const rt = this.deps.router.lookup(bot.id, msg.chatId);
|
|
2378
|
-
await msg.reply.notice(rt === void 0 ? `项目:${bot.project}\n会话:未创建(发送消息即创建)` : `项目:${bot.project}\n会话:${rt.sessionId}\n状态:${rt.inflight !== void 0 ? "处理中" : "空闲"}`);
|
|
2379
|
-
return;
|
|
2380
|
-
}
|
|
2381
|
-
const rt = await this.deps.router.ensure(bot, msg.chatId, msg.reply);
|
|
2382
|
-
if (rt.inflight !== void 0) {
|
|
2383
|
-
await msg.reply.notice("上一条还在处理中,请稍候(或发送 /stop 取消)");
|
|
2384
|
-
return;
|
|
2385
|
-
}
|
|
2386
|
-
rt.inflight = { ack: void 0 };
|
|
2387
|
-
rt.inflight.ack = await msg.ackProcessing().catch(() => void 0) ?? void 0;
|
|
2388
|
-
const message = createUserMessage({
|
|
2389
|
-
content: [{
|
|
2390
|
-
type: "text",
|
|
2391
|
-
text: msg.text
|
|
2392
|
-
}],
|
|
2393
|
-
source: { kind: "user" }
|
|
2394
|
-
});
|
|
2395
|
-
try {
|
|
2396
|
-
rt.agent.followup(message);
|
|
2397
|
-
} catch (error) {
|
|
2398
|
-
const ack = rt.inflight.ack;
|
|
2399
|
-
rt.inflight = void 0;
|
|
2400
|
-
await ack?.();
|
|
2401
|
-
throw error;
|
|
2402
|
-
}
|
|
2403
|
-
}
|
|
2404
|
-
};
|
|
2405
2348
|
/** 向段序列追加内容:与尾段同类则合并,异类开新段。 */
|
|
2406
2349
|
function appendToSegments(segments, kind, text) {
|
|
2407
2350
|
const tail = segments[segments.length - 1];
|
|
@@ -2519,6 +2462,67 @@ var Outbound = class {
|
|
|
2519
2462
|
}
|
|
2520
2463
|
};
|
|
2521
2464
|
//#endregion
|
|
2465
|
+
//#region src/channels/inbound.ts
|
|
2466
|
+
/** 入站:指令分流 → 路由 → 单 in-flight 准入 → 表情回复 → followup 投递。 */
|
|
2467
|
+
var Inbound = class {
|
|
2468
|
+
deps;
|
|
2469
|
+
constructor(deps) {
|
|
2470
|
+
this.deps = deps;
|
|
2471
|
+
}
|
|
2472
|
+
onMessage(msg) {
|
|
2473
|
+
this.handle(msg).catch(async (error) => {
|
|
2474
|
+
const detail = truncateDetail(error instanceof Error ? error.message : String(error), this.deps.maxErrorDetailChars);
|
|
2475
|
+
this.deps.onError(`[project-bot] 入站处理失败:${detail}`);
|
|
2476
|
+
await msg.reply.notice(`处理失败:${detail}`).catch(() => void 0);
|
|
2477
|
+
});
|
|
2478
|
+
}
|
|
2479
|
+
async handle(msg) {
|
|
2480
|
+
const bot = this.deps.bots.get(msg.botId);
|
|
2481
|
+
if (bot === void 0) return;
|
|
2482
|
+
const directive = parseDirective(msg.text);
|
|
2483
|
+
if (directive === "new") {
|
|
2484
|
+
await this.deps.router.reset(bot, msg.chatId, msg.reply);
|
|
2485
|
+
await msg.reply.notice("已开启新会话");
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2488
|
+
if (directive === "stop") {
|
|
2489
|
+
const rt = this.deps.router.lookup(bot.id, msg.chatId);
|
|
2490
|
+
if (rt?.inflight !== void 0) {
|
|
2491
|
+
rt.agent.cancel();
|
|
2492
|
+
await msg.reply.notice("已请求停止当前任务");
|
|
2493
|
+
} else await msg.reply.notice("当前没有进行中的任务");
|
|
2494
|
+
return;
|
|
2495
|
+
}
|
|
2496
|
+
if (directive === "status") {
|
|
2497
|
+
const rt = this.deps.router.lookup(bot.id, msg.chatId);
|
|
2498
|
+
await msg.reply.notice(rt === void 0 ? `项目:${bot.project}\n会话:未创建(发送消息即创建)` : `项目:${bot.project}\n会话:${rt.sessionId}\n状态:${rt.inflight !== void 0 ? "处理中" : "空闲"}`);
|
|
2499
|
+
return;
|
|
2500
|
+
}
|
|
2501
|
+
const rt = await this.deps.router.ensure(bot, msg.chatId, msg.reply);
|
|
2502
|
+
if (rt.inflight !== void 0) {
|
|
2503
|
+
await msg.reply.notice("上一条还在处理中,请稍候(或发送 /stop 取消)");
|
|
2504
|
+
return;
|
|
2505
|
+
}
|
|
2506
|
+
rt.inflight = { ack: void 0 };
|
|
2507
|
+
rt.inflight.ack = await msg.ackProcessing().catch(() => void 0) ?? void 0;
|
|
2508
|
+
const message = createUserMessage({
|
|
2509
|
+
content: [{
|
|
2510
|
+
type: "text",
|
|
2511
|
+
text: msg.text
|
|
2512
|
+
}],
|
|
2513
|
+
source: { kind: "user" }
|
|
2514
|
+
});
|
|
2515
|
+
try {
|
|
2516
|
+
rt.agent.followup(message);
|
|
2517
|
+
} catch (error) {
|
|
2518
|
+
const ack = rt.inflight.ack;
|
|
2519
|
+
rt.inflight = void 0;
|
|
2520
|
+
await ack?.();
|
|
2521
|
+
throw error;
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
};
|
|
2525
|
+
//#endregion
|
|
2522
2526
|
//#region src/channels/ports.ts
|
|
2523
2527
|
/** 从 bot 记录提取创作期注入(主 Agent 绑定形态)。 */
|
|
2524
2528
|
function hooksOf(bot) {
|
|
@@ -2659,6 +2663,7 @@ var BotRuntime = class {
|
|
|
2659
2663
|
this.inbound = new Inbound({
|
|
2660
2664
|
router: this.router,
|
|
2661
2665
|
bots: deps.bots,
|
|
2666
|
+
maxErrorDetailChars: deps.maxErrorDetailChars,
|
|
2662
2667
|
onError: (m) => deps.log.warn(m)
|
|
2663
2668
|
});
|
|
2664
2669
|
this.outbound = new Outbound(this.sessions, (m) => deps.log.warn(m), deps.maxErrorDetailChars);
|
|
@@ -2993,6 +2998,18 @@ function createApiHandler(deps) {
|
|
|
2993
2998
|
//#endregion
|
|
2994
2999
|
//#region src/bots/register-app.ts
|
|
2995
3000
|
/** 扫码一键创建飞书应用:lark.registerApp(OAuth 2.0 Device Authorization Grant)的状态机封装。 */
|
|
3001
|
+
/** 扫码创建应用时申请的权限/事件(流式卡片 + 收发消息 + 表情 + 通讯录基础信息)。
|
|
3002
|
+
* 故意不加 as const:readonly 元组不可赋值给 SDK AppAddons 的 mutable string[],
|
|
3003
|
+
* 否则 bots/index.ts 的 lark.registerApp(options) 透传会 typecheck 失败。 */
|
|
3004
|
+
const FEISHU_REGISTER_APP_ADDONS = {
|
|
3005
|
+
scopes: { tenant: [
|
|
3006
|
+
"im:message",
|
|
3007
|
+
"im:message:send_as_bot",
|
|
3008
|
+
"cardkit:card:write",
|
|
3009
|
+
"contact:user.base:readonly"
|
|
3010
|
+
] },
|
|
3011
|
+
events: { items: { tenant: ["im.message.receive_v1"] } }
|
|
3012
|
+
};
|
|
2996
3013
|
var RegisterAppService = class {
|
|
2997
3014
|
deps;
|
|
2998
3015
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -3013,6 +3030,7 @@ var RegisterAppService = class {
|
|
|
3013
3030
|
this.sessions.set(id, entry);
|
|
3014
3031
|
this.deps.registerApp({
|
|
3015
3032
|
signal: controller.signal,
|
|
3033
|
+
addons: FEISHU_REGISTER_APP_ADDONS,
|
|
3016
3034
|
onQRCodeReady: (info) => {
|
|
3017
3035
|
entry.state = {
|
|
3018
3036
|
status: "pending",
|