@ai-setting/roy-agent-core 1.7.85 → 1.7.89

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.
Files changed (148) hide show
  1. package/dist/config/index.js +7 -7
  2. package/dist/env/agent/agent-component.d.ts +1 -1
  3. package/dist/env/agent/agent-component.js +13 -12
  4. package/dist/env/agent/index.js +13 -12
  5. package/dist/env/agent/types.d.ts +14 -0
  6. package/dist/env/commands/index.js +7 -7
  7. package/dist/env/context/index.js +3 -3
  8. package/dist/env/debug/index.js +7 -7
  9. package/dist/env/error-reply.js +1 -1
  10. package/dist/env/event-source/event-source-handlers.d.ts +18 -2
  11. package/dist/env/event-source/event-source-handlers.js +26 -21
  12. package/dist/env/event-source/event-store.js +2 -2
  13. package/dist/env/event-source/index.js +25 -22
  14. package/dist/env/event-source/timer-handler.d.ts +98 -0
  15. package/dist/env/event-source/types.d.ts +53 -1
  16. package/dist/env/event-source/wecom-card-action-handler.d.ts +235 -3
  17. package/dist/env/event-source/wecom-card-builder.d.ts +207 -1
  18. package/dist/env/event-source/wecom-cli-handler.d.ts +25 -0
  19. package/dist/{shared/@ai-setting/roy-agent-core-vyr6svt6.js → env/event-source/wecom-respond-registry.js} +8 -6
  20. package/dist/env/event-source/wecom-session-card-sender.d.ts +135 -0
  21. package/dist/env/event-source/wecom-session-card-sender.js +153 -0
  22. package/dist/env/hook/index.js +5 -5
  23. package/dist/env/index.js +50 -45
  24. package/dist/env/llm/index.js +9 -8
  25. package/dist/env/log-trace/index.js +7 -7
  26. package/dist/env/log-trace/trace-filters.d.ts +6 -1
  27. package/dist/env/mcp/index.js +7 -7
  28. package/dist/env/memory/index.js +7 -7
  29. package/dist/env/plugin/index.js +7 -7
  30. package/dist/env/prompt/index.js +8 -8
  31. package/dist/env/prompt/prompts-index.d.ts +1 -1
  32. package/dist/env/session/group-session-link.d.ts +99 -0
  33. package/dist/env/session/index.js +11 -10
  34. package/dist/env/session/session-component.d.ts +89 -0
  35. package/dist/env/session/storage/index.js +5 -4
  36. package/dist/env/session/types.d.ts +10 -0
  37. package/dist/env/skill/index.js +7 -7
  38. package/dist/env/task/backend/index.d.ts +3 -0
  39. package/dist/env/task/backend/index.js +151 -3
  40. package/dist/env/task/backend/remote-task-port.d.ts +85 -0
  41. package/dist/env/task/backend/types.d.ts +5 -0
  42. package/dist/env/task/delegate/delegate-channel-hint.d.ts +39 -0
  43. package/dist/env/task/delegate/delegate-tool.d.ts +71 -6
  44. package/dist/env/task/delegate/delegate-tool.js +11 -9
  45. package/dist/env/task/delegate/index.js +8 -8
  46. package/dist/env/task/index.d.ts +1 -1
  47. package/dist/env/task/index.js +34 -18
  48. package/dist/env/task/mcp/index.js +4 -4
  49. package/dist/env/task/plugins/card-subject.d.ts +117 -0
  50. package/dist/env/task/plugins/index.js +19 -17
  51. package/dist/env/task/plugins/lark-card-action-handler.d.ts +261 -6
  52. package/dist/env/task/plugins/lark-card-patch-notifier.d.ts +501 -0
  53. package/dist/env/task/plugins/lark-card-patch-notifier.js +12 -2
  54. package/dist/env/task/plugins/lark-card-state-store.d.ts +60 -0
  55. package/dist/env/task/plugins/lark-cli-task-notify-plugin.d.ts +45 -0
  56. package/dist/env/task/plugins/sub-session-activity.d.ts +415 -0
  57. package/dist/env/task/plugins/wecom-session-card-store.d.ts +134 -0
  58. package/dist/env/task/plugins/wecom-session-card-store.js +23 -0
  59. package/dist/env/task/plugins/wecom-task-notify-plugin.d.ts +40 -0
  60. package/dist/env/task/storage/index.d.ts +1 -0
  61. package/dist/env/task/storage/index.js +24 -4
  62. package/dist/env/task/storage/migrations/006_add_task_owner.d.ts +24 -0
  63. package/dist/env/task/storage/remote-task-store.d.ts +186 -0
  64. package/dist/env/task/task-component.d.ts +7 -0
  65. package/dist/env/task/tools/index.js +4 -4
  66. package/dist/env/task/tools/task-types.d.ts +7 -0
  67. package/dist/env/task/types.d.ts +17 -0
  68. package/dist/env/tool/built-in/index.js +6 -4
  69. package/dist/env/tool/index.js +14 -10
  70. package/dist/env/tool/types.d.ts +25 -0
  71. package/dist/env/tool/validator.d.ts +8 -0
  72. package/dist/env/workflow/engine/index.js +12 -12
  73. package/dist/env/workflow/hooks/index.js +7 -7
  74. package/dist/env/workflow/index.js +24 -23
  75. package/dist/env/workflow/nodes/index.js +2 -2
  76. package/dist/env/workflow/plugins/index.js +10 -8
  77. package/dist/env/workflow/service/index.js +2 -2
  78. package/dist/env/workflow/storage/index.js +3 -3
  79. package/dist/env/workflow/tools/index.js +16 -15
  80. package/dist/env/workflow/utils/index.js +4 -4
  81. package/dist/index.d.ts +1 -1
  82. package/dist/index.js +71 -60
  83. package/dist/shared/@ai-setting/{roy-agent-core-q813vafd.js → roy-agent-core-05z35shp.js} +1 -1
  84. package/dist/shared/@ai-setting/{roy-agent-core-dc9zq75z.js → roy-agent-core-0crmsc12.js} +3 -3
  85. package/dist/shared/@ai-setting/{roy-agent-core-7dd0s3xb.js → roy-agent-core-0n1wwndq.js} +1027 -14
  86. package/dist/shared/@ai-setting/{roy-agent-core-cha0jc7n.js → roy-agent-core-0sbmdz8d.js} +137 -16
  87. package/dist/shared/@ai-setting/{roy-agent-core-87942bw4.js → roy-agent-core-1mhyh4c5.js} +1 -1
  88. package/dist/shared/@ai-setting/{roy-agent-core-v6vr6za7.js → roy-agent-core-1vv4fx15.js} +4 -4
  89. package/dist/shared/@ai-setting/{roy-agent-core-nwbfepba.js → roy-agent-core-3e040tc5.js} +1 -1
  90. package/dist/shared/@ai-setting/roy-agent-core-418zc9ha.js +288 -0
  91. package/dist/shared/@ai-setting/{roy-agent-core-qk9hd89p.js → roy-agent-core-49qcpqwg.js} +54 -19
  92. package/dist/shared/@ai-setting/{roy-agent-core-xf6z96qy.js → roy-agent-core-4b38m749.js} +818 -346
  93. package/dist/shared/@ai-setting/{roy-agent-core-r5wt1h3c.js → roy-agent-core-4fkxy2gv.js} +1 -1
  94. package/dist/shared/@ai-setting/{roy-agent-core-na18zwj0.js → roy-agent-core-4t3yskp8.js} +1 -1
  95. package/dist/shared/@ai-setting/{roy-agent-core-d1n4jbza.js → roy-agent-core-5dhvfgaw.js} +5 -5
  96. package/dist/shared/@ai-setting/{roy-agent-core-5pr4zp88.js → roy-agent-core-5kzhaap1.js} +1 -1
  97. package/dist/shared/@ai-setting/{roy-agent-core-qq96p0tj.js → roy-agent-core-5s2t8z00.js} +22 -1
  98. package/dist/shared/@ai-setting/{roy-agent-core-6rh8k6ba.js → roy-agent-core-6gj1hc5z.js} +7 -7
  99. package/dist/shared/@ai-setting/{roy-agent-core-g8htfwxj.js → roy-agent-core-7f10p7m2.js} +1 -1
  100. package/dist/shared/@ai-setting/{roy-agent-core-h21gngxf.js → roy-agent-core-7yh5wps0.js} +1 -1
  101. package/dist/shared/@ai-setting/{roy-agent-core-efkjyh69.js → roy-agent-core-9710zwwz.js} +1 -1
  102. package/dist/shared/@ai-setting/{roy-agent-core-rykf7c04.js → roy-agent-core-9c565frx.js} +1 -1
  103. package/dist/shared/@ai-setting/{roy-agent-core-vffccgf6.js → roy-agent-core-9cen1jvg.js} +18 -7
  104. package/dist/shared/@ai-setting/{roy-agent-core-fghc2m8z.js → roy-agent-core-aa8kv18f.js} +34 -2
  105. package/dist/shared/@ai-setting/roy-agent-core-age3qseb.js +177 -0
  106. package/dist/shared/@ai-setting/{roy-agent-core-7bpj859q.js → roy-agent-core-azyz78ky.js} +7 -7
  107. package/dist/shared/@ai-setting/{roy-agent-core-264qexac.js → roy-agent-core-b7h39vrc.js} +4 -4
  108. package/dist/shared/@ai-setting/{roy-agent-core-dqxec05w.js → roy-agent-core-bjtc9d35.js} +2 -2
  109. package/dist/shared/@ai-setting/roy-agent-core-c4ec7k0p.js +426 -0
  110. package/dist/shared/@ai-setting/{roy-agent-core-ddyk1rc0.js → roy-agent-core-cre2y2ct.js} +160 -4
  111. package/dist/shared/@ai-setting/{roy-agent-core-tr3ep81v.js → roy-agent-core-d6zdbgtc.js} +1 -1
  112. package/dist/shared/@ai-setting/{roy-agent-core-0qyrk5k0.js → roy-agent-core-ds6qzmf8.js} +14 -5
  113. package/dist/shared/@ai-setting/{roy-agent-core-p6ks90tb.js → roy-agent-core-dvec4nn2.js} +6 -6
  114. package/dist/shared/@ai-setting/{roy-agent-core-cgtq6427.js → roy-agent-core-e08bvpaq.js} +1 -1
  115. package/dist/shared/@ai-setting/{roy-agent-core-12n08pg5.js → roy-agent-core-e69qxdyy.js} +1 -1
  116. package/dist/shared/@ai-setting/{roy-agent-core-xcp8vwax.js → roy-agent-core-fepm835e.js} +2 -2
  117. package/dist/shared/@ai-setting/{roy-agent-core-6j02sbee.js → roy-agent-core-fhg03v43.js} +1 -1
  118. package/dist/shared/@ai-setting/{roy-agent-core-dvtg4sn0.js → roy-agent-core-g8yr733d.js} +1 -1
  119. package/dist/shared/@ai-setting/{roy-agent-core-m3vjepzz.js → roy-agent-core-h1e1fm9b.js} +38 -202
  120. package/dist/shared/@ai-setting/{roy-agent-core-c2gbt68e.js → roy-agent-core-h83zdsrq.js} +2 -2
  121. package/dist/shared/@ai-setting/{roy-agent-core-tk98f92b.js → roy-agent-core-k3gcvybs.js} +2 -2
  122. package/dist/shared/@ai-setting/{roy-agent-core-b31v3qpv.js → roy-agent-core-k3h8t4q1.js} +992 -212
  123. package/dist/shared/@ai-setting/{roy-agent-core-pgvcf91v.js → roy-agent-core-m39v7qpx.js} +2 -2
  124. package/dist/shared/@ai-setting/{roy-agent-core-ezvpreqz.js → roy-agent-core-m66ysky0.js} +54 -6
  125. package/dist/shared/@ai-setting/{roy-agent-core-begm7ytz.js → roy-agent-core-m7d1t3db.js} +3 -3
  126. package/dist/shared/@ai-setting/{roy-agent-core-tm1mxttk.js → roy-agent-core-mf5p38yf.js} +2 -2
  127. package/dist/shared/@ai-setting/{roy-agent-core-83bewqx8.js → roy-agent-core-mvh0td7p.js} +2 -2
  128. package/dist/shared/@ai-setting/{roy-agent-core-ze5cqpf2.js → roy-agent-core-mx855td4.js} +17 -38
  129. package/dist/shared/@ai-setting/{roy-agent-core-0dh8npnz.js → roy-agent-core-n197medr.js} +13 -13
  130. package/dist/shared/@ai-setting/{roy-agent-core-cmprygrp.js → roy-agent-core-nqkfkpf4.js} +4 -4
  131. package/dist/shared/@ai-setting/{roy-agent-core-7cbpmk4q.js → roy-agent-core-p31ftgq9.js} +1 -1
  132. package/dist/shared/@ai-setting/{roy-agent-core-1v4g0d4x.js → roy-agent-core-rm7seqwb.js} +1 -1
  133. package/dist/shared/@ai-setting/{roy-agent-core-ax9e9szb.js → roy-agent-core-smf94h73.js} +1 -1
  134. package/dist/shared/@ai-setting/{roy-agent-core-acj8ag08.js → roy-agent-core-tjnabyvq.js} +1 -1
  135. package/dist/shared/@ai-setting/{roy-agent-core-qqaak24r.js → roy-agent-core-tkpp1ba0.js} +1 -1
  136. package/dist/shared/@ai-setting/{roy-agent-core-dkrvmjsh.js → roy-agent-core-tpm1dd1g.js} +23 -15
  137. package/dist/shared/@ai-setting/{roy-agent-core-ed233k5z.js → roy-agent-core-v1n0106v.js} +1 -1
  138. package/dist/shared/@ai-setting/{roy-agent-core-zxz5fkwj.js → roy-agent-core-v6yshv0z.js} +1 -1
  139. package/dist/shared/@ai-setting/{roy-agent-core-mcy5apay.js → roy-agent-core-vf9sp6s3.js} +1 -1
  140. package/dist/shared/@ai-setting/{roy-agent-core-xvt7kf7p.js → roy-agent-core-w9ryeg2p.js} +3 -3
  141. package/dist/shared/@ai-setting/{roy-agent-core-es203w7p.js → roy-agent-core-wqs6yypq.js} +1 -1
  142. package/dist/shared/@ai-setting/roy-agent-core-wxrkcb17.js +56 -0
  143. package/dist/shared/@ai-setting/{roy-agent-core-0snm5hc5.js → roy-agent-core-y6shd91r.js} +1 -1
  144. package/dist/shared/@ai-setting/{roy-agent-core-9vxh6f8h.js → roy-agent-core-y7fqtzk2.js} +7 -7
  145. package/dist/shared/@ai-setting/{roy-agent-core-cpcd24n2.js → roy-agent-core-yet36q5k.js} +2 -2
  146. package/dist/shared/@ai-setting/{roy-agent-core-3fh1f7s7.js → roy-agent-core-yfpnkc4z.js} +5 -5
  147. package/dist/shared/@ai-setting/roy-agent-core-zhwcje5a.js +352 -0
  148. package/package.json +9 -1
