@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,28 @@
1
+ /**
2
+ * `onItemEvent` 条目过滤:已由专用回调覆盖的条目(工具、Reasoning)不再进入
3
+ * RUN_EVENT 兜底,避免把内部诊断标识 `unmapped:*` 展示给最终用户。
4
+ */
5
+ export interface ItemEventPayload {
6
+ toolCallId?: string;
7
+ kind?: string;
8
+ title?: string;
9
+ name?: string;
10
+ phase?: string;
11
+ status?: string;
12
+ }
13
+ export type ItemEventGuardResult = {
14
+ suppress: true;
15
+ reason: "tool" | "reasoning";
16
+ } | {
17
+ suppress: false;
18
+ kind: string;
19
+ title: string;
20
+ };
21
+ /**
22
+ * 判断 `onItemEvent` 条目是否应被抑制:
23
+ * - 工具类(`toolCallId` 或 `kind=tool`)已由 onToolStart/onToolResult 覆盖;
24
+ * - Reasoning 条目(`kind=analysis` 且 `title=reasoning`)已由
25
+ * onReasoningStream/onReasoningEnd 覆盖,同一条目 start/end 各触发一次,禁止重复投递。
26
+ */
27
+ export declare function resolveItemEventGuard(p: ItemEventPayload): ItemEventGuardResult;
28
+ //# sourceMappingURL=item-event-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item-event-guard.d.ts","sourceRoot":"","sources":["../../src/item-event-guard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,gBAAgB;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,oBAAoB,GAC1B;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,GAChD;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,gBAAgB,GAAG,oBAAoB,CAU/E"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `onItemEvent` 条目过滤:已由专用回调覆盖的条目(工具、Reasoning)不再进入
3
+ * RUN_EVENT 兜底,避免把内部诊断标识 `unmapped:*` 展示给最终用户。
4
+ */
5
+ /**
6
+ * 判断 `onItemEvent` 条目是否应被抑制:
7
+ * - 工具类(`toolCallId` 或 `kind=tool`)已由 onToolStart/onToolResult 覆盖;
8
+ * - Reasoning 条目(`kind=analysis` 且 `title=reasoning`)已由
9
+ * onReasoningStream/onReasoningEnd 覆盖,同一条目 start/end 各触发一次,禁止重复投递。
10
+ */
11
+ export function resolveItemEventGuard(p) {
12
+ if (p.toolCallId || p.kind === "tool") {
13
+ return { suppress: true, reason: "tool" };
14
+ }
15
+ const kind = String(p.kind ?? "").trim().toLowerCase();
16
+ const title = String(p.title ?? "").trim().toLowerCase();
17
+ if (kind === "analysis" && title === "reasoning") {
18
+ return { suppress: true, reason: "reasoning" };
19
+ }
20
+ return { suppress: false, kind, title };
21
+ }
22
+ //# sourceMappingURL=item-event-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item-event-guard.js","sourceRoot":"","sources":["../../src/item-event-guard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAmB;IACrD,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACpC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAC9C,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzD,IAAI,IAAI,KAAK,UAAU,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;QAC/C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=item-event-guard.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item-event-guard.test.d.ts","sourceRoot":"","sources":["../../src/item-event-guard.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+ import { resolveItemEventGuard } from "./item-event-guard.js";
4
+ describe("item-event-guard", () => {
5
+ it("suppresses reasoning item start (phase=start)", () => {
6
+ const r = resolveItemEventGuard({
7
+ kind: "analysis",
8
+ title: "Reasoning",
9
+ phase: "start",
10
+ status: "running",
11
+ });
12
+ assert.equal(r.suppress, true);
13
+ assert.equal(r.reason, "reasoning");
14
+ });
15
+ it("suppresses reasoning item end (phase=end)", () => {
16
+ const r = resolveItemEventGuard({
17
+ kind: "analysis",
18
+ title: "Reasoning",
19
+ phase: "end",
20
+ status: "completed",
21
+ });
22
+ assert.equal(r.suppress, true);
23
+ assert.equal(r.reason, "reasoning");
24
+ });
25
+ it("suppresses tool-call items even when title is reasoning", () => {
26
+ const r = resolveItemEventGuard({
27
+ toolCallId: "call_123",
28
+ kind: "analysis",
29
+ title: "Reasoning",
30
+ });
31
+ assert.equal(r.suppress, true);
32
+ assert.equal(r.reason, "tool");
33
+ });
34
+ it("suppresses kind=tool items", () => {
35
+ const r = resolveItemEventGuard({ kind: "tool", title: "Web search" });
36
+ assert.equal(r.suppress, true);
37
+ assert.equal(r.reason, "tool");
38
+ });
39
+ it("matches reasoning case-insensitively with surrounding whitespace", () => {
40
+ const r = resolveItemEventGuard({ kind: " ANALYSIS ", title: " reasoning " });
41
+ assert.equal(r.suppress, true);
42
+ });
43
+ it("keeps supported user-facing progress events (not suppressed)", () => {
44
+ const r = resolveItemEventGuard({
45
+ kind: "search",
46
+ title: "Web search",
47
+ phase: "start",
48
+ status: "running",
49
+ });
50
+ assert.equal(r.suppress, false);
51
+ assert.equal(r.kind, "search");
52
+ assert.equal(r.title, "web search");
53
+ });
54
+ });
55
+ //# sourceMappingURL=item-event-guard.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"item-event-guard.test.js","sourceRoot":"","sources":["../../src/item-event-guard.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,GAAG,qBAAqB,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,WAAW;YAClB,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,SAAS;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,GAAG,qBAAqB,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,WAAW;YAClB,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,WAAW;SACtB,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,GAAG,qBAAqB,CAAC;YAC5B,UAAU,EAAE,UAAU;YACtB,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,WAAW;SACrB,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,GAAG,qBAAqB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,GAAG,qBAAqB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACpE,MAAM,CAAC,GAAG,qBAAqB,CAAC;YAC5B,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,SAAS;SACpB,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC/B,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { Logger } from "./channel-log.js";
2
+ import { type ReplyDeliverPayload } from "./send-service.js";
3
+ import type { WsMessageParams, XgImConfig } from "./types.js";
4
+ export type PatchSummaryPayload = {
5
+ added?: string[];
6
+ modified?: string[];
7
+ deleted?: string[];
8
+ };
9
+ type FlushArgs = {
10
+ config: XgImConfig;
11
+ token: string;
12
+ params: WsMessageParams;
13
+ };
14
+ export declare function createModifiedFilePushTracker(options: {
15
+ agentWorkspaceDir?: string;
16
+ log: Logger;
17
+ logPrefix: string;
18
+ }): {
19
+ recordPatchSummary: (payload: PatchSummaryPayload) => void;
20
+ markDelivered: (payload: ReplyDeliverPayload) => void;
21
+ flush: (args: FlushArgs) => Promise<void>;
22
+ };
23
+ export {};
24
+ //# sourceMappingURL=modified-file-push-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modified-file-push-tracker.d.ts","sourceRoot":"","sources":["../../src/modified-file-push-tracker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAyB,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,MAAM,mBAAmB,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AAEF,KAAK,SAAS,GAAG;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,CAAC;CAC3B,CAAC;AAwFF,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACnD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACrB,GAAG;IACA,kBAAkB,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACtD,KAAK,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C,CAgDA"}
@@ -0,0 +1,125 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { buildTargetReplyMeta } from "./inbound-display.js";
5
+ import { resolveLocalFsPath, resolveWorkspaceCandidatePaths } from "./resource-file.js";
6
+ import { sendReplyDeliverBlock } from "./send-service.js";
7
+ function isUrlLike(value) {
8
+ return /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(value.trim());
9
+ }
10
+ function normalizePushPath(filePath, workspaceDir) {
11
+ const clean = filePath.trim();
12
+ if (clean.startsWith("/workspace/") || clean === "/workspace") {
13
+ return clean;
14
+ }
15
+ if (isUrlLike(clean)) {
16
+ return clean;
17
+ }
18
+ const wsDir = workspaceDir?.trim();
19
+ if (wsDir) {
20
+ const wsResolved = path.resolve(wsDir);
21
+ const fileResolved = path.isAbsolute(clean) ? path.resolve(clean) : path.resolve(wsResolved, clean);
22
+ const relToWorkspace = path.relative(wsResolved, fileResolved);
23
+ if (!relToWorkspace.startsWith("..") && !path.isAbsolute(relToWorkspace)) {
24
+ return relToWorkspace ? `/workspace/${relToWorkspace.replace(/\\/g, "/")}` : "/workspace";
25
+ }
26
+ }
27
+ return clean;
28
+ }
29
+ function pushPathCandidates(filePath, workspaceDir) {
30
+ const clean = filePath.trim();
31
+ if (!clean)
32
+ return [];
33
+ if (clean.startsWith("/workspace/") || clean === "/workspace") {
34
+ try {
35
+ return resolveWorkspaceCandidatePaths(clean, workspaceDir);
36
+ }
37
+ catch {
38
+ return [];
39
+ }
40
+ }
41
+ if (clean.startsWith("file://")) {
42
+ try {
43
+ return [fileURLToPath(clean)];
44
+ }
45
+ catch {
46
+ return [];
47
+ }
48
+ }
49
+ const local = resolveLocalFsPath(clean);
50
+ if (local)
51
+ return [local.fsPath];
52
+ const wsDir = workspaceDir?.trim();
53
+ if (wsDir && !path.isAbsolute(clean)) {
54
+ return [path.resolve(wsDir, clean)];
55
+ }
56
+ return [];
57
+ }
58
+ async function isExistingRegularPushFile(filePath, workspaceDir) {
59
+ for (const candidate of pushPathCandidates(filePath, workspaceDir)) {
60
+ try {
61
+ const stat = await fs.stat(candidate);
62
+ if (stat.isFile())
63
+ return true;
64
+ }
65
+ catch {
66
+ /* try next candidate */
67
+ }
68
+ }
69
+ return false;
70
+ }
71
+ async function filterExistingPushFiles(files, workspaceDir, log, logPrefix) {
72
+ const out = [];
73
+ for (const file of files) {
74
+ if (await isExistingRegularPushFile(file, workspaceDir)) {
75
+ out.push(file);
76
+ }
77
+ else {
78
+ log.warn(`${logPrefix} [sync-push] Skip non-existing or non-file path: ${JSON.stringify(file)}`);
79
+ }
80
+ }
81
+ return out;
82
+ }
83
+ function payloadMediaUrls(payload) {
84
+ return [
85
+ ...(payload.mediaUrl ? [payload.mediaUrl] : []),
86
+ ...(payload.mediaUrls ?? []),
87
+ ].filter((u) => typeof u === "string" && u.trim());
88
+ }
89
+ export function createModifiedFilePushTracker(options) {
90
+ const { agentWorkspaceDir, log, logPrefix } = options;
91
+ const modifiedFiles = new Set();
92
+ return {
93
+ recordPatchSummary(payload) {
94
+ payload.added?.forEach((f) => modifiedFiles.add(normalizePushPath(f, agentWorkspaceDir)));
95
+ payload.modified?.forEach((f) => modifiedFiles.add(normalizePushPath(f, agentWorkspaceDir)));
96
+ },
97
+ markDelivered(payload) {
98
+ for (const url of payloadMediaUrls(payload)) {
99
+ modifiedFiles.delete(normalizePushPath(url, agentWorkspaceDir));
100
+ }
101
+ },
102
+ async flush(args) {
103
+ if (modifiedFiles.size === 0)
104
+ return;
105
+ const mediaUrls = await filterExistingPushFiles(modifiedFiles, agentWorkspaceDir, log, logPrefix);
106
+ if (mediaUrls.length === 0) {
107
+ log.info(`${logPrefix} [sync-push] No existing modified files to push`);
108
+ return;
109
+ }
110
+ log.info(`${logPrefix} [sync-push] 自动推送变动文件至客户端: ${JSON.stringify(mediaUrls)}`);
111
+ try {
112
+ const reply = buildTargetReplyMeta(args.params);
113
+ await sendReplyDeliverBlock(args.config, args.token, args.params.groupId, {
114
+ text: "已自动将本次修改的文件同步到工作区,您可以在右侧面板进行审阅:",
115
+ isThinking: false,
116
+ mediaUrls,
117
+ }, [reply.targetUserId], log, undefined, reply, agentWorkspaceDir);
118
+ }
119
+ catch (err) {
120
+ log.error(`${logPrefix} [sync-push] 自动推送文件附件失败: ${String(err)}`);
121
+ }
122
+ },
123
+ };
124
+ }
125
+ //# sourceMappingURL=modified-file-push-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modified-file-push-tracker.js","sourceRoot":"","sources":["../../src/modified-file-push-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 会话级 NAS 目录声明:路径规范化、安全校验、幂等指纹与 OpenClaw sandbox bind 注入。
3
+ */
4
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
5
+ import type { NasVolume } from "./agent-context-types.js";
6
+ import type { XgImConfig } from "./types.js";
7
+ export interface NormalizedNasVolume {
8
+ /** 已解析软链接后的宿主机真实目录。 */
9
+ realDir: string;
10
+ /** 相对 Agent workspace 的 POSIX 路径。 */
11
+ dockerDir: string;
12
+ /** 容器内绝对路径。 */
13
+ sandboxDir: string;
14
+ mode: "ro" | "rw";
15
+ }
16
+ /** 将 IM 的 dockerDir 规范为不带 /workspace 前缀的 workspace 相对路径。 */
17
+ export declare function normalizeNasDockerDir(raw: string): string;
18
+ export declare function nasVolumeSandboxDir(dockerDir: string): string;
19
+ /** Prompt 使用的轻量规范化;真实路径与白名单在 dispatch 前再次校验。 */
20
+ export declare function normalizeNasVolumesForPrompt(volumes: NasVolume[] | undefined): Array<{
21
+ dockerDir: string;
22
+ sandboxDir: string;
23
+ mode: "ro" | "rw";
24
+ }>;
25
+ export declare function validateAndNormalizeNasVolumes(volumes: NasVolume[], config: XgImConfig): NormalizedNasVolume[];
26
+ export declare function nasVolumeSpecHash(volumes: NormalizedNasVolume[]): string;
27
+ /**
28
+ * 将本会话期望的 NAS mounts 注入本轮 cfg。重复传入相同声明是幂等的;同一 session 改绑则拒绝。
29
+ */
30
+ export declare function resolveNasVolumeDispatchConfig(args: {
31
+ cfg: OpenClawConfig;
32
+ config: XgImConfig;
33
+ agentId: string;
34
+ sessionKey: string;
35
+ volumes?: NasVolume[];
36
+ }): {
37
+ cfg: OpenClawConfig;
38
+ specHash?: string;
39
+ reused: boolean;
40
+ };
41
+ /** 测试与 Gateway 停止时使用。 */
42
+ export declare function clearSessionNasVolumeStates(): void;
43
+ //# sourceMappingURL=nas-volumes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nas-volumes.d.ts","sourceRoot":"","sources":["../../src/nas-volumes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ7C,MAAM,WAAW,mBAAmB;IAChC,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACrB;AAqED,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAqBzD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,gDAAgD;AAChD,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,GAAG,KAAK,CAAC;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CACrB,CAAC,CAMD;AA6GD,wBAAgB,8BAA8B,CAC1C,OAAO,EAAE,SAAS,EAAE,EACpB,MAAM,EAAE,UAAU,GACnB,mBAAmB,EAAE,CAcvB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,MAAM,CAKxE;AAyDD;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACjD,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;CACzB,GAAG;IAAE,GAAG,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CA0C9D;AAED,yBAAyB;AACzB,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * 会话级 NAS 目录声明:路径规范化、安全校验、幂等指纹与 OpenClaw sandbox bind 注入。
3
+ */
4
+ import { createHash } from "node:crypto";
5
+ import { existsSync, mkdirSync, realpathSync, statSync } from "node:fs";
6
+ import path from "node:path";
7
+ const SANDBOX_WORKSPACE_ROOT = "/workspace";
8
+ /** 缓存仅用于短期复用同一会话声明;硬上限防止长期运行时随历史会话无限增长。 */
9
+ const SESSION_NAS_VOLUME_STATE_MAX_ENTRIES = 2_000;
10
+ const SESSION_NAS_VOLUME_STATE_TTL_MS = 2 * 60 * 60 * 1_000;
11
+ const SESSION_NAS_VOLUME_STATE_PRUNE_INTERVAL_MS = 60 * 1_000;
12
+ const sessionVolumeStates = new Map();
13
+ let lastSessionVolumeStatePruneAt = 0;
14
+ function pruneSessionNasVolumeStates(now, force = false) {
15
+ if (!force &&
16
+ sessionVolumeStates.size <= SESSION_NAS_VOLUME_STATE_MAX_ENTRIES &&
17
+ now - lastSessionVolumeStatePruneAt < SESSION_NAS_VOLUME_STATE_PRUNE_INTERVAL_MS) {
18
+ return;
19
+ }
20
+ lastSessionVolumeStatePruneAt = now;
21
+ for (const [key, state] of sessionVolumeStates) {
22
+ if (now - state.lastSeenAt >= SESSION_NAS_VOLUME_STATE_TTL_MS) {
23
+ sessionVolumeStates.delete(key);
24
+ }
25
+ }
26
+ while (sessionVolumeStates.size > SESSION_NAS_VOLUME_STATE_MAX_ENTRIES) {
27
+ const oldestKey = sessionVolumeStates.keys().next().value;
28
+ if (oldestKey == null)
29
+ break;
30
+ sessionVolumeStates.delete(oldestKey);
31
+ }
32
+ }
33
+ function isInsideOrEqual(root, target) {
34
+ const relative = path.relative(root, target);
35
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
36
+ }
37
+ function bindContainerTarget(bind) {
38
+ const parts = bind.split(":");
39
+ for (let index = parts.length - 1; index >= 0; index -= 1) {
40
+ const candidate = parts[index].trim().replace(/\\/g, "/");
41
+ if (candidate.startsWith("/"))
42
+ return path.posix.normalize(candidate);
43
+ }
44
+ return undefined;
45
+ }
46
+ function assertNoExistingBindTargetConflicts(existingBinds, incomingBinds) {
47
+ for (const incoming of incomingBinds) {
48
+ const incomingTarget = bindContainerTarget(incoming);
49
+ if (!incomingTarget)
50
+ continue;
51
+ for (const existing of existingBinds) {
52
+ if (existing === incoming)
53
+ continue;
54
+ const existingTarget = bindContainerTarget(existing);
55
+ if (!existingTarget)
56
+ continue;
57
+ if (incomingTarget === existingTarget ||
58
+ incomingTarget.startsWith(`${existingTarget}/`) ||
59
+ existingTarget.startsWith(`${incomingTarget}/`)) {
60
+ throw new Error(`NAS_VOLUME_TARGET_CONFLICT: dockerDir 与已有 sandbox bind 目标冲突: ${incomingTarget}, ${existingTarget}`);
61
+ }
62
+ }
63
+ }
64
+ }
65
+ /** 将 IM 的 dockerDir 规范为不带 /workspace 前缀的 workspace 相对路径。 */
66
+ export function normalizeNasDockerDir(raw) {
67
+ let value = raw.trim().replace(/\\/g, "/");
68
+ if (value === "/workspace" || value === "/workspace/") {
69
+ throw new Error("nasVolumes.dockerDir 不能指向 workspace 根目录");
70
+ }
71
+ if (value.startsWith("/workspace/"))
72
+ value = value.slice("/workspace/".length);
73
+ while (value.startsWith("./"))
74
+ value = value.slice(2);
75
+ while (value.startsWith("/"))
76
+ value = value.slice(1);
77
+ value = value.replace(/\/+$/, "");
78
+ if (!value)
79
+ throw new Error("nasVolumes.dockerDir 不能为空");
80
+ const parts = value.split("/");
81
+ for (const part of parts) {
82
+ if (!part || part === "." || part === "..") {
83
+ throw new Error(`nasVolumes.dockerDir 含非法路径段: ${raw}`);
84
+ }
85
+ if (/[\0-\x1f:*?"<>|]/.test(part)) {
86
+ throw new Error(`nasVolumes.dockerDir 含非法字符: ${raw}`);
87
+ }
88
+ }
89
+ return parts.join("/");
90
+ }
91
+ export function nasVolumeSandboxDir(dockerDir) {
92
+ return `${SANDBOX_WORKSPACE_ROOT}/${normalizeNasDockerDir(dockerDir)}`;
93
+ }
94
+ /** Prompt 使用的轻量规范化;真实路径与白名单在 dispatch 前再次校验。 */
95
+ export function normalizeNasVolumesForPrompt(volumes) {
96
+ if (!volumes?.length)
97
+ return [];
98
+ return volumes.map((volume) => {
99
+ const dockerDir = normalizeNasDockerDir(volume.dockerDir);
100
+ return { dockerDir, sandboxDir: nasVolumeSandboxDir(dockerDir), mode: volume.mode };
101
+ });
102
+ }
103
+ function normalizeAllowedRoots(config) {
104
+ const mappings = config.nasVolumeRootMappings ?? [];
105
+ if (mappings.length === 0) {
106
+ throw new Error("NAS_VOLUME_ROOTS_NOT_CONFIGURED: channels.xg_cwork_im.nasVolumeRootMappings 未配置");
107
+ }
108
+ return mappings.map((mapping) => {
109
+ const logicalRoot = normalizeLogicalRoot(mapping.logicalRoot);
110
+ const hostRoot = mapping.hostRoot.trim();
111
+ if (!path.isAbsolute(hostRoot)) {
112
+ throw new Error(`NAS_VOLUME_ROOT_INVALID: hostRoot 必须是宿主机绝对路径: ${hostRoot}`);
113
+ }
114
+ const configuredRoot = path.resolve(hostRoot);
115
+ const realRoot = realpathSync(configuredRoot);
116
+ if (!statSync(realRoot).isDirectory()) {
117
+ throw new Error(`NAS_VOLUME_ROOT_INVALID: hostRoot 不是目录: ${hostRoot}`);
118
+ }
119
+ return { logicalRoot, configuredRoot, realRoot };
120
+ }).sort((left, right) => right.logicalRoot.length - left.logicalRoot.length);
121
+ }
122
+ function normalizeLogicalRoot(raw) {
123
+ const value = raw.trim().replace(/\\/g, "/");
124
+ if (!value.startsWith("/")) {
125
+ throw new Error(`NAS_VOLUME_ROOT_INVALID: logicalRoot 必须是绝对逻辑路径: ${raw}`);
126
+ }
127
+ const normalized = path.posix.normalize(value).replace(/\/+$/, "") || "/";
128
+ if (normalized === "/") {
129
+ throw new Error("NAS_VOLUME_ROOT_INVALID: logicalRoot 不能是根目录 /");
130
+ }
131
+ return normalized;
132
+ }
133
+ function nearestExistingAncestor(target) {
134
+ let current = target;
135
+ while (!existsSync(current)) {
136
+ const parent = path.dirname(current);
137
+ if (parent === current)
138
+ break;
139
+ current = parent;
140
+ }
141
+ return current;
142
+ }
143
+ /**
144
+ * 业务目录允许按需创建,但创建前后都必须确认路径仍位于已存在的白名单根内。
145
+ */
146
+ function ensureNasSourceDirectory(rawDir, allowedRoots) {
147
+ const logicalDir = path.posix.normalize(rawDir.trim().replace(/\\/g, "/"));
148
+ if (!logicalDir.startsWith("/")) {
149
+ throw new Error(`NAS_VOLUME_SOURCE_INVALID: realDir 必须是绝对逻辑路径: ${rawDir}`);
150
+ }
151
+ const allowed = allowedRoots.find((root) => logicalDir !== root.logicalRoot && logicalDir.startsWith(`${root.logicalRoot}/`));
152
+ if (!allowed) {
153
+ throw new Error(`NAS_VOLUME_SOURCE_FORBIDDEN: realDir 未匹配允许的 logicalRoot: ${rawDir}`);
154
+ }
155
+ const target = path.resolve(allowed.configuredRoot, ...path.posix.relative(allowed.logicalRoot, logicalDir).split("/"));
156
+ if (!isInsideOrEqual(allowed.configuredRoot, target) || target === allowed.configuredRoot) {
157
+ throw new Error(`NAS_VOLUME_SOURCE_FORBIDDEN: realDir 越出映射根目录: ${rawDir}`);
158
+ }
159
+ if (!existsSync(target)) {
160
+ const existingAncestor = realpathSync(nearestExistingAncestor(target));
161
+ if (!isInsideOrEqual(allowed.realRoot, existingAncestor)) {
162
+ throw new Error(`NAS_VOLUME_SOURCE_FORBIDDEN: realDir 的父目录越出允许根: ${rawDir}`);
163
+ }
164
+ mkdirSync(target, { recursive: true });
165
+ }
166
+ const realDir = realpathSync(target);
167
+ if (realDir === allowed.realRoot || !isInsideOrEqual(allowed.realRoot, realDir)) {
168
+ throw new Error(`NAS_VOLUME_SOURCE_FORBIDDEN: realDir 不在允许根的业务子目录内: ${rawDir}`);
169
+ }
170
+ if (!statSync(realDir).isDirectory()) {
171
+ throw new Error(`NAS_VOLUME_SOURCE_INVALID: realDir 不是目录: ${rawDir}`);
172
+ }
173
+ const colonIndex = realDir.indexOf(":");
174
+ const isWindowsDrivePrefix = process.platform === "win32" && colonIndex === 1 && /^[A-Za-z]:[\\/]/.test(realDir);
175
+ if (colonIndex >= 0 && !isWindowsDrivePrefix) {
176
+ throw new Error(`NAS_VOLUME_SOURCE_INVALID: realDir 含 Docker bind 不支持的冒号: ${rawDir}`);
177
+ }
178
+ return realDir;
179
+ }
180
+ function assertNonOverlappingTargets(volumes) {
181
+ for (let i = 0; i < volumes.length; i += 1) {
182
+ for (let j = i + 1; j < volumes.length; j += 1) {
183
+ const left = volumes[i].dockerDir;
184
+ const right = volumes[j].dockerDir;
185
+ if (left === right || left.startsWith(`${right}/`) || right.startsWith(`${left}/`)) {
186
+ throw new Error(`NAS_VOLUME_TARGET_CONFLICT: dockerDir 不能重复或嵌套: ${left}, ${right}`);
187
+ }
188
+ }
189
+ }
190
+ }
191
+ export function validateAndNormalizeNasVolumes(volumes, config) {
192
+ const allowedRoots = normalizeAllowedRoots(config);
193
+ const normalized = volumes.map((volume) => {
194
+ const realDir = ensureNasSourceDirectory(volume.realDir.trim(), allowedRoots);
195
+ const dockerDir = normalizeNasDockerDir(volume.dockerDir);
196
+ return {
197
+ realDir,
198
+ dockerDir,
199
+ sandboxDir: nasVolumeSandboxDir(dockerDir),
200
+ mode: volume.mode,
201
+ };
202
+ });
203
+ assertNonOverlappingTargets(normalized);
204
+ return normalized;
205
+ }
206
+ export function nasVolumeSpecHash(volumes) {
207
+ const stable = [...volumes]
208
+ .sort((left, right) => left.dockerDir.localeCompare(right.dockerDir))
209
+ .map(({ realDir, dockerDir, mode }) => ({ realDir, dockerDir, mode }));
210
+ return createHash("sha256").update(JSON.stringify(stable)).digest("hex");
211
+ }
212
+ function effectiveSandboxScope(cfg, agentId) {
213
+ const agents = cfg.agents;
214
+ const defaults = agents?.defaults;
215
+ const defaultSandbox = defaults?.sandbox;
216
+ const list = Array.isArray(agents?.list) ? agents.list : [];
217
+ const agent = list.find((entry) => entry.id === agentId);
218
+ const agentSandbox = agent?.sandbox;
219
+ return agentSandbox?.scope ?? defaultSandbox?.scope;
220
+ }
221
+ function injectDockerBinds(cfg, agentId, binds) {
222
+ const cfgRecord = cfg;
223
+ const agents = cfgRecord.agents ?? {};
224
+ const list = Array.isArray(agents.list) ? agents.list : [];
225
+ const agentIndex = list.findIndex((entry) => entry.id === agentId);
226
+ const patchSandbox = (holder) => {
227
+ const sandbox = holder.sandbox ?? {};
228
+ const docker = sandbox.docker ?? {};
229
+ const existingBinds = Array.isArray(docker.binds)
230
+ ? docker.binds.filter((entry) => typeof entry === "string")
231
+ : [];
232
+ assertNoExistingBindTargetConflicts(existingBinds, binds);
233
+ return {
234
+ ...holder,
235
+ sandbox: {
236
+ ...sandbox,
237
+ docker: {
238
+ ...docker,
239
+ binds: [...new Set([...existingBinds, ...binds])],
240
+ // OpenClaw 默认禁止 workspace 子路径和 workspace 外来源;本插件已在上方执行真实路径白名单校验。
241
+ dangerouslyAllowExternalBindSources: true,
242
+ dangerouslyAllowReservedContainerTargets: true,
243
+ },
244
+ },
245
+ };
246
+ };
247
+ if (agentIndex >= 0) {
248
+ const nextList = [...list];
249
+ nextList[agentIndex] = patchSandbox(list[agentIndex]);
250
+ return { ...cfgRecord, agents: { ...agents, list: nextList } };
251
+ }
252
+ const defaults = agents.defaults ?? {};
253
+ return {
254
+ ...cfgRecord,
255
+ agents: { ...agents, defaults: patchSandbox(defaults) },
256
+ };
257
+ }
258
+ /**
259
+ * 将本会话期望的 NAS mounts 注入本轮 cfg。重复传入相同声明是幂等的;同一 session 改绑则拒绝。
260
+ */
261
+ export function resolveNasVolumeDispatchConfig(args) {
262
+ const stateKey = `${args.agentId}\0${args.sessionKey}`;
263
+ const now = Date.now();
264
+ pruneSessionNasVolumeStates(now);
265
+ let prior = sessionVolumeStates.get(stateKey);
266
+ if (prior && now - prior.lastSeenAt >= SESSION_NAS_VOLUME_STATE_TTL_MS) {
267
+ sessionVolumeStates.delete(stateKey);
268
+ prior = undefined;
269
+ }
270
+ let binds;
271
+ let specHash;
272
+ if (args.volumes?.length) {
273
+ const normalized = validateAndNormalizeNasVolumes(args.volumes, args.config);
274
+ specHash = nasVolumeSpecHash(normalized);
275
+ binds = normalized.map((volume) => `${volume.realDir}:${volume.sandboxDir}:${volume.mode}`);
276
+ if (prior && prior.specHash !== specHash) {
277
+ throw new Error("NAS_VOLUME_SESSION_CONFLICT: 当前会话已绑定另一组 NAS 目录,请创建新会话");
278
+ }
279
+ }
280
+ else if (prior) {
281
+ binds = prior.binds;
282
+ specHash = prior.specHash;
283
+ }
284
+ else {
285
+ return { cfg: args.cfg, reused: false };
286
+ }
287
+ if (effectiveSandboxScope(args.cfg, args.agentId) !== "session") {
288
+ throw new Error("NAS_VOLUME_SANDBOX_SCOPE_INVALID: NAS 挂载要求 sandbox.scope=session");
289
+ }
290
+ // 先完成无状态的配置注入与冲突校验,失败时不得污染会话缓存。
291
+ const nextCfg = injectDockerBinds(args.cfg, args.agentId, binds);
292
+ // delete + set 让 Map 插入顺序同时承担 LRU 顺序;达到硬上限时淘汰最久未使用项。
293
+ sessionVolumeStates.delete(stateKey);
294
+ sessionVolumeStates.set(stateKey, { specHash, binds, lastSeenAt: now });
295
+ pruneSessionNasVolumeStates(now, sessionVolumeStates.size > SESSION_NAS_VOLUME_STATE_MAX_ENTRIES);
296
+ return {
297
+ cfg: nextCfg,
298
+ specHash,
299
+ reused: prior?.specHash === specHash,
300
+ };
301
+ }
302
+ /** 测试与 Gateway 停止时使用。 */
303
+ export function clearSessionNasVolumeStates() {
304
+ sessionVolumeStates.clear();
305
+ lastSessionVolumeStatePruneAt = 0;
306
+ }
307
+ //# sourceMappingURL=nas-volumes.js.map