im-hub-pro 0.2.29

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 (384) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +497 -0
  3. package/README.zh-CN.md +496 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +921 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/core/acp-server.d.ts +8 -0
  9. package/dist/core/acp-server.d.ts.map +1 -0
  10. package/dist/core/acp-server.js +266 -0
  11. package/dist/core/acp-server.js.map +1 -0
  12. package/dist/core/agent-base.d.ts +94 -0
  13. package/dist/core/agent-base.d.ts.map +1 -0
  14. package/dist/core/agent-base.js +374 -0
  15. package/dist/core/agent-base.js.map +1 -0
  16. package/dist/core/agent-cwd.d.ts +45 -0
  17. package/dist/core/agent-cwd.d.ts.map +1 -0
  18. package/dist/core/agent-cwd.js +178 -0
  19. package/dist/core/agent-cwd.js.map +1 -0
  20. package/dist/core/agent-cwd.test.d.ts +2 -0
  21. package/dist/core/agent-cwd.test.d.ts.map +1 -0
  22. package/dist/core/agent-cwd.test.js +149 -0
  23. package/dist/core/agent-cwd.test.js.map +1 -0
  24. package/dist/core/approval-bus.d.ts +232 -0
  25. package/dist/core/approval-bus.d.ts.map +1 -0
  26. package/dist/core/approval-bus.js +703 -0
  27. package/dist/core/approval-bus.js.map +1 -0
  28. package/dist/core/approval-bus.synthetic.test.d.ts +2 -0
  29. package/dist/core/approval-bus.synthetic.test.d.ts.map +1 -0
  30. package/dist/core/approval-bus.synthetic.test.js +182 -0
  31. package/dist/core/approval-bus.synthetic.test.js.map +1 -0
  32. package/dist/core/approval-bus.test.d.ts +2 -0
  33. package/dist/core/approval-bus.test.d.ts.map +1 -0
  34. package/dist/core/approval-bus.test.js +537 -0
  35. package/dist/core/approval-bus.test.js.map +1 -0
  36. package/dist/core/approval-router.d.ts +95 -0
  37. package/dist/core/approval-router.d.ts.map +1 -0
  38. package/dist/core/approval-router.js +450 -0
  39. package/dist/core/approval-router.js.map +1 -0
  40. package/dist/core/approval-router.test.d.ts +2 -0
  41. package/dist/core/approval-router.test.d.ts.map +1 -0
  42. package/dist/core/approval-router.test.js +413 -0
  43. package/dist/core/approval-router.test.js.map +1 -0
  44. package/dist/core/audit-log.d.ts +55 -0
  45. package/dist/core/audit-log.d.ts.map +1 -0
  46. package/dist/core/audit-log.js +203 -0
  47. package/dist/core/audit-log.js.map +1 -0
  48. package/dist/core/bgjob-reader.d.ts +65 -0
  49. package/dist/core/bgjob-reader.d.ts.map +1 -0
  50. package/dist/core/bgjob-reader.js +212 -0
  51. package/dist/core/bgjob-reader.js.map +1 -0
  52. package/dist/core/bgjob-reader.test.d.ts +2 -0
  53. package/dist/core/bgjob-reader.test.d.ts.map +1 -0
  54. package/dist/core/bgjob-reader.test.js +178 -0
  55. package/dist/core/bgjob-reader.test.js.map +1 -0
  56. package/dist/core/circuit-breaker.d.ts +37 -0
  57. package/dist/core/circuit-breaker.d.ts.map +1 -0
  58. package/dist/core/circuit-breaker.js +115 -0
  59. package/dist/core/circuit-breaker.js.map +1 -0
  60. package/dist/core/commands/agent.d.ts +4 -0
  61. package/dist/core/commands/agent.d.ts.map +1 -0
  62. package/dist/core/commands/agent.js +21 -0
  63. package/dist/core/commands/agent.js.map +1 -0
  64. package/dist/core/commands/approval.d.ts +3 -0
  65. package/dist/core/commands/approval.d.ts.map +1 -0
  66. package/dist/core/commands/approval.js +44 -0
  67. package/dist/core/commands/approval.js.map +1 -0
  68. package/dist/core/commands/approval.test.d.ts +2 -0
  69. package/dist/core/commands/approval.test.d.ts.map +1 -0
  70. package/dist/core/commands/approval.test.js +85 -0
  71. package/dist/core/commands/approval.test.js.map +1 -0
  72. package/dist/core/commands/audit.d.ts +3 -0
  73. package/dist/core/commands/audit.d.ts.map +1 -0
  74. package/dist/core/commands/audit.js +84 -0
  75. package/dist/core/commands/audit.js.map +1 -0
  76. package/dist/core/commands/builtin.d.ts +3 -0
  77. package/dist/core/commands/builtin.d.ts.map +1 -0
  78. package/dist/core/commands/builtin.js +26 -0
  79. package/dist/core/commands/builtin.js.map +1 -0
  80. package/dist/core/commands/job.d.ts +3 -0
  81. package/dist/core/commands/job.d.ts.map +1 -0
  82. package/dist/core/commands/job.js +195 -0
  83. package/dist/core/commands/job.js.map +1 -0
  84. package/dist/core/commands/model.d.ts +9 -0
  85. package/dist/core/commands/model.d.ts.map +1 -0
  86. package/dist/core/commands/model.js +183 -0
  87. package/dist/core/commands/model.js.map +1 -0
  88. package/dist/core/commands/plan.d.ts +3 -0
  89. package/dist/core/commands/plan.d.ts.map +1 -0
  90. package/dist/core/commands/plan.js +75 -0
  91. package/dist/core/commands/plan.js.map +1 -0
  92. package/dist/core/commands/plan.test.d.ts +2 -0
  93. package/dist/core/commands/plan.test.d.ts.map +1 -0
  94. package/dist/core/commands/plan.test.js +122 -0
  95. package/dist/core/commands/plan.test.js.map +1 -0
  96. package/dist/core/commands/router.d.ts +3 -0
  97. package/dist/core/commands/router.d.ts.map +1 -0
  98. package/dist/core/commands/router.js +71 -0
  99. package/dist/core/commands/router.js.map +1 -0
  100. package/dist/core/commands/schedule.d.ts +3 -0
  101. package/dist/core/commands/schedule.d.ts.map +1 -0
  102. package/dist/core/commands/schedule.js +123 -0
  103. package/dist/core/commands/schedule.js.map +1 -0
  104. package/dist/core/commands/sessions.d.ts +3 -0
  105. package/dist/core/commands/sessions.d.ts.map +1 -0
  106. package/dist/core/commands/sessions.js +88 -0
  107. package/dist/core/commands/sessions.js.map +1 -0
  108. package/dist/core/commands/stats.d.ts +3 -0
  109. package/dist/core/commands/stats.d.ts.map +1 -0
  110. package/dist/core/commands/stats.js +73 -0
  111. package/dist/core/commands/stats.js.map +1 -0
  112. package/dist/core/commands/think.d.ts +3 -0
  113. package/dist/core/commands/think.d.ts.map +1 -0
  114. package/dist/core/commands/think.js +28 -0
  115. package/dist/core/commands/think.js.map +1 -0
  116. package/dist/core/commands/workspaces.d.ts +3 -0
  117. package/dist/core/commands/workspaces.d.ts.map +1 -0
  118. package/dist/core/commands/workspaces.js +47 -0
  119. package/dist/core/commands/workspaces.js.map +1 -0
  120. package/dist/core/config-schema.d.ts +58 -0
  121. package/dist/core/config-schema.d.ts.map +1 -0
  122. package/dist/core/config-schema.js +63 -0
  123. package/dist/core/config-schema.js.map +1 -0
  124. package/dist/core/cron.d.ts +29 -0
  125. package/dist/core/cron.d.ts.map +1 -0
  126. package/dist/core/cron.js +184 -0
  127. package/dist/core/cron.js.map +1 -0
  128. package/dist/core/event-bus.d.ts +80 -0
  129. package/dist/core/event-bus.d.ts.map +1 -0
  130. package/dist/core/event-bus.js +62 -0
  131. package/dist/core/event-bus.js.map +1 -0
  132. package/dist/core/intent-llm.d.ts +27 -0
  133. package/dist/core/intent-llm.d.ts.map +1 -0
  134. package/dist/core/intent-llm.js +170 -0
  135. package/dist/core/intent-llm.js.map +1 -0
  136. package/dist/core/intent.d.ts +12 -0
  137. package/dist/core/intent.d.ts.map +1 -0
  138. package/dist/core/intent.js +187 -0
  139. package/dist/core/intent.js.map +1 -0
  140. package/dist/core/job-board.d.ts +84 -0
  141. package/dist/core/job-board.d.ts.map +1 -0
  142. package/dist/core/job-board.js +379 -0
  143. package/dist/core/job-board.js.map +1 -0
  144. package/dist/core/logger.d.ts +6 -0
  145. package/dist/core/logger.d.ts.map +1 -0
  146. package/dist/core/logger.js +54 -0
  147. package/dist/core/logger.js.map +1 -0
  148. package/dist/core/metrics.d.ts +55 -0
  149. package/dist/core/metrics.d.ts.map +1 -0
  150. package/dist/core/metrics.js +291 -0
  151. package/dist/core/metrics.js.map +1 -0
  152. package/dist/core/onboarding.d.ts +94 -0
  153. package/dist/core/onboarding.d.ts.map +1 -0
  154. package/dist/core/onboarding.js +426 -0
  155. package/dist/core/onboarding.js.map +1 -0
  156. package/dist/core/onboarding.test.d.ts +2 -0
  157. package/dist/core/onboarding.test.d.ts.map +1 -0
  158. package/dist/core/onboarding.test.js +112 -0
  159. package/dist/core/onboarding.test.js.map +1 -0
  160. package/dist/core/rate-limiter.d.ts +44 -0
  161. package/dist/core/rate-limiter.d.ts.map +1 -0
  162. package/dist/core/rate-limiter.js +115 -0
  163. package/dist/core/rate-limiter.js.map +1 -0
  164. package/dist/core/registry.d.ts +32 -0
  165. package/dist/core/registry.d.ts.map +1 -0
  166. package/dist/core/registry.js +122 -0
  167. package/dist/core/registry.js.map +1 -0
  168. package/dist/core/router.d.ts +41 -0
  169. package/dist/core/router.d.ts.map +1 -0
  170. package/dist/core/router.js +431 -0
  171. package/dist/core/router.js.map +1 -0
  172. package/dist/core/schedule.d.ts +65 -0
  173. package/dist/core/schedule.d.ts.map +1 -0
  174. package/dist/core/schedule.js +316 -0
  175. package/dist/core/schedule.js.map +1 -0
  176. package/dist/core/session-subtasks.test.d.ts +2 -0
  177. package/dist/core/session-subtasks.test.d.ts.map +1 -0
  178. package/dist/core/session-subtasks.test.js +88 -0
  179. package/dist/core/session-subtasks.test.js.map +1 -0
  180. package/dist/core/session.d.ts +182 -0
  181. package/dist/core/session.d.ts.map +1 -0
  182. package/dist/core/session.js +774 -0
  183. package/dist/core/session.js.map +1 -0
  184. package/dist/core/sqlite-helper.d.ts +37 -0
  185. package/dist/core/sqlite-helper.d.ts.map +1 -0
  186. package/dist/core/sqlite-helper.js +79 -0
  187. package/dist/core/sqlite-helper.js.map +1 -0
  188. package/dist/core/transcribe.d.ts +25 -0
  189. package/dist/core/transcribe.d.ts.map +1 -0
  190. package/dist/core/transcribe.js +217 -0
  191. package/dist/core/transcribe.js.map +1 -0
  192. package/dist/core/transcribe.test.d.ts +2 -0
  193. package/dist/core/transcribe.test.d.ts.map +1 -0
  194. package/dist/core/transcribe.test.js +163 -0
  195. package/dist/core/transcribe.test.js.map +1 -0
  196. package/dist/core/types.d.ts +352 -0
  197. package/dist/core/types.d.ts.map +1 -0
  198. package/dist/core/types.js +3 -0
  199. package/dist/core/types.js.map +1 -0
  200. package/dist/core/workspace.d.ts +67 -0
  201. package/dist/core/workspace.d.ts.map +1 -0
  202. package/dist/core/workspace.js +113 -0
  203. package/dist/core/workspace.js.map +1 -0
  204. package/dist/index.d.ts +5 -0
  205. package/dist/index.d.ts.map +1 -0
  206. package/dist/index.js +6 -0
  207. package/dist/index.js.map +1 -0
  208. package/dist/plugins/agents/acp/acp-adapter.d.ts +16 -0
  209. package/dist/plugins/agents/acp/acp-adapter.d.ts.map +1 -0
  210. package/dist/plugins/agents/acp/acp-adapter.js +49 -0
  211. package/dist/plugins/agents/acp/acp-adapter.js.map +1 -0
  212. package/dist/plugins/agents/acp/acp-client.d.ts +32 -0
  213. package/dist/plugins/agents/acp/acp-client.d.ts.map +1 -0
  214. package/dist/plugins/agents/acp/acp-client.js +175 -0
  215. package/dist/plugins/agents/acp/acp-client.js.map +1 -0
  216. package/dist/plugins/agents/acp/discovery.d.ts +19 -0
  217. package/dist/plugins/agents/acp/discovery.d.ts.map +1 -0
  218. package/dist/plugins/agents/acp/discovery.js +109 -0
  219. package/dist/plugins/agents/acp/discovery.js.map +1 -0
  220. package/dist/plugins/agents/acp/index.d.ts +4 -0
  221. package/dist/plugins/agents/acp/index.d.ts.map +1 -0
  222. package/dist/plugins/agents/acp/index.js +4 -0
  223. package/dist/plugins/agents/acp/index.js.map +1 -0
  224. package/dist/plugins/agents/acp/types.d.ts +62 -0
  225. package/dist/plugins/agents/acp/types.d.ts.map +1 -0
  226. package/dist/plugins/agents/acp/types.js +5 -0
  227. package/dist/plugins/agents/acp/types.js.map +1 -0
  228. package/dist/plugins/agents/claude-code/adapter.test.d.ts +2 -0
  229. package/dist/plugins/agents/claude-code/adapter.test.d.ts.map +1 -0
  230. package/dist/plugins/agents/claude-code/adapter.test.js +195 -0
  231. package/dist/plugins/agents/claude-code/adapter.test.js.map +1 -0
  232. package/dist/plugins/agents/claude-code/index.d.ts +25 -0
  233. package/dist/plugins/agents/claude-code/index.d.ts.map +1 -0
  234. package/dist/plugins/agents/claude-code/index.js +184 -0
  235. package/dist/plugins/agents/claude-code/index.js.map +1 -0
  236. package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts +42 -0
  237. package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts.map +1 -0
  238. package/dist/plugins/agents/claude-code/mcp-approval-server.js +235 -0
  239. package/dist/plugins/agents/claude-code/mcp-approval-server.js.map +1 -0
  240. package/dist/plugins/agents/claude-code/mcp-approval-server.test.d.ts +2 -0
  241. package/dist/plugins/agents/claude-code/mcp-approval-server.test.d.ts.map +1 -0
  242. package/dist/plugins/agents/claude-code/mcp-approval-server.test.js +188 -0
  243. package/dist/plugins/agents/claude-code/mcp-approval-server.test.js.map +1 -0
  244. package/dist/plugins/agents/codex/adapter.test.d.ts +2 -0
  245. package/dist/plugins/agents/codex/adapter.test.d.ts.map +1 -0
  246. package/dist/plugins/agents/codex/adapter.test.js +192 -0
  247. package/dist/plugins/agents/codex/adapter.test.js.map +1 -0
  248. package/dist/plugins/agents/codex/index.d.ts +37 -0
  249. package/dist/plugins/agents/codex/index.d.ts.map +1 -0
  250. package/dist/plugins/agents/codex/index.js +254 -0
  251. package/dist/plugins/agents/codex/index.js.map +1 -0
  252. package/dist/plugins/agents/copilot/index.d.ts +35 -0
  253. package/dist/plugins/agents/copilot/index.d.ts.map +1 -0
  254. package/dist/plugins/agents/copilot/index.js +182 -0
  255. package/dist/plugins/agents/copilot/index.js.map +1 -0
  256. package/dist/plugins/agents/opencode/adapter.test.d.ts +2 -0
  257. package/dist/plugins/agents/opencode/adapter.test.d.ts.map +1 -0
  258. package/dist/plugins/agents/opencode/adapter.test.js +139 -0
  259. package/dist/plugins/agents/opencode/adapter.test.js.map +1 -0
  260. package/dist/plugins/agents/opencode/http-adapter.test.d.ts +2 -0
  261. package/dist/plugins/agents/opencode/http-adapter.test.d.ts.map +1 -0
  262. package/dist/plugins/agents/opencode/http-adapter.test.js +492 -0
  263. package/dist/plugins/agents/opencode/http-adapter.test.js.map +1 -0
  264. package/dist/plugins/agents/opencode/index.d.ts +5 -0
  265. package/dist/plugins/agents/opencode/index.d.ts.map +1 -0
  266. package/dist/plugins/agents/opencode/index.js +30 -0
  267. package/dist/plugins/agents/opencode/index.js.map +1 -0
  268. package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts +138 -0
  269. package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts.map +1 -0
  270. package/dist/plugins/agents/opencode/opencode-http-adapter.js +549 -0
  271. package/dist/plugins/agents/opencode/opencode-http-adapter.js.map +1 -0
  272. package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts +24 -0
  273. package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts.map +1 -0
  274. package/dist/plugins/agents/opencode/opencode-stdio-adapter.js +103 -0
  275. package/dist/plugins/agents/opencode/opencode-stdio-adapter.js.map +1 -0
  276. package/dist/plugins/agents/opencode/serve-manager.d.ts +27 -0
  277. package/dist/plugins/agents/opencode/serve-manager.d.ts.map +1 -0
  278. package/dist/plugins/agents/opencode/serve-manager.js +190 -0
  279. package/dist/plugins/agents/opencode/serve-manager.js.map +1 -0
  280. package/dist/plugins/messengers/discord/discord-adapter.d.ts +22 -0
  281. package/dist/plugins/messengers/discord/discord-adapter.d.ts.map +1 -0
  282. package/dist/plugins/messengers/discord/discord-adapter.js +241 -0
  283. package/dist/plugins/messengers/discord/discord-adapter.js.map +1 -0
  284. package/dist/plugins/messengers/discord/discord-adapter.test.d.ts +2 -0
  285. package/dist/plugins/messengers/discord/discord-adapter.test.d.ts.map +1 -0
  286. package/dist/plugins/messengers/discord/discord-adapter.test.js +332 -0
  287. package/dist/plugins/messengers/discord/discord-adapter.test.js.map +1 -0
  288. package/dist/plugins/messengers/discord/index.d.ts +4 -0
  289. package/dist/plugins/messengers/discord/index.d.ts.map +1 -0
  290. package/dist/plugins/messengers/discord/index.js +4 -0
  291. package/dist/plugins/messengers/discord/index.js.map +1 -0
  292. package/dist/plugins/messengers/discord/markdown-to-discord.d.ts +11 -0
  293. package/dist/plugins/messengers/discord/markdown-to-discord.d.ts.map +1 -0
  294. package/dist/plugins/messengers/discord/markdown-to-discord.js +59 -0
  295. package/dist/plugins/messengers/discord/markdown-to-discord.js.map +1 -0
  296. package/dist/plugins/messengers/discord/types.d.ts +9 -0
  297. package/dist/plugins/messengers/discord/types.d.ts.map +1 -0
  298. package/dist/plugins/messengers/discord/types.js +3 -0
  299. package/dist/plugins/messengers/discord/types.js.map +1 -0
  300. package/dist/plugins/messengers/feishu/card-builder.d.ts +23 -0
  301. package/dist/plugins/messengers/feishu/card-builder.d.ts.map +1 -0
  302. package/dist/plugins/messengers/feishu/card-builder.js +89 -0
  303. package/dist/plugins/messengers/feishu/card-builder.js.map +1 -0
  304. package/dist/plugins/messengers/feishu/feishu-adapter.d.ts +33 -0
  305. package/dist/plugins/messengers/feishu/feishu-adapter.d.ts.map +1 -0
  306. package/dist/plugins/messengers/feishu/feishu-adapter.js +195 -0
  307. package/dist/plugins/messengers/feishu/feishu-adapter.js.map +1 -0
  308. package/dist/plugins/messengers/feishu/feishu-client.d.ts +44 -0
  309. package/dist/plugins/messengers/feishu/feishu-client.d.ts.map +1 -0
  310. package/dist/plugins/messengers/feishu/feishu-client.js +120 -0
  311. package/dist/plugins/messengers/feishu/feishu-client.js.map +1 -0
  312. package/dist/plugins/messengers/feishu/feishu-dedup.test.d.ts +2 -0
  313. package/dist/plugins/messengers/feishu/feishu-dedup.test.d.ts.map +1 -0
  314. package/dist/plugins/messengers/feishu/feishu-dedup.test.js +70 -0
  315. package/dist/plugins/messengers/feishu/feishu-dedup.test.js.map +1 -0
  316. package/dist/plugins/messengers/feishu/index.d.ts +4 -0
  317. package/dist/plugins/messengers/feishu/index.d.ts.map +1 -0
  318. package/dist/plugins/messengers/feishu/index.js +4 -0
  319. package/dist/plugins/messengers/feishu/index.js.map +1 -0
  320. package/dist/plugins/messengers/feishu/types.d.ts +113 -0
  321. package/dist/plugins/messengers/feishu/types.d.ts.map +1 -0
  322. package/dist/plugins/messengers/feishu/types.js +4 -0
  323. package/dist/plugins/messengers/feishu/types.js.map +1 -0
  324. package/dist/plugins/messengers/telegram/index.d.ts +4 -0
  325. package/dist/plugins/messengers/telegram/index.d.ts.map +1 -0
  326. package/dist/plugins/messengers/telegram/index.js +4 -0
  327. package/dist/plugins/messengers/telegram/index.js.map +1 -0
  328. package/dist/plugins/messengers/telegram/markdown-to-html.d.ts +5 -0
  329. package/dist/plugins/messengers/telegram/markdown-to-html.d.ts.map +1 -0
  330. package/dist/plugins/messengers/telegram/markdown-to-html.js +186 -0
  331. package/dist/plugins/messengers/telegram/markdown-to-html.js.map +1 -0
  332. package/dist/plugins/messengers/telegram/media-download.d.ts +51 -0
  333. package/dist/plugins/messengers/telegram/media-download.d.ts.map +1 -0
  334. package/dist/plugins/messengers/telegram/media-download.js +224 -0
  335. package/dist/plugins/messengers/telegram/media-download.js.map +1 -0
  336. package/dist/plugins/messengers/telegram/media-download.test.d.ts +2 -0
  337. package/dist/plugins/messengers/telegram/media-download.test.d.ts.map +1 -0
  338. package/dist/plugins/messengers/telegram/media-download.test.js +125 -0
  339. package/dist/plugins/messengers/telegram/media-download.test.js.map +1 -0
  340. package/dist/plugins/messengers/telegram/telegram-adapter.d.ts +62 -0
  341. package/dist/plugins/messengers/telegram/telegram-adapter.d.ts.map +1 -0
  342. package/dist/plugins/messengers/telegram/telegram-adapter.js +653 -0
  343. package/dist/plugins/messengers/telegram/telegram-adapter.js.map +1 -0
  344. package/dist/plugins/messengers/telegram/types.d.ts +47 -0
  345. package/dist/plugins/messengers/telegram/types.d.ts.map +1 -0
  346. package/dist/plugins/messengers/telegram/types.js +3 -0
  347. package/dist/plugins/messengers/telegram/types.js.map +1 -0
  348. package/dist/plugins/messengers/wechat/ilink-adapter.d.ts +68 -0
  349. package/dist/plugins/messengers/wechat/ilink-adapter.d.ts.map +1 -0
  350. package/dist/plugins/messengers/wechat/ilink-adapter.js +483 -0
  351. package/dist/plugins/messengers/wechat/ilink-adapter.js.map +1 -0
  352. package/dist/plugins/messengers/wechat/ilink-client.d.ts +66 -0
  353. package/dist/plugins/messengers/wechat/ilink-client.d.ts.map +1 -0
  354. package/dist/plugins/messengers/wechat/ilink-client.js +288 -0
  355. package/dist/plugins/messengers/wechat/ilink-client.js.map +1 -0
  356. package/dist/plugins/messengers/wechat/ilink-types.d.ts +173 -0
  357. package/dist/plugins/messengers/wechat/ilink-types.d.ts.map +1 -0
  358. package/dist/plugins/messengers/wechat/ilink-types.js +12 -0
  359. package/dist/plugins/messengers/wechat/ilink-types.js.map +1 -0
  360. package/dist/utils/backoff.d.ts +35 -0
  361. package/dist/utils/backoff.d.ts.map +1 -0
  362. package/dist/utils/backoff.js +59 -0
  363. package/dist/utils/backoff.js.map +1 -0
  364. package/dist/utils/cross-platform.d.ts +26 -0
  365. package/dist/utils/cross-platform.d.ts.map +1 -0
  366. package/dist/utils/cross-platform.js +58 -0
  367. package/dist/utils/cross-platform.js.map +1 -0
  368. package/dist/utils/message-split.d.ts +14 -0
  369. package/dist/utils/message-split.d.ts.map +1 -0
  370. package/dist/utils/message-split.js +65 -0
  371. package/dist/utils/message-split.js.map +1 -0
  372. package/dist/utils/safe-equal.d.ts +2 -0
  373. package/dist/utils/safe-equal.d.ts.map +1 -0
  374. package/dist/utils/safe-equal.js +11 -0
  375. package/dist/utils/safe-equal.js.map +1 -0
  376. package/dist/web/public/_app.js +196 -0
  377. package/dist/web/public/index.html +935 -0
  378. package/dist/web/public/settings.html +1181 -0
  379. package/dist/web/public/tasks.html +1827 -0
  380. package/dist/web/server.d.ts +11 -0
  381. package/dist/web/server.d.ts.map +1 -0
  382. package/dist/web/server.js +1820 -0
  383. package/dist/web/server.js.map +1 -0
  384. package/package.json +73 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Jerry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,497 @@