@@ -4,35 +4,35 @@ import {
4
4
  } from "./roy-agent-core-fttgm52a.js";
5
5
  import {
6
6
  getSharedEventStore
7
- } from "./roy-agent-core-na18zwj0.js";
7
+ } from "./roy-agent-core-4t3yskp8.js";
8
8
  import {
9
9
  builtInPrompts
10
- } from "./roy-agent-core-9vxh6f8h.js";
10
+ } from "./roy-agent-core-y7fqtzk2.js";
11
11
  import {
12
12
  TaskHookPoints
13
13
  } from "./roy-agent-core-1pg0fepg.js";
14
14
  import {
15
15
  DEFAULT_SUBAGENT_PROMPT
16
- } from "./roy-agent-core-ed233k5z.js";
16
+ } from "./roy-agent-core-v1n0106v.js";
17
17
  import {
18
18
  runWithBgTaskIdAsync
19
19
  } from "./roy-agent-core-c1v263jn.js";
20
20
  import {
21
21
  globalHookManager,
22
22
  init_global_hook_manager
23
- } from "./roy-agent-core-cpcd24n2.js";
23
+ } from "./roy-agent-core-yet36q5k.js";
24
24
  import {
25
25
  init_context
26
- } from "./roy-agent-core-qqaak24r.js";
26
+ } from "./roy-agent-core-tkpp1ba0.js";
27
27
  import {
28
28
  getCurrentTaskId,
29
29
  getEnvContext
30
- } from "./roy-agent-core-7cbpmk4q.js";
30
+ } from "./roy-agent-core-p31ftgq9.js";
31
31
  import {
32
32
  TracedAs,
33
33
  init_decorator,
34
34
  wrapFunction
35
- } from "./roy-agent-core-qq96p0tj.js";
35
+ } from "./roy-agent-core-5s2t8z00.js";
36
36
  import {
37
37
  createLogger,
38
38
  init_logger
@@ -47,6 +47,43 @@ init_decorator();
47
47
  init_context();
48
48
  import { z } from "zod";
49
49
 
50
+ // src/env/task/delegate/delegate-channel-hint.ts
51
+ var DELEGATE_CHANNEL_HINT_TITLE = "## 渠道交付提示(当前会话来自外部渠道)";
52
+ function buildDelegateChannelHint(channelType) {
53
+ if (!channelType)
54
+ return;
55
+ let channelBody;
56
+ if (channelType === "lark-cli" || channelType.startsWith("lark")) {
57
+ channelBody = [
58
+ `- 触发渠道是**飞书**。文档类产出(调研文档 / 报告 / PPT / doc 等)`,
59
+ ` 必须用**飞书云盘**存储:\`lark-cli docs +create --title <标题> --markdown @<本地md>\`,用完即弃。`,
60
+ `- 交付时只给**云盘链接**(https://my.feishu.cn/...),**不落本地路径**交付。`,
61
+ ` 本地路径只作中转(生成 md → 上传云盘 → 回复里贴云盘链接),不作为交付物。`
62
+ ].join(`
63
+ `);
64
+ } else if (channelType === "wecom-cli" || channelType.startsWith("wecom")) {
65
+ channelBody = [
66
+ `- 触发渠道是**企业微信**。文档类产出(调研文档 / docs / ppt 等)`,
67
+ ` 必须上传到**企微文档**,链接作为交付物:`,
68
+ ` - 在线文档:\`wecom-cli doc create --doc-name <标题> --doc-type doc --content-type text --file-path <本地md>\``,
69
+ ` - 微盘文件:\`wecom-cli disk files upload --file-path <本地文件>\`(默认传到我的空间)`,
70
+ `- 本地路径只作中转(生成 → 上传企微文档 → 回复里贴链接),**不落本地路径**交付。`
71
+ ].join(`
72
+ `);
73
+ }
74
+ if (!channelBody)
75
+ return;
76
+ return [
77
+ DELEGATE_CHANNEL_HINT_TITLE,
78
+ ``,
79
+ `通用措辞:当前会话来自外部渠道,交付类产出优先用该渠道的原生存储/展示方式,`,
80
+ `不要把本地文件路径当作交付物(渠道用户无法访问本机文件系统)。`,
81
+ ``,
82
+ channelBody
83
+ ].join(`
84
+ `);
85
+ }
86
+
50
87
  // src/env/task/delegate/subagent-resolver.ts
51
88
  function isKnownSubagentType(subagentType, registry) {
52
89
  if (getSubAgentSpec(subagentType)) {
@@ -743,7 +780,8 @@ var BackgroundTaskEventTypes = {
743
780
  FAILED: "task.background.failed",
744
781
  TIMEOUT: "task.background.timeout",
745
782
  STOPPED: "task.background.stopped",
746
- ASK_USER: "task.background.ask_user"
783
+ ASK_USER: "task.background.ask_user",
784
+ SESSION_STARTED: "task.background.session_started"
747
785
  };
748
786
  var builtInSubAgents = [
749
787
  {
@@ -825,6 +863,21 @@ var builtInSubAgents = [
825
863
  function getSubAgentSpec(id) {
826
864
  return builtInSubAgents.find((agent) => agent.id === id);
827
865
  }
866
+ function normalizeExtendTools(raw) {
867
+ if (!Array.isArray(raw))
868
+ return;
869
+ const out = [];
870
+ for (const v of raw) {
871
+ if (typeof v !== "string")
872
+ continue;
873
+ const trimmed = v.trim();
874
+ if (trimmed.length === 0)
875
+ continue;
876
+ if (!out.includes(trimmed))
877
+ out.push(trimmed);
878
+ }
879
+ return out.length > 0 ? out : undefined;
880
+ }
828
881
  function ensureSubAgentRegistered(agentComponent, subagentType, basePrompt, subAgent, deniedTools) {
829
882
  const registry = agentComponent.getRegistry?.();
830
883
  if (registry) {
@@ -858,7 +911,7 @@ var DelegateToolParameters = z.object({
858
911
  timeout: z.number().describe("Task timeout in milliseconds. Default: 1800000 (30 minutes). If set, task will be terminated after timeout.").optional(),
859
912
  reason: z.string().describe("Brief reason for calling this tool (max 30 chars, e.g., 'Delegate refactor task')").optional(),
860
913
  similar_task_ids: z.array(z.number()).max(3).describe("Similar task IDs (max 3) to reference for improving task execution. Search for similar tasks before calling this tool."),
861
- sub_session_id: z.string().describe("Existing sub-agent session ID to resume. " + "If provided, the sub-agent will continue from the previous conversation " + "context (used for retry on timeout/failure). " + "Leave empty for a new session.").optional(),
914
+ sub_session_id: z.string().describe("⚠️ 硬约束:同一任务链的续跑必须传此参数(从终态 notify 的「子 session:」行" + "或 delegate 返回的「\uD83D\uDD17 Sub-session:」行复制)。" + "仅当旧 session 上下文已确认不可救(compact_session 后仍超限 / 迭代上限且无可复用断点)时才留空;" + "留空等于丢弃全部上下文,从零开始。").optional(),
862
915
  triggerEventId: z.string().describe("EventStore trigger event ID (ESPlugin v2). Pass it when this delegate_task " + "is triggered by an external event source (e.g. Feishu message) so the " + "completion notification can reply to the original chat instead of a " + "fallback channel. Leave empty if not triggered by an event source.").optional()
863
916
  });
864
917
  function buildEntryAgentPrompt(options) {
@@ -1116,7 +1169,7 @@ class BackgroundTaskManager {
1116
1169
  return null;
1117
1170
  }
1118
1171
  async createTask(options) {
1119
- const { parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt } = options;
1172
+ const { parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt, extendTools } = options;
1120
1173
  const taskIdGen = `process_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
1121
1174
  const sessionComponent = this.getSessionComponent();
1122
1175
  if (!sessionComponent) {
@@ -1175,6 +1228,10 @@ class BackgroundTaskManager {
1175
1228
  if (profile) {
1176
1229
  metadata.larkProfile = profile;
1177
1230
  }
1231
+ const channelType = replyChannel?.type;
1232
+ if (channelType) {
1233
+ metadata.channelType = channelType;
1234
+ }
1178
1235
  }
1179
1236
  if (triggerEventId) {
1180
1237
  metadata.triggerEventId = triggerEventId;
@@ -1219,6 +1276,7 @@ class BackgroundTaskManager {
1219
1276
  fallbackModel,
1220
1277
  fallbackModels,
1221
1278
  systemPrompt,
1279
+ extendTools,
1222
1280
  replyChannel: replyChannelSnapshot,
1223
1281
  pluginEnabledSnapshot
1224
1282
  };
@@ -1234,6 +1292,16 @@ class BackgroundTaskManager {
1234
1292
  timeoutMs: timeout || DEFAULT_TIMEOUT
1235
1293
  };
1236
1294
  this.publishBackgroundEvent(BackgroundTaskEventTypes.STARTED, startedPayload, parentSessionId, triggerEventId, replyChannelSnapshot, task.pluginEnabledSnapshot);
1295
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
1296
+ backgroundTaskId: taskIdGen,
1297
+ subSessionId: subSession.id,
1298
+ parentSessionId,
1299
+ description,
1300
+ subagentType,
1301
+ associatedTaskId: undefined,
1302
+ lifecycle: "running",
1303
+ startedAt: createdAt
1304
+ }, parentSessionId, triggerEventId, replyChannelSnapshot, task.pluginEnabledSnapshot);
1237
1305
  this.executeTask(taskIdGen, prompt, timeout, parentSessionId).catch((err) => {
1238
1306
  logger3.error(`[BackgroundTaskManager] executeTask unhandled rejection`, {
1239
1307
  taskId: taskIdGen,
@@ -1277,6 +1345,16 @@ class BackgroundTaskManager {
1277
1345
  if (task.associatedTaskId === undefined) {
1278
1346
  task.associatedTaskId = getCurrentTaskId();
1279
1347
  }
1348
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
1349
+ backgroundTaskId: task.id,
1350
+ subSessionId: task.subSessionId,
1351
+ parentSessionId: parentSessionId || task.parentSessionId,
1352
+ description: task.description,
1353
+ subagentType: task.subagentType,
1354
+ associatedTaskId: task.associatedTaskId,
1355
+ lifecycle: "completed",
1356
+ executionTimeMs
1357
+ }, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
1280
1358
  const completedPayload = {
1281
1359
  backgroundTaskId: task.id,
1282
1360
  subSessionId: task.subSessionId,
@@ -1324,7 +1402,7 @@ class BackgroundTaskManager {
1324
1402
  executionTimeMs,
1325
1403
  hints: [
1326
1404
  "请把上面的问题原样通过 ask_user tool 展示给用户并等待答复",
1327
- `得到用户回复后,通过 delegate_task(subagentType="${task.subagentType}", existingSubSessionId="${task.subSessionId}", prompt=<基于用户回复>) 复用 sub-session 让 sub-agent 继承之前消息历史继续推进,无需实现 resume function`
1405
+ `得到用户回复后,通过 delegate_task(subagent_type="${task.subagentType}", sub_session_id="${task.subSessionId}", prompt=<基于用户回复>) 复用 sub-session 让 sub-agent 继承之前消息历史继续推进,无需实现 resume function`
1328
1406
  ],
1329
1407
  associatedTaskId: task.associatedTaskId
1330
1408
  };
@@ -1351,6 +1429,16 @@ class BackgroundTaskManager {
1351
1429
  associatedTaskId: task.associatedTaskId
1352
1430
  };
1353
1431
  this.publishBackgroundEvent(BackgroundTaskEventTypes.STOPPED, stoppedPayload, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
1432
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
1433
+ backgroundTaskId: task.id,
1434
+ subSessionId: task.subSessionId,
1435
+ parentSessionId: parentSessionId || task.parentSessionId,
1436
+ description: task.description,
1437
+ subagentType: task.subagentType,
1438
+ associatedTaskId: task.associatedTaskId,
1439
+ lifecycle: "stopped",
1440
+ executionTimeMs
1441
+ }, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
1354
1442
  } else if (errorMessage.startsWith("Task execution timeout after")) {
1355
1443
  task.status = "timeout";
1356
1444
  const timeoutPayload = {
@@ -1364,6 +1452,16 @@ class BackgroundTaskManager {
1364
1452
  associatedTaskId: task.associatedTaskId
1365
1453
  };
1366
1454
  this.publishBackgroundEvent(BackgroundTaskEventTypes.TIMEOUT, timeoutPayload, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
1455
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
1456
+ backgroundTaskId: task.id,
1457
+ subSessionId: task.subSessionId,
1458
+ parentSessionId: parentSessionId || task.parentSessionId,
1459
+ description: task.description,
1460
+ subagentType: task.subagentType,
1461
+ associatedTaskId: task.associatedTaskId,
1462
+ lifecycle: "timeout",
1463
+ executionTimeMs
1464
+ }, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
1367
1465
  } else {
1368
1466
  task.status = "failed";
1369
1467
  const failedPayload = {
@@ -1376,6 +1474,16 @@ class BackgroundTaskManager {
1376
1474
  associatedTaskId: task.associatedTaskId
1377
1475
  };
1378
1476
  this.publishBackgroundEvent(BackgroundTaskEventTypes.FAILED, failedPayload, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
1477
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.SESSION_STARTED, {
1478
+ backgroundTaskId: task.id,
1479
+ subSessionId: task.subSessionId,
1480
+ parentSessionId: parentSessionId || task.parentSessionId,
1481
+ description: task.description,
1482
+ subagentType: task.subagentType,
1483
+ associatedTaskId: task.associatedTaskId,
1484
+ lifecycle: "failed",
1485
+ executionTimeMs
1486
+ }, parentSessionId || task.parentSessionId, task.triggerEventId, task.replyChannel, task.pluginEnabledSnapshot);
1379
1487
  }
1380
1488
  task.error = errorMessage;
1381
1489
  logger3.error(`[BackgroundTaskManager] Task execution error`, {
@@ -1552,6 +1660,15 @@ ${reuseSection.markdown}`;
1552
1660
  error: err instanceof Error ? err.message : String(err)
1553
1661
  });
1554
1662
  }
1663
+ const channelTypeHint = metadata.channelType ?? getEnvContext()?.replyChannel?.type;
1664
+ const channelHint = buildDelegateChannelHint(channelTypeHint);
1665
+ if (channelHint) {
1666
+ fullPrompt += `
1667
+
1668
+ ---
1669
+
1670
+ ${channelHint}`;
1671
+ }
1555
1672
  const subAgentForRegister = subAgent ? { ...subAgent, allowedTools } : allowedTools ? {
1556
1673
  id: subagentType,
1557
1674
  name: subagentType,
@@ -1641,7 +1758,8 @@ ${reuseSection.markdown}`;
1641
1758
  ...inheritedModel ? { model: inheritedModel } : {},
1642
1759
  ...inheritedFallbackModel ? { fallbackModel: inheritedFallbackModel } : {},
1643
1760
  ...Array.isArray(inheritedFallbackModels) ? { fallbackModels: inheritedFallbackModels } : {},
1644
- ...task?.systemPrompt ? { metadata: { systemPrompt: task.systemPrompt } } : {}
1761
+ ...task?.systemPrompt ? { metadata: { systemPrompt: task.systemPrompt } } : {},
1762
+ ...task?.extendTools?.length ? { extendTools: task.extendTools } : {}
1645
1763
  });
1646
1764
  };
1647
1765
  const wrappedPromise = processRegistry ? runWithProcessRegistryAsync(processRegistry, () => runWithBgTaskIdAsync(bgTaskId, () => invokeHandleQuery())) : runWithBgTaskIdAsync(bgTaskId, () => invokeHandleQuery());
@@ -2057,7 +2175,7 @@ No need to poll — just wait for the notification and use \`task_get\` with the
2057
2175
  };
2058
2176
  await globalHookManager.execute(TaskHookPoints.DELEGATE_BEFORE, delegateCtx, { sessionId: parentSessionId });
2059
2177
  promptWithTaskInfo = delegateCtx.prompt;
2060
- return await handleBackgroundTask(backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, similar_task_ids, params.sub_session_id, resolvedTriggerEventId, ctx.model, ctx.fallbackModel, ctx.fallbackModels, ctx.metadata?.systemPrompt);
2178
+ return await handleBackgroundTask(backgroundTaskManager, parentSessionId, description, promptWithTaskInfo, delegateCtx.subagentType, delegateCtx.timeout, similar_task_ids, params.sub_session_id, resolvedTriggerEventId, ctx.model, ctx.fallbackModel, ctx.fallbackModels, ctx.metadata?.systemPrompt, normalizeExtendTools(ctx.metadata?.extendTools));
2061
2179
  }
2062
2180
  };
2063
2181
  tool.execute = wrapFunction(tool.execute, "delegate.execute", {
@@ -2113,7 +2231,7 @@ function _capturePluginEnabledSnapshot() {
2113
2231
  return { ...pluginEnabled };
2114
2232
  }
2115
2233
  var capturePluginEnabledSnapshot = wrapFunction(_capturePluginEnabledSnapshot, "delegate.capturePluginEnabled", { recordParams: false, recordResult: true, recordError: true });
2116
- async function handleBackgroundTask(backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt) {
2234
+ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, description, prompt, subagentType, timeout, similarTaskIds, existingSubSessionId, triggerEventId, model, fallbackModel, fallbackModels, systemPrompt, extendTools) {
2117
2235
  const startTime = Date.now();
2118
2236
  try {
2119
2237
  let actualSubagentType = subagentType;
@@ -2143,7 +2261,8 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
2143
2261
  model,
2144
2262
  fallbackModel,
2145
2263
  fallbackModels,
2146
- systemPrompt
2264
+ systemPrompt,
2265
+ extendTools
2147
2266
  });
2148
2267
  const output = [
2149
2268
  `✅ Background task accepted`,
@@ -2153,6 +2272,8 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
2153
2272
  `\uD83E\uDD16 Sub-agent: ${actualSubagentType}${originalWorkflowName ? ` (workflow: ${originalWorkflowName})` : ""}`,
2154
2273
  `⏱️ Timeout: ${(timeout || DEFAULT_TIMEOUT) / 1000}s`,
2155
2274
  "",
2275
+ `\uD83D\uDD17 Sub-session: ${subSessionId} (续跑本任务:delegate_task(sub_session_id="${subSessionId}", prompt="..."))`,
2276
+ "",
2156
2277
  `Use stop_task with task_id="${bgProcessId}" to cancel this task.`
2157
2278
  ].join(`
2158
2279
  `);
@@ -2176,4 +2297,4 @@ async function handleBackgroundTask(backgroundTaskManager, parentSessionId, desc
2176
2297
  };
2177
2298
  }
2178
2299
  }
2179
- export { BackgroundTaskEventTypes, builtInSubAgents, getSubAgentSpec, DelegateToolParameters, buildEntryAgentPrompt, WORKFLOW_COMPAT_ALIASES, DEFAULT_TIMEOUT, PROGRESS_INTERVAL, BackgroundTaskManager, createDelegateTool, deriveTriggerEventIdFromEnvContext, captureReplyChannelSnapshot, capturePluginEnabledSnapshot, handleBackgroundTask };
2300
+ export { BackgroundTaskEventTypes, builtInSubAgents, getSubAgentSpec, normalizeExtendTools, DelegateToolParameters, buildEntryAgentPrompt, WORKFLOW_COMPAT_ALIASES, DEFAULT_TIMEOUT, PROGRESS_INTERVAL, BackgroundTaskManager, createDelegateTool, deriveTriggerEventIdFromEnvContext, captureReplyChannelSnapshot, capturePluginEnabledSnapshot, handleBackgroundTask };
@@ -4,7 +4,7 @@ import {
4
4
  } from "./roy-agent-core-rvv6ydff.js";
5
5
  import {
6
6
  BaseComponent
7
- } from "./roy-agent-core-pgvcf91v.js";
7
+ } from "./roy-agent-core-m39v7qpx.js";
8
8
  import {
9
9
  __require
10
10
  } from "./roy-agent-core-fs0mn2jk.js";
@@ -3,17 +3,17 @@ import {
3
3
  } from "./roy-agent-core-az13yzmc.js";
4
4
  import {
5
5
  BaseComponent
6
- } from "./roy-agent-core-pgvcf91v.js";
6
+ } from "./roy-agent-core-m39v7qpx.js";
7
7
  import {
8
8
  globalHookManager,
9
9
  init_global_hook_manager
10
- } from "./roy-agent-core-cpcd24n2.js";
10
+ } from "./roy-agent-core-yet36q5k.js";
11
11
  import {
12
12
  init_context
13
- } from "./roy-agent-core-qqaak24r.js";
13
+ } from "./roy-agent-core-tkpp1ba0.js";
14
14
  import {
15
15
  getEnvContextOrEmpty
16
- } from "./roy-agent-core-7cbpmk4q.js";
16
+ } from "./roy-agent-core-p31ftgq9.js";
17
17
  import {
18
18
  createLogger,
19
19
  init_logger
@@ -6,7 +6,7 @@ import {
6
6
  } from "./roy-agent-core-7hh0brvs.js";
7
7
  import {
8
8
  BaseComponent
9
- } from "./roy-agent-core-pgvcf91v.js";
9
+ } from "./roy-agent-core-m39v7qpx.js";
10
10
  import {
11
11
  createLogger,
12
12
  init_logger
@@ -0,0 +1,288 @@
1
+ // src/env/task/plugins/sub-session-activity.ts
2
+ function flattenInline(text) {
3
+ return text.replace(/\r\n?/g, `
4
+ `).replace(/\n+/g, " · ").replace(/\s{2,}/g, " ").replace(/(?:\s*·\s*){2,}/g, " · ").replace(/^(\s*·\s*)+/, "").replace(/(\s*·\s*)+$/, "").trim();
5
+ }
6
+ var ACTIVITY_ACTIVE_MS = 5 * 60 * 1000;
7
+ var ACTIVITY_SLOW_MS = 20 * 60 * 1000;
8
+ var DEFAULT_ACTIVITY_MESSAGE_MAX = 200;
9
+ function formatAgo(updatedAt, now) {
10
+ if (updatedAt === undefined || !Number.isFinite(updatedAt))
11
+ return;
12
+ const diff = now - updatedAt;
13
+ if (!Number.isFinite(diff) || diff < 60000)
14
+ return "刚刚";
15
+ const minutes = Math.floor(diff / 60000);
16
+ if (minutes < 60)
17
+ return `${minutes} 分钟前`;
18
+ const hours = Math.floor(minutes / 60);
19
+ if (hours < 24)
20
+ return `${hours} 小时前`;
21
+ return `${Math.floor(hours / 24)} 天前`;
22
+ }
23
+ function formatClockTime(ts) {
24
+ if (ts === undefined || !Number.isFinite(ts))
25
+ return;
26
+ const d = new Date(ts);
27
+ if (Number.isNaN(d.getTime()))
28
+ return;
29
+ const pad = (n) => n < 10 ? `0${n}` : String(n);
30
+ return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
31
+ }
32
+ function resolveActivityLiveness(activity, now, terminal = false) {
33
+ if (!activity) {
34
+ return { level: "unknown", dot: "❔", label: "未知" };
35
+ }
36
+ const agoText = formatAgo(activity.updatedAt, now);
37
+ if (terminal) {
38
+ return { level: "terminal", dot: "⚪", label: "已结束", agoText };
39
+ }
40
+ const updatedAt = activity.updatedAt;
41
+ if (updatedAt === undefined || !Number.isFinite(updatedAt)) {
42
+ return { level: "unknown", dot: "❔", label: "未知", agoText };
43
+ }
44
+ const age = now - updatedAt;
45
+ if (!Number.isFinite(age) || age < ACTIVITY_ACTIVE_MS) {
46
+ return { level: "active", dot: "\uD83D\uDFE2", label: "活跃", agoText };
47
+ }
48
+ if (age < ACTIVITY_SLOW_MS) {
49
+ return { level: "slow", dot: "\uD83D\uDFE1", label: "缓慢", agoText };
50
+ }
51
+ return { level: "stalled", dot: "\uD83D\uDD34", label: "疑似停滞", agoText };
52
+ }
53
+ function truncateActivityMessage(text, max = DEFAULT_ACTIVITY_MESSAGE_MAX) {
54
+ if (!text)
55
+ return "";
56
+ const flat = flattenInline(text);
57
+ if (!flat)
58
+ return "";
59
+ if (flat.length <= max)
60
+ return flat;
61
+ const cut = flat.slice(0, max - 1);
62
+ const lastSpace = cut.lastIndexOf(" ");
63
+ if (lastSpace > max * 0.6)
64
+ return `${cut.slice(0, lastSpace).trimEnd()}…`;
65
+ return `${cut}…`;
66
+ }
67
+ function formatActivityLines(activity, now, terminal = false) {
68
+ const live = resolveActivityLiveness(activity, now, terminal);
69
+ if (!activity) {
70
+ return ["❔ 暂无数据(子会话已归档或未落盘)"];
71
+ }
72
+ const headParts = [];
73
+ const agoPhrase = live.agoText ? `(${live.agoText}有写入)` : "";
74
+ headParts.push(`${live.dot} ${live.label}${agoPhrase}`);
75
+ headParts.push(`消息数 ${activity.messageCount} 条`);
76
+ const lines = [headParts.join(" · ")];
77
+ const clock = formatClockTime(activity.updatedAt);
78
+ if (clock)
79
+ lines.push(`\uD83D\uDD50 最近写入:${clock}`);
80
+ const last = activity.lastMessage;
81
+ if (last && last.content) {
82
+ const role = last.role ? `[${last.role}] ` : "";
83
+ lines.push(`\uD83D\uDCAC 最近消息:${role}${last.content}`);
84
+ } else {
85
+ lines.push("\uD83D\uDCAC 最近消息:(暂无文本消息)");
86
+ }
87
+ return lines;
88
+ }
89
+ function formatActivityQuote(activity, now, terminal = false) {
90
+ const live = resolveActivityLiveness(activity, now, terminal);
91
+ if (!activity) {
92
+ return {
93
+ title: "⚡ 子会话活性",
94
+ text: "❔ 暂无数据(子会话已归档或未落盘)",
95
+ overflow: false
96
+ };
97
+ }
98
+ const agoPhrase = live.agoText ? `(${live.agoText}有写入)` : "";
99
+ const head = `${live.dot} ${live.label}${agoPhrase} · 消息数 ${activity.messageCount} 条`;
100
+ const last = activity.lastMessage;
101
+ const role = last?.role ? `[${last.role}] ` : "";
102
+ const body = last?.content ? `${role}${truncateActivityMessage(last.content, 80)}` : "(暂无文本消息)";
103
+ const text = `${head}
104
+ \uD83D\uDCAC ${body}`;
105
+ const overflow = text.length > 112;
106
+ return { title: "⚡ 子会话活性", text, overflow };
107
+ }
108
+ function findBackgroundTaskByAssociatedTaskId(tasks, taskId) {
109
+ if (!tasks || tasks.length === 0)
110
+ return;
111
+ if (!Number.isFinite(taskId))
112
+ return;
113
+ let found;
114
+ for (const t of tasks) {
115
+ if (!t || typeof t.subSessionId !== "string" || !t.subSessionId)
116
+ continue;
117
+ if (t.associatedTaskId === taskId)
118
+ found = t;
119
+ }
120
+ return found;
121
+ }
122
+ function createSessionActivityProbe(ports) {
123
+ return async (sessionId) => {
124
+ if (!sessionId)
125
+ return { activity: undefined, terminal: false };
126
+ let session;
127
+ try {
128
+ session = await ports.getSession?.(sessionId);
129
+ } catch {
130
+ session = undefined;
131
+ }
132
+ if (!session)
133
+ return { activity: undefined, terminal: false };
134
+ let lastMessage;
135
+ try {
136
+ lastMessage = await ports.getLastMessage?.(sessionId);
137
+ } catch {
138
+ lastMessage = undefined;
139
+ }
140
+ let lifecycle = "running";
141
+ try {
142
+ lifecycle = await ports.getLifecycle?.(sessionId) ?? "running";
143
+ } catch {
144
+ lifecycle = "running";
145
+ }
146
+ return {
147
+ lifecycle,
148
+ terminal: lifecycle !== "running",
149
+ activity: {
150
+ subSessionId: sessionId,
151
+ messageCount: typeof session.messageCount === "number" ? session.messageCount : 0,
152
+ updatedAt: typeof session.updatedAt === "number" ? session.updatedAt : Number.NaN,
153
+ ...lastMessage ? { lastMessage } : {}
154
+ }
155
+ };
156
+ };
157
+ }
158
+ function createActivityProbe(ports) {
159
+ return async (taskId) => {
160
+ let terminal = false;
161
+ try {
162
+ terminal = await ports.isTerminalTask?.(taskId) ?? false;
163
+ } catch {
164
+ terminal = false;
165
+ }
166
+ let task;
167
+ try {
168
+ task = findBackgroundTaskByAssociatedTaskId(ports.listBackgroundTasks?.(), taskId);
169
+ } catch {
170
+ task = undefined;
171
+ }
172
+ if (!task)
173
+ return { activity: undefined, terminal };
174
+ let stats;
175
+ try {
176
+ stats = await ports.getSubSessionActivity?.(task.id);
177
+ } catch {
178
+ stats = undefined;
179
+ }
180
+ if (!stats)
181
+ return { activity: undefined, terminal };
182
+ let lastMessage;
183
+ try {
184
+ lastMessage = await ports.getLastMessage?.(task.subSessionId);
185
+ } catch {
186
+ lastMessage = undefined;
187
+ }
188
+ return {
189
+ terminal,
190
+ activity: {
191
+ subSessionId: task.subSessionId,
192
+ messageCount: stats.messageCount ?? 0,
193
+ updatedAt: stats.updatedAt,
194
+ ...lastMessage ? { lastMessage } : {}
195
+ }
196
+ };
197
+ };
198
+ }
199
+ function toActivityMessage(msg, max = DEFAULT_ACTIVITY_MESSAGE_MAX) {
200
+ if (!msg)
201
+ return;
202
+ let text = msg.content;
203
+ if (!text || text.length === 0) {
204
+ const textParts = [];
205
+ for (const part of msg.parts ?? []) {
206
+ if (part?.type === "text" && typeof part.content === "string") {
207
+ textParts.push(part.content);
208
+ } else if (part?.type === "tool-result" && typeof part.output === "string") {
209
+ textParts.push(part.output);
210
+ }
211
+ }
212
+ if (textParts.length > 0)
213
+ text = textParts.join(" ");
214
+ }
215
+ const content = truncateActivityMessage(text, max);
216
+ if (!content) {
217
+ if (max === DEFAULT_ACTIVITY_MESSAGE_MAX)
218
+ return;
219
+ return {
220
+ role: typeof msg.role === "string" ? msg.role : "unknown",
221
+ content: "(无文本内容)",
222
+ ...typeof msg.timestamp === "number" ? { timestamp: msg.timestamp } : {}
223
+ };
224
+ }
225
+ return {
226
+ role: typeof msg.role === "string" ? msg.role : "unknown",
227
+ content,
228
+ ...typeof msg.timestamp === "number" ? { timestamp: msg.timestamp } : {}
229
+ };
230
+ }
231
+ function mapBgTaskStatusToSessionLifecycle(status) {
232
+ switch (status) {
233
+ case "completed":
234
+ return "completed";
235
+ case "timeout":
236
+ case "timed_out":
237
+ return "timeout";
238
+ case "failed":
239
+ case "error":
240
+ return "failed";
241
+ case "stopped":
242
+ case "cancelled":
243
+ case "canceled":
244
+ case "aborted":
245
+ return "stopped";
246
+ default:
247
+ return "running";
248
+ }
249
+ }
250
+ var RECENT_MESSAGE_LIMIT = 5;
251
+ var RECENT_MESSAGE_MAX = 100;
252
+ function extractToolCallsFromMessages(messages) {
253
+ const calls = [];
254
+ for (const msg of messages ?? []) {
255
+ for (const part of msg?.parts ?? []) {
256
+ if (part?.type !== "tool-call")
257
+ continue;
258
+ const toolName = typeof part.toolName === "string" ? part.toolName : undefined;
259
+ if (!toolName)
260
+ continue;
261
+ let args;
262
+ if (typeof part.arguments === "string") {
263
+ try {
264
+ const parsed = JSON.parse(part.arguments);
265
+ if (parsed && typeof parsed === "object") {
266
+ args = parsed;
267
+ }
268
+ } catch {}
269
+ } else if (part.arguments && typeof part.arguments === "object") {
270
+ args = part.arguments;
271
+ }
272
+ const reason = typeof args?.reason === "string" && args.reason.trim().length > 0 ? args.reason.trim() : undefined;
273
+ calls.push({ toolName, ...reason ? { reason } : {} });
274
+ }
275
+ }
276
+ return calls;
277
+ }
278
+ function formatRecentToolCallLines(calls, max = RECENT_MESSAGE_MAX) {
279
+ if (!calls || calls.length === 0) {
280
+ return ["暂无工具调用"];
281
+ }
282
+ return calls.map((c) => {
283
+ const reason = truncateActivityMessage(c?.reason, max) || "—";
284
+ return `- ${c?.toolName ?? "未知"}:${reason}`;
285
+ });
286
+ }
287
+
288
+ export { formatActivityLines, formatActivityQuote, createSessionActivityProbe, createActivityProbe, toActivityMessage, mapBgTaskStatusToSessionLifecycle, RECENT_MESSAGE_LIMIT, extractToolCallsFromMessages, formatRecentToolCallLines };