dsh-agent-toolkit 0.2.6 → 0.2.8
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 +264 -176
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +108 -46
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -45,6 +45,8 @@ interface BotsModuleConfig {
|
|
|
45
45
|
processingReactionEmoji: string;
|
|
46
46
|
/** 回传飞书的错误摘要最大字符数。 */
|
|
47
47
|
errorDetailMaxChars: number;
|
|
48
|
+
/** 会话创建/恢复时注入「渠道 + 发起人 open_id」提示段(dsh-agent-toolkit:channel:sender)。 */
|
|
49
|
+
injectSender: boolean;
|
|
48
50
|
}
|
|
49
51
|
//#endregion
|
|
50
52
|
//#region src/agents/team-preset.d.ts
|
package/lib/index.js
CHANGED
|
@@ -1835,6 +1835,15 @@ function createFeishuApi(client) {
|
|
|
1835
1835
|
data,
|
|
1836
1836
|
mediaType
|
|
1837
1837
|
};
|
|
1838
|
+
},
|
|
1839
|
+
async getBotOpenId() {
|
|
1840
|
+
const res = await client.request({
|
|
1841
|
+
method: "GET",
|
|
1842
|
+
url: "https://open.feishu.cn/open-apis/bot/v3/info"
|
|
1843
|
+
});
|
|
1844
|
+
const openId = res.bot?.open_id;
|
|
1845
|
+
if (typeof openId !== "string" || openId.length === 0) throw new Error(`获取机器人信息失败:code=${res.code} msg=${res.msg}`);
|
|
1846
|
+
return openId;
|
|
1838
1847
|
}
|
|
1839
1848
|
};
|
|
1840
1849
|
}
|
|
@@ -1888,8 +1897,10 @@ function parsePostContent(content) {
|
|
|
1888
1897
|
* SDK handler 收到的 data 即事件体(README 示例 `data.message` 直接解构);
|
|
1889
1898
|
* 兼容包一层 { event } 的形态。过滤:机器人消息、非 text/post/image 类型、
|
|
1890
1899
|
* 群内未 @机器人、无文本且无图片。
|
|
1900
|
+
* 群消息 @ 校验身份:mention 的 open_id 必须等于本机器人(应用若持全部群消息权限,
|
|
1901
|
+
* 会收到 @ 其他机器人的消息,不能误触发)。
|
|
1891
1902
|
*/
|
|
1892
|
-
function parseMessageEvent(data) {
|
|
1903
|
+
function parseMessageEvent(data, botOpenId) {
|
|
1893
1904
|
const wrapped = data;
|
|
1894
1905
|
const event = wrapped.event ?? wrapped;
|
|
1895
1906
|
if (event.sender?.sender_type !== "user") return null;
|
|
@@ -1900,7 +1911,7 @@ function parseMessageEvent(data) {
|
|
|
1900
1911
|
if (typeof msg.content !== "string") return null;
|
|
1901
1912
|
if (typeof msg.message_id !== "string" || typeof msg.chat_id !== "string") return null;
|
|
1902
1913
|
if (msg.chat_type !== "p2p" && msg.chat_type !== "group") return null;
|
|
1903
|
-
if (msg.chat_type === "group" && !(msg.mentions ?? []).some((m) => m.mentioned_type === "bot")) return null;
|
|
1914
|
+
if (msg.chat_type === "group" && !(msg.mentions ?? []).some((m) => m.mentioned_type === "bot" && m.id?.open_id === botOpenId)) return null;
|
|
1904
1915
|
let text = "";
|
|
1905
1916
|
let imageKeys = [];
|
|
1906
1917
|
if (msg.message_type === "text") try {
|
|
@@ -2353,11 +2364,12 @@ const feishuChannel = {
|
|
|
2353
2364
|
appId,
|
|
2354
2365
|
appSecret: bot.secret
|
|
2355
2366
|
}));
|
|
2367
|
+
const botOpenId = await api.getBotOpenId();
|
|
2356
2368
|
const dedup = new MessageDedup();
|
|
2357
2369
|
const dispatcher = new lark.EventDispatcher({}).register({
|
|
2358
2370
|
"im.message.message_read_v1": async () => void 0,
|
|
2359
2371
|
"im.message.receive_v1": async (data) => {
|
|
2360
|
-
const parsed = parseMessageEvent(data);
|
|
2372
|
+
const parsed = parseMessageEvent(data, botOpenId);
|
|
2361
2373
|
if (parsed === null || !dedup.check(parsed.messageId)) return;
|
|
2362
2374
|
const reply = new FeishuReplyHandle(api, parsed.chatId, tunables, log);
|
|
2363
2375
|
const loadImages = parsed.imageKeys.length > 0 ? async () => Promise.all(parsed.imageKeys.map(async (key) => api.downloadImage(parsed.messageId, key))) : void 0;
|
|
@@ -2404,8 +2416,9 @@ const FeishuConfigSchema = z$1.object({
|
|
|
2404
2416
|
const BotRecordSchema = z$1.object({
|
|
2405
2417
|
id: z$1.string().regex(BOT_ID_RE),
|
|
2406
2418
|
name: z$1.string().min(1).max(64),
|
|
2407
|
-
|
|
2408
|
-
|
|
2419
|
+
/** 渠道类型;与 feishu 同有或同无(未绑定为双双缺省)。 */
|
|
2420
|
+
channel: z$1.literal("feishu").optional(),
|
|
2421
|
+
feishu: FeishuConfigSchema.optional(),
|
|
2409
2422
|
/** 绑定项目(agent 的 cwd,绝对路径)。一 bot 一项目。 */
|
|
2410
2423
|
project: z$1.string().min(1),
|
|
2411
2424
|
/** 透传到 agent 创作期的 persona 提示段。 */
|
|
@@ -2420,7 +2433,7 @@ const BotRecordSchema = z$1.object({
|
|
|
2420
2433
|
}).optional(),
|
|
2421
2434
|
createdAt: z$1.number().int().nonnegative(),
|
|
2422
2435
|
updatedAt: z$1.number().int().nonnegative()
|
|
2423
|
-
});
|
|
2436
|
+
}).refine((r) => r.channel === void 0 === (r.feishu === void 0), { message: "channel 与 feishu 必须同有或同无" });
|
|
2424
2437
|
const BindingSchema = z$1.object({ sessionId: z$1.string().min(1) });
|
|
2425
2438
|
/** domain 名受 UNIT_NAME_RE 约束(^[a-z][a-z0-9_]*$),不允许连字符。 */
|
|
2426
2439
|
const projectBotDomain = defineDomain({
|
|
@@ -2571,7 +2584,7 @@ var Inbound = class {
|
|
|
2571
2584
|
if (bot === void 0) return;
|
|
2572
2585
|
const directive = parseDirective(msg.text);
|
|
2573
2586
|
if (directive === "new") {
|
|
2574
|
-
await this.deps.router.reset(bot, msg.chatId, msg.reply);
|
|
2587
|
+
await this.deps.router.reset(bot, msg.chatId, msg.reply, msg.userId);
|
|
2575
2588
|
await msg.reply.notice("已开启新会话");
|
|
2576
2589
|
return;
|
|
2577
2590
|
}
|
|
@@ -2588,7 +2601,7 @@ var Inbound = class {
|
|
|
2588
2601
|
await msg.reply.notice(rt === void 0 ? `项目:${bot.project}\n会话:未创建(发送消息即创建)` : `项目:${bot.project}\n会话:${rt.sessionId}\n状态:${rt.inflight !== void 0 ? "处理中" : "空闲"}`);
|
|
2589
2602
|
return;
|
|
2590
2603
|
}
|
|
2591
|
-
const rt = await this.deps.router.ensure(bot, msg.chatId, msg.reply);
|
|
2604
|
+
const rt = await this.deps.router.ensure(bot, msg.chatId, msg.reply, msg.userId);
|
|
2592
2605
|
if (rt.inflight !== void 0) {
|
|
2593
2606
|
await msg.reply.notice("上一条还在处理中,请稍候(或发送 /stop 取消)");
|
|
2594
2607
|
return;
|
|
@@ -2636,6 +2649,12 @@ function hooksOf(bot) {
|
|
|
2636
2649
|
//#endregion
|
|
2637
2650
|
//#region src/channels/router.ts
|
|
2638
2651
|
/** 绑定路由:(botId, chatId) → 长期会话;create / resume / reset。 */
|
|
2652
|
+
/** 发起人提示段名:bot 会话声明来源渠道与发起人 open_id。 */
|
|
2653
|
+
const SENDER_SECTION_NAME = "dsh-agent-toolkit:channel:sender";
|
|
2654
|
+
/** sender 段文本(单聊语义;channel 取 BotRecord.channel,未来新渠道零改动透传)。 */
|
|
2655
|
+
function senderSectionText(channel, userId) {
|
|
2656
|
+
return `本会话由 ${channel} 渠道的单聊会话发起。发起人 ID(${channel} open_id):\`${userId}\`。`;
|
|
2657
|
+
}
|
|
2639
2658
|
var Router = class {
|
|
2640
2659
|
agents;
|
|
2641
2660
|
bindings;
|
|
@@ -2644,7 +2663,8 @@ var Router = class {
|
|
|
2644
2663
|
workspace;
|
|
2645
2664
|
onWarn;
|
|
2646
2665
|
registry;
|
|
2647
|
-
|
|
2666
|
+
injectSender;
|
|
2667
|
+
constructor(agents, bindings, sessions, defaultModel, workspace, onWarn, registry, injectSender = true) {
|
|
2648
2668
|
this.agents = agents;
|
|
2649
2669
|
this.bindings = bindings;
|
|
2650
2670
|
this.sessions = sessions;
|
|
@@ -2652,9 +2672,10 @@ var Router = class {
|
|
|
2652
2672
|
this.workspace = workspace;
|
|
2653
2673
|
this.onWarn = onWarn;
|
|
2654
2674
|
this.registry = registry;
|
|
2675
|
+
this.injectSender = injectSender;
|
|
2655
2676
|
}
|
|
2656
2677
|
/** 取(或建/恢复)该 chat 的会话 runtime;reply 刷新为最近一次入站携带的句柄。 */
|
|
2657
|
-
async ensure(bot, chatId, reply) {
|
|
2678
|
+
async ensure(bot, chatId, reply, userId) {
|
|
2658
2679
|
const bound = this.bindings.get(bot.id, chatId);
|
|
2659
2680
|
if (bound !== void 0) {
|
|
2660
2681
|
const existing = this.sessions.get(bound);
|
|
@@ -2664,7 +2685,7 @@ var Router = class {
|
|
|
2664
2685
|
}
|
|
2665
2686
|
const agent = await this.agents.resume({
|
|
2666
2687
|
sessionId: bound,
|
|
2667
|
-
...this.resolveSession(bot)
|
|
2688
|
+
...this.resolveSession(bot, userId)
|
|
2668
2689
|
});
|
|
2669
2690
|
await this.attach(bot.project, bound);
|
|
2670
2691
|
return this.adopt(bot.id, chatId, bound, agent, reply);
|
|
@@ -2673,7 +2694,7 @@ var Router = class {
|
|
|
2673
2694
|
const agent = await this.agents.create({
|
|
2674
2695
|
sessionId,
|
|
2675
2696
|
cwd: bot.project,
|
|
2676
|
-
...this.resolveSession(bot)
|
|
2697
|
+
...this.resolveSession(bot, userId)
|
|
2677
2698
|
});
|
|
2678
2699
|
await this.bindings.set(bot.id, chatId, sessionId);
|
|
2679
2700
|
await this.attach(bot.project, sessionId);
|
|
@@ -2687,24 +2708,33 @@ var Router = class {
|
|
|
2687
2708
|
this.onWarn(`[project-bot] 会话 ${sessionId} 挂载 workspace 失败:${error instanceof Error ? error.message : String(error)}`);
|
|
2688
2709
|
}
|
|
2689
2710
|
}
|
|
2690
|
-
/**
|
|
2691
|
-
|
|
2692
|
-
|
|
2711
|
+
/** injectSender 开启时向 hooks.sections 末尾追加 sender 段(主/角色形态通用)。 */
|
|
2712
|
+
withSenderSection(hooks, bot, userId) {
|
|
2713
|
+
if (!this.injectSender) return hooks;
|
|
2714
|
+
const section = {
|
|
2715
|
+
name: SENDER_SECTION_NAME,
|
|
2716
|
+
order: 20,
|
|
2717
|
+
text: senderSectionText(bot.channel ?? "unknown", userId)
|
|
2718
|
+
};
|
|
2719
|
+
return {
|
|
2720
|
+
...hooks,
|
|
2721
|
+
sections: [...hooks.sections ?? [], section]
|
|
2722
|
+
};
|
|
2693
2723
|
}
|
|
2694
2724
|
/**
|
|
2695
2725
|
* 按 bot.agentRef 解析会话组装(agentOptions + 创作期 hooks):
|
|
2696
|
-
* - 缺省/指向 main → 主 Agent 形态:bot 自带 persona/tools +
|
|
2726
|
+
* - 缺省/指向 main → 主 Agent 形态:bot 自带 persona/tools + 模型(自配 agentOptions 优先,缺省回退宿主默认模型);
|
|
2697
2727
|
* - 指向角色 → 角色形态:persona 单 section + tools.restrict + role.model;
|
|
2698
2728
|
* - 指向不存在角色 → warn 并降级为主 Agent 形态。
|
|
2699
2729
|
*/
|
|
2700
|
-
resolveSession(bot) {
|
|
2730
|
+
resolveSession(bot, userId) {
|
|
2701
2731
|
const ref = bot.agentRef ?? "main";
|
|
2702
2732
|
const role = this.registry.get(ref);
|
|
2703
2733
|
if (role === void 0 || ref === "main") {
|
|
2704
2734
|
if (role === void 0 && ref !== "main") this.onWarn(`[project-bot] bot "${bot.id}" 的 agentRef "${ref}" 不存在,降级绑定主 Agent`);
|
|
2705
2735
|
return {
|
|
2706
|
-
agentOptions: this.
|
|
2707
|
-
hooks: hooksOf(bot)
|
|
2736
|
+
agentOptions: bot.agentOptions ?? this.defaultModel(),
|
|
2737
|
+
hooks: this.withSenderSection(hooksOf(bot), bot, userId)
|
|
2708
2738
|
};
|
|
2709
2739
|
}
|
|
2710
2740
|
const sections = role.persona === void 0 || role.persona.trim().length === 0 ? [] : [{
|
|
@@ -2713,22 +2743,22 @@ var Router = class {
|
|
|
2713
2743
|
text: role.persona
|
|
2714
2744
|
}];
|
|
2715
2745
|
return {
|
|
2716
|
-
agentOptions: role.model ?? this.
|
|
2717
|
-
hooks: {
|
|
2746
|
+
agentOptions: role.model ?? this.defaultModel(),
|
|
2747
|
+
hooks: this.withSenderSection({
|
|
2718
2748
|
...sections.length > 0 ? { sections } : {},
|
|
2719
2749
|
...role.tools !== void 0 ? { tools: role.tools.allow } : {}
|
|
2720
|
-
}
|
|
2750
|
+
}, bot, userId)
|
|
2721
2751
|
};
|
|
2722
2752
|
}
|
|
2723
2753
|
/** /new:取消旧会话、清绑定、开新会话。 */
|
|
2724
|
-
async reset(bot, chatId, reply) {
|
|
2754
|
+
async reset(bot, chatId, reply, userId) {
|
|
2725
2755
|
const bound = this.bindings.get(bot.id, chatId);
|
|
2726
2756
|
if (bound !== void 0) {
|
|
2727
2757
|
this.sessions.get(bound)?.agent.cancel();
|
|
2728
2758
|
this.sessions.delete(bound);
|
|
2729
2759
|
await this.bindings.delete(bot.id, chatId);
|
|
2730
2760
|
}
|
|
2731
|
-
return this.ensure(bot, chatId, reply);
|
|
2761
|
+
return this.ensure(bot, chatId, reply, userId);
|
|
2732
2762
|
}
|
|
2733
2763
|
lookup(botId, chatId) {
|
|
2734
2764
|
const bound = this.bindings.get(botId, chatId);
|
|
@@ -2761,7 +2791,7 @@ var BotRuntime = class {
|
|
|
2761
2791
|
constructor(deps) {
|
|
2762
2792
|
this.deps = deps;
|
|
2763
2793
|
const bindingStore = this.bindingStore();
|
|
2764
|
-
this.router = new Router(deps.agents, bindingStore, this.sessions, deps.defaultModel, deps.workspace, (m) => deps.log.warn(m), deps.registry);
|
|
2794
|
+
this.router = new Router(deps.agents, bindingStore, this.sessions, deps.defaultModel, deps.workspace, (m) => deps.log.warn(m), deps.registry, deps.injectSender ?? true);
|
|
2765
2795
|
this.inbound = new Inbound({
|
|
2766
2796
|
router: this.router,
|
|
2767
2797
|
bots: deps.bots,
|
|
@@ -2774,11 +2804,12 @@ var BotRuntime = class {
|
|
|
2774
2804
|
async startAll() {
|
|
2775
2805
|
for (const botId of [...this.deps.bots.keys()]) await this.reconcile(botId);
|
|
2776
2806
|
}
|
|
2777
|
-
/** 按最新记录重建该 bot
|
|
2807
|
+
/** 按最新记录重建该 bot 的渠道(创建/更新后调用;记录已删或未绑定则纯停止)。 */
|
|
2778
2808
|
async reconcile(botId) {
|
|
2779
2809
|
await this.stopChannel(botId);
|
|
2780
2810
|
const record = this.deps.bots.get(botId);
|
|
2781
2811
|
if (record === void 0) return;
|
|
2812
|
+
if (record.feishu === void 0 || record.channel === void 0) return;
|
|
2782
2813
|
if (!this.deps.validateProject(record.project)) {
|
|
2783
2814
|
this.deps.log.warn(`[project-bot] bot "${botId}" 的项目路径不可用:${record.project}`);
|
|
2784
2815
|
return;
|
|
@@ -2812,7 +2843,17 @@ var BotRuntime = class {
|
|
|
2812
2843
|
}
|
|
2813
2844
|
await this.bindingStore().deleteBot(botId);
|
|
2814
2845
|
}
|
|
2846
|
+
/** 解绑渠道:停渠道、取消在飞会话;绑定表与持久会话保留(重绑后 resume 接续)。 */
|
|
2847
|
+
async unbindBot(botId) {
|
|
2848
|
+
await this.stopChannel(botId);
|
|
2849
|
+
for (const [sessionId, rt] of [...this.sessions]) if (rt.botId === botId) {
|
|
2850
|
+
rt.agent.cancel();
|
|
2851
|
+
this.sessions.delete(sessionId);
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2815
2854
|
statusOf(botId) {
|
|
2855
|
+
const record = this.deps.bots.get(botId);
|
|
2856
|
+
if (record !== void 0 && record.feishu === void 0) return "unbound";
|
|
2816
2857
|
return this.handles.get(botId)?.status() ?? "not-running";
|
|
2817
2858
|
}
|
|
2818
2859
|
/** 卸载时序:取消在飞会话 → 等 idle → drain 出站链(卡片定格)→ 断全部渠道。 */
|
|
@@ -2920,7 +2961,7 @@ const CreateBodySchema = z$1.object({
|
|
|
2920
2961
|
/** 手动填写路径:明文密钥(立即入 credentials,不落表)。 */
|
|
2921
2962
|
appSecret: z$1.string().min(1).optional(),
|
|
2922
2963
|
/** 扫码路径:registerApp 已入库,直接给引用。 */
|
|
2923
|
-
appSecretRef: z$1.string().optional()
|
|
2964
|
+
appSecretRef: z$1.string().regex(CREDENTIAL_REF_RE).optional()
|
|
2924
2965
|
})
|
|
2925
2966
|
});
|
|
2926
2967
|
const UpdateBodySchema = z$1.object({
|
|
@@ -2933,11 +2974,12 @@ const UpdateBodySchema = z$1.object({
|
|
|
2933
2974
|
provider: z$1.string().min(1).optional(),
|
|
2934
2975
|
model: z$1.string().min(1).optional()
|
|
2935
2976
|
}).nullable().optional(),
|
|
2936
|
-
/**
|
|
2977
|
+
/** 重绑:明文新密钥(立即入 credentials)或扫码引用(已入库);null = 解绑渠道(删密钥、保留会话绑定)。 */
|
|
2937
2978
|
feishu: z$1.object({
|
|
2938
2979
|
appId: z$1.string().regex(FEISHU_APP_ID_RE),
|
|
2939
|
-
appSecret: z$1.string().min(1)
|
|
2940
|
-
|
|
2980
|
+
appSecret: z$1.string().min(1).optional(),
|
|
2981
|
+
appSecretRef: z$1.string().regex(CREDENTIAL_REF_RE).optional()
|
|
2982
|
+
}).refine((f) => f.appSecret !== void 0 || f.appSecretRef !== void 0, { message: "缺少 appSecret 或 appSecretRef" }).nullable().optional()
|
|
2941
2983
|
});
|
|
2942
2984
|
function json(res, code, body) {
|
|
2943
2985
|
res.writeHead(code, { "content-type": "application/json" }).end(JSON.stringify(body));
|
|
@@ -2999,7 +3041,7 @@ function createApiHandler(deps) {
|
|
|
2999
3041
|
json(res, 409, { error: `bot id "${id}" 已存在` });
|
|
3000
3042
|
return;
|
|
3001
3043
|
}
|
|
3002
|
-
for (const [, existing] of deps.bots.entries()) if (existing.feishu.appId === input.feishu.appId) {
|
|
3044
|
+
for (const [, existing] of deps.bots.entries()) if (existing.feishu !== void 0 && existing.feishu.appId === input.feishu.appId) {
|
|
3003
3045
|
json(res, 409, { error: `appId 已被 bot "${existing.id}" 使用` });
|
|
3004
3046
|
return;
|
|
3005
3047
|
}
|
|
@@ -3054,23 +3096,40 @@ function createApiHandler(deps) {
|
|
|
3054
3096
|
return;
|
|
3055
3097
|
}
|
|
3056
3098
|
const input = parsed.data;
|
|
3057
|
-
let feishu = existing.feishu;
|
|
3058
|
-
if (input.feishu !== void 0) feishu = {
|
|
3059
|
-
appId: input.feishu.appId,
|
|
3060
|
-
appSecretRef: await deps.storeSecret(id, input.feishu.appSecret)
|
|
3061
|
-
};
|
|
3062
3099
|
const project = input.project ?? existing.project;
|
|
3063
3100
|
if (!deps.validateProject(project)) {
|
|
3064
3101
|
json(res, 400, { error: `项目路径不可用:${project}` });
|
|
3065
3102
|
return;
|
|
3066
3103
|
}
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3104
|
+
if (input.feishu !== null && input.feishu !== void 0) {
|
|
3105
|
+
for (const [, other] of deps.bots.entries()) if (other.id !== id && other.feishu?.appId === input.feishu.appId) {
|
|
3106
|
+
json(res, 409, { error: `appId 已被 bot "${other.id}" 使用` });
|
|
3107
|
+
return;
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
let appSecretRef;
|
|
3111
|
+
if (input.feishu === null) {
|
|
3112
|
+
await deps.runtime.unbindBot(id);
|
|
3113
|
+
if (existing.feishu !== void 0) await deps.deleteSecret(existing.feishu.appSecretRef);
|
|
3114
|
+
} else if (input.feishu !== void 0) {
|
|
3115
|
+
if (input.feishu.appSecret !== void 0) appSecretRef = await deps.storeSecret(id, input.feishu.appSecret);
|
|
3116
|
+
else appSecretRef = input.feishu.appSecretRef;
|
|
3117
|
+
if (existing.feishu !== void 0 && existing.feishu.appSecretRef !== appSecretRef) await deps.deleteSecret(existing.feishu.appSecretRef);
|
|
3118
|
+
}
|
|
3119
|
+
const merged = { ...existing };
|
|
3120
|
+
if (input.name !== void 0) merged.name = input.name;
|
|
3121
|
+
merged.project = project;
|
|
3122
|
+
merged.updatedAt = deps.now();
|
|
3123
|
+
if (input.feishu === null) {
|
|
3124
|
+
delete merged.channel;
|
|
3125
|
+
delete merged.feishu;
|
|
3126
|
+
} else if (input.feishu !== void 0 && appSecretRef !== void 0) {
|
|
3127
|
+
merged.channel = "feishu";
|
|
3128
|
+
merged.feishu = {
|
|
3129
|
+
appId: input.feishu.appId,
|
|
3130
|
+
appSecretRef
|
|
3131
|
+
};
|
|
3132
|
+
}
|
|
3074
3133
|
if (input.persona === null) delete merged.persona;
|
|
3075
3134
|
else if (input.persona !== void 0) merged.persona = input.persona;
|
|
3076
3135
|
if (input.agentRef === null) delete merged.agentRef;
|
|
@@ -3097,7 +3156,7 @@ function createApiHandler(deps) {
|
|
|
3097
3156
|
}
|
|
3098
3157
|
await deps.runtime.stopBot(id);
|
|
3099
3158
|
await deps.bots.delete(id);
|
|
3100
|
-
await deps.deleteSecret(existing.feishu.appSecretRef);
|
|
3159
|
+
if (existing.feishu !== void 0) await deps.deleteSecret(existing.feishu.appSecretRef);
|
|
3101
3160
|
json(res, 200, { ok: true });
|
|
3102
3161
|
return;
|
|
3103
3162
|
}
|
|
@@ -3321,6 +3380,7 @@ function setupBots(ctx, config, deps) {
|
|
|
3321
3380
|
tunables,
|
|
3322
3381
|
maxErrorDetailChars: config.errorDetailMaxChars,
|
|
3323
3382
|
attachments: attachmentsOf,
|
|
3383
|
+
injectSender: config.injectSender,
|
|
3324
3384
|
resolveSecret: async (ref) => (await ctx.credentials.resolve(credentialRef(ref)))?.value,
|
|
3325
3385
|
validateProject: (path) => existsSync(path),
|
|
3326
3386
|
log
|
|
@@ -3546,14 +3606,16 @@ const Config = z.object({
|
|
|
3546
3606
|
processMaxBytes: z.number().default(8e3),
|
|
3547
3607
|
registerAppTimeoutMs: z.number().default(6e5),
|
|
3548
3608
|
processingReactionEmoji: z.string().default("OneSecond"),
|
|
3549
|
-
errorDetailMaxChars: z.number().default(500)
|
|
3609
|
+
errorDetailMaxChars: z.number().default(500),
|
|
3610
|
+
injectSender: z.boolean().default(true)
|
|
3550
3611
|
}).default({
|
|
3551
3612
|
cardUpdateThrottleMs: 500,
|
|
3552
3613
|
cardMaxBytes: 28e3,
|
|
3553
3614
|
processMaxBytes: 8e3,
|
|
3554
3615
|
registerAppTimeoutMs: 6e5,
|
|
3555
3616
|
processingReactionEmoji: "OneSecond",
|
|
3556
|
-
errorDetailMaxChars: 500
|
|
3617
|
+
errorDetailMaxChars: 500,
|
|
3618
|
+
injectSender: true
|
|
3557
3619
|
}),
|
|
3558
3620
|
agentTeamPreset: z.object({
|
|
3559
3621
|
enabled: z.boolean().default(true),
|