@ai-setting/roy-agent-core 1.7.58 → 1.7.61
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/config/index.js +8 -8
- package/dist/env/agent/index.js +14 -14
- package/dist/env/commands/index.js +8 -8
- package/dist/env/context/index.js +4 -4
- package/dist/env/debug/index.js +8 -8
- package/dist/env/event-source/cli-command-handler.d.ts +90 -0
- package/dist/env/event-source/event-source-handlers.d.ts +12 -1
- package/dist/env/event-source/index.d.ts +4 -2
- package/dist/env/event-source/index.js +30 -20
- package/dist/env/event-source/types.d.ts +89 -1
- package/dist/env/hook/index.js +6 -6
- package/dist/env/index.d.ts +1 -1
- package/dist/env/index.js +46 -46
- package/dist/env/llm/index.js +9 -9
- package/dist/env/log-trace/index.d.ts +1 -1
- package/dist/env/log-trace/index.js +12 -8
- package/dist/env/log-trace/logger.d.ts +2 -0
- package/dist/env/mcp/index.js +9 -9
- package/dist/env/mcp/tool/index.js +2 -2
- package/dist/env/memory/index.js +9 -9
- package/dist/env/memory/plugin/index.js +2 -2
- package/dist/env/plugin/index.js +8 -8
- package/dist/env/prompt/index.js +8 -8
- package/dist/env/session/index.js +11 -11
- package/dist/env/session/storage/index.js +5 -5
- package/dist/env/skill/index.js +8 -8
- package/dist/env/task/delegate/index.js +9 -9
- package/dist/env/task/index.js +16 -16
- package/dist/env/task/mcp/index.d.ts +16 -0
- package/dist/env/task/mcp/index.js +222 -0
- package/dist/env/task/mcp/task-mcp-server.d.ts +142 -0
- package/dist/env/task/plugins/index.d.ts +1 -0
- package/dist/env/task/plugins/index.js +47 -12
- package/dist/env/task/storage/index.js +4 -4
- package/dist/env/task/storage/migrations/log-migration.d.ts +19 -0
- package/dist/env/task/storage/sqlite-task-store.d.ts +29 -0
- package/dist/env/task/task-component.d.ts +48 -3
- package/dist/env/task/tools/index.js +4 -4
- package/dist/env/task/tools/task-types.d.ts +60 -11
- package/dist/env/tool/built-in/index.js +4 -4
- package/dist/env/tool/index.js +11 -11
- package/dist/env/workflow/engine/index.js +13 -13
- package/dist/env/workflow/hooks/index.js +8 -8
- package/dist/env/workflow/index.js +23 -23
- package/dist/env/workflow/nodes/index.js +3 -3
- package/dist/env/workflow/plugins/index.js +9 -9
- package/dist/env/workflow/service/index.js +3 -3
- package/dist/env/workflow/storage/index.js +4 -4
- package/dist/env/workflow/tools/index.js +15 -15
- package/dist/env/workflow/tools/run-workflow.d.ts +30 -0
- package/dist/env/workflow/utils/index.js +5 -5
- package/dist/env/workflow/utils/session-recovery.d.ts +27 -0
- package/dist/index.js +81 -71
- package/dist/shared/@ai-setting/{roy-agent-core-tze5596n.js → roy-agent-core-0f989bnp.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-e250355z.js → roy-agent-core-22r4zmkw.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-8p63s836.js → roy-agent-core-2qkrpc7m.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-47s81t6g.js → roy-agent-core-3bpntd80.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-rcgvmtms.js → roy-agent-core-3p59ap0x.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-en2xqxs9.js → roy-agent-core-4m5spt7m.js} +39 -14
- package/dist/shared/@ai-setting/{roy-agent-core-5f7myqnb.js → roy-agent-core-5565cvw8.js} +11 -5
- package/dist/shared/@ai-setting/{roy-agent-core-2fk8c9ax.js → roy-agent-core-5knpegzr.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-08njdcpj.js → roy-agent-core-60p2380d.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-0yn7a78e.js → roy-agent-core-6cyjps72.js} +14 -14
- package/dist/shared/@ai-setting/{roy-agent-core-89sxsrc7.js → roy-agent-core-8fy467qs.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-x6c45yqd.js → roy-agent-core-99nwgj84.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-20m8je6e.js → roy-agent-core-9k8ms63r.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-0kn3zt1t.js → roy-agent-core-9s3payp1.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-hefarcp0.js → roy-agent-core-a5nh5q6v.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-hs41gx9w.js → roy-agent-core-aa514zm8.js} +5 -5
- package/dist/shared/@ai-setting/{roy-agent-core-yphwdm9x.js → roy-agent-core-ajmgyawx.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-caevk7xd.js → roy-agent-core-arx535cs.js} +30 -8
- package/dist/shared/@ai-setting/{roy-agent-core-vath15kt.js → roy-agent-core-bc3v8pw4.js} +6 -6
- package/dist/shared/@ai-setting/{roy-agent-core-m97jn2ra.js → roy-agent-core-bdzdw1g3.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-ck60j1q9.js → roy-agent-core-bxkjk7zx.js} +2 -1
- package/dist/shared/@ai-setting/{roy-agent-core-6bradb0j.js → roy-agent-core-cndvj1hv.js} +8 -8
- package/dist/shared/@ai-setting/{roy-agent-core-d75t8gea.js → roy-agent-core-dg286rpd.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-q4gdfypk.js → roy-agent-core-dp1hp24k.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-ygn5tzt1.js → roy-agent-core-dythsgkn.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-em4hks9t.js → roy-agent-core-e6k448ka.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-ytd5eztz.js → roy-agent-core-expvav8a.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-vgdhxbx3.js → roy-agent-core-g44nbgtt.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-14bq77wr.js → roy-agent-core-g5sw19fa.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-991pk4ss.js → roy-agent-core-gtb4fj8j.js} +16 -16
- package/dist/shared/@ai-setting/{roy-agent-core-gksw1gjb.js → roy-agent-core-hf0t8agb.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-txwptxk1.js → roy-agent-core-j0x9yf96.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-84rs0c8d.js → roy-agent-core-jrksyqb6.js} +7 -7
- package/dist/shared/@ai-setting/{roy-agent-core-ge87xbas.js → roy-agent-core-jsdqzfbj.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-m68z3pw1.js → roy-agent-core-jsn21cb9.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-n0p0hwgd.js → roy-agent-core-kfmrfaft.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-7q4wdze2.js → roy-agent-core-khc23qs1.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-e1w17tht.js → roy-agent-core-m2tv4pj0.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-4096f575.js → roy-agent-core-mhppywse.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-t64nmayv.js → roy-agent-core-mw0bc9g6.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-8bngppw0.js → roy-agent-core-n1ck0x1r.js} +13 -13
- package/dist/shared/@ai-setting/{roy-agent-core-w93z6a42.js → roy-agent-core-nd5171pv.js} +12 -12
- package/dist/shared/@ai-setting/{roy-agent-core-geh6j7bw.js → roy-agent-core-p2dpcyrz.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-fw6k4w1h.js → roy-agent-core-pj5tfmn5.js} +6 -6
- package/dist/shared/@ai-setting/{roy-agent-core-029r8kdw.js → roy-agent-core-q212q0w1.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-psg6f1v6.js → roy-agent-core-qgapy83x.js} +6 -6
- package/dist/shared/@ai-setting/{roy-agent-core-jjxdmedn.js → roy-agent-core-qpqqx1wd.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-syyw58p9.js → roy-agent-core-qrjs2500.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-84xtww7d.js → roy-agent-core-qw5fpa24.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-kq9pz2a7.js → roy-agent-core-rnzm0tpf.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-7nb23tdd.js → roy-agent-core-s7w47mnn.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-t4x089js.js → roy-agent-core-sf9tsj0g.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-jjhw9am6.js → roy-agent-core-tn96n4wz.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-c7w2h47a.js → roy-agent-core-vmfk4m1v.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-cyefe8z5.js → roy-agent-core-x1m0gs0q.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-baaa4wtp.js → roy-agent-core-xc0es9zc.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-fbjd7bt6.js → roy-agent-core-xeqp659x.js} +64 -29
- package/dist/shared/@ai-setting/{roy-agent-core-rt115qfc.js → roy-agent-core-y0k9kaxz.js} +14 -4
- package/dist/shared/@ai-setting/{roy-agent-core-c36335nw.js → roy-agent-core-yd85623y.js} +15 -3
- package/dist/shared/@ai-setting/{roy-agent-core-9zhkdg6w.js → roy-agent-core-ygfjgk9b.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-vh0qzb24.js → roy-agent-core-ymcvsdzn.js} +36 -15
- package/dist/shared/@ai-setting/{roy-agent-core-eanq305k.js → roy-agent-core-yr5eqyhz.js} +11 -11
- package/dist/shared/@ai-setting/{roy-agent-core-fy4mcj6x.js → roy-agent-core-ytnedzks.js} +292 -105
- package/dist/shared/@ai-setting/{roy-agent-core-2ctyjy62.js → roy-agent-core-z51jktet.js} +1 -1
- package/dist/utils/temp-file-manager/index.js +2 -2
- package/package.json +16 -1
- /package/dist/shared/@ai-setting/{roy-agent-core-3ztzc83c.js → roy-agent-core-5enxfga2.js} +0 -0
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defaultLarkCliRunner
|
|
3
|
-
} from "./roy-agent-core-
|
|
3
|
+
} from "./roy-agent-core-bxkjk7zx.js";
|
|
4
4
|
import {
|
|
5
5
|
TaskTagPlugin,
|
|
6
6
|
createLarkCliTaskNotifyHook,
|
|
7
7
|
createPerTaskGroupChatPlugin,
|
|
8
8
|
extractPerTaskChatId,
|
|
9
9
|
extractPerTaskChatName
|
|
10
|
-
} from "./roy-agent-core-
|
|
10
|
+
} from "./roy-agent-core-n1ck0x1r.js";
|
|
11
11
|
import {
|
|
12
12
|
getSharedEventStore
|
|
13
|
-
} from "./roy-agent-core-
|
|
13
|
+
} from "./roy-agent-core-z51jktet.js";
|
|
14
14
|
import {
|
|
15
15
|
createLarkCliWorkflowNotifyHook
|
|
16
|
-
} from "./roy-agent-core-
|
|
16
|
+
} from "./roy-agent-core-qgapy83x.js";
|
|
17
17
|
import {
|
|
18
18
|
LarkCardPatchNotifier,
|
|
19
19
|
buildTaskCard
|
|
20
|
-
} from "./roy-agent-core-
|
|
20
|
+
} from "./roy-agent-core-yd85623y.js";
|
|
21
21
|
import {
|
|
22
22
|
normalizeLarkAtMentions
|
|
23
23
|
} from "./roy-agent-core-64f22h1g.js";
|
|
@@ -26,29 +26,29 @@ import {
|
|
|
26
26
|
} from "./roy-agent-core-7hh0brvs.js";
|
|
27
27
|
import {
|
|
28
28
|
BaseComponent
|
|
29
|
-
} from "./roy-agent-core-
|
|
29
|
+
} from "./roy-agent-core-9s3payp1.js";
|
|
30
30
|
import {
|
|
31
31
|
globalHookManager,
|
|
32
32
|
init_global_hook_manager
|
|
33
|
-
} from "./roy-agent-core-
|
|
33
|
+
} from "./roy-agent-core-ajmgyawx.js";
|
|
34
34
|
import {
|
|
35
35
|
init_context
|
|
36
|
-
} from "./roy-agent-core-
|
|
36
|
+
} from "./roy-agent-core-bdzdw1g3.js";
|
|
37
37
|
import {
|
|
38
38
|
createEnvContext,
|
|
39
39
|
normalizeParentTaskId,
|
|
40
40
|
runWithEnvContext
|
|
41
|
-
} from "./roy-agent-core-
|
|
41
|
+
} from "./roy-agent-core-qrjs2500.js";
|
|
42
42
|
import {
|
|
43
43
|
TracedAs,
|
|
44
44
|
init_decorator,
|
|
45
45
|
wrapFunction
|
|
46
|
-
} from "./roy-agent-core-
|
|
46
|
+
} from "./roy-agent-core-2qkrpc7m.js";
|
|
47
47
|
import {
|
|
48
48
|
createLogger,
|
|
49
49
|
getTracerProvider,
|
|
50
50
|
init_logger
|
|
51
|
-
} from "./roy-agent-core-
|
|
51
|
+
} from "./roy-agent-core-y0k9kaxz.js";
|
|
52
52
|
import {
|
|
53
53
|
__legacyDecorateClassTS,
|
|
54
54
|
__require
|
|
@@ -609,6 +609,155 @@ var bountyIMHandler = {
|
|
|
609
609
|
}
|
|
610
610
|
};
|
|
611
611
|
|
|
612
|
+
// src/env/event-source/cli-command-handler.ts
|
|
613
|
+
init_logger();
|
|
614
|
+
var logger = createLogger("cli-command:event-source");
|
|
615
|
+
var CLI_COMMAND_ES_TYPE = "cli-command";
|
|
616
|
+
var CLI_SESSION_CHAT_ID_PREFIX = "cli:";
|
|
617
|
+
function buildCliReplyChannel(params) {
|
|
618
|
+
const sid = params.sessionId?.trim() ? params.sessionId.trim() : "default";
|
|
619
|
+
return {
|
|
620
|
+
type: CLI_COMMAND_ES_TYPE,
|
|
621
|
+
chatId: `${CLI_SESSION_CHAT_ID_PREFIX}${sid}`,
|
|
622
|
+
params: { sink: "stdout", cliSessionId: sid }
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function parseCliSessionChatId(chatId) {
|
|
626
|
+
if (!chatId || !chatId.startsWith(CLI_SESSION_CHAT_ID_PREFIX))
|
|
627
|
+
return;
|
|
628
|
+
const sid = chatId.slice(CLI_SESSION_CHAT_ID_PREFIX.length);
|
|
629
|
+
return sid.length > 0 ? sid : undefined;
|
|
630
|
+
}
|
|
631
|
+
function describeNotifyEvent(type, taskLabel, desc) {
|
|
632
|
+
const actionable = new Set([
|
|
633
|
+
"task.background.completed",
|
|
634
|
+
"task.background.failed",
|
|
635
|
+
"task.background.timeout",
|
|
636
|
+
"task.background.stopped"
|
|
637
|
+
]).has(type);
|
|
638
|
+
switch (type) {
|
|
639
|
+
case "task.background.completed":
|
|
640
|
+
return { headline: `Sub-agent 完成了 ${taskLabel}「${desc}」。`, actionable };
|
|
641
|
+
case "task.background.failed":
|
|
642
|
+
return { headline: `Sub-agent 执行 ${taskLabel}「${desc}」失败。`, actionable };
|
|
643
|
+
case "task.background.timeout":
|
|
644
|
+
return { headline: `Sub-agent 执行 ${taskLabel}「${desc}」**超时**(未跑完)。`, actionable };
|
|
645
|
+
case "task.background.stopped":
|
|
646
|
+
return { headline: `Sub-agent 已停止 ${taskLabel}「${desc}」。`, actionable };
|
|
647
|
+
case "task.background.ask_user":
|
|
648
|
+
return { headline: `Sub-agent 在 ${taskLabel}「${desc}」中请求用户输入。`, actionable };
|
|
649
|
+
case "task.background.started":
|
|
650
|
+
return { headline: `Sub-agent 已启动 ${taskLabel}「${desc}」(后台运行中)。`, actionable };
|
|
651
|
+
case "task.background.progress":
|
|
652
|
+
return { headline: `Sub-agent 仍在执行 ${taskLabel}「${desc}」(进行中)。`, actionable };
|
|
653
|
+
default:
|
|
654
|
+
return { headline: `Sub-agent 更新了 ${taskLabel}「${desc}」。`, actionable };
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
function renderRuleNoticeSectionForCli(ruleNotice, headline) {
|
|
658
|
+
if (!ruleNotice || !ruleNotice.attempted) {
|
|
659
|
+
return `(本事件不直发规则回执)
|
|
660
|
+
` + `→ 你的回复要把结果讲**完整**(终端用户只能从你这条输出知道结论)。`;
|
|
661
|
+
}
|
|
662
|
+
if (ruleNotice.delivered) {
|
|
663
|
+
const when = ruleNotice.sentAt ? new Date(ruleNotice.sentAt).toLocaleTimeString("zh-CN", {
|
|
664
|
+
hour12: false,
|
|
665
|
+
hour: "2-digit",
|
|
666
|
+
minute: "2-digit"
|
|
667
|
+
}) : "";
|
|
668
|
+
const sent = ruleNotice.text ? `:「${ruleNotice.text.replace(/\s*\n+\s*/g, " ")}」` : "";
|
|
669
|
+
return `✅ 系统已于 ${when || "刚才"} 向终端输出过下面这条${sent}
|
|
670
|
+
` + `→ 你的回复**只发增量**:不要再重复「任务已结束」这类回执原文,` + `直接讲结论/交付 + 下一步选项。`;
|
|
671
|
+
}
|
|
672
|
+
return `❌ **回执未送达**(原因:${ruleNotice.error ?? "unknown"})
|
|
673
|
+
` + `→ 用户目前**还不知道**「${headline}」这件事,必须由你在回复里讲清楚,` + `并且不要假装系统已经通知过。`;
|
|
674
|
+
}
|
|
675
|
+
var cliCommandHandler = {
|
|
676
|
+
type: CLI_COMMAND_ES_TYPE,
|
|
677
|
+
validateConfig(_config) {
|
|
678
|
+
return [];
|
|
679
|
+
},
|
|
680
|
+
createInstance(config) {
|
|
681
|
+
return {
|
|
682
|
+
config,
|
|
683
|
+
start: async () => {},
|
|
684
|
+
stop: async () => {},
|
|
685
|
+
isRunning: () => false,
|
|
686
|
+
getStatus: () => ({
|
|
687
|
+
id: config.id,
|
|
688
|
+
type: CLI_COMMAND_ES_TYPE,
|
|
689
|
+
running: false
|
|
690
|
+
})
|
|
691
|
+
};
|
|
692
|
+
},
|
|
693
|
+
async emitTriggerEvent(payload, store) {
|
|
694
|
+
const eventId = await store.insertTriggerEvent(payload, CLI_COMMAND_ES_TYPE);
|
|
695
|
+
logger.info(`[cliCommandHandler] emitTriggerEvent: id=${eventId}`, {
|
|
696
|
+
sessionId: payload.metadata?.sessionId,
|
|
697
|
+
cwd: payload.metadata?.cwd
|
|
698
|
+
});
|
|
699
|
+
return eventId;
|
|
700
|
+
},
|
|
701
|
+
extractReplyContext(event, profile) {
|
|
702
|
+
const meta = event.metadata ?? {};
|
|
703
|
+
return {
|
|
704
|
+
esType: CLI_COMMAND_ES_TYPE,
|
|
705
|
+
chatId: typeof meta.chatId === "string" ? meta.chatId : "",
|
|
706
|
+
messageId: typeof meta.messageId === "string" ? meta.messageId : "",
|
|
707
|
+
senderOpenId: typeof meta.senderId === "string" ? meta.senderId : "",
|
|
708
|
+
profile: profile ?? (typeof meta.profile === "string" ? meta.profile : undefined)
|
|
709
|
+
};
|
|
710
|
+
},
|
|
711
|
+
buildNotifyHandlePrompt(input) {
|
|
712
|
+
const { notifyEvent, triggerEvent, ruleNotice, subAgentResult, channel } = input;
|
|
713
|
+
const triggerMeta = triggerEvent.metadata ?? {};
|
|
714
|
+
const legacyPayload = notifyEvent.payload ?? {};
|
|
715
|
+
const rawTaskId = notifyEvent.taskId ?? legacyPayload.associatedTaskId;
|
|
716
|
+
const bgId = notifyEvent.backgroundTaskId ?? legacyPayload.backgroundTaskId;
|
|
717
|
+
const shortBgId = bgId ? bgId.split("_").pop() : undefined;
|
|
718
|
+
const taskLabel = rawTaskId !== undefined ? `Task #${rawTaskId}` : shortBgId ? `后台任务 ${shortBgId}` : "后台任务";
|
|
719
|
+
const desc = notifyEvent.description ?? legacyPayload.description ?? "后台任务";
|
|
720
|
+
const result = (subAgentResult?.summary && subAgentResult.summary.trim() ? subAgentResult.summary : undefined) ?? notifyEvent.result ?? notifyEvent.error ?? legacyPayload.result ?? legacyPayload.error ?? "(无结果)";
|
|
721
|
+
const cwd = typeof triggerMeta.cwd === "string" ? triggerMeta.cwd : "(未知)";
|
|
722
|
+
const cliSession = typeof triggerMeta.sessionId === "string" ? triggerMeta.sessionId : "(未知)";
|
|
723
|
+
const query = typeof triggerEvent.text === "string" && triggerEvent.text ? triggerEvent.text : "(未记录)";
|
|
724
|
+
const { headline } = describeNotifyEvent(notifyEvent.type, taskLabel, desc);
|
|
725
|
+
const channelLabel = channel?.esType ?? CLI_COMMAND_ES_TYPE;
|
|
726
|
+
return {
|
|
727
|
+
promptText: [
|
|
728
|
+
`# 后台任务通知(渠道:CLI 命令行)`,
|
|
729
|
+
``,
|
|
730
|
+
`## 触发渠道`,
|
|
731
|
+
`- 渠道类型: \`${channelLabel}\`(用户在**终端**直接输入 query 触发,不是飞书消息)`,
|
|
732
|
+
`- 工作目录: \`${cwd}\``,
|
|
733
|
+
`- CLI session: \`${cliSession}\``,
|
|
734
|
+
`- 用户原始 query: ${query.length > 400 ? query.slice(0, 400) + "…" : query}`,
|
|
735
|
+
`- **回复方式: 直接输出到 stdout(终端)**。`,
|
|
736
|
+
``,
|
|
737
|
+
`⚠️ **本渠道没有 IM 通道,不要调用 lark-cli**。`,
|
|
738
|
+
` 不要尝试 \`lark-cli im +messages-send\` / \`+messages-reply\`,`,
|
|
739
|
+
` 不要编造 chatId(\`cli:*\` 不是真实飞书会话,发过去必然失败),`,
|
|
740
|
+
` 也不要调用任何飞书相关工具。用户就在终端前等你的文字输出。`,
|
|
741
|
+
``,
|
|
742
|
+
`## 系统回执`,
|
|
743
|
+
renderRuleNoticeSectionForCli(ruleNotice, headline),
|
|
744
|
+
``,
|
|
745
|
+
`## 事件`,
|
|
746
|
+
headline,
|
|
747
|
+
``,
|
|
748
|
+
`## Sub-agent 输出`,
|
|
749
|
+
result,
|
|
750
|
+
``,
|
|
751
|
+
`## 你要做什么`,
|
|
752
|
+
`1. 把上面 Sub-agent 的结论整理成**给终端用户直接读的一段话**。`,
|
|
753
|
+
`2. **直接输出这段文字**(它就是用户看到的内容),不要包 JSON、不要写文件。`,
|
|
754
|
+
`3. 若「系统回执」显示已送达,只讲**增量**;未送达则把结论讲完整。`
|
|
755
|
+
].join(`
|
|
756
|
+
`)
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
};
|
|
760
|
+
|
|
612
761
|
// src/env/event-source/event-source-handlers.ts
|
|
613
762
|
import { spawn as spawn3, exec as execSync } from "child_process";
|
|
614
763
|
import { promisify as promisify2 } from "node:util";
|
|
@@ -619,7 +768,7 @@ init_context();
|
|
|
619
768
|
init_logger();
|
|
620
769
|
import { exec } from "node:child_process";
|
|
621
770
|
import { promisify } from "node:util";
|
|
622
|
-
var
|
|
771
|
+
var logger2 = createLogger("lark-card-action-handler");
|
|
623
772
|
var execAsync = promisify(exec);
|
|
624
773
|
var CTX_FIELD_CHAT_ID = "larkPerTaskChatId";
|
|
625
774
|
var CTX_FIELD_CHAT_NAME = "larkPerTaskChatName";
|
|
@@ -639,7 +788,7 @@ async function handleCardAction(event, ports) {
|
|
|
639
788
|
const inflightKey = `${event.profile ?? "-"}:${event.messageId || String(taskId)}:${action}`;
|
|
640
789
|
const inflight = cardActionInflight.get(inflightKey);
|
|
641
790
|
if (inflight) {
|
|
642
|
-
|
|
791
|
+
logger2.warn(`handleCardAction: ${inflightKey} 已有同操作在处理中(疑似用户重复点击),本次忽略。`);
|
|
643
792
|
return { ok: false, action, error: `重复点击:${inflightKey} 正在处理中,已忽略` };
|
|
644
793
|
}
|
|
645
794
|
const pending = handleCardActionInner(event, ports, taskId);
|
|
@@ -670,10 +819,10 @@ function buildCardAfterGroupChange(event, ports, task, perTaskChatId, perTaskCha
|
|
|
670
819
|
const meta = buildTaskMetaFromTask(task, perTaskChatId, perTaskChatName);
|
|
671
820
|
const preserved = ports.notifier?.updateMetaAndBuildCard?.(event.messageId, meta, { clearPerTaskChat: !perTaskChatId });
|
|
672
821
|
if (preserved) {
|
|
673
|
-
|
|
822
|
+
logger2.debug(`buildCardAfterGroupChange: 复用 notifier 累积状态(里程碑历史保留)messageId=${event.messageId}`);
|
|
674
823
|
return preserved;
|
|
675
824
|
}
|
|
676
|
-
|
|
825
|
+
logger2.warn(`buildCardAfterGroupChange: notifier 无 messageId=${event.messageId} 的状态,` + `fallback 重建卡片(该卡片的历史里程碑可能丢失)`);
|
|
677
826
|
return buildTaskCard({
|
|
678
827
|
status: "running",
|
|
679
828
|
meta,
|
|
@@ -685,7 +834,7 @@ function buildCardAfterGroupChange(event, ports, task, perTaskChatId, perTaskCha
|
|
|
685
834
|
async function handleCreateGroup(event, ports, task, existingChatId) {
|
|
686
835
|
if (existingChatId) {
|
|
687
836
|
const existingName = extractPerTaskChatName(task.context);
|
|
688
|
-
|
|
837
|
+
logger2.info(`handleCreateGroup: Task #${task.id} 已有专属群 ${existingChatId}(幂等命中,不重复建群)`);
|
|
689
838
|
return {
|
|
690
839
|
ok: true,
|
|
691
840
|
action: "create_group",
|
|
@@ -711,17 +860,17 @@ async function handleCreateGroup(event, ports, task, existingChatId) {
|
|
|
711
860
|
if (operatorOpenId) {
|
|
712
861
|
if (initialUserIds) {
|
|
713
862
|
invitedOpenIds = [operatorOpenId];
|
|
714
|
-
|
|
863
|
+
logger2.debug(`handleCreateGroup: ${operatorOpenId} 已在建群时邀请(initialUserIds 路径)`);
|
|
715
864
|
} else if (ports.inviteUser) {
|
|
716
865
|
try {
|
|
717
866
|
await ports.inviteUser(chatId, operatorOpenId, event.profile);
|
|
718
867
|
invitedOpenIds = [operatorOpenId];
|
|
719
|
-
|
|
868
|
+
logger2.debug(`handleCreateGroup: 走 inviteUser 端口邀请 ${operatorOpenId} 进 ${chatId}`);
|
|
720
869
|
} catch (err) {
|
|
721
|
-
|
|
870
|
+
logger2.warn(`handleCreateGroup: inviteUser(${chatId}, ${operatorOpenId}) 失败(不阻断主流程): ${err.message}`);
|
|
722
871
|
}
|
|
723
872
|
} else {
|
|
724
|
-
|
|
873
|
+
logger2.warn(`handleCreateGroup: createGroupChat 不支持 initialUserIds 且 inviteUser 未注入,` + `${operatorOpenId} 未被拉进群 ${chatId}。` + `需升级 caller(bridge/real impl)使用 ports.inviteUser 或实现 createGroupChat.initialUserIds 参数。`);
|
|
725
874
|
}
|
|
726
875
|
}
|
|
727
876
|
const newContext = patchContext(task.context ?? "{}", {
|
|
@@ -737,7 +886,7 @@ async function handleCreateGroup(event, ports, task, existingChatId) {
|
|
|
737
886
|
const cardUpdate = buildCardAfterGroupChange(event, ports, task, chatId, renderedName);
|
|
738
887
|
return { ok: true, action: "create_group", newChatId: chatId, cardUpdate };
|
|
739
888
|
} catch (err) {
|
|
740
|
-
|
|
889
|
+
logger2.error(`handleCardAction.create_group failed: ${err.message}`);
|
|
741
890
|
return { ok: false, action: "create_group", error: err.message };
|
|
742
891
|
}
|
|
743
892
|
}
|
|
@@ -775,7 +924,7 @@ async function handleDisbandGroup(event, ports, task, existingChatId) {
|
|
|
775
924
|
const cardUpdate = buildCardAfterGroupChange(event, ports, task, undefined, undefined);
|
|
776
925
|
return { ok: true, action: "disband_group", cardUpdate };
|
|
777
926
|
} catch (err) {
|
|
778
|
-
|
|
927
|
+
logger2.error(`handleCardAction.disband_group failed: ${err.message}`);
|
|
779
928
|
return { ok: false, action: "disband_group", error: err.message };
|
|
780
929
|
}
|
|
781
930
|
}
|
|
@@ -824,9 +973,9 @@ async function deleteGroupChatViaLarkCli(chatId, profile) {
|
|
|
824
973
|
}
|
|
825
974
|
const cmd = `lark-cli ${profileFlag}api DELETE /open-apis/im/v1/chats/${chatId}/members ` + `--params '{"member_id_type":"app_id"}' ` + `--data ${shellQuote(JSON.stringify({ id_list: [appId] }))} ` + `--as bot`;
|
|
826
975
|
const { stdout, stderr } = await execAsync(cmd, { timeout: 30000 });
|
|
827
|
-
|
|
976
|
+
logger2.debug(`deleteGroupChatViaLarkCli(${chatId}) bot 退群 ok: ` + `stdout=${stdout?.slice(0, 300)} stderr=${stderr?.slice(0, 300)}`);
|
|
828
977
|
} catch (err) {
|
|
829
|
-
|
|
978
|
+
logger2.warn(`deleteGroupChatViaLarkCli(${chatId}) bot 退群失败(task.context 仍会清掉,` + `飞书侧群会保留):${err.message}`);
|
|
830
979
|
}
|
|
831
980
|
}
|
|
832
981
|
function shellQuote(s) {
|
|
@@ -1089,7 +1238,7 @@ init_logger();
|
|
|
1089
1238
|
// src/env/error-reply.ts
|
|
1090
1239
|
init_logger();
|
|
1091
1240
|
import { spawn as spawn2 } from "node:child_process";
|
|
1092
|
-
var
|
|
1241
|
+
var logger3 = createLogger("env:error-reply");
|
|
1093
1242
|
var UPSTREAM_RETRY_PATTERNS = [
|
|
1094
1243
|
/failed after \d+ attempts/i,
|
|
1095
1244
|
/endpoint is unavailable/i,
|
|
@@ -1447,7 +1596,7 @@ function spawnLarkReply(options) {
|
|
|
1447
1596
|
async function notifyReactFailure(options) {
|
|
1448
1597
|
const info = classifyReactFailure(options.error);
|
|
1449
1598
|
if (!info.notify) {
|
|
1450
|
-
|
|
1599
|
+
logger3.debug(`[#4418] 命中规则 ${info.ruleId}(非失败),不发失败说明` + (options.sessionId ? ` (session=${options.sessionId})` : ""));
|
|
1451
1600
|
return { sent: false, kind: info.kind, info, skipped: "not_a_failure" };
|
|
1452
1601
|
}
|
|
1453
1602
|
const channel = (isUsableChannel(options.replyChannel) ? options.replyChannel : undefined) ?? extractReplyChannelFromEvent(options.envEvent);
|
|
@@ -1455,14 +1604,14 @@ async function notifyReactFailure(options) {
|
|
|
1455
1604
|
const hasTrigger = Boolean(options.envEvent);
|
|
1456
1605
|
const noChannelMsg = `[#4418] React 中断(${info.kind}/${info.ruleId})无法定位 replyChannel,` + `飞书端收不到失败说明` + (hasTrigger ? " —— triggerEvent 存在但缺少 metadata.replyChannel" : "(本地执行,无 triggerEvent)") + (options.sessionId ? ` (session=${options.sessionId})` : "");
|
|
1457
1606
|
if (hasTrigger)
|
|
1458
|
-
|
|
1607
|
+
logger3.warn(noChannelMsg);
|
|
1459
1608
|
else
|
|
1460
|
-
|
|
1609
|
+
logger3.debug(noChannelMsg);
|
|
1461
1610
|
return { sent: false, kind: info.kind, info, skipped: "no_channel" };
|
|
1462
1611
|
}
|
|
1463
1612
|
const dedupKey = makeDedupKey(channel, info, options.dedupKey);
|
|
1464
1613
|
if (isDuplicate(dedupKey)) {
|
|
1465
|
-
|
|
1614
|
+
logger3.info(`[#4418] React 中断(${info.kind})已回复过 ${dedupKey},跳过`);
|
|
1466
1615
|
return { sent: false, kind: info.kind, info, skipped: "duplicate" };
|
|
1467
1616
|
}
|
|
1468
1617
|
rememberTrigger(dedupKey);
|
|
@@ -1475,19 +1624,18 @@ async function notifyReactFailure(options) {
|
|
|
1475
1624
|
profile: channel.profile,
|
|
1476
1625
|
timeoutMs: options.replyTimeoutMs
|
|
1477
1626
|
});
|
|
1478
|
-
|
|
1627
|
+
logger3.info(`[#4418] React 中断(${info.kind}/${info.ruleId})已回飞书 ` + `(${channel.messageId ?? channel.chatId})`);
|
|
1479
1628
|
return { sent: true, kind: info.kind, info };
|
|
1480
1629
|
} catch (err) {
|
|
1481
1630
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
1482
1631
|
repliedTriggers.delete(dedupKey);
|
|
1483
|
-
|
|
1632
|
+
logger3.warn(`[#4418] React 中断(${info.kind}/${info.ruleId})回飞书失败(已忽略): ${errorMsg}`);
|
|
1484
1633
|
return { sent: false, kind: info.kind, info, error: errorMsg };
|
|
1485
1634
|
}
|
|
1486
1635
|
}
|
|
1487
|
-
|
|
1488
1636
|
// src/env/event-source/event-source-handlers.ts
|
|
1489
1637
|
var execAsync2 = promisify2(execSync);
|
|
1490
|
-
var
|
|
1638
|
+
var logger4 = createLogger("lark-cli:event-source");
|
|
1491
1639
|
var CHILD_READY_TIMEOUT_MS = 5000;
|
|
1492
1640
|
var GRACEFUL_STOP_TIMEOUT_MS = 5000;
|
|
1493
1641
|
var CARD_ACTION_EVENT_TYPE = "card.action.trigger";
|
|
@@ -1716,8 +1864,8 @@ class LarkCliInstance {
|
|
|
1716
1864
|
cardActionPorts;
|
|
1717
1865
|
setCardActionPorts(ports) {
|
|
1718
1866
|
this.cardActionPorts = ports;
|
|
1719
|
-
if (typeof
|
|
1720
|
-
|
|
1867
|
+
if (typeof logger4 !== "undefined" && logger4?.debug) {
|
|
1868
|
+
logger4.debug(`[LarkCliInstance] CardActionPorts injected: ` + `getTask=${typeof ports.getTask}, updateTaskContext=${typeof ports.updateTaskContext}, ` + `createGroupChat=${typeof ports.createGroupChat}, deleteGroupChat=${typeof ports.deleteGroupChat}, ` + `notifier=${typeof ports.notifier}`);
|
|
1721
1869
|
}
|
|
1722
1870
|
}
|
|
1723
1871
|
hasCardActionPorts() {
|
|
@@ -1744,7 +1892,7 @@ class LarkCliInstance {
|
|
|
1744
1892
|
if (this.status === "running")
|
|
1745
1893
|
return;
|
|
1746
1894
|
if (this.starting) {
|
|
1747
|
-
|
|
1895
|
+
logger4.warn(`[LarkCliInstance] start() 已在执行中,忽略重复调用`);
|
|
1748
1896
|
return;
|
|
1749
1897
|
}
|
|
1750
1898
|
this.starting = true;
|
|
@@ -1774,9 +1922,9 @@ class LarkCliInstance {
|
|
|
1774
1922
|
if (!consumesCardAction)
|
|
1775
1923
|
return;
|
|
1776
1924
|
if (this.config.eventTypes?.length && !matchEventType(CARD_ACTION_EVENT_TYPE, this.config.eventTypes)) {
|
|
1777
|
-
|
|
1925
|
+
logger4.warn(`[LarkCliInstance] eventKeys 含 ${CARD_ACTION_EVENT_TYPE},但 eventTypes=` + `${JSON.stringify(this.config.eventTypes)} 不含它 → 卡片点击会被**静默丢弃**。` + `请把 ${CARD_ACTION_EVENT_TYPE} 加进 eventTypes,或清空 eventTypes。`);
|
|
1778
1926
|
}
|
|
1779
|
-
|
|
1927
|
+
logger4.info(`[LarkCliInstance] 已监听 ${CARD_ACTION_EVENT_TYPE}。` + `⚠️ 若点击卡片无反应,先确认飞书开发者后台「事件与回调 → 回调配置」已开启该事件。`);
|
|
1780
1928
|
}
|
|
1781
1929
|
spawnConsumeChild(command) {
|
|
1782
1930
|
return spawn3("exec " + command, [], {
|
|
@@ -1816,7 +1964,7 @@ class LarkCliInstance {
|
|
|
1816
1964
|
const conflicts = keys.filter((k) => busy.has(k));
|
|
1817
1965
|
if (conflicts.length > 0) {
|
|
1818
1966
|
const profile = this.config.profile;
|
|
1819
|
-
|
|
1967
|
+
logger4.warn(`[LarkCliInstance] eventKey 已被其它 consumer 占用(lark-cli 一个 key 只允许一个 consumer):` + `${conflicts.join(", ")}。本 event-source 启动后可能 exit 2。` + `用 \`lark-cli${profile ? ` --profile ${profile}` : ""} event status\` 查看,必要时 \`event stop\`。`);
|
|
1820
1968
|
}
|
|
1821
1969
|
}
|
|
1822
1970
|
async probeBusyEventKeys() {
|
|
@@ -1867,16 +2015,16 @@ class LarkCliInstance {
|
|
|
1867
2015
|
});
|
|
1868
2016
|
const handleExit = (code, source) => {
|
|
1869
2017
|
if (code !== 0 && code !== null) {
|
|
1870
|
-
|
|
2018
|
+
logger4.warn(`[LarkCliInstance] consume 子进程异常退出 code=${code} (${source}) cmd="${command}"`);
|
|
1871
2019
|
this.status = "error";
|
|
1872
2020
|
} else {
|
|
1873
|
-
|
|
2021
|
+
logger4.info(`[LarkCliInstance] consume 子进程已退出 code=${code} (${source}) cmd="${command}"`);
|
|
1874
2022
|
}
|
|
1875
2023
|
settle();
|
|
1876
2024
|
queueMicrotask(() => {
|
|
1877
2025
|
if (this.children.length > 0 && this.children.every((c) => !isChildAlive(c))) {
|
|
1878
2026
|
if (this.status !== "error") {
|
|
1879
|
-
|
|
2027
|
+
logger4.warn(`[LarkCliInstance] 所有 consume 子进程都已退出,状态从 running 改为 stopped`);
|
|
1880
2028
|
this.status = "stopped";
|
|
1881
2029
|
}
|
|
1882
2030
|
}
|
|
@@ -1885,12 +2033,12 @@ class LarkCliInstance {
|
|
|
1885
2033
|
child.on("exit", (code) => handleExit(code, "exit"));
|
|
1886
2034
|
child.on("close", (code) => handleExit(code, "close"));
|
|
1887
2035
|
child.on("error", (error) => {
|
|
1888
|
-
|
|
2036
|
+
logger4.error(`[LarkCliInstance] consume 子进程 error: ${error.message}`);
|
|
1889
2037
|
this.status = "error";
|
|
1890
2038
|
settle();
|
|
1891
2039
|
});
|
|
1892
2040
|
const timer = setTimeout(() => {
|
|
1893
|
-
|
|
2041
|
+
logger4.warn(`[LarkCliInstance] consume 子进程 ${CHILD_READY_TIMEOUT_MS}ms 内未见 ready marker: cmd="${command}"`);
|
|
1894
2042
|
settle();
|
|
1895
2043
|
}, CHILD_READY_TIMEOUT_MS);
|
|
1896
2044
|
ready.then(() => clearTimeout(timer));
|
|
@@ -1913,7 +2061,7 @@ class LarkCliInstance {
|
|
|
1913
2061
|
try {
|
|
1914
2062
|
child.kill("SIGTERM");
|
|
1915
2063
|
} catch (error) {
|
|
1916
|
-
|
|
2064
|
+
logger4.warn(`[LarkCliInstance] Error sending SIGTERM to ${child.pid}: ${error}`);
|
|
1917
2065
|
}
|
|
1918
2066
|
}
|
|
1919
2067
|
const allExited = Promise.all(children.map((child) => new Promise((resolve) => {
|
|
@@ -1968,12 +2116,12 @@ class LarkCliInstance {
|
|
|
1968
2116
|
}
|
|
1969
2117
|
wireCardActionPorts() {
|
|
1970
2118
|
if (this.cardActionPorts) {
|
|
1971
|
-
|
|
2119
|
+
logger4.debug("[LarkCliInstance] cardActionPorts 已由外部注入,跳过默认 cross-wire");
|
|
1972
2120
|
return;
|
|
1973
2121
|
}
|
|
1974
2122
|
const taskComponent = this.environment?.getComponent?.("task");
|
|
1975
2123
|
if (!taskComponent?.getTask || !taskComponent?.updateTask) {
|
|
1976
|
-
|
|
2124
|
+
logger4.debug(`[LarkCliInstance] card.action.trigger 端口未注入:taskComponent 不可用` + `(getTask=${typeof taskComponent?.getTask}, updateTask=${typeof taskComponent?.updateTask})。` + `卡片按钮点击会被跳过。`);
|
|
1977
2125
|
return;
|
|
1978
2126
|
}
|
|
1979
2127
|
const sharedNotifier = this.pluginInstances.get("LarkCliTaskNotifyPlugin")?.cardNotifier ?? this.pluginInstances.get("PerTaskGroupChatPlugin")?.cardNotifier;
|
|
@@ -2002,7 +2150,7 @@ class LarkCliInstance {
|
|
|
2002
2150
|
deleteGroupChat: (chatId, profile) => deleteGroupChatViaLarkCli(chatId, profile),
|
|
2003
2151
|
notifier: sharedNotifier ?? new LarkCardPatchNotifier
|
|
2004
2152
|
});
|
|
2005
|
-
|
|
2153
|
+
logger4.info(`[LarkCliInstance] card.action.trigger 端口已注入` + `(notifier ${sharedNotifier ? "复用插件共享实例" : "新建实例"})`);
|
|
2006
2154
|
}
|
|
2007
2155
|
getPluginHookPoints(plugin) {
|
|
2008
2156
|
if (Array.isArray(plugin.hooks)) {
|
|
@@ -2200,7 +2348,7 @@ class LarkCliInstance {
|
|
|
2200
2348
|
}
|
|
2201
2349
|
return null;
|
|
2202
2350
|
} catch (err) {
|
|
2203
|
-
|
|
2351
|
+
logger4.warn(`[LarkCliInstance] resolveChatTaskBinding failed for chatId=${chatId}: ${err}. ` + `群消息将不会注入 parentTaskId。`);
|
|
2204
2352
|
return null;
|
|
2205
2353
|
}
|
|
2206
2354
|
}
|
|
@@ -2222,7 +2370,7 @@ class LarkCliInstance {
|
|
|
2222
2370
|
processStreamWith(data, buffer, opts = {}) {
|
|
2223
2371
|
buffer.value += data;
|
|
2224
2372
|
if (buffer.value.length > 2 * 1024 * 1024) {
|
|
2225
|
-
|
|
2373
|
+
logger4.warn(`[LarkCliInstance] stream 行缓冲超过 2MB 仍无换行,丢弃(疑似非 NDJSON 输出)`);
|
|
2226
2374
|
buffer.value = "";
|
|
2227
2375
|
return;
|
|
2228
2376
|
}
|
|
@@ -2258,12 +2406,12 @@ class LarkCliInstance {
|
|
|
2258
2406
|
const now = Date.now();
|
|
2259
2407
|
const lastShared = LarkCliInstance.SHARED_SEEN.get(dedupKey);
|
|
2260
2408
|
if (lastShared !== undefined && now - lastShared < LarkCliInstance.SHARED_MSG_TTL_MS) {
|
|
2261
|
-
|
|
2409
|
+
logger4.warn(`[LarkCliInstance] duplicate lark-cli event suppressed across instances (event_id=${dedupKey}, ` + `lastSeen=${now - lastShared}ms ago). ` + `Task #4137: SHARED_SEEN 跨实例去重。`);
|
|
2262
2410
|
return;
|
|
2263
2411
|
}
|
|
2264
2412
|
const last = this.recentEventIds.get(dedupKey);
|
|
2265
2413
|
if (last !== undefined && now - last < this.DEDUP_WINDOW_MS) {
|
|
2266
|
-
|
|
2414
|
+
logger4.warn(`[LarkCliInstance] duplicate lark-cli event suppressed (event_id=${dedupKey}, ` + `lastSeen=${now - last}ms ago). ` + `Task #3977/3978: 防止同一飞书事件触发两次任务创建。`);
|
|
2267
2415
|
return;
|
|
2268
2416
|
}
|
|
2269
2417
|
LarkCliInstance.SHARED_SEEN.set(dedupKey, now);
|
|
@@ -2443,11 +2591,11 @@ class LarkCliInstance {
|
|
|
2443
2591
|
const chatId = event.chat_id || "";
|
|
2444
2592
|
const operatorId = event.operator_id?.open_id ?? event.operator_id ?? undefined;
|
|
2445
2593
|
if (!token || !messageId || !chatId) {
|
|
2446
|
-
|
|
2594
|
+
logger4.warn(`[LarkCliInstance] handleCardActionEvent: missing token/messageId/chatId, skip`);
|
|
2447
2595
|
return;
|
|
2448
2596
|
}
|
|
2449
2597
|
if (!this.cardActionPorts) {
|
|
2450
|
-
|
|
2598
|
+
logger4.warn(`[LarkCliInstance] handleCardActionEvent: cardActionPorts 未注入,` + `card.action.trigger 事件被跳过。` + `调 instance.setCardActionPorts({getTask, updateTaskContext, createGroupChat, deleteGroupChat, notifier}) 注入。`);
|
|
2451
2599
|
return;
|
|
2452
2600
|
}
|
|
2453
2601
|
const result = await handleCardAction({
|
|
@@ -2462,10 +2610,10 @@ class LarkCliInstance {
|
|
|
2462
2610
|
const patch = this.cardActionPorts.patchByToken ?? patchCardByLarkCli;
|
|
2463
2611
|
await patch(token, result.cardUpdate, profile);
|
|
2464
2612
|
} else {
|
|
2465
|
-
|
|
2613
|
+
logger4.warn(`[LarkCliInstance] handleCardActionEvent failed: ${result.error ?? "unknown"}`);
|
|
2466
2614
|
}
|
|
2467
2615
|
} catch (err) {
|
|
2468
|
-
|
|
2616
|
+
logger4.error(`[LarkCliInstance] handleCardActionEvent error: ${err.message}`);
|
|
2469
2617
|
}
|
|
2470
2618
|
}
|
|
2471
2619
|
async patchCardByToken(token, card, profile) {
|
|
@@ -2600,7 +2748,7 @@ var NOTIFY_TERMINAL_TYPES = new Set([
|
|
|
2600
2748
|
"task.background.timeout",
|
|
2601
2749
|
"task.background.stopped"
|
|
2602
2750
|
]);
|
|
2603
|
-
function
|
|
2751
|
+
function describeNotifyEvent2(type, taskId, desc) {
|
|
2604
2752
|
const actionable = NOTIFY_TERMINAL_TYPES.has(type);
|
|
2605
2753
|
switch (type) {
|
|
2606
2754
|
case "task.background.completed":
|
|
@@ -2621,6 +2769,24 @@ function describeNotifyEvent(type, taskId, desc) {
|
|
|
2621
2769
|
return { headline: `Sub-agent 更新了 Task #${taskId}「${desc}」。`, actionable };
|
|
2622
2770
|
}
|
|
2623
2771
|
}
|
|
2772
|
+
function renderRuleNoticeSection(ruleNotice, headline) {
|
|
2773
|
+
if (!ruleNotice || !ruleNotice.attempted) {
|
|
2774
|
+
return `(本事件不直发规则回执)
|
|
2775
|
+
` + `→ 你的回复要把结果讲**完整**(用户只能从你这条消息知道结论)。`;
|
|
2776
|
+
}
|
|
2777
|
+
if (ruleNotice.delivered) {
|
|
2778
|
+
const when = ruleNotice.sentAt ? new Date(ruleNotice.sentAt).toLocaleTimeString("zh-CN", {
|
|
2779
|
+
hour12: false,
|
|
2780
|
+
hour: "2-digit",
|
|
2781
|
+
minute: "2-digit"
|
|
2782
|
+
}) : "";
|
|
2783
|
+
const sent = ruleNotice.text ? `:「${ruleNotice.text.replace(/\s*\n+\s*/g, " ")}」` : "";
|
|
2784
|
+
return `✅ 系统已于 ${when || "刚才"} 把下面这条发到群里${sent}
|
|
2785
|
+
` + `→ 你的回复**只发增量**:不要再重复「任务已结束」这类回执原文,` + `直接讲结论/交付 + 下一步选项。`;
|
|
2786
|
+
}
|
|
2787
|
+
return `❌ **回执未送达**(原因:${ruleNotice.error ?? "unknown"})
|
|
2788
|
+
` + `→ 用户目前**还不知道**「${headline}」这件事,必须由你在回复里讲清楚,` + `并且不要假装系统已经通知过。`;
|
|
2789
|
+
}
|
|
2624
2790
|
var larkCliHandler = {
|
|
2625
2791
|
type: "lark-cli",
|
|
2626
2792
|
validateConfig(config) {
|
|
@@ -2632,7 +2798,7 @@ var larkCliHandler = {
|
|
|
2632
2798
|
},
|
|
2633
2799
|
async emitTriggerEvent(payload, store) {
|
|
2634
2800
|
const eventId = await store.insertTriggerEvent(payload, "lark-cli");
|
|
2635
|
-
|
|
2801
|
+
logger4.info(`[larkCliHandler] emitTriggerEvent: id=${eventId}`, {
|
|
2636
2802
|
chatId: payload.metadata?.chatId,
|
|
2637
2803
|
senderId: payload.senderId
|
|
2638
2804
|
});
|
|
@@ -2647,7 +2813,7 @@ var larkCliHandler = {
|
|
|
2647
2813
|
try {
|
|
2648
2814
|
const result = await runner.run(command);
|
|
2649
2815
|
if (result.code !== 0) {
|
|
2650
|
-
|
|
2816
|
+
logger4.error(`[larkCliHandler] replyMessage non-zero exit`, {
|
|
2651
2817
|
code: result.code,
|
|
2652
2818
|
stderr: result.stderr
|
|
2653
2819
|
});
|
|
@@ -2661,7 +2827,7 @@ var larkCliHandler = {
|
|
|
2661
2827
|
return { success: true, messageId: replyMessageId };
|
|
2662
2828
|
} catch (err) {
|
|
2663
2829
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
2664
|
-
|
|
2830
|
+
logger4.error(`[larkCliHandler] replyMessage spawn error`, { error: errMsg });
|
|
2665
2831
|
return { success: false, error: errMsg };
|
|
2666
2832
|
}
|
|
2667
2833
|
},
|
|
@@ -2683,47 +2849,67 @@ var larkCliHandler = {
|
|
|
2683
2849
|
senderOpenId: input.triggerEvent.metadata?.senderId ?? input.triggerEvent.senderId,
|
|
2684
2850
|
profile: input.profile
|
|
2685
2851
|
};
|
|
2686
|
-
const
|
|
2852
|
+
const esType = input.channel?.esType ?? ctx.esType ?? "lark-cli";
|
|
2853
|
+
const chatId = input.channel?.chatId || ctx.chatId;
|
|
2854
|
+
const messageId = input.channel?.messageId || ctx.messageId;
|
|
2855
|
+
const senderId = input.channel?.senderId || ctx.senderOpenId;
|
|
2856
|
+
const chatType = input.channel?.chatType ?? "unknown";
|
|
2857
|
+
const profile = input.channel?.profile ?? ctx.profile;
|
|
2858
|
+
const profileFlag = profile ? `--profile ${profile} ` : "";
|
|
2687
2859
|
const desc = input.notifyEvent.description ?? "(未命名任务)";
|
|
2688
2860
|
const result = input.subAgentResult.summary ?? input.notifyEvent.result ?? "";
|
|
2689
2861
|
const notifyType = input.notifyEvent.type;
|
|
2690
2862
|
const taskId = input.notifyEvent.taskId ?? "?";
|
|
2691
|
-
const { headline, actionable } =
|
|
2863
|
+
const { headline, actionable } = describeNotifyEvent2(notifyType, taskId, desc);
|
|
2864
|
+
const chatTypeLabel = chatType === "group" ? "群聊" : chatType === "p2p" ? "私聊" : "会话类型未知";
|
|
2865
|
+
const canReply = Boolean(chatId);
|
|
2866
|
+
const receiptSection = renderRuleNoticeSection(input.ruleNotice, headline);
|
|
2867
|
+
const replyCommand = messageId ? `lark-cli ${profileFlag}im +messages-reply --message-id ${messageId} --chat-id ${chatId} --as bot --markdown '<你的回复>'` : `lark-cli ${profileFlag}im +messages-send --chat-id ${chatId} --as bot --markdown '<你的回复>'`;
|
|
2868
|
+
const scopeWord = chatType === "group" ? "群聊" : chatType === "p2p" ? "私聊" : "会话";
|
|
2692
2869
|
const promptText = actionable ? `
|
|
2693
2870
|
## Notify Event: ${notifyType}
|
|
2694
2871
|
|
|
2695
2872
|
${headline}
|
|
2696
2873
|
|
|
2697
|
-
###
|
|
2698
|
-
- ES:
|
|
2699
|
-
- **chatId: ${
|
|
2700
|
-
- **messageId: ${
|
|
2701
|
-
- sender: ${
|
|
2702
|
-
${
|
|
2874
|
+
### 触发渠道(EventSource)
|
|
2875
|
+
- ES: ${esType}(飞书,${chatTypeLabel})
|
|
2876
|
+
- **chatId: ${chatId || "(缺失)"}** ← 关键!必须发到这里
|
|
2877
|
+
- **messageId: ${messageId || "(缺失)"}** ← ${messageId ? "reply 这条,保持话题线索" : "无触发消息,用 +messages-send"}
|
|
2878
|
+
- sender: ${senderId || "(未知)"}
|
|
2879
|
+
${input.notifyEvent.subSessionId ? `- 子 session: ${input.notifyEvent.subSessionId} ← 如需续跑:delegate_task(existingSubSessionId=<此值>, prompt=<新要求>)
|
|
2880
|
+
` : ""}${profile ? `- profile: ${profile} ← 调用 lark-cli 必须带 --profile
|
|
2703
2881
|
` : ""}
|
|
2882
|
+
### 系统回执(rule-based 直发)
|
|
2883
|
+
${receiptSection}
|
|
2884
|
+
|
|
2704
2885
|
### Sub-agent 输出
|
|
2705
2886
|
${result}
|
|
2706
2887
|
|
|
2707
|
-
### \uD83D\uDC49
|
|
2708
|
-
用
|
|
2709
|
-
|
|
2888
|
+
### \uD83D\uDC49 你要做什么
|
|
2889
|
+
1. 用 2~5 行总结:这次完成了什么 / 卡在哪(依据上面的输出与子 session)
|
|
2890
|
+
2. 给出 1~3 个下一步选项(继续推进 / 拆小 / 放弃),并**问用户选哪个**
|
|
2891
|
+
3. 用 lark-cli 把回复发到上面的${scopeWord}(见下)
|
|
2892
|
+
|
|
2893
|
+
### 发送方式(渠道 = lark-cli)
|
|
2894
|
+
${canReply ? ` ${replyCommand}` : `⚠️ 没有可用的 chatId —— 无法投递到触发会话。请在会话内汇报,并说明「未投递」的原因。`}
|
|
2710
2895
|
|
|
2711
2896
|
⚠️ 不要 fallback 到 lastReplyChannel 或 metadata.replyChannel — 那个 chatId
|
|
2712
2897
|
可能跟用户原始消息的 chatId 不一致(参见 #4035/#4038/#4039 bug)。
|
|
2898
|
+
⚠️ 必须 --as bot(否则会被自己的 lark-cli consumer 当用户消息回灌);不要用 user 身份。
|
|
2713
2899
|
` : `
|
|
2714
2900
|
## Notify Event: ${notifyType}
|
|
2715
2901
|
|
|
2716
2902
|
${headline}
|
|
2717
2903
|
|
|
2718
|
-
###
|
|
2719
|
-
- ES:
|
|
2720
|
-
- chatId: ${
|
|
2721
|
-
- messageId: ${
|
|
2904
|
+
### 触发渠道(EventSource)
|
|
2905
|
+
- ES: ${esType}(${chatTypeLabel})
|
|
2906
|
+
- chatId: ${chatId || "(缺失)"}
|
|
2907
|
+
- messageId: ${messageId || "(缺失)"}
|
|
2722
2908
|
|
|
2723
2909
|
(这是中间态通知:仅作状态同步,**不要**回复用户,也不要调用 lark-cli 发消息。
|
|
2724
2910
|
等收到 task.background.completed / failed / timeout / stopped 终态通知后再回复。)
|
|
2725
2911
|
`;
|
|
2726
|
-
const systemHint = actionable ? `回复必须用 lark-cli im +messages-reply(${profileFlag.trim() ? `带 ${profileFlag.trim()};` : ""}` + `chatId=${
|
|
2912
|
+
const systemHint = actionable ? `回复必须用 lark-cli im +messages-reply(${profileFlag.trim() ? `带 ${profileFlag.trim()};` : ""}` + `chatId=${chatId} / messageId=${messageId} 来自 trigger event(esType=${esType}),不要 fallback。` + (input.ruleNotice?.delivered ? "系统回执已送达,只发增量。" : "") : `这是 ${notifyType} 中间态通知,不要回复用户;仅等待终态通知。`;
|
|
2727
2913
|
return { promptText, systemHint };
|
|
2728
2914
|
},
|
|
2729
2915
|
setRunner(runner) {
|
|
@@ -2748,16 +2934,17 @@ async function patchCardByLarkCli(token, card, profile) {
|
|
|
2748
2934
|
const cmd = `lark-cli ${profileFlag}api POST /open-apis/interactive/v1/card/update ` + `--data '${JSON.stringify({ token, card }).replace(/'/g, "'\\''")}' --as bot`;
|
|
2749
2935
|
try {
|
|
2750
2936
|
const { stdout } = await execAsync2(cmd, { timeout: 30000 });
|
|
2751
|
-
|
|
2937
|
+
logger4.debug(`patchCardByLarkCli ok: ${stdout?.slice(0, 200)}`);
|
|
2752
2938
|
} catch (err) {
|
|
2753
|
-
|
|
2939
|
+
logger4.error(`patchCardByLarkCli failed: ${err.message}`);
|
|
2754
2940
|
}
|
|
2755
2941
|
}
|
|
2756
2942
|
var builtInHandlers = [
|
|
2757
2943
|
larkCliHandler,
|
|
2758
2944
|
timerHandler,
|
|
2759
2945
|
bountyIMHandler,
|
|
2760
|
-
bountyCliHandler
|
|
2946
|
+
bountyCliHandler,
|
|
2947
|
+
cliCommandHandler
|
|
2761
2948
|
];
|
|
2762
2949
|
function getBuiltInHandler(type) {
|
|
2763
2950
|
return builtInHandlers.find((h) => h.type === type);
|
|
@@ -2787,7 +2974,7 @@ var EVENT_SOURCE_CONFIG_REGISTRATION = {
|
|
|
2787
2974
|
};
|
|
2788
2975
|
|
|
2789
2976
|
// src/env/event-source/event-source-component.ts
|
|
2790
|
-
var
|
|
2977
|
+
var logger5 = createLogger("event-source");
|
|
2791
2978
|
|
|
2792
2979
|
class EventSourceComponent extends BaseComponent {
|
|
2793
2980
|
name = "event-source";
|
|
@@ -2854,25 +3041,25 @@ class EventSourceComponent extends BaseComponent {
|
|
|
2854
3041
|
for (const handler of builtInHandlers) {
|
|
2855
3042
|
if (!this.handlers.has(handler.type)) {
|
|
2856
3043
|
this.handlers.set(handler.type, handler);
|
|
2857
|
-
|
|
3044
|
+
logger5.debug(`Registered built-in handler: ${handler.type}`);
|
|
2858
3045
|
}
|
|
2859
3046
|
}
|
|
2860
3047
|
}
|
|
2861
3048
|
async executeInitHooks() {
|
|
2862
|
-
const { EventSourceInitHooks } = await import("./roy-agent-core-
|
|
3049
|
+
const { EventSourceInitHooks } = await import("./roy-agent-core-99nwgj84.js");
|
|
2863
3050
|
await EventSourceInitHooks.execute(this);
|
|
2864
3051
|
}
|
|
2865
3052
|
registerHandler(handler) {
|
|
2866
3053
|
if (this.handlers.has(handler.type)) {
|
|
2867
|
-
|
|
3054
|
+
logger5.warn(`Handler already registered for type: ${handler.type}, overwriting`);
|
|
2868
3055
|
}
|
|
2869
3056
|
this.handlers.set(handler.type, handler);
|
|
2870
|
-
|
|
3057
|
+
logger5.debug(`Handler registered: ${handler.type}`);
|
|
2871
3058
|
}
|
|
2872
3059
|
unregisterHandler(type) {
|
|
2873
3060
|
const deleted = this.handlers.delete(type);
|
|
2874
3061
|
if (deleted) {
|
|
2875
|
-
|
|
3062
|
+
logger5.debug(`Handler unregistered: ${type}`);
|
|
2876
3063
|
}
|
|
2877
3064
|
return deleted;
|
|
2878
3065
|
}
|
|
@@ -2962,7 +3149,7 @@ class EventSourceComponent extends BaseComponent {
|
|
|
2962
3149
|
});
|
|
2963
3150
|
}
|
|
2964
3151
|
onConfigChange(event) {
|
|
2965
|
-
|
|
3152
|
+
logger5.info(`EventSource config changed: ${event.key}`, {
|
|
2966
3153
|
oldValue: event.oldValue,
|
|
2967
3154
|
newValue: event.newValue
|
|
2968
3155
|
});
|
|
@@ -2981,9 +3168,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
2981
3168
|
}
|
|
2982
3169
|
this.sources.set(config.id, config);
|
|
2983
3170
|
this.statuses.set(config.id, "created");
|
|
2984
|
-
|
|
3171
|
+
logger5.debug(`EventSource registered: ${config.id} (${config.type})`);
|
|
2985
3172
|
this.saveConfig().catch((err) => {
|
|
2986
|
-
|
|
3173
|
+
logger5.error(`Failed to save config after registering ${config.id}:`, err);
|
|
2987
3174
|
});
|
|
2988
3175
|
}
|
|
2989
3176
|
unregister(id) {
|
|
@@ -2998,9 +3185,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
2998
3185
|
this.eventHandlers.delete(id);
|
|
2999
3186
|
this.buffers.delete(id);
|
|
3000
3187
|
if (existed) {
|
|
3001
|
-
|
|
3188
|
+
logger5.debug(`EventSource unregistered: ${id}`);
|
|
3002
3189
|
this.saveConfig().catch((err) => {
|
|
3003
|
-
|
|
3190
|
+
logger5.error(`Failed to save config after unregistering ${id}:`, err);
|
|
3004
3191
|
});
|
|
3005
3192
|
}
|
|
3006
3193
|
return existed;
|
|
@@ -3038,13 +3225,13 @@ class EventSourceComponent extends BaseComponent {
|
|
|
3038
3225
|
}
|
|
3039
3226
|
}
|
|
3040
3227
|
this.sources.set(id, updated);
|
|
3041
|
-
|
|
3228
|
+
logger5.info(`EventSource updated: ${id}`, {
|
|
3042
3229
|
fields: Object.keys(partial)
|
|
3043
3230
|
});
|
|
3044
3231
|
try {
|
|
3045
3232
|
await this.saveConfig();
|
|
3046
3233
|
} catch (err) {
|
|
3047
|
-
|
|
3234
|
+
logger5.error(`Failed to save config after updating ${id}:`, err);
|
|
3048
3235
|
throw err;
|
|
3049
3236
|
}
|
|
3050
3237
|
return {
|
|
@@ -3113,18 +3300,18 @@ class EventSourceComponent extends BaseComponent {
|
|
|
3113
3300
|
type: "event-source.started",
|
|
3114
3301
|
payload: { sourceId: id, sourceType: config.type }
|
|
3115
3302
|
});
|
|
3116
|
-
|
|
3303
|
+
logger5.info(`EventSource started: ${id} (${config.type})`);
|
|
3117
3304
|
} catch (error) {
|
|
3118
3305
|
this.statuses.set(id, "error");
|
|
3119
|
-
|
|
3306
|
+
logger5.error(`EventSource failed to start: ${id}`, error);
|
|
3120
3307
|
throw error;
|
|
3121
3308
|
}
|
|
3122
3309
|
}
|
|
3123
3310
|
async stopSource(id) {
|
|
3124
3311
|
const status = this.statuses.get(id);
|
|
3125
|
-
|
|
3312
|
+
logger5.info(`[EventSource ${id}] stopSource called, current status: ${status}`);
|
|
3126
3313
|
if (status === "stopped" || status === "created") {
|
|
3127
|
-
|
|
3314
|
+
logger5.info(`[EventSource ${id}] already stopped/created, skipping`);
|
|
3128
3315
|
return;
|
|
3129
3316
|
}
|
|
3130
3317
|
this.statuses.set(id, "stopping");
|
|
@@ -3140,10 +3327,10 @@ class EventSourceComponent extends BaseComponent {
|
|
|
3140
3327
|
type: "event-source.stopped",
|
|
3141
3328
|
payload: { sourceId: id, sourceType: config?.type }
|
|
3142
3329
|
});
|
|
3143
|
-
|
|
3330
|
+
logger5.info(`EventSource stopped: ${id}`);
|
|
3144
3331
|
} catch (error) {
|
|
3145
3332
|
this.statuses.set(id, "error");
|
|
3146
|
-
|
|
3333
|
+
logger5.error(`EventSource failed to stop: ${id}`, error);
|
|
3147
3334
|
throw error;
|
|
3148
3335
|
}
|
|
3149
3336
|
}
|
|
@@ -3168,9 +3355,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
3168
3355
|
sources: Array.from(this.sources.values())
|
|
3169
3356
|
};
|
|
3170
3357
|
writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
3171
|
-
|
|
3358
|
+
logger5.debug(`Saved ${this.sources.size} event source configurations`);
|
|
3172
3359
|
} catch (error) {
|
|
3173
|
-
|
|
3360
|
+
logger5.error("Failed to save event source configurations:", error);
|
|
3174
3361
|
throw error;
|
|
3175
3362
|
}
|
|
3176
3363
|
}
|
|
@@ -3180,13 +3367,13 @@ class EventSourceComponent extends BaseComponent {
|
|
|
3180
3367
|
try {
|
|
3181
3368
|
const configPath = this.getConfigFilePath();
|
|
3182
3369
|
if (!existsSync(configPath)) {
|
|
3183
|
-
|
|
3370
|
+
logger5.debug(`No event source config file found at ${configPath}`);
|
|
3184
3371
|
return;
|
|
3185
3372
|
}
|
|
3186
3373
|
const content = readFileSync(configPath, "utf-8");
|
|
3187
3374
|
const config = JSON.parse(content);
|
|
3188
3375
|
if (!config.sources || !Array.isArray(config.sources)) {
|
|
3189
|
-
|
|
3376
|
+
logger5.warn("Invalid event source config format, skipping load");
|
|
3190
3377
|
return;
|
|
3191
3378
|
}
|
|
3192
3379
|
let loadedCount = 0;
|
|
@@ -3197,9 +3384,9 @@ class EventSourceComponent extends BaseComponent {
|
|
|
3197
3384
|
loadedCount++;
|
|
3198
3385
|
}
|
|
3199
3386
|
}
|
|
3200
|
-
|
|
3387
|
+
logger5.info(`Loaded ${loadedCount} event source configurations`);
|
|
3201
3388
|
} catch (error) {
|
|
3202
|
-
|
|
3389
|
+
logger5.error("Failed to load event source configurations:", error);
|
|
3203
3390
|
}
|
|
3204
3391
|
}
|
|
3205
3392
|
}
|
|
@@ -3213,4 +3400,4 @@ __legacyDecorateClassTS([
|
|
|
3213
3400
|
TracedAs("event_source.stop", { recordParams: true, recordResult: false })
|
|
3214
3401
|
], EventSourceComponent.prototype, "stopSource", null);
|
|
3215
3402
|
|
|
3216
|
-
export { TimerInstance, timerHandler, buildDefaultBountyIMSystemPrompt, resolveBountyIMSystemPrompt, BountyIMInstance, bountyIMHandler, extractMetadata, larkCliHandler, builtInHandlers, getBuiltInHandler, EventSourceComponent };
|
|
3403
|
+
export { TimerInstance, timerHandler, buildDefaultBountyIMSystemPrompt, resolveBountyIMSystemPrompt, BountyIMInstance, bountyIMHandler, CLI_COMMAND_ES_TYPE, CLI_SESSION_CHAT_ID_PREFIX, buildCliReplyChannel, parseCliSessionChatId, cliCommandHandler, extractMetadata, larkCliHandler, builtInHandlers, getBuiltInHandler, EventSourceComponent };
|