@xgjktech/xg_cwork_im 1.19.41 → 1.19.43

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 (428) hide show
  1. package/README.md +488 -488
  2. package/dist/src/account-connection.d.ts +37 -0
  3. package/dist/src/account-connection.d.ts.map +1 -0
  4. package/dist/src/account-connection.js +437 -0
  5. package/dist/src/account-connection.js.map +1 -0
  6. package/dist/src/account-reconciler.d.ts +55 -0
  7. package/dist/src/account-reconciler.d.ts.map +1 -0
  8. package/dist/src/account-reconciler.js +294 -0
  9. package/dist/src/account-reconciler.js.map +1 -0
  10. package/dist/src/account-reconciler.test.d.ts +2 -0
  11. package/dist/src/account-reconciler.test.d.ts.map +1 -0
  12. package/dist/src/account-reconciler.test.js +148 -0
  13. package/dist/src/account-reconciler.test.js.map +1 -0
  14. package/dist/src/action-run-event.d.ts +20 -0
  15. package/dist/src/action-run-event.d.ts.map +1 -0
  16. package/dist/src/action-run-event.js +62 -0
  17. package/dist/src/action-run-event.js.map +1 -0
  18. package/dist/src/action-run-event.test.d.ts +2 -0
  19. package/dist/src/action-run-event.test.d.ts.map +1 -0
  20. package/dist/src/action-run-event.test.js +83 -0
  21. package/dist/src/action-run-event.test.js.map +1 -0
  22. package/dist/src/action-store-access.d.ts +27 -0
  23. package/dist/src/action-store-access.d.ts.map +1 -0
  24. package/dist/src/action-store-access.js +74 -0
  25. package/dist/src/action-store-access.js.map +1 -0
  26. package/dist/src/active-round-registry.d.ts +29 -0
  27. package/dist/src/active-round-registry.d.ts.map +1 -0
  28. package/dist/src/active-round-registry.js +60 -0
  29. package/dist/src/active-round-registry.js.map +1 -0
  30. package/dist/src/active-round-registry.test.d.ts +2 -0
  31. package/dist/src/active-round-registry.test.d.ts.map +1 -0
  32. package/dist/src/active-round-registry.test.js +62 -0
  33. package/dist/src/active-round-registry.test.js.map +1 -0
  34. package/dist/src/agent-context-types.d.ts +205 -0
  35. package/dist/src/agent-context-types.d.ts.map +1 -0
  36. package/dist/src/agent-context-types.js +132 -0
  37. package/dist/src/agent-context-types.js.map +1 -0
  38. package/dist/src/agent-context-types.test.d.ts +2 -0
  39. package/dist/src/agent-context-types.test.d.ts.map +1 -0
  40. package/dist/src/agent-context-types.test.js +123 -0
  41. package/dist/src/agent-context-types.test.js.map +1 -0
  42. package/dist/src/agent-stream-client-registry.d.ts +6 -0
  43. package/dist/src/agent-stream-client-registry.d.ts.map +1 -0
  44. package/dist/src/agent-stream-client-registry.js +14 -0
  45. package/dist/src/agent-stream-client-registry.js.map +1 -0
  46. package/dist/src/apply-sync-mapping.d.ts +15 -0
  47. package/dist/src/apply-sync-mapping.d.ts.map +1 -0
  48. package/dist/src/apply-sync-mapping.js +98 -0
  49. package/dist/src/apply-sync-mapping.js.map +1 -0
  50. package/dist/src/auth.d.ts +30 -0
  51. package/dist/src/auth.d.ts.map +1 -0
  52. package/dist/src/auth.js +66 -0
  53. package/dist/src/auth.js.map +1 -0
  54. package/dist/src/auto-model-router.d.ts +36 -0
  55. package/dist/src/auto-model-router.d.ts.map +1 -0
  56. package/dist/src/auto-model-router.js +60 -0
  57. package/dist/src/auto-model-router.js.map +1 -0
  58. package/dist/src/auto-model-router.test.d.ts +2 -0
  59. package/dist/src/auto-model-router.test.d.ts.map +1 -0
  60. package/dist/src/auto-model-router.test.js +99 -0
  61. package/dist/src/auto-model-router.test.js.map +1 -0
  62. package/dist/src/block-streaming-config.test.d.ts +2 -0
  63. package/dist/src/block-streaming-config.test.d.ts.map +1 -0
  64. package/dist/src/block-streaming-config.test.js +85 -0
  65. package/dist/src/block-streaming-config.test.js.map +1 -0
  66. package/dist/src/build-project-prompt.d.ts +40 -0
  67. package/dist/src/build-project-prompt.d.ts.map +1 -0
  68. package/dist/src/build-project-prompt.js +183 -0
  69. package/dist/src/build-project-prompt.js.map +1 -0
  70. package/dist/src/build-project-prompt.test.d.ts +2 -0
  71. package/dist/src/build-project-prompt.test.d.ts.map +1 -0
  72. package/dist/src/build-project-prompt.test.js +100 -0
  73. package/dist/src/build-project-prompt.test.js.map +1 -0
  74. package/dist/src/channel-config.d.ts +650 -0
  75. package/dist/src/channel-config.d.ts.map +1 -0
  76. package/dist/src/channel-config.js +372 -0
  77. package/dist/src/channel-config.js.map +1 -0
  78. package/dist/src/channel-config.test.d.ts +2 -0
  79. package/dist/src/channel-config.test.d.ts.map +1 -0
  80. package/dist/src/channel-config.test.js +56 -0
  81. package/dist/src/channel-config.test.js.map +1 -0
  82. package/dist/src/channel-disabled-account.test.d.ts +2 -0
  83. package/dist/src/channel-disabled-account.test.d.ts.map +1 -0
  84. package/dist/src/channel-disabled-account.test.js +44 -0
  85. package/dist/src/channel-disabled-account.test.js.map +1 -0
  86. package/dist/src/channel-log.d.ts +17 -0
  87. package/dist/src/channel-log.d.ts.map +1 -0
  88. package/dist/src/channel-log.js +45 -0
  89. package/dist/src/channel-log.js.map +1 -0
  90. package/dist/src/channel.d.ts +16 -0
  91. package/dist/src/channel.d.ts.map +1 -0
  92. package/dist/src/channel.js +149 -0
  93. package/dist/src/channel.js.map +1 -0
  94. package/dist/src/connection.d.ts +82 -0
  95. package/dist/src/connection.d.ts.map +1 -0
  96. package/dist/src/connection.js +386 -0
  97. package/dist/src/connection.js.map +1 -0
  98. package/dist/src/deliver-text.d.ts +30 -0
  99. package/dist/src/deliver-text.d.ts.map +1 -0
  100. package/dist/src/deliver-text.js +88 -0
  101. package/dist/src/deliver-text.js.map +1 -0
  102. package/dist/src/deliver-text.test.d.ts +2 -0
  103. package/dist/src/deliver-text.test.d.ts.map +1 -0
  104. package/dist/src/deliver-text.test.js +117 -0
  105. package/dist/src/deliver-text.test.js.map +1 -0
  106. package/dist/src/delivery/deliver-text.test.js +22 -22
  107. package/dist/src/delivery/turn-deliver-buffer.test.js +25 -25
  108. package/dist/src/delivery/user-facing-errors.d.ts +1 -0
  109. package/dist/src/delivery/user-facing-errors.d.ts.map +1 -1
  110. package/dist/src/delivery/user-facing-errors.js +7 -0
  111. package/dist/src/delivery/user-facing-errors.js.map +1 -1
  112. package/dist/src/delivery/user-facing-errors.test.js +12 -1
  113. package/dist/src/delivery/user-facing-errors.test.js.map +1 -1
  114. package/dist/src/dispatch-mentioned-reply.d.ts +42 -0
  115. package/dist/src/dispatch-mentioned-reply.d.ts.map +1 -0
  116. package/dist/src/dispatch-mentioned-reply.js +822 -0
  117. package/dist/src/dispatch-mentioned-reply.js.map +1 -0
  118. package/dist/src/gateway-session-queue.d.ts +41 -0
  119. package/dist/src/gateway-session-queue.d.ts.map +1 -0
  120. package/dist/src/gateway-session-queue.js +29 -0
  121. package/dist/src/gateway-session-queue.js.map +1 -0
  122. package/dist/src/group-history-tool.d.ts +31 -0
  123. package/dist/src/group-history-tool.d.ts.map +1 -0
  124. package/dist/src/group-history-tool.js +177 -0
  125. package/dist/src/group-history-tool.js.map +1 -0
  126. package/dist/src/im-tool-progress.d.ts +4 -0
  127. package/dist/src/im-tool-progress.d.ts.map +1 -0
  128. package/dist/src/im-tool-progress.js +87 -0
  129. package/dist/src/im-tool-progress.js.map +1 -0
  130. package/dist/src/inbound-archive.d.ts +4 -0
  131. package/dist/src/inbound-archive.d.ts.map +1 -0
  132. package/dist/src/inbound-archive.js +105 -0
  133. package/dist/src/inbound-archive.js.map +1 -0
  134. package/dist/src/inbound-attachment-meta.d.ts +13 -0
  135. package/dist/src/inbound-attachment-meta.d.ts.map +1 -0
  136. package/dist/src/inbound-attachment-meta.js +39 -0
  137. package/dist/src/inbound-attachment-meta.js.map +1 -0
  138. package/dist/src/inbound-chat-type.d.ts +33 -0
  139. package/dist/src/inbound-chat-type.d.ts.map +1 -0
  140. package/dist/src/inbound-chat-type.js +52 -0
  141. package/dist/src/inbound-chat-type.js.map +1 -0
  142. package/dist/src/inbound-display.d.ts +41 -0
  143. package/dist/src/inbound-display.d.ts.map +1 -0
  144. package/dist/src/inbound-display.js +169 -0
  145. package/dist/src/inbound-display.js.map +1 -0
  146. package/dist/src/inbound-file-download.d.ts +15 -0
  147. package/dist/src/inbound-file-download.d.ts.map +1 -0
  148. package/dist/src/inbound-file-download.js +48 -0
  149. package/dist/src/inbound-file-download.js.map +1 -0
  150. package/dist/src/inbound-input-media.d.ts +43 -0
  151. package/dist/src/inbound-input-media.d.ts.map +1 -0
  152. package/dist/src/inbound-input-media.js +230 -0
  153. package/dist/src/inbound-input-media.js.map +1 -0
  154. package/dist/src/inbound-media-local.d.ts +49 -0
  155. package/dist/src/inbound-media-local.d.ts.map +1 -0
  156. package/dist/src/inbound-media-local.js +194 -0
  157. package/dist/src/inbound-media-local.js.map +1 -0
  158. package/dist/src/inbound-model.d.ts +30 -0
  159. package/dist/src/inbound-model.d.ts.map +1 -0
  160. package/dist/src/inbound-model.js +40 -0
  161. package/dist/src/inbound-model.js.map +1 -0
  162. package/dist/src/inbound-model.test.d.ts +2 -0
  163. package/dist/src/inbound-model.test.d.ts.map +1 -0
  164. package/dist/src/inbound-model.test.js +66 -0
  165. package/dist/src/inbound-model.test.js.map +1 -0
  166. package/dist/src/inbound-terminal-delivery.d.ts +77 -0
  167. package/dist/src/inbound-terminal-delivery.d.ts.map +1 -0
  168. package/dist/src/inbound-terminal-delivery.js +251 -0
  169. package/dist/src/inbound-terminal-delivery.js.map +1 -0
  170. package/dist/src/inbound-terminal-state.d.ts +66 -0
  171. package/dist/src/inbound-terminal-state.d.ts.map +1 -0
  172. package/dist/src/inbound-terminal-state.js +180 -0
  173. package/dist/src/inbound-terminal-state.js.map +1 -0
  174. package/dist/src/inbound-terminal-state.test.d.ts +2 -0
  175. package/dist/src/inbound-terminal-state.test.d.ts.map +1 -0
  176. package/dist/src/inbound-terminal-state.test.js +224 -0
  177. package/dist/src/inbound-terminal-state.test.js.map +1 -0
  178. package/dist/src/interrupt-round.d.ts +9 -0
  179. package/dist/src/interrupt-round.d.ts.map +1 -0
  180. package/dist/src/interrupt-round.js +44 -0
  181. package/dist/src/interrupt-round.js.map +1 -0
  182. package/dist/src/interrupt-round.test.d.ts +2 -0
  183. package/dist/src/interrupt-round.test.d.ts.map +1 -0
  184. package/dist/src/interrupt-round.test.js +133 -0
  185. package/dist/src/interrupt-round.test.js.map +1 -0
  186. package/dist/src/item-event-guard.d.ts +28 -0
  187. package/dist/src/item-event-guard.d.ts.map +1 -0
  188. package/dist/src/item-event-guard.js +22 -0
  189. package/dist/src/item-event-guard.js.map +1 -0
  190. package/dist/src/item-event-guard.test.d.ts +2 -0
  191. package/dist/src/item-event-guard.test.d.ts.map +1 -0
  192. package/dist/src/item-event-guard.test.js +55 -0
  193. package/dist/src/item-event-guard.test.js.map +1 -0
  194. package/dist/src/modified-file-push-tracker.d.ts +24 -0
  195. package/dist/src/modified-file-push-tracker.d.ts.map +1 -0
  196. package/dist/src/modified-file-push-tracker.js +125 -0
  197. package/dist/src/modified-file-push-tracker.js.map +1 -0
  198. package/dist/src/nas-volumes.d.ts +43 -0
  199. package/dist/src/nas-volumes.d.ts.map +1 -0
  200. package/dist/src/nas-volumes.js +307 -0
  201. package/dist/src/nas-volumes.js.map +1 -0
  202. package/dist/src/nas-volumes.test.d.ts +2 -0
  203. package/dist/src/nas-volumes.test.d.ts.map +1 -0
  204. package/dist/src/nas-volumes.test.js +229 -0
  205. package/dist/src/nas-volumes.test.js.map +1 -0
  206. package/dist/src/per-message-fallback-notice.d.ts +43 -0
  207. package/dist/src/per-message-fallback-notice.d.ts.map +1 -0
  208. package/dist/src/per-message-fallback-notice.js +93 -0
  209. package/dist/src/per-message-fallback-notice.js.map +1 -0
  210. package/dist/src/per-message-fallback-notice.test.d.ts +2 -0
  211. package/dist/src/per-message-fallback-notice.test.d.ts.map +1 -0
  212. package/dist/src/per-message-fallback-notice.test.js +47 -0
  213. package/dist/src/per-message-fallback-notice.test.js.map +1 -0
  214. package/dist/src/per-message-model-pending.d.ts +17 -0
  215. package/dist/src/per-message-model-pending.d.ts.map +1 -0
  216. package/dist/src/per-message-model-pending.js +45 -0
  217. package/dist/src/per-message-model-pending.js.map +1 -0
  218. package/dist/src/plan/action-dispatch-event-compat.test.d.ts +2 -0
  219. package/dist/src/plan/action-dispatch-event-compat.test.d.ts.map +1 -0
  220. package/dist/src/plan/action-dispatch-event-compat.test.js +81 -0
  221. package/dist/src/plan/action-dispatch-event-compat.test.js.map +1 -0
  222. package/dist/src/plan/action-store-lifecycle.test.js +5 -5
  223. package/dist/src/plan/plan-core-db.test.js +9 -9
  224. package/dist/src/plan/plan-core-snapshot.test.js +9 -9
  225. package/dist/src/plan-blocked-notice.d.ts +14 -0
  226. package/dist/src/plan-blocked-notice.d.ts.map +1 -0
  227. package/dist/src/plan-blocked-notice.js +41 -0
  228. package/dist/src/plan-blocked-notice.js.map +1 -0
  229. package/dist/src/plan-blocked-notice.test.d.ts +2 -0
  230. package/dist/src/plan-blocked-notice.test.d.ts.map +1 -0
  231. package/dist/src/plan-blocked-notice.test.js +96 -0
  232. package/dist/src/plan-blocked-notice.test.js.map +1 -0
  233. package/dist/src/plan-event-subscription.d.ts +36 -0
  234. package/dist/src/plan-event-subscription.d.ts.map +1 -0
  235. package/dist/src/plan-event-subscription.js +57 -0
  236. package/dist/src/plan-event-subscription.js.map +1 -0
  237. package/dist/src/plan-event-subscription.test.d.ts +2 -0
  238. package/dist/src/plan-event-subscription.test.d.ts.map +1 -0
  239. package/dist/src/plan-event-subscription.test.js +167 -0
  240. package/dist/src/plan-event-subscription.test.js.map +1 -0
  241. package/dist/src/plan-stat-event.d.ts +28 -0
  242. package/dist/src/plan-stat-event.d.ts.map +1 -0
  243. package/dist/src/plan-stat-event.js +74 -0
  244. package/dist/src/plan-stat-event.js.map +1 -0
  245. package/dist/src/plan-stat-event.test.d.ts +2 -0
  246. package/dist/src/plan-stat-event.test.d.ts.map +1 -0
  247. package/dist/src/plan-stat-event.test.js +248 -0
  248. package/dist/src/plan-stat-event.test.js.map +1 -0
  249. package/dist/src/plan-store-access.d.ts +23 -0
  250. package/dist/src/plan-store-access.d.ts.map +1 -0
  251. package/dist/src/plan-store-access.js +96 -0
  252. package/dist/src/plan-store-access.js.map +1 -0
  253. package/dist/src/plan-store-access.test.d.ts +2 -0
  254. package/dist/src/plan-store-access.test.d.ts.map +1 -0
  255. package/dist/src/plan-store-access.test.js +207 -0
  256. package/dist/src/plan-store-access.test.js.map +1 -0
  257. package/dist/src/plan-tool-middleware.d.ts +27 -0
  258. package/dist/src/plan-tool-middleware.d.ts.map +1 -0
  259. package/dist/src/plan-tool-middleware.js +112 -0
  260. package/dist/src/plan-tool-middleware.js.map +1 -0
  261. package/dist/src/plan-tool-middleware.test.d.ts +2 -0
  262. package/dist/src/plan-tool-middleware.test.d.ts.map +1 -0
  263. package/dist/src/plan-tool-middleware.test.js +623 -0
  264. package/dist/src/plan-tool-middleware.test.js.map +1 -0
  265. package/dist/src/plan-tool-result.d.ts +18 -0
  266. package/dist/src/plan-tool-result.d.ts.map +1 -0
  267. package/dist/src/plan-tool-result.js +77 -0
  268. package/dist/src/plan-tool-result.js.map +1 -0
  269. package/dist/src/plan-tool-result.test.d.ts +2 -0
  270. package/dist/src/plan-tool-result.test.d.ts.map +1 -0
  271. package/dist/src/plan-tool-result.test.js +129 -0
  272. package/dist/src/plan-tool-result.test.js.map +1 -0
  273. package/dist/src/plan-ws-registry.d.ts +11 -0
  274. package/dist/src/plan-ws-registry.d.ts.map +1 -0
  275. package/dist/src/plan-ws-registry.js +27 -0
  276. package/dist/src/plan-ws-registry.js.map +1 -0
  277. package/dist/src/plan-ws-registry.test.d.ts +2 -0
  278. package/dist/src/plan-ws-registry.test.d.ts.map +1 -0
  279. package/dist/src/plan-ws-registry.test.js +43 -0
  280. package/dist/src/plan-ws-registry.test.js.map +1 -0
  281. package/dist/src/progress-display.d.ts +77 -0
  282. package/dist/src/progress-display.d.ts.map +1 -0
  283. package/dist/src/progress-display.js +420 -0
  284. package/dist/src/progress-display.js.map +1 -0
  285. package/dist/src/project-path-normalize.d.ts +30 -0
  286. package/dist/src/project-path-normalize.d.ts.map +1 -0
  287. package/dist/src/project-path-normalize.js +101 -0
  288. package/dist/src/project-path-normalize.js.map +1 -0
  289. package/dist/src/recommended-system-prompt.d.ts +3 -0
  290. package/dist/src/recommended-system-prompt.d.ts.map +1 -0
  291. package/dist/src/recommended-system-prompt.js +8 -0
  292. package/dist/src/recommended-system-prompt.js.map +1 -0
  293. package/dist/src/register-per-message-model-hook.d.ts +6 -0
  294. package/dist/src/register-per-message-model-hook.d.ts.map +1 -0
  295. package/dist/src/register-per-message-model-hook.js +22 -0
  296. package/dist/src/register-per-message-model-hook.js.map +1 -0
  297. package/dist/src/resolve-inbound-group-prompt.d.ts +21 -0
  298. package/dist/src/resolve-inbound-group-prompt.d.ts.map +1 -0
  299. package/dist/src/resolve-inbound-group-prompt.js +43 -0
  300. package/dist/src/resolve-inbound-group-prompt.js.map +1 -0
  301. package/dist/src/resource-file.d.ts +119 -0
  302. package/dist/src/resource-file.d.ts.map +1 -0
  303. package/dist/src/resource-file.js +533 -0
  304. package/dist/src/resource-file.js.map +1 -0
  305. package/dist/src/resource-file.test.d.ts +2 -0
  306. package/dist/src/resource-file.test.d.ts.map +1 -0
  307. package/dist/src/resource-file.test.js +64 -0
  308. package/dist/src/resource-file.test.js.map +1 -0
  309. package/dist/src/run-usage-session.d.ts +10 -0
  310. package/dist/src/run-usage-session.d.ts.map +1 -0
  311. package/dist/src/run-usage-session.js +29 -0
  312. package/dist/src/run-usage-session.js.map +1 -0
  313. package/dist/src/run-usage.d.ts +52 -0
  314. package/dist/src/run-usage.d.ts.map +1 -0
  315. package/dist/src/run-usage.js +93 -0
  316. package/dist/src/run-usage.js.map +1 -0
  317. package/dist/src/run-usage.test.d.ts +2 -0
  318. package/dist/src/run-usage.test.d.ts.map +1 -0
  319. package/dist/src/run-usage.test.js +90 -0
  320. package/dist/src/run-usage.test.js.map +1 -0
  321. package/dist/src/send-file-event.d.ts +26 -0
  322. package/dist/src/send-file-event.d.ts.map +1 -0
  323. package/dist/src/send-file-event.js +33 -0
  324. package/dist/src/send-file-event.js.map +1 -0
  325. package/dist/src/send-file-event.test.d.ts +2 -0
  326. package/dist/src/send-file-event.test.d.ts.map +1 -0
  327. package/dist/src/send-file-event.test.js +86 -0
  328. package/dist/src/send-file-event.test.js.map +1 -0
  329. package/dist/src/send-file-tool.d.ts +81 -0
  330. package/dist/src/send-file-tool.d.ts.map +1 -0
  331. package/dist/src/send-file-tool.js +363 -0
  332. package/dist/src/send-file-tool.js.map +1 -0
  333. package/dist/src/send-file-tool.test.d.ts +2 -0
  334. package/dist/src/send-file-tool.test.d.ts.map +1 -0
  335. package/dist/src/send-file-tool.test.js +176 -0
  336. package/dist/src/send-file-tool.test.js.map +1 -0
  337. package/dist/src/send-group-message-tool.d.ts +17 -0
  338. package/dist/src/send-group-message-tool.d.ts.map +1 -0
  339. package/dist/src/send-group-message-tool.js +82 -0
  340. package/dist/src/send-group-message-tool.js.map +1 -0
  341. package/dist/src/send-service.d.ts +83 -0
  342. package/dist/src/send-service.d.ts.map +1 -0
  343. package/dist/src/send-service.js +324 -0
  344. package/dist/src/send-service.js.map +1 -0
  345. package/dist/src/send-service.test.d.ts +2 -0
  346. package/dist/src/send-service.test.d.ts.map +1 -0
  347. package/dist/src/send-service.test.js +40 -0
  348. package/dist/src/send-service.test.js.map +1 -0
  349. package/dist/src/session/build-project-prompt.test.js +18 -18
  350. package/dist/src/session-im-context.d.ts +13 -0
  351. package/dist/src/session-im-context.d.ts.map +1 -0
  352. package/dist/src/session-im-context.js +45 -0
  353. package/dist/src/session-im-context.js.map +1 -0
  354. package/dist/src/subagent-delivery-phase.d.ts +10 -0
  355. package/dist/src/subagent-delivery-phase.d.ts.map +1 -0
  356. package/dist/src/subagent-delivery-phase.js +4 -0
  357. package/dist/src/subagent-delivery-phase.js.map +1 -0
  358. package/dist/src/subagent-delivery-phase.test.d.ts +2 -0
  359. package/dist/src/subagent-delivery-phase.test.d.ts.map +1 -0
  360. package/dist/src/subagent-delivery-phase.test.js +12 -0
  361. package/dist/src/subagent-delivery-phase.test.js.map +1 -0
  362. package/dist/src/subagent-monitor.d.ts +32 -0
  363. package/dist/src/subagent-monitor.d.ts.map +1 -0
  364. package/dist/src/subagent-monitor.js +370 -0
  365. package/dist/src/subagent-monitor.js.map +1 -0
  366. package/dist/src/subagent-monitor.test.d.ts +2 -0
  367. package/dist/src/subagent-monitor.test.d.ts.map +1 -0
  368. package/dist/src/subagent-monitor.test.js +214 -0
  369. package/dist/src/subagent-monitor.test.js.map +1 -0
  370. package/dist/src/sync-mapping-types.d.ts +220 -0
  371. package/dist/src/sync-mapping-types.d.ts.map +1 -0
  372. package/dist/src/sync-mapping-types.js +55 -0
  373. package/dist/src/sync-mapping-types.js.map +1 -0
  374. package/dist/src/sync-service-client.d.ts +29 -0
  375. package/dist/src/sync-service-client.d.ts.map +1 -0
  376. package/dist/src/sync-service-client.js +72 -0
  377. package/dist/src/sync-service-client.js.map +1 -0
  378. package/dist/src/thinking-ws-progress.d.ts +24 -0
  379. package/dist/src/thinking-ws-progress.d.ts.map +1 -0
  380. package/dist/src/thinking-ws-progress.js +45 -0
  381. package/dist/src/thinking-ws-progress.js.map +1 -0
  382. package/dist/src/thinking-ws-progress.test.d.ts +2 -0
  383. package/dist/src/thinking-ws-progress.test.d.ts.map +1 -0
  384. package/dist/src/thinking-ws-progress.test.js +38 -0
  385. package/dist/src/thinking-ws-progress.test.js.map +1 -0
  386. package/dist/src/tool-json-result.d.ts +14 -0
  387. package/dist/src/tool-json-result.d.ts.map +1 -0
  388. package/dist/src/tool-json-result.js +20 -0
  389. package/dist/src/tool-json-result.js.map +1 -0
  390. package/dist/src/turn/turn-agent-event-subscription.d.ts.map +1 -1
  391. package/dist/src/turn/turn-agent-event-subscription.js +14 -0
  392. package/dist/src/turn/turn-agent-event-subscription.js.map +1 -1
  393. package/dist/src/turn-deliver-buffer.d.ts +60 -0
  394. package/dist/src/turn-deliver-buffer.d.ts.map +1 -0
  395. package/dist/src/turn-deliver-buffer.js +133 -0
  396. package/dist/src/turn-deliver-buffer.js.map +1 -0
  397. package/dist/src/turn-deliver-buffer.test.d.ts +2 -0
  398. package/dist/src/turn-deliver-buffer.test.d.ts.map +1 -0
  399. package/dist/src/turn-deliver-buffer.test.js +184 -0
  400. package/dist/src/turn-deliver-buffer.test.js.map +1 -0
  401. package/dist/src/types.d.ts +386 -0
  402. package/dist/src/types.d.ts.map +1 -0
  403. package/dist/src/types.js +32 -0
  404. package/dist/src/types.js.map +1 -0
  405. package/dist/src/user-facing-errors.d.ts +32 -0
  406. package/dist/src/user-facing-errors.d.ts.map +1 -0
  407. package/dist/src/user-facing-errors.js +120 -0
  408. package/dist/src/user-facing-errors.js.map +1 -0
  409. package/dist/src/user-facing-errors.test.d.ts +2 -0
  410. package/dist/src/user-facing-errors.test.d.ts.map +1 -0
  411. package/dist/src/user-facing-errors.test.js +102 -0
  412. package/dist/src/user-facing-errors.test.js.map +1 -0
  413. package/dist/src/workspace/nas-volumes.test.js +3 -2
  414. package/dist/src/workspace/nas-volumes.test.js.map +1 -1
  415. package/dist/src/ws-inbound-schema.d.ts +14 -0
  416. package/dist/src/ws-inbound-schema.d.ts.map +1 -0
  417. package/dist/src/ws-inbound-schema.js +67 -0
  418. package/dist/src/ws-inbound-schema.js.map +1 -0
  419. package/dist/src/ws-run-event-unmapped.d.ts +10 -0
  420. package/dist/src/ws-run-event-unmapped.d.ts.map +1 -0
  421. package/dist/src/ws-run-event-unmapped.js +16 -0
  422. package/dist/src/ws-run-event-unmapped.js.map +1 -0
  423. package/dist/src/ws-run-event-unmapped.test.d.ts +2 -0
  424. package/dist/src/ws-run-event-unmapped.test.d.ts.map +1 -0
  425. package/dist/src/ws-run-event-unmapped.test.js +15 -0
  426. package/dist/src/ws-run-event-unmapped.test.js.map +1 -0
  427. package/openclaw.plugin.json +30 -30
  428. package/package.json +83 -83