1
+ # im-hub-pro
2
+
3
+ [中文文档](README.zh-CN.md)
4
+
5
+ **Universal messenger-to-agent bridge** — connect WeChat / Feishu / Telegram / **Discord** to Claude Code / Codex / Copilot / OpenCode, **or any custom agent via ACP**. Single Node.js process, no Docker, no Redis. Browser dashboard, persistent jobs, multi-tenant workspaces, and real human-in-the-loop tool approval over IM.
6
+
7
+ > Productized fork of the original [`im-hub`](https://www.npmjs.com/package/im-hub). On-disk config (`~/.im-hub/`), env vars (`IMHUB_*`), and HTTP headers (`X-IM-Hub-Token`) are unchanged — drop-in compatible. See [Migrating from `im-hub`](#migrating-from-im-hub) below.
8
+
9
+ ## What's new in v0.2.13 → v0.2.23
10
+
11
+ - **Discord adapter** (Gateway WebSocket via `discord.js`)
12
+ - **Human-in-the-loop tool approval** — Claude pauses on tool calls; you reply `y`/`n` in the same IM thread, **or click an in-page card from the web chat**
13
+ - **Tasks dashboard** at `/tasks` with **Jobs · Background · Subtasks · Schedules · Approvals · Health · Files · Audit** tabs (per-agent filtering, multi-select batch ops, real-time SSE updates)
14
+ - **Multi-tenant workspaces** — per-workspace agent whitelist + rate limits, **with full CRUD UI in /settings**, plus command-level ACL on `/job` `/schedule` `/audit` (each user only sees their own)
15
+ - **ACP server mode** — im-hub-pro itself is an ACP-compatible agent (`POST /tasks` sync + SSE)
16
+ - **Persistent Job Board** + cron scheduler (SQLite, survives restarts) with 30-day retention sweep
17
+ - **Smart routing**: intent classifier (CJK + ASCII), circuit breaker, sticky sessions
18
+ - **Structured logging** (`pino`) with `traceId` end-to-end + audit log + Prometheus `/api/metrics`
19
+ - **Three-state theme** (light / dark / system) on every page — applied before first paint to avoid flash
20
+ - **v0.2.16 — Security hardening (P0 + P1)**: timing-safe token compare, Schedule `notify_url` SSRF guard, secret redaction in logs, approval-socket entropy + perms, `Session.addMessage` per-key mutex
21
+ - **v0.2.17 — Observability & IM polish (P2 + P3)**: static-page CSP / `X-Frame-Options` / `X-Content-Type-Options`, WebSocket connection cap + backpressure, Prometheus label-cardinality whitelist, new counters (`im_hub_audit_prune_failed_total` / `im_hub_agent_cleanup_failed_total` / `im_hub_approval_*`), UTF-16 surrogate-safe message split, auto-allow fingerprint 5→10 chars, SQLite WAL clean checkpoint on SIGINT
22
+ - **v0.2.18 — IM reconnect backoff (M9)**: shared `Backoff` helper (exponential + ±50% jitter) replaces fixed 2s / 5s reconnect delays in Telegram + WeChat polling; defeats thundering-herd on shared network recovery
23
+ - **v0.2.19 — Codex sandbox-mode plan + Dashboard filter / Audit tab**: codex now honors `session.planMode` (default sandbox switched to explicit `-s workspace-write`); jobs / subtasks / schedules tabs gain per-agent filter; new Audit tab pulls the SQLite audit log into the dashboard
24
+ - **v0.2.20 — Web console PR-A**: three-state theme manager + global error boundary + in-page approval cards (click Allow / Deny / Allow + Auto from the chat UI itself)
25
+ - **v0.2.21 — Web console PR-B**: Health tab (per-agent breaker / rate-limiter / latency p50/95/99 / sparkline) + Approvals tab (browse and resolve every pending HITL approval from the dashboard)
26
+ - **v0.2.22 — Web console PR-C**: SSE event stream (`/events`) replaces polling for audit / approval / job / metrics events; full Workspace CRUD UI in /settings
27
+ - **v0.2.23 — Web console PR-D**: Files tab — read-only browser of `~/.im-hub-workspaces/<agent>/`; Jobs tab gains multi-select + batch cancel / run; settings page header / container restyled
28
+
29
+ See [CHANGELOG.md](CHANGELOG.md) and [docs/code-review-2026-05-06-main.md](docs/code-review-2026-05-06-main.md) for the full list.
30
+
31
+ ## Web Chat & Tasks Dashboard
32
+
33
+ ```
34
+ im-hub-pro start # Web UI at http://localhost:3000
35
+ # / chat (with in-page approval cards)
36
+ # /tasks jobs · background · subtasks · schedules
37
+ # · approvals · health · files · audit
38
+ # /settings agents · messengers · ACP · workspaces
39
+ ```
40
+
41
+ - Real-time streaming via WebSocket; **dashboard pushed via SSE `/events`** (audit / approval / job / metrics)
42
+ - Agent switching and chat history
43
+ - **Three-state theme** (light / dark / system) with per-tab persistence + global error boundary
44
+ - Bilingual UI (English / 中文) — auto-detects browser language
45
+ - `/tasks` surfaces persistent jobs, cron schedules, **`~/.claude/bgjobs`** + **`~/.config/opencode/bgjobs`** + **`~/.codex/bgjobs`** background tasks (override via `IMHUB_BGJOB_ROOTS`), every subtask in every session, agent health (breaker · rate-limiter · p50/95/99 · sparkline), pending HITL approvals (resolve from the browser), and a read-only file browser into `~/.im-hub-workspaces/<agent>/`
46
+
47
+ ## Features
48
+
49
+ - **Universal multiplexer** — one instance, multiple messengers, multiple agents
50
+ - **Custom agent support** — connect any agent via [ACP](https://agentcommunicationprotocol.dev) with `im-hub-pro config agent`, or auto-discover via `/.well-known/acp`
51
+ - **Built-in IMs** — WeChat (iLink), Feishu (WebSocket long-poll), Telegram (grammy), **Discord** (discord.js)
52
+ - **Built-in CLI agents** — Claude Code, Codex, Copilot, OpenCode (all via shared `AgentBase` adapter)
53
+ - **Plugin architecture** — easy to add new messengers / agents
54
+ - **TypeScript native** — no Go, no Docker, no Redis
55
+ - **JSONL streaming** — real-time agent responses with multi-byte UTF-8 safety
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ npm install -g im-hub-pro
61
+ ```
62
+
63
+ Requires **Node.js ≥ 18** (production deployments use ≥ 22 LTS — see [`docs/deployment.md`](docs/deployment.md)).
64
+
65
+ ### Migrating from `im-hub`
66
+
67
+ Your `~/.im-hub/` config dir, `IMHUB_*` env vars, `X-IM-Hub-Token` header, and ACP wire identifiers (`im-hub-gateway`) are unchanged — this is a brand rename only.
68
+
69
+ ```bash
70
+ npm uninstall -g im-hub
71
+ npm install -g im-hub-pro
72
+ im-hub-pro start
73
+ ```
74
+
75
+ ## Quick Start
76
+
77
+ ```bash
78
+ # 1. Configure at least one messenger
79
+ im-hub-pro config wechat # QR-code login
80
+ im-hub-pro config feishu # App ID + Secret (no webhook needed)
81
+ im-hub-pro config telegram # @BotFather token
82
+ im-hub-pro config discord # Bot token; see docs/discord-setup.md
83
+
84
+ # 2. (Optional) Configure a CLI agent — most are auto-detected
85
+ im-hub-pro config claude
86
+
87
+ # 3. (Optional) Connect a custom remote agent over ACP
88
+ im-hub-pro config agent
89
+
90
+ # 4. Start the bridge
91
+ im-hub-pro start
92
+ ```
93
+
94
+ ### Feishu (WebSocket Long Polling)
95
+
96
+ - ✅ No webhook configuration needed
97
+ - ✅ No public IP or domain required
98
+ - ✅ No ngrok or similar tools needed
99
+ - ✅ Works directly from localhost
100
+
101
+ ### Discord
102
+
103
+ See [`docs/discord-setup.md`](docs/discord-setup.md) for the full bot-token / intents / OAuth flow.
104
+
105
+ ### Connect Your Own Agent
106
+
107
+ im-hub-pro speaks **ACP (Agent Communication Protocol)**, so you can plug in any agent that exposes a standard HTTP endpoint — your own business bots, internal tools, cloud services, anything.
108
+
109
+ ```bash
110
+ im-hub-pro config agent
111
+ # Interactive setup: name, endpoint URL, auth (none / Bearer / API key)
112
+ # Connection is validated automatically; /.well-known/acp is auto-discovered
113
+ ```
114
+
115
+ After setup, chat with it the same way as built-in agents:
116
+
117
+ ```
118
+ /myagent analyze the Q1 sales report
119
+ ```
120
+
121
+ ### Use im-hub-pro *as* an agent
122
+
123
+ im-hub-pro also exposes an ACP server — point any ACP-compliant client at `POST http://localhost:3000/tasks` (sync) or with `?mode=stream` (SSE). Auth is the same `Authorization: Bearer <web-token>`.
124
+
125
+ ## CLI Commands
126
+
127
+ ```
128
+ im-hub-pro # Same as 'start'
129
+ im-hub-pro start # Start the bridge + web UI
130
+ im-hub-pro config wechat # Configure WeChat
131
+ im-hub-pro config feishu # Configure Feishu
132
+ im-hub-pro config telegram # Configure Telegram
133
+ im-hub-pro config discord # Configure Discord
134
+ im-hub-pro config claude # Configure Claude Code
135
+ im-hub-pro config agent # Connect a custom ACP agent
136
+ im-hub-pro agents # List available agents
137
+ im-hub-pro messengers # List available messengers
138
+ im-hub-pro help
139
+ ```
140
+
141
+ ## Chat Commands
142
+
143
+ Send these as messages to the bot. Responses are streamed back in the same thread.
144
+
145
+ | Command | What it does |
146
+ |---|---|
147
+ | (any text) | Route to the agent (sticky session, intent-classified) |
148
+ | `/<agent> <prompt>` | Switch agent and send (e.g. `/cc explain this`, `/oc`, `/cx`, `/co`) |
149
+ | `/help` | Show available commands |
150
+ | `/agents` | List available agents |
151
+ | `/status` | Show connection status |
152
+ | `/new` | Start a new conversation (clear context) |
153
+ | `/router status\|policy\|explain\|reset` | Inspect routing decisions, predict where a message would go |
154
+ | `/audit [n]` | Recent invocations from the audit log |
155
+ | `/job ...` | Inspect / cancel persistent jobs |
156
+ | `/schedule ...` | List / add / remove cron schedules |
157
+ | `/sessions` | List recent sessions for this thread |
158
+ | `/model [provider/model]` | View or change the session's model |
159
+ | `/models` | List models the current agent supports |
160
+ | `/think on\|off\|...` | Toggle "think harder" / extended-thinking modes |
161
+ | `/stats` | Per-agent invocation / latency / error stats |
162
+ | `y` / `n` / `批准` / `拒绝` | Approve or deny a pending Claude tool call (HITL) |
163
+
164
+ ## Human-in-the-loop Tool Approval
165
+
166
+ When a Claude run launched from IM tries to use a tool, im-hub-pro pauses it and posts an approval card to the same IM thread:
167
+
168
+ ```
169
+ 🔐 Tool approval request
170
+ Tool: Bash
171
+ Input: {"command":"rm -rf node_modules"}
172
+ Reply y to approve / n to deny (auto-deny in 5 min)
173
+ req: a3f1c0d2
174
+ ```
175
+
176
+ Reply `y`, `n`, `批准`, `拒绝`, etc. — the decision flows back through an MCP sidecar to Claude, which resumes (or aborts) accordingly. The same chain works for WeChat, Telegram, Feishu, and Discord with no per-platform changes. Disable with `IMHUB_APPROVAL_DISABLED=1`.
177
+
178
+ ## Architecture
179
+
180
+ ```
181
+ ┌─── External triggers ───┐
182
+ │ cron 30s tick │
183
+ │ webhook → /api/notify │
184
+ │ REST → /api/invoke │
185
+ │ ACP → /tasks (sync/SSE)│
186
+ └────────────┬─────────────┘
187
+ ┌─ IM ingress ──────────────────────┼───────────────────┐
188
+ │ WeChat iLink (long-poll + heartbeat) │
189
+ │ Telegram (grammy) │
190
+ │ Feishu (Lark SDK WebSocket) │
191
+ │ Discord (discord.js Gateway) │
192
+ │ Web Chat (browser WebSocket) │
193
+ └────────────────────────────────┬──────────────────────┘
194
+ │ MessageContext
195
+
196
+ ┌── Pre-route gates ────────────────┐
197
+ │ workspace.resolve(userId) │
198
+ │ rateLimiter.allow(userKey) │
199
+ │ traceId + pino child logger │
200
+ └────────────────┬───────────────────┘
201
+
202
+ ┌── parseMessage + Intent ──────────┐
203
+ │ /<cmd> → builtin sub-command │
204
+ │ /<agent> → explicit switch │
205
+ │ default → classifyIntent │
206
+ │ ├ topic regex (CJK + ASCII) │
207
+ │ ├ keyword profile │
208
+ │ ├ sticky session bias │
209
+ │ └ LLM judge (opt-in fallback) │
210
+ └────────────────┬───────────────────┘
211
+
212
+ ┌── Agent invocation ───────────────┐
213
+ │ workspace whitelist + circuit │
214
+ │ breaker + isAvailable cache │
215
+ │ AgentBase.sendPrompt → spawnStream │
216
+ │ (LineBuffer · true streaming · │
217
+ │ abort/timeout · UTF-8 safe) │
218
+ └────────────────┬───────────────────┘
219
+ ┌──────┬───────┼────────┬─────────┐
220
+ ▼ ▼ ▼ ▼ ▼
221
+ opencode claude codex copilot ACP remote
222
+
223
+ ▼ (if a tool needs approval)
224
+ MCP sidecar ─ unix socket ─ approvalBus
225
+ └─ approvalRouter → IM thread
226
+
227
+ ┌─ Cross-cutting ───────────────────────────────────────┐
228
+ │ audit-log (SQLite, 30-day retention) │
229
+ │ job-board (SQLite, persistent + AbortController) │
230
+ │ scheduler (30s tick → cron → enqueue jobs) │
231
+ │ workspaces (per-tenant agent whitelist + limits) │
232
+ │ metrics (Prometheus text via /api/metrics) │
233
+ │ session (~/.im-hub/sessions/, append-only JSONL) │
234
+ │ pino (traceId end-to-end, JSON in production) │
235
+ └───────────────────────────────────────────────────────┘
236
+ ```
237
+
238
+ Single-process, single-instance: SQLite (`audit.db` / `jobs.db` / `schedules.db`) plus a session file tree is the entire persistence layer. No Redis, no MQ.
239
+
240
+ For the full deep-dive see [`docs/architecture/current.md`](docs/architecture/current.md).
241
+
242
+ ## Project Structure
243
+
244
+ ```
245
+ im-hub-pro/
246
+ ├── src/
247
+ │ ├── core/
248
+ │ │ ├── types.ts # Plugin interfaces
249
+ │ │ ├── registry.ts # Plugin registration
250
+ │ │ ├── router.ts # Message routing
251
+ │ │ ├── session.ts # Session manager (append-only JSONL)
252
+ │ │ ├── workspace.ts # Multi-tenant workspaces
253
+ │ │ ├── intent.ts # Intent classifier
254
+ │ │ ├── intent-llm.ts # LLM judge fallback (LRU cached)
255
+ │ │ ├── circuit-breaker.ts # Per-agent breaker
256
+ │ │ ├── rate-limiter.ts # Token-bucket
257
+ │ │ ├── job-board.ts # Persistent jobs + cancel
258
+ │ │ ├── schedule.ts # Cron tick → job enqueue
259
+ │ │ ├── audit-log.ts # SQLite audit
260
+ │ │ ├── metrics.ts # Prometheus quantiles
261
+ │ │ ├── acp-server.ts # /tasks ACP server
262
+ │ │ ├── approval-bus.ts # Tool-approval pub/sub
263
+ │ │ ├── approval-router.ts # Approval ↔ IM bridge
264
+ │ │ ├── bgjob-reader.ts # ~/.claude + ~/.config/opencode bgjobs
265
+ │ │ ├── agent-base.ts # Shared spawn-stream for CLI agents
266
+ │ │ ├── config-schema.ts # Zod schema
267
+ │ │ ├── logger.ts # pino + traceId
268
+ │ │ ├── sqlite-helper.ts # Shared prepare/PRAGMA cache
269
+ │ │ └── commands/ # /audit /router /job /schedule /model …
270
+ │ ├── plugins/
271
+ │ │ ├── messengers/
272
+ │ │ │ ├── wechat/ # iLink long-poll
273
+ │ │ │ ├── feishu/ # Lark SDK WebSocket
274
+ │ │ │ ├── telegram/ # grammy
275
+ │ │ │ └── discord/ # discord.js
276
+ │ │ └── agents/
277
+ │ │ ├── claude-code/ # + MCP approval sidecar
278
+ │ │ ├── codex/
279
+ │ │ ├── copilot/
280
+ │ │ ├── opencode/
281
+ │ │ └── acp/ # ACP client + /.well-known discovery
282
+ │ ├── index.ts
283
+ │ ├── cli.ts
284
+ │ └── web/
285
+ │ ├── server.ts # HTTP + WS + REST + ACP server
286
+ │ └── public/
287
+ │ ├── index.html # Chat UI
288
+ │ ├── tasks.html # Tasks dashboard
289
+ │ └── settings.html # Settings UI
290
+ ├── docs/
291
+ │ ├── architecture/{current,target}.md
292
+ │ ├── adr/{0001,0002,0003}-*.md
293
+ │ ├── deployment.md
294
+ │ ├── discord-setup.md
295
+ │ └── upgrade-plan.md
296
+ ├── package.json
297
+ ├── tsconfig.json
298
+ └── README.md
299
+ ```
300
+
301
+ ## Configuration
302
+
303
+ Config file: `~/.im-hub/config.json`
304
+
305
+ ```json
306
+ {
307
+ "messengers": ["wechat", "discord"],
308
+ "agents": ["claude-code", "opencode"],
309
+ "defaultAgent": "claude-code",
310
+ "discord": {
311
+ "botToken": "***",
312
+ "allowedGuilds": [],
313
+ "allowedChannels": []
314
+ },
315
+ "acpAgents": [
316
+ {
317
+ "name": "my-agent",
318
+ "aliases": ["ma"],
319
+ "endpoint": "https://api.example.com",
320
+ "auth": { "type": "bearer", "token": "***" },
321
+ "enabled": true
322
+ }
323
+ ],
324
+ "workspaces": [
325
+ {
326
+ "id": "team-data",
327
+ "name": "Data team",
328
+ "agents": ["opencode", "my-agent"],
329
+ "members": ["user-123"],
330
+ "rateLimit": { "rate": 30, "intervalSec": 60, "burst": 60 }
331
+ }
332
+ ]
333
+ }
334
+ ```
335
+
336
+ The schema is enforced by `zod` at startup and on every PUT `/api/config` — bad configs reject loudly instead of silently breaking the bridge.
337
+
338
+ ## Requirements
339
+
340
+ - **Node.js 18+** (≥ 22 LTS recommended for production)
341
+ - **At least one Agent CLI** (or an ACP remote endpoint):
342
+ - `npm i -g @anthropic-ai/claude-code`
343
+ - `npm i -g @openai/codex`
344
+ - `npm i -g @github/copilot`
345
+ - `npm i -g opencode-ai`
346
+
347
+ ## Development
348
+
349
+ ```bash
350
+ git clone https://github.com/benking007/imhub.git
351
+ cd imhub
352
+ npm install
353
+ npm run build # tsc + copy public/
354
+ npm run dev # tsc --watch
355
+ npm test # bun test
356
+ npm run typecheck # tsc --noEmit (src + tests)
357
+ npm start
358
+ ```
359
+
360
+ ## Roadmap
361
+
362
+ ### v0.1.x (MVP)
363
+ - [x] WeChat adapter with QR login
364
+ - [x] Claude Code, Codex, Copilot, OpenCode agents
365
+ - [x] Basic command routing
366
+
367
+ ### v0.2.0 — Multi-IM
368
+ - [x] Feishu adapter
369
+ - [x] Telegram adapter
370
+ - [x] Session persistence with conversation history
371
+ - [x] ACP custom agent support
372
+
373
+ ### v0.2.x — Web & UI
374
+ - [x] Web Chat UI with streaming
375
+ - [x] Settings page
376
+ - [x] Bilingual UI (EN / 中文)
377
+
378
+ ### v0.2.13 — Foundations
379
+ - [x] Structured logging (pino) + traceId
380
+ - [x] Zod config schema validation
381
+ - [x] AgentBase abstraction + healthCheck cache
382
+ - [x] Audit log (SQLite) + `/audit`
383
+ - [x] Intent classifier + circuit breaker + rate limiter
384
+ - [x] ACP server mode (`POST /tasks` sync + SSE)
385
+ - [x] `/.well-known/acp` discovery
386
+ - [x] Multi-tenant workspaces + agent whitelist
387
+ - [x] Persistent Job Board + cron scheduler
388
+ - [x] Web `/tasks` panel + REST jobs API
389
+ - [x] Prometheus metrics
390
+
391
+ ### v0.2.14 — Tool approval
392
+ - [x] Human-in-the-loop tool approval over IM
393
+ - [x] MCP approval sidecar (claude-code adapter)
394
+
395
+ ### v0.2.15 — Discord & Dashboard
396
+ - [x] Discord messenger adapter
397
+ - [x] Tasks dashboard surfaces Claude / opencode bgjobs
398
+ - [x] Flattened subtasks tab
399
+
400
+ ### v0.2.16 — Security hardening (P0 + P1)
401
+ - [x] Timing-safe REST + WS token compare (shared `safe-equal`)
402
+ - [x] Schedule `notify_url` SSRF gate (http(s) only, RFC1918 / loopback / IPv6 ULA blocked) + 10s fetch timeout + redirect:'manual'
403
+ - [x] HTML token injection: `JSON.stringify` instead of single-quote splice
404
+ - [x] Telegram bot-token redaction in logs (pino `redact.paths` + adapter-level scrub)
405
+ - [x] WeChat credential file `0o600` + parent dir `0o700`
406
+ - [x] Approval socket path uses 128-bit random + post-listen `chmod 0o600` + stat verification
407
+ - [x] Job result size cap (`IMHUB_JOB_RESULT_MAX_BYTES`, default 1 MiB) + UTF-8/JSON safe truncation
408
+ - [x] Job-board retention + 6h sweep + `creator_id` / `workspace_id` schema migration
409
+ - [x] Multi-tenant ACL on `/job` `/schedule` `/audit` commands (each user sees only their own rows; legacy ownerless rows stay visible for safe upgrades)
410
+ - [x] Workspace whitelist enforced on direct command paths, not just routing
411
+ - [x] Rate-limiter opportunistic auto-cleanup (no setInterval timer)
412
+ - [x] `Session.addMessage` per-key mutex (defeats concurrent read-modify-write race)
413
+
414
+ ### v0.2.17 — Observability & IM polish (P2 + P3)
415
+ - [x] Static-page security headers (`X-Frame-Options` / `X-Content-Type-Options` / `Referrer-Policy` / CSP)
416
+ - [x] `/api/health` declared public (k8s liveness friendly)
417
+ - [x] WebSocket connection cap (`IMHUB_MAX_WS_CLIENTS`, default 100) + `bufferedAmount` backpressure (4 MiB highwater)
418
+ - [x] Prometheus label-cardinality whitelist (`intent` / `platform` → `'other'` for unknowns)
419
+ - [x] New counters: `im_hub_audit_prune_failed_total`, `im_hub_agent_cleanup_failed_total`, `im_hub_approval_pending` / `im_hub_approval_requests_total` / `im_hub_approval_resolved_total{result=allow|deny|timeout}`
420
+ - [x] `intent-llm` cache key SHA-256 + 256-char prompt cap (defeats LRU memory bloat)
421
+ - [x] Auto-allow fingerprint 5 → 10 chars (`git status` ≠ `git stash` ≠ `git submo`)
422
+ - [x] UTF-16 surrogate-safe message split (emoji at boundary no longer renders as `□`)
423
+ - [x] Telegram HTML escape covers `'` / `"` (approval-card `<a href="...">` safety)
424
+ - [x] approval-bus over-cap deny instead of silent socket destroy
425
+ - [x] SQLite WAL clean checkpoint on SIGINT
426
+ - [x] traceId 12 hex → 16 hex (`~2^48` → `~2^64`)
427
+ - [x] WeChat ilink-client fetch timeouts on remaining 4 callsites
428
+ - [x] Discord typing interval companion `AbortController` (no race with `client.destroy()`)
429
+ - [x] WeChat `contextTokens` periodic cleanup on heartbeat tick
430
+ - [x] CI lockfile fix (Tencent mirror URLs → `https://registry.npmjs.org/`)
431
+
432
+ ### v0.2.18 — IM reconnect backoff (M9)
433
+ - [x] Shared `Backoff` helper (exponential + ±jitter, RNG-injectable for tests)
434
+ - [x] Telegram `runPollingLoop`: fixed 2s / 5s setTimeouts → `Backoff(2s, 60s, 0.5)`; 30s healthy-run threshold resets backoff
435
+ - [x] WeChat ilink `pollLoop`: inline `Math.pow(2,n-1)` → `Backoff(2s, 30s, 0.5)`; success path resets
436
+
437
+ ### v0.2.19 — Codex sandbox + Dashboard filter / Audit tab
438
+ - [x] Codex now honors `session.planMode`; default sandbox `--full-auto` → explicit `-s workspace-write`
439
+ - [x] Per-agent filter on Jobs / Subtasks / Schedules tabs (`OwnerOpts.agent` plumbed through)
440
+ - [x] New Audit tab in `/tasks` pulling SQLite audit log + `GET /api/audit?agent=&days=&user=&intent=`
441
+
442
+ ### v0.2.20 — Web console PR-A: theme + error boundary + in-page approval
443
+ - [x] Three-state theme (light / dark / system) applied synchronously in `<head>` to defeat flash
444
+ - [x] `_app.js` shared utility: `window.imhub.{theme,i18n,api,showError}` + auto-installed error boundary
445
+ - [x] In-chat approval cards on `/` (Allow / Deny / Allow + Auto), routed through the same `approvalBus.resolvePending()` path as Telegram
446
+ - [x] `approval-router` `bindButtonHandlerForPlatform(platform)` exported so late-registered messengers (web is one) can wire their button handler
447
+
448
+ ### v0.2.21 — Web console PR-B: Health + Approvals tabs
449
+ - [x] Health tab: per-agent breaker phase (closed/open/half-open) + rate-limiter remaining + p50/95/99 latency + invocations / success rate / cost / cooldown + 60-poll p95 sparkline
450
+ - [x] Approvals tab: list every pending HITL approval (reqId / threadId / tool / age / registeredAt) with browser-side Allow / Deny / Allow + Auto buttons
451
+ - [x] Backend: `GET /api/agent-health` / `GET /api/approvals` / `POST /api/approvals/:reqId/resolve`
452
+ - [x] `approval-bus.PendingApproval` now carries `input` + `registeredAt`; emits `'approval'` events for SSE
453
+
454
+ ### v0.2.22 — Web console PR-C: SSE event stream + Workspace CRUD UI
455
+ - [x] `src/core/event-bus.ts` — typed publish/subscribe (audit / approval / job / metrics) with 200-entry replay ring buffer
456
+ - [x] `GET /events` SSE endpoint — token via `?token=`, 25s heartbeat, listener-error swallow
457
+ - [x] Dashboard `EventSource('/events?token=...')` refreshes only the visible tab; polling kept as fallback; `approval requested` flashes the tab badge
458
+ - [x] Settings page Workspace card — list + create / edit / delete (id locked on edit; default row uneditable + undeletable)
459
+ - [x] Backend `GET/POST/PATCH/DELETE /api/workspaces` + `WorkspaceRegistry.{remove(id), listFull()}`; mutations persisted back to `~/.im-hub/config.json`
460
+
461
+ ### v0.2.23 — Web console PR-D: Files tab + Jobs batch ops + settings polish
462
+ - [x] Files tab — read-only browse of `~/.im-hub-workspaces/<agent>/`, two-pane (dir tree + content), 1 MiB cap, NUL-byte binary detect → base64
463
+ - [x] Path-traversal defense: agent name whitelisted against `registry.listAgents()`; resolved path must equal or live below `defaultAgentCwd(agent)`
464
+ - [x] Jobs tab multi-select + select-all + hidden-until-needed batch toolbar; selection state survives refresh
465
+ - [x] `POST /api/jobs/batch-cancel` / `batch-run` accept `{ ids: number[] }` (max 100); per-id failures don't fail the whole request
466
+ - [x] Settings header restyle (`.brand` + `.controls` flex groups) — fixes language `<select>` stretching across the bar; container 720→880, sticky header, theme-aware toast / `.btn-danger:hover`
467
+
468
+ ### v0.3.0
469
+ - [ ] DingTalk adapter
470
+ - [ ] Slack adapter
471
+ - [ ] Approval cards (Feishu/Discord buttons) instead of plain text
472
+ - [ ] Cron `nextOccurrence` internal UTC normalization (DST safety, M5 from CR-2026-05-06)
473
+ - [ ] Multi-instance event bus (Redis Streams / NATS) so SSE works across replicas
474
+ - [ ] Workspace member picker UI (current CSV input is ops-friendly but error-prone)
475
+
476
+ ## Community <a name="wechat-group"></a>
477
+
478
+ Questions? Feel free to reach out on [X](https://x.com/lijieisme) or join the Discord.
479
+
480
+ <p align="center">
481
+ <a href="https://discord.gg/R83CXYz5">
482
+ <img src="https://img.shields.io/badge/Join_Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Join Discord">
483
+ </a>
484
+ &nbsp;
485
+ <a href="https://x.com/lijieisme">
486
+ <img src="https://img.shields.io/badge/Follow_on_X-000000?style=for-the-badge&logo=x&logoColor=white" alt="X">
487
+ </a>
488
+ </p>
489
+
490
+ <p align="center">
491
+ <img src="assets/wechat-group" alt="Original author WeChat" width="180"><br>
492
+ <sub><i>Original author's contact</i></sub>
493
+ </p>
494
+
495
+ ## License
496
+
497
+ MIT