@@ -0,0 +1,822 @@
1
+ /**
2
+ * @ 触发的单轮回复:WebSocket BEGIN、OpenClaw dispatchReplyWithBufferedBlockDispatcher、HTTP deliver、RUN_USAGE、FINISHED。
3
+ */
4
+ import { isImSingleChat, resolveSendMessageReply } from "./inbound-chat-type.js";
5
+ import { buildTerminalSendFn, InboundTerminalController, } from "./inbound-terminal-delivery.js";
6
+ import { formatConfirmedUpstreamErrorForIm } from "./user-facing-errors.js";
7
+ import { shouldOmitDuplicateFileCaption, shouldSuppressDuplicateTextDeliver, stripMediaDirectiveLines, stripModelUsageFooter, } from "./deliver-text.js";
8
+ import { shouldSuppressFallbackNoticeForIm } from "./per-message-fallback-notice.js";
9
+ import { resolveThinkingWsDisplayUpdate, THINKING_WS_SUMMARY_HINT, ThinkingWsBuffer, WS_THINKING_DISPLAY_MAX, } from "./thinking-ws-progress.js";
10
+ import { resolveItemEventGuard } from "./item-event-guard.js";
11
+ import { clearPendingPerMessageModel, setPendingPerMessageModel, splitModelRef, } from "./per-message-model-pending.js";
12
+ import { IM_BLOCK_STREAMING_COALESCE_DEFAULT, isDeliverPartialSnapshotEnabled, isDeliverSegmentBufferEnabled, isInboundBlockStreamingEnabled, resolveBlockStreamingReplyOptions, resolveDispatchOpenClawCfg, } from "./channel-config.js";
13
+ import { sendReplyDeliverBlock, sendTextMessage } from "./send-service.js";
14
+ import { isDeliverPayloadSendable, snapshotSupersedesBufferText, TurnDeliverBuffer } from "./turn-deliver-buffer.js";
15
+ import { buildRunUsageFromSessionEntry, hasReportableUsage, toImStreamRunUsageData } from "./run-usage.js";
16
+ import { readSessionUsageFields } from "./run-usage-session.js";
17
+ import { hasActiveSubagents, deferFinished } from "./subagent-monitor.js";
18
+ import { registerPlanWsClientAndSnapshot } from "./plan-stat-event.js";
19
+ import { setSessionImContext } from "./session-im-context.js";
20
+ import { completeActiveRound, registerActiveRound, } from "./active-round-registry.js";
21
+ import { resolveNasVolumeDispatchConfig } from "./nas-volumes.js";
22
+ /** WS `displayText` 过长封顶(避免网关/客户端溢出) */
23
+ const WS_DISPLAY_TEXT_MAX = 200;
24
+ /** 进度 `summary` 封顶(与网关约定一致) */
25
+ const WS_PROGRESS_SUMMARY_MAX = 200;
26
+ /** 流式正文预览(onPartialReply 快照)经 WS 展示的封顶长度 */
27
+ const WS_REPLY_PREVIEW_MAX = 2000;
28
+ /** 流式正文预览 WS 推送最小间隔(节流,避免 ~13 次/秒刷屏) */
29
+ const WS_REPLY_PREVIEW_MIN_INTERVAL_MS = 500;
30
+ /** 流式正文预览的 WS summary 标记(客户端据此更新同一输出位;定稿 HTTP 后清草稿) */
31
+ const WS_REPLY_PREVIEW_SUMMARY = "reply_preview";
32
+ function clipWsDisplayText(text, max = WS_DISPLAY_TEXT_MAX) {
33
+ const t = text.trim();
34
+ if (!t)
35
+ return "";
36
+ if (t.length <= max)
37
+ return t;
38
+ return `${t.slice(0, Math.max(0, max - 1))}…`;
39
+ }
40
+ function clipWsProgressSummary(text, max = WS_PROGRESS_SUMMARY_MAX) {
41
+ const t = text.trim().replace(/\r\n/g, "\n").replace(/\n+/g, " ");
42
+ if (!t)
43
+ return "";
44
+ if (t.length <= max)
45
+ return t;
46
+ return `${t.slice(0, Math.max(0, max - 1))}…`;
47
+ }
48
+ /** 流式 BEGIN → dispatch → 可选 RUN_USAGE → 必发 FINISHED;首包超时仅日志(不对 IM 发超时话术) */
49
+ export async function dispatchMentionedReply(args) {
50
+ const { accountId, rt, cfg, config, log, logPrefix, route, inboundCtx, params, currentIdentity, streamClient, agentWorkspaceDir, nasVolumes, modelOverride, thinkingLevelOverride, autoRouteMeta, inboundTrigger, isStopControl = false } = args;
51
+ const terminal = new InboundTerminalController({
52
+ messageId: params.msgId,
53
+ groupId: params.groupId,
54
+ sessionKey: route.sessionKey,
55
+ trigger: inboundTrigger ?? "user",
56
+ log,
57
+ logPrefix,
58
+ });
59
+ const replyMetaForSend = resolveSendMessageReply(params);
60
+ const terminalSend = buildTerminalSendFn({
61
+ isSingleChat: isImSingleChat(params),
62
+ replyMeta: replyMetaForSend,
63
+ sendText: async (text, reply) => {
64
+ await sendTextMessage(config, currentIdentity.token, params.groupId, text, reply ? [reply.targetUserId] : [], log, undefined, reply);
65
+ },
66
+ });
67
+ log.info(`${logPrefix} [dispatch] Dispatching to OpenClaw AI, sessionKey=${route.sessionKey}`);
68
+ if (modelOverride) {
69
+ log.info(`${logPrefix} [model] per-message override requested: ${modelOverride}`);
70
+ }
71
+ if (autoRouteMeta) {
72
+ log.info(`${logPrefix} [route] dispatch version=${autoRouteMeta.version} tier=${autoRouteMeta.tier} ` +
73
+ `reason=${autoRouteMeta.reason} requestedModel=${modelOverride ?? "(none)"} ` +
74
+ `requestedThinking=${thinkingLevelOverride ?? "(default)"}`);
75
+ }
76
+ let isFirstReply = true;
77
+ let subagentNotificationSent = false;
78
+ const dispatchStart = Date.now();
79
+ const replyAnchorId = params.msgId.trim();
80
+ const progressGroupId = params.groupId;
81
+ const toolNameStack = [];
82
+ const notifyStreamProgress = async (event, displayText, summary, displayMax = WS_DISPLAY_TEXT_MAX) => {
83
+ if (isStopControl)
84
+ return;
85
+ const msg = clipWsDisplayText(displayText, displayMax);
86
+ const sum = summary?.trim() ? clipWsProgressSummary(summary) : undefined;
87
+ if (!progressGroupId.trim() || !replyAnchorId || !msg)
88
+ return;
89
+ try {
90
+ await streamClient.streamProgress({
91
+ groupId: progressGroupId,
92
+ replyToMsgId: replyAnchorId,
93
+ event,
94
+ displayText: msg,
95
+ ...(sum ? { summary: sum } : {}),
96
+ });
97
+ }
98
+ catch (e) {
99
+ log.warn(`${logPrefix} [stream] ${event} notify failed: ${String(e)}`);
100
+ }
101
+ };
102
+ const thinkingWsBuffer = new ThinkingWsBuffer();
103
+ let lastThinkingWsDisplay = "";
104
+ const flushThinkingWsOnce = async (reason) => {
105
+ const text = thinkingWsBuffer.take();
106
+ if (!text)
107
+ return;
108
+ const { displayText, changed } = resolveThinkingWsDisplayUpdate(lastThinkingWsDisplay, text);
109
+ if (!changed)
110
+ return;
111
+ lastThinkingWsDisplay = displayText;
112
+ await notifyStreamProgress("RUN_EVENT", displayText, THINKING_WS_SUMMARY_HINT, WS_THINKING_DISPLAY_MAX);
113
+ log.info(`${logPrefix} [stream] Thinking WS once (${reason}) len=${displayText.length}`);
114
+ };
115
+ let hasFirstReply = false;
116
+ let agentRunStarted = false;
117
+ let dispatchInFlight = false;
118
+ const firstReplyTimeoutMs = config.firstReplyTimeoutMs ?? 30 * 60_000;
119
+ const resolveFirstReplyTimeoutCause = () => {
120
+ if (!agentRunStarted)
121
+ return "never_started";
122
+ if (dispatchInFlight)
123
+ return "in_progress";
124
+ return "ended_without_http_reply";
125
+ };
126
+ const timeoutLabel = `${logPrefix} [stream] First reply timeout after ${firstReplyTimeoutMs}ms`;
127
+ const firstReplyTimeout = setTimeout(() => {
128
+ if (hasFirstReply)
129
+ return;
130
+ const timeoutCause = resolveFirstReplyTimeoutCause();
131
+ terminal.markTimeoutFired();
132
+ log.warn(`${timeoutLabel} cause=${timeoutCause} agentRunStarted=${agentRunStarted} ` +
133
+ `dispatchInFlight=${dispatchInFlight} (no IM timeout notice; channel timer ≠ OpenClaw terminal)`);
134
+ }, firstReplyTimeoutMs);
135
+ let deliverInvokeCount = 0;
136
+ let deliverCallCount = 0;
137
+ let deliverSkippedCount = 0;
138
+ let lastDeliveredText = "";
139
+ let lastDeliveredHadMedia = false;
140
+ let agentRunId;
141
+ let dispatchError = undefined;
142
+ let lastDeliverError = undefined;
143
+ let dispatchResult;
144
+ const blockStreamingEnabled = isInboundBlockStreamingEnabled(config);
145
+ const segmentBufferEnabled = blockStreamingEnabled && isDeliverSegmentBufferEnabled(config);
146
+ const segmentBuffer = segmentBufferEnabled ? new TurnDeliverBuffer() : undefined;
147
+ let hasBufferedSendable = false;
148
+ let flushSegmentBuffer = async () => { };
149
+ // —— onPartialReply 全量快照:当前 tool 区间内正文的权威来源 ——
150
+ // text 是「当前 assistant 消息」的完整快照(非增量);tool 边界 / 轮末 flush 时用它覆盖
151
+ // deliver 拼接文本,消除段缓冲对「覆盖 vs 追加」的启发式猜测(CO2)。
152
+ const partialSnapshotEnabled = segmentBufferEnabled && isDeliverPartialSnapshotEnabled(config);
153
+ let segmentSnapshotText = "";
154
+ let segmentSnapshotHadPartial = false;
155
+ // WS 正文预览节流状态
156
+ let lastReplyPreviewAt = 0;
157
+ let lastReplyPreviewText = "";
158
+ // 观测统计(保留少量,便于线上核对)
159
+ let partialReplyCount = 0;
160
+ let partialReplyMaxTextLen = 0;
161
+ let partialReplyFirstAt = 0;
162
+ const resetSegmentSnapshot = () => {
163
+ segmentSnapshotText = "";
164
+ segmentSnapshotHadPartial = false;
165
+ lastReplyPreviewText = "";
166
+ };
167
+ const emitReplyPreviewWs = async (snapshot, force) => {
168
+ const text = snapshot.trim();
169
+ if (!text)
170
+ return;
171
+ const now = Date.now();
172
+ if (!force && now - lastReplyPreviewAt < WS_REPLY_PREVIEW_MIN_INTERVAL_MS)
173
+ return;
174
+ const clipped = clipWsDisplayText(text, WS_REPLY_PREVIEW_MAX);
175
+ if (clipped === lastReplyPreviewText)
176
+ return;
177
+ lastReplyPreviewAt = now;
178
+ lastReplyPreviewText = clipped;
179
+ await notifyStreamProgress("RUN_EVENT", clipped, WS_REPLY_PREVIEW_SUMMARY, WS_REPLY_PREVIEW_MAX);
180
+ };
181
+ const postHttpDeliver = async (args) => {
182
+ const { payloadForSend, textPart, sendLabel, invokeNum, hasMedia, omitDuplicateFileCaption } = args;
183
+ deliverCallCount++;
184
+ if (isFirstReply) {
185
+ const ttfr = Date.now() - dispatchStart;
186
+ log.info(`${logPrefix} [deliver] First response block received from AI (TTFB: ${ttfr}ms)`);
187
+ isFirstReply = false;
188
+ }
189
+ const reply = resolveSendMessageReply(params);
190
+ const atIds = reply ? [reply.targetUserId] : [];
191
+ if (!hasFirstReply) {
192
+ clearTimeout(firstReplyTimeout);
193
+ }
194
+ await sendReplyDeliverBlock(config, currentIdentity.token, params.groupId, payloadForSend, atIds, log, undefined, reply, agentWorkspaceDir);
195
+ if (!hasFirstReply) {
196
+ hasFirstReply = true;
197
+ }
198
+ terminal.markBusinessReplySent();
199
+ if (hasMedia) {
200
+ lastDeliveredHadMedia = true;
201
+ if (!omitDuplicateFileCaption) {
202
+ lastDeliveredText = textPart || "[media]";
203
+ }
204
+ }
205
+ else {
206
+ lastDeliveredText = textPart;
207
+ lastDeliveredHadMedia = false;
208
+ }
209
+ const preview = textPart.length > 80 ? `${textPart.slice(0, 80)}...` : textPart || "[media]";
210
+ log.info(`${logPrefix} [send] ${sendLabel} sent via HTTP: groupId=${params.groupId} ` +
211
+ `invoke=#${invokeNum} preview="${preview}"`);
212
+ };
213
+ let activeRound;
214
+ try {
215
+ if (!isStopControl) {
216
+ setSessionImContext(route.sessionKey, {
217
+ groupId: params.groupId,
218
+ replyToMsgId: params.msgId,
219
+ agentId: config.agentId || "main",
220
+ });
221
+ await streamClient.start({
222
+ groupId: params.groupId,
223
+ replyToMsgId: params.msgId,
224
+ });
225
+ activeRound = registerActiveRound({
226
+ accountId,
227
+ groupId: params.groupId,
228
+ agentId: config.agentId || "main",
229
+ sessionKey: route.sessionKey,
230
+ replyToMsgId: params.msgId,
231
+ streamClient,
232
+ });
233
+ registerPlanWsClientAndSnapshot(params.groupId, streamClient, params.msgId);
234
+ }
235
+ if (modelOverride) {
236
+ const parsed = splitModelRef(modelOverride);
237
+ if (parsed) {
238
+ setPendingPerMessageModel(route.sessionKey, modelOverride);
239
+ }
240
+ else {
241
+ log.warn(`${logPrefix} [model] invalid per-message model ref, ignoring: ${modelOverride}`);
242
+ }
243
+ }
244
+ const baseDispatchCfg = resolveDispatchOpenClawCfg(cfg, config);
245
+ let nasDispatch;
246
+ try {
247
+ nasDispatch = resolveNasVolumeDispatchConfig({
248
+ cfg: baseDispatchCfg,
249
+ config,
250
+ agentId: route.agentId,
251
+ sessionKey: route.sessionKey,
252
+ volumes: nasVolumes,
253
+ });
254
+ }
255
+ catch (error) {
256
+ // NAS 是可选增强信息。任何非法声明或运行时挂载校验失败都不得阻断原消息。
257
+ log.warn(`${logPrefix} [nas-volumes] invalid mount ignored: ${String(error)}`);
258
+ try {
259
+ // 若本会话此前已有有效声明,继续复用它;否则完全退回原 dispatch 配置。
260
+ nasDispatch = resolveNasVolumeDispatchConfig({
261
+ cfg: baseDispatchCfg,
262
+ config,
263
+ agentId: route.agentId,
264
+ sessionKey: route.sessionKey,
265
+ });
266
+ }
267
+ catch (cachedError) {
268
+ log.warn(`${logPrefix} [nas-volumes] cached mount unavailable, continuing without NAS: ${String(cachedError)}`);
269
+ nasDispatch = { cfg: baseDispatchCfg, reused: false };
270
+ }
271
+ }
272
+ const dispatchCfg = nasDispatch.cfg;
273
+ if (nasDispatch.specHash) {
274
+ log.info(`${logPrefix} [nas-volumes] session=${route.sessionKey} volumes=${nasVolumes?.length ?? "cached"} ` +
275
+ `spec=${nasDispatch.specHash.slice(0, 12)} reused=${nasDispatch.reused}`);
276
+ }
277
+ if (blockStreamingEnabled && baseDispatchCfg !== cfg) {
278
+ log.info(`${logPrefix} [dispatch] IM blockStreamingCoalesce override ` +
279
+ `(minChars=${IM_BLOCK_STREAMING_COALESCE_DEFAULT.minChars} idleMs=${IM_BLOCK_STREAMING_COALESCE_DEFAULT.idleMs}) ` +
280
+ `— agents.defaults coalesce will not delay tool-before HTTP`);
281
+ }
282
+ if (blockStreamingEnabled) {
283
+ log.info(`${logPrefix} [dispatch] blockStreaming=on (assistant text before tools → HTTP; tool progress → WS)`);
284
+ }
285
+ if (segmentBufferEnabled) {
286
+ log.info(`${logPrefix} [dispatch] deliverSegmentBuffer=on (segment buffer → flush on tool start / dispatch end)`);
287
+ }
288
+ flushSegmentBuffer = async (kind) => {
289
+ if (!segmentBuffer)
290
+ return;
291
+ const result = segmentBuffer.takeForFlush(kind);
292
+ // 本段快照(onPartialReply 全量);仅在启用且确有回调时作为正文权威来源。
293
+ const snapshot = partialSnapshotEnabled && segmentSnapshotHadPartial ? segmentSnapshotText.trim() : "";
294
+ const sendLabel = kind === "interim"
295
+ ? "Interim block"
296
+ : deliverCallCount === 0
297
+ ? "First reply"
298
+ : "Final block";
299
+ if (result.status === "empty") {
300
+ // buffer 无内容但有快照(纯文本、无 deliver 文本块)→ 直接发快照。
301
+ if (snapshot) {
302
+ if (shouldSuppressDuplicateTextDeliver({
303
+ textPart: snapshot,
304
+ hasMedia: false,
305
+ lastDeliveredText,
306
+ lastDeliveredHadMedia,
307
+ })) {
308
+ log.info(`${logPrefix} [deliver-buffer] flush_${kind} snapshot_only skipped ` +
309
+ `(normalized same as last HTTP, len=${snapshot.length})`);
310
+ resetSegmentSnapshot();
311
+ }
312
+ else {
313
+ log.info(`${logPrefix} [deliver-buffer] flush_${kind} snapshot_only textLen=${snapshot.length}`);
314
+ resetSegmentSnapshot();
315
+ await postHttpDeliver({
316
+ payloadForSend: { text: snapshot },
317
+ textPart: snapshot,
318
+ sendLabel,
319
+ invokeNum: deliverInvokeCount,
320
+ hasMedia: false,
321
+ omitDuplicateFileCaption: false,
322
+ });
323
+ }
324
+ }
325
+ return;
326
+ }
327
+ if (result.status === "skipped_duplicate") {
328
+ log.info(`${logPrefix} [deliver-buffer] flush_${kind} skipped (same as previous HTTP, comparable match)`);
329
+ resetSegmentSnapshot();
330
+ return;
331
+ }
332
+ let { payload: payloadForSend, textPart } = result.entry;
333
+ const { hasMedia } = result.entry;
334
+ // 快照覆盖正文:仅当快照包含缓冲文本(归一化后为超集)时才覆盖,避免竞态截断;
335
+ // 媒体/附件等元数据仍沿用 deliver 的 payload。
336
+ if (snapshot && snapshot !== textPart) {
337
+ if (snapshotSupersedesBufferText(snapshot, textPart)) {
338
+ log.info(`${logPrefix} [deliver-buffer] flush_${kind} snapshot_override ` +
339
+ `bufferLen=${textPart.length} → snapshotLen=${snapshot.length}`);
340
+ payloadForSend = {
341
+ ...payloadForSend,
342
+ text: snapshot,
343
+ ...(payloadForSend.markdown != null ? { markdown: snapshot } : {}),
344
+ };
345
+ textPart = snapshot;
346
+ }
347
+ else {
348
+ log.warn(`${logPrefix} [deliver-buffer] flush_${kind} snapshot_skip (not superset; keep buffer) ` +
349
+ `bufferLen=${textPart.length} snapshotLen=${snapshot.length}`);
350
+ }
351
+ }
352
+ log.info(`${logPrefix} [deliver-buffer] flush_${kind} textLen=${textPart.length} hasMedia=${hasMedia}`);
353
+ resetSegmentSnapshot();
354
+ await postHttpDeliver({
355
+ payloadForSend,
356
+ textPart,
357
+ sendLabel,
358
+ invokeNum: deliverInvokeCount,
359
+ hasMedia,
360
+ omitDuplicateFileCaption: false,
361
+ });
362
+ };
363
+ dispatchInFlight = true;
364
+ dispatchResult = await rt.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
365
+ ctx: inboundCtx,
366
+ cfg: dispatchCfg,
367
+ replyOptions: {
368
+ ...resolveBlockStreamingReplyOptions(config),
369
+ sourceReplyDeliveryMode: "automatic",
370
+ suppressDefaultToolProgressMessages: true,
371
+ ...(modelOverride ? { modelOverride } : {}),
372
+ ...(thinkingLevelOverride ? { thinkingLevelOverride } : {}),
373
+ onAgentRunStart: (runId) => {
374
+ agentRunStarted = true;
375
+ agentRunId = runId.trim() || undefined;
376
+ terminal.setRunId(runId);
377
+ log.info(`${logPrefix} [dispatch] agent run started runId=${runId}`);
378
+ },
379
+ onModelSelected: (m) => {
380
+ // failover 候选启动时会多次触发;终态模型以 session store 为准(RUN_USAGE)
381
+ log.info(`${logPrefix} [model] run candidate provider=${m.provider} model=${m.model}`);
382
+ },
383
+ onPartialReply: async (payload) => {
384
+ if (!partialSnapshotEnabled)
385
+ return;
386
+ const text = typeof payload.text === "string" ? payload.text : "";
387
+ if (!text)
388
+ return;
389
+ partialReplyCount++;
390
+ if (text.length > partialReplyMaxTextLen)
391
+ partialReplyMaxTextLen = text.length;
392
+ const now = Date.now();
393
+ if (partialReplyFirstAt === 0) {
394
+ partialReplyFirstAt = now;
395
+ log.info(`${logPrefix} [partial] FIRST +${now - dispatchStart}ms textLen=${text.length}`);
396
+ }
397
+ // text 是当前 assistant 消息的全量快照(非增量):直接作为本段正文权威来源。
398
+ segmentSnapshotText = text;
399
+ segmentSnapshotHadPartial = true;
400
+ // 节流推送 WS 正文预览,供前端尽早覆盖显示同一输出位(HTTP 定稿前)。
401
+ await emitReplyPreviewWs(text, false);
402
+ },
403
+ onReasoningStream: async (payload) => {
404
+ const text = typeof payload.text === "string" ? payload.text : "";
405
+ if (!text.trim())
406
+ return;
407
+ thinkingWsBuffer.noteStream(text);
408
+ },
409
+ onReasoningEnd: async () => {
410
+ await flushThinkingWsOnce("reasoning_end");
411
+ },
412
+ onToolStart: async (p) => {
413
+ const name = typeof p.name === "string" && p.name.trim().length > 0 ? p.name.trim() : "tool";
414
+ const rawPhase = typeof p.phase === "string" ? p.phase.toLowerCase() : "";
415
+ console.log(`[xg_cwork_im] ${logPrefix} [onToolStart] name="${name}" phase="${rawPhase}" argsKeys=${p.args ? Object.keys(p.args).join(",") : "none"}`);
416
+ if (rawPhase === "update" || rawPhase === "delta" || rawPhase === "progress") {
417
+ return;
418
+ }
419
+ if (rawPhase === "end" || rawPhase === "fail" || rawPhase === "error") {
420
+ return;
421
+ }
422
+ if (!rawPhase || rawPhase === "start") {
423
+ try {
424
+ await flushSegmentBuffer("interim");
425
+ }
426
+ catch (interimErr) {
427
+ lastDeliverError = interimErr;
428
+ log.error(`${logPrefix} [deliver-buffer] flush_interim failed: ${String(interimErr)}`);
429
+ }
430
+ await flushThinkingWsOnce("before_tool");
431
+ toolNameStack.push(name);
432
+ if (name.includes("sessions_spawn") && !subagentNotificationSent) {
433
+ subagentNotificationSent = true;
434
+ try {
435
+ await sendTextMessage(config, currentIdentity.token, params.groupId, "已将任务分配给子助手处理,稍后会把结果发给您。");
436
+ console.log(`[xg_cwork_im] ${logPrefix} [subagent] sent notification from onToolStart`);
437
+ }
438
+ catch (sendErr) {
439
+ console.warn(`[xg_cwork_im] ${logPrefix} [subagent] onToolStart send failed: ${String(sendErr)}`);
440
+ }
441
+ }
442
+ }
443
+ // WS TOOL_PHASE 已移至全局 before_tool_call hook
444
+ },
445
+ onToolResult: async (payload) => {
446
+ const toolName = toolNameStack.length > 0 ? toolNameStack.pop() : "tool";
447
+ // WS TOOL_PHASE 已移至全局 after_tool_call hook
448
+ },
449
+ onItemEvent: async (p) => {
450
+ // 工具生命周期已由 onToolStart/onToolResult 覆盖;Reasoning 已由
451
+ // onReasoningStream/onReasoningEnd 覆盖(start/end 各触发一次)。二者
452
+ // 均不再进入 RUN_EVENT 兜底,避免内部诊断标识 `unmapped:*` 展示给用户。
453
+ const guard = resolveItemEventGuard(p);
454
+ if (guard.suppress)
455
+ return;
456
+ const text = (typeof p.progressText === "string" && p.progressText.trim()) ||
457
+ (typeof p.summary === "string" && p.summary.trim()) ||
458
+ (typeof p.title === "string" && p.title.trim()) ||
459
+ (typeof p.meta === "string" && p.meta.trim()) ||
460
+ "";
461
+ if (!text)
462
+ return;
463
+ // 未识别事件只记录日志,不发送给最终用户
464
+ log.debug?.(`${logPrefix} [stream] ignored unmapped onItemEvent ` +
465
+ `kind=${guard.kind || "unknown"} title=${guard.title || "unknown"}`);
466
+ },
467
+ onPlanUpdate: async (p) => {
468
+ const title = typeof p.title === "string" ? p.title.trim() : "";
469
+ if (title.length > 0) {
470
+ await notifyStreamProgress("PLAN_UPDATE", clipWsDisplayText(`正在更新计划:${title}`, 160), typeof p.explanation === "string" && p.explanation.trim()
471
+ ? clipWsProgressSummary(p.explanation.trim())
472
+ : undefined);
473
+ }
474
+ else if (typeof p.explanation === "string" && p.explanation.trim().length > 0) {
475
+ await notifyStreamProgress("PLAN_UPDATE", clipWsDisplayText(`计划更新:${p.explanation.trim()}`, 160));
476
+ }
477
+ else {
478
+ await notifyStreamProgress("PLAN_UPDATE", "正在更新执行计划…");
479
+ }
480
+ },
481
+ onCompactionStart: async () => {
482
+ terminal.noteCompactionWsEvent("start");
483
+ await notifyStreamProgress("RUN_EVENT", "正在整理上下文…");
484
+ },
485
+ onCompactionEnd: async () => {
486
+ terminal.noteCompactionWsEvent("end");
487
+ await notifyStreamProgress("RUN_EVENT", "上下文整理完成");
488
+ },
489
+ onApprovalEvent: async (p) => {
490
+ const raw = typeof p.title === "string" && p.title.trim().length > 0
491
+ ? p.title.trim()
492
+ : typeof p.message === "string" && p.message.trim().length > 0
493
+ ? p.message.trim()
494
+ : "审批状态更新";
495
+ await notifyStreamProgress("RUN_EVENT", clipWsDisplayText(raw, 160));
496
+ },
497
+ onCommandOutput: async (p) => {
498
+ const ph = typeof p.phase === "string" ? p.phase.toLowerCase() : "";
499
+ if (ph === "delta" || ph === "stream" || ph === "progress")
500
+ return;
501
+ const st = typeof p.status === "string" ? p.status.toLowerCase() : "";
502
+ const terminalPhase = ["completed", "complete", "done", "end", "failed", "fail", "error"].includes(ph);
503
+ const terminalStatus = ["completed", "failed", "error", "done"].includes(st);
504
+ const hasExit = p.exitCode != null;
505
+ if (!terminalPhase && !terminalStatus && !hasExit)
506
+ return;
507
+ const outRaw = typeof p.output === "string" ? p.output.trim() : "";
508
+ const outSum = outRaw ? clipWsProgressSummary(outRaw) : undefined;
509
+ if (ph === "failed" || ph === "fail" || ph === "error" || st === "failed" || st === "error") {
510
+ await notifyStreamProgress("RUN_EVENT", "计划有变,正在调整策略", outSum); //命令执行失败
511
+ return;
512
+ }
513
+ if (hasExit && p.exitCode !== 0) {
514
+ await notifyStreamProgress("RUN_EVENT", `命令已结束(退出码 ${p.exitCode})`, outSum);
515
+ return;
516
+ }
517
+ await notifyStreamProgress("RUN_EVENT", "命令已执行完毕", outSum);
518
+ },
519
+ onPatchSummary: async (_p) => {
520
+ await notifyStreamProgress("RUN_EVENT", "已记录文件变更摘要");
521
+ },
522
+ },
523
+ dispatcherOptions: {
524
+ responsePrefix: "",
525
+ onSkip: (payload, meta) => {
526
+ deliverSkippedCount++;
527
+ terminal.noteNormalizerSkip(meta.reason);
528
+ log.info(`${logPrefix} [deliver] Payload skipped by normalizer kind=${meta.kind} reason=${meta.reason}`);
529
+ },
530
+ onError: (err, meta) => {
531
+ lastDeliverError = err;
532
+ log.error(`${logPrefix} [deliver] Dispatcher caught unhandled error kind=${meta.kind}: ${String(err)}`);
533
+ },
534
+ deliver: async (payload, info) => {
535
+ try {
536
+ deliverInvokeCount++;
537
+ const textPayload = payload.markdown || payload.text || "";
538
+ const trimmedForSend = textPayload.trim();
539
+ const textPart = stripMediaDirectiveLines(trimmedForSend);
540
+ const hasMedia = Boolean(payload.mediaUrl?.trim()) ||
541
+ Boolean(payload.mediaUrls?.some((u) => typeof u === "string" && u.trim()));
542
+ const textPreview = textPart.length > 160
543
+ ? `${textPart.slice(0, 80)}…${textPart.slice(-80)}`
544
+ : textPart;
545
+ log.info(`${logPrefix} [deliver] invoke #${deliverInvokeCount} isThinking=${payload.isThinking ?? false} ` +
546
+ `textLen=${textPart.length} hasMedia=${hasMedia} mediaUrl=${Boolean(payload.mediaUrl?.trim())} ` +
547
+ `kind=${info?.kind ?? "none"} ` +
548
+ `preview=${JSON.stringify(textPreview || "(empty)")}`);
549
+ if (!hasMedia && !stripModelUsageFooter(textPart).trim()) {
550
+ deliverSkippedCount++;
551
+ log.info(`${logPrefix} [deliver] skip: model usage footer only (rawLen=${trimmedForSend.length})`);
552
+ return;
553
+ }
554
+ if (payload.isError === true) {
555
+ const errRaw = textPart || "(empty)";
556
+ terminal.noteRuntimeErrorFromPayload(errRaw);
557
+ const userText = formatConfirmedUpstreamErrorForIm(errRaw);
558
+ if (!userText) {
559
+ deliverSkippedCount++;
560
+ log.info(`${logPrefix} [deliver] isError payload empty after format; skipped HTTP`);
561
+ return;
562
+ }
563
+ // 上游已 deliver 的错误:HTTP 发出(白名单人话或原文),不再等到终态换插件空话
564
+ const errorPayload = {
565
+ ...payload,
566
+ text: userText,
567
+ markdown: userText,
568
+ isError: true,
569
+ };
570
+ log.info(`${logPrefix} [deliver] isError → HTTP (confirmed map or passthrough) ` +
571
+ `len=${userText.length}`);
572
+ await postHttpDeliver({
573
+ payloadForSend: errorPayload,
574
+ textPart: userText,
575
+ sendLabel: deliverInvokeCount === 1 ? "First reply (error)" : "Error payload",
576
+ invokeNum: deliverInvokeCount,
577
+ hasMedia: false,
578
+ omitDuplicateFileCaption: false,
579
+ });
580
+ return;
581
+ }
582
+ if (payload.isCompactionNotice === true) {
583
+ deliverSkippedCount++;
584
+ terminal.noteCompactionNotice(textPart || "Compacting context...");
585
+ log.info(`${logPrefix} [deliver] Compaction notice suppressed from HTTP (WS progress only): ` +
586
+ `${JSON.stringify((textPart || "").slice(0, 80))}`);
587
+ return;
588
+ }
589
+ if (payload.isReasoning === true) {
590
+ deliverSkippedCount++;
591
+ if (textPart)
592
+ thinkingWsBuffer.noteStream(textPart);
593
+ await flushThinkingWsOnce("deliver_reasoning");
594
+ log.info(`${logPrefix} [deliver] Thinking block → single WS RUN_EVENT (len=${textPart.length})`);
595
+ return;
596
+ }
597
+ if (shouldSuppressFallbackNoticeForIm({
598
+ isFallbackNotice: payload.isFallbackNotice === true,
599
+ deliverModelFallbackNotice: config.deliverModelFallbackNotice,
600
+ requestedModelRaw: modelOverride,
601
+ noticeText: textPart,
602
+ })) {
603
+ deliverSkippedCount++;
604
+ const reason = config.deliverModelFallbackNotice === true
605
+ ? "spurious per-message fallback notice"
606
+ : "model fallback notice disabled for IM (deliverModelFallbackNotice)";
607
+ log.info(`${logPrefix} [model] Suppressing fallback notice (${reason}): ` +
608
+ `${JSON.stringify(textPart.slice(0, 120))}`);
609
+ return;
610
+ }
611
+ if (!segmentBufferEnabled &&
612
+ shouldSuppressDuplicateTextDeliver({
613
+ textPart,
614
+ hasMedia,
615
+ lastDeliveredText,
616
+ lastDeliveredHadMedia,
617
+ })) {
618
+ deliverSkippedCount++;
619
+ log.info(`${logPrefix} [deliver] Suppressed duplicate text-only deliver ` +
620
+ `(normalized same as previous, rawLen=${textPart.length})`);
621
+ return;
622
+ }
623
+ let omitDuplicateFileCaption = false;
624
+ if (!segmentBufferEnabled) {
625
+ omitDuplicateFileCaption = shouldOmitDuplicateFileCaption({
626
+ textPart,
627
+ hasMedia,
628
+ lastDeliveredText,
629
+ lastDeliveredHadMedia,
630
+ });
631
+ if (omitDuplicateFileCaption) {
632
+ log.info(`${logPrefix} [deliver] Omitting duplicate file caption ` +
633
+ `(normalized same as previous text, rawLen=${textPart.length})`);
634
+ }
635
+ }
636
+ if (!isDeliverPayloadSendable({
637
+ textPart,
638
+ hasMedia,
639
+ isThinking: payload.isThinking,
640
+ })) {
641
+ deliverSkippedCount++;
642
+ log.info(`${logPrefix} [deliver] Payload has no sendable content, skipping` +
643
+ ` (isThinking=${payload.isThinking ?? false} hasMedia=${hasMedia})`);
644
+ return;
645
+ }
646
+ let payloadForSend = textPart !== trimmedForSend
647
+ ? {
648
+ ...payload,
649
+ ...(payload.markdown != null
650
+ ? { markdown: textPart }
651
+ : { text: textPart }),
652
+ }
653
+ : payload;
654
+ if (omitDuplicateFileCaption) {
655
+ payloadForSend = { ...payloadForSend, text: "", markdown: "" };
656
+ }
657
+ if (segmentBufferEnabled && segmentBuffer) {
658
+ if (info?.kind === "final" && segmentBuffer.hasContent()) {
659
+ segmentBuffer.clear();
660
+ log.info(`${logPrefix} [deliver] final block replaces buffer (intermediates discarded, textLen=${textPart.length})`);
661
+ }
662
+ if (shouldSuppressDuplicateTextDeliver({ textPart, hasMedia, lastDeliveredText, lastDeliveredHadMedia })) {
663
+ deliverSkippedCount++;
664
+ log.info(`${logPrefix} [deliver-buffer] skip: same as last HTTP delivered ` +
665
+ `(normalized match, textLen=${textPart.length})`);
666
+ return;
667
+ }
668
+ segmentBuffer.write({ payload: payloadForSend, textPart, rawTextPart: textPayload, hasMedia });
669
+ if (!hasBufferedSendable) {
670
+ hasBufferedSendable = true;
671
+ clearTimeout(firstReplyTimeout);
672
+ }
673
+ log.info(`${logPrefix} [deliver-buffer] write invoke=#${deliverInvokeCount} ` +
674
+ `textLen=${textPart.length} hasMedia=${hasMedia}`);
675
+ return;
676
+ }
677
+ const sendLabel = deliverInvokeCount === 1
678
+ ? "First reply"
679
+ : blockStreamingEnabled
680
+ ? "Interim block"
681
+ : "Additional reply";
682
+ await postHttpDeliver({
683
+ payloadForSend,
684
+ textPart,
685
+ sendLabel,
686
+ invokeNum: deliverInvokeCount,
687
+ hasMedia,
688
+ omitDuplicateFileCaption,
689
+ });
690
+ }
691
+ catch (err) {
692
+ log.error(`${logPrefix} [deliver] Reply deliver failed: ${String(err)}`);
693
+ throw err;
694
+ }
695
+ },
696
+ },
697
+ });
698
+ dispatchInFlight = false;
699
+ const bufStats = segmentBuffer?.getStats();
700
+ log.info(`${logPrefix} [dispatch] Dispatch completed for sessionKey=${route.sessionKey}` +
701
+ ` (invoke=${deliverInvokeCount} delivered=${deliverCallCount} skipped=${deliverSkippedCount}` +
702
+ (bufStats
703
+ ? ` buffer_writes=${bufStats.writeCount}` +
704
+ ` revision_overwrite=${bufStats.revisionOverwriteCount}` +
705
+ ` segment_append=${bufStats.segmentAppendCount}` +
706
+ ` flush_interim=${bufStats.flushInterimCount}` +
707
+ ` flush_final=${bufStats.flushFinalCount}` +
708
+ ` flush_dup_skip=${bufStats.skippedDuplicateFlushCount}`
709
+ : "") +
710
+ `)`);
711
+ if (partialSnapshotEnabled) {
712
+ log.info(`${logPrefix} [partial] SUMMARY count=${partialReplyCount} ` +
713
+ `maxTextLen=${partialReplyMaxTextLen} ` +
714
+ `firstAt=${partialReplyFirstAt ? partialReplyFirstAt - dispatchStart : -1}ms ` +
715
+ `(count=0 → 该配置下未回调 partial,flush 回退到 deliver 段缓冲)`);
716
+ }
717
+ if (deliverInvokeCount === 0) {
718
+ log.warn(`${logPrefix} [dispatch] OpenClaw never invoked channel deliver() for this turn — ` +
719
+ `this plugin will not POST /im/message/send; IM「收到消息」若存在,多半来自占位/END 或其它通道,而非本插件 HTTP 合并`);
720
+ }
721
+ else if (deliverCallCount === 0 && !segmentBuffer?.hasContent()) {
722
+ log.warn(`${logPrefix} [dispatch] deliver() invoked ${deliverInvokeCount} time(s) but none had sendable text/media — ` +
723
+ `check model output (thinking-only / empty blocks) or OpenClaw normalizer`);
724
+ }
725
+ }
726
+ catch (dispatchErr) {
727
+ dispatchError = dispatchErr;
728
+ log.error(`${logPrefix} [dispatch] Dispatch failed (invoke=${deliverInvokeCount} delivered=${deliverCallCount} skipped=${deliverSkippedCount}): ${String(dispatchErr)}`);
729
+ }
730
+ finally {
731
+ dispatchInFlight = false;
732
+ clearPendingPerMessageModel(route.sessionKey);
733
+ try {
734
+ await flushSegmentBuffer("final");
735
+ }
736
+ catch (flushErr) {
737
+ lastDeliverError = flushErr;
738
+ log.error(`${logPrefix} [deliver-buffer] flush_final failed: ${String(flushErr)}`);
739
+ }
740
+ clearTimeout(firstReplyTimeout);
741
+ const terminalState = await terminal.finalizeAndDeliver({
742
+ sendFn: terminalSend,
743
+ dispatchThrew: dispatchError !== undefined,
744
+ dispatchError,
745
+ lastDeliverError,
746
+ beforeAgentRunBlocked: dispatchResult?.beforeAgentRunBlocked === true,
747
+ deliverInvokeCount,
748
+ deliverCallCount,
749
+ });
750
+ const endReason = terminalState === "success" ||
751
+ hasFirstReply ||
752
+ terminal.wasTerminalDelivered() ||
753
+ terminal.didTimeoutFire() ||
754
+ subagentNotificationSent
755
+ ? "stop"
756
+ : "no_reply";
757
+ // `/stop` 仅借用 OpenClaw dispatch 触发 fast-abort;原轮次的 suspended/aborted
758
+ // 由 account-connection 在 dispatch 返回后串行收口,控制消息自身不产生 WS 事件。
759
+ if (isStopControl)
760
+ return;
761
+ // 当前业务轮次已被并发 `/stop` 接管时,收口事件由 interrupt-round 负责。
762
+ if (activeRound?.interrupted) {
763
+ log.info(`${logPrefix} [stream] round interrupted; skip late RUN_USAGE/FINISHED`);
764
+ return;
765
+ }
766
+ try {
767
+ const storePath = rt.channel.session.resolveStorePath(cfg.session?.store, {
768
+ agentId: config.agentId || "main",
769
+ });
770
+ const sessionFields = readSessionUsageFields({
771
+ storePath,
772
+ sessionKey: route.sessionKey,
773
+ });
774
+ const usage = buildRunUsageFromSessionEntry(sessionFields, {
775
+ runId: agentRunId ?? terminal.getRunId(),
776
+ });
777
+ if (hasReportableUsage(usage) && usage) {
778
+ await streamClient.streamUsage(toImStreamRunUsageData(usage, {
779
+ groupId: params.groupId,
780
+ replyToMsgId: params.msgId,
781
+ }));
782
+ }
783
+ else {
784
+ log.info(`${logPrefix} [stream] RUN_USAGE skipped (session store has no model/token; ` +
785
+ `sessionKey=${route.sessionKey} deliver_call=${deliverCallCount})`);
786
+ }
787
+ }
788
+ catch (usageErr) {
789
+ log.warn(`${logPrefix} [stream] RUN_USAGE failed: ${String(usageErr)}`);
790
+ }
791
+ // ✅ 检查是否有活跃的 subagent,如果有则延迟 FINISHED
792
+ if (activeRound &&
793
+ hasActiveSubagents(activeRound.roundKey, activeRound.generation)) {
794
+ log.info(`${logPrefix} [stream] FINISHED deferred: has active subagents, ` +
795
+ `will be sent by monitor when all complete. reason=${endReason} ` +
796
+ `terminal_state=${terminalState} deliver_invoke=${deliverInvokeCount}`);
797
+ // 记录延迟的 FINISHED,由 subagent-monitor 在所有完成后发送
798
+ deferFinished(activeRound.roundKey, activeRound.generation, endReason);
799
+ }
800
+ else {
801
+ // 没有活跃 subagent,正常发送 FINISHED
802
+ try {
803
+ await streamClient.end(endReason, {
804
+ groupId: params.groupId,
805
+ replyToMsgId: params.msgId,
806
+ });
807
+ log.info(`${logPrefix} [stream] FINISHED sent: reason=${endReason} terminal_state=${terminalState} ` +
808
+ `has_first_reply=${hasFirstReply} deliver_invoke=${deliverInvokeCount} ` +
809
+ `deliver_call=${deliverCallCount} skipped=${deliverSkippedCount}`);
810
+ }
811
+ catch (endErr) {
812
+ log.error(`${logPrefix} [stream] FINISHED failed: ${String(endErr)}`);
813
+ }
814
+ finally {
815
+ if (activeRound) {
816
+ completeActiveRound(activeRound.roundKey, activeRound.generation);
817
+ }
818
+ }
819
+ }
820
+ }
821
+ }
822
+ //# sourceMappingURL=dispatch-mentioned-reply.js.map