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
@@ -0,0 +1,235 @@
1
+ // MCP sidecar — Claude Code 通过 --permission-prompt-tool 调用本进程的 `request` 工具,
2
+ // 本进程把请求转发给 im-hub 主进程的 approval-bus(unix socket),等用户决策回包后
3
+ // 翻译成 MCP tool result。
4
+ //
5
+ // 这是个独立进程,由 claude 子进程通过 --mcp-config 启动;与 im-hub 通信只走 socket。
6
+ // 启动需要两个 env:
7
+ // IMHUB_APPROVAL_SOCK unix socket 路径
8
+ // IMHUB_RUN_ID 本次 claude run 的 ID(与 approvalBus.registerRun 配套)
9
+ //
10
+ // 协议见 src/core/approval-bus.ts。
11
+ //
12
+ // 入口(编译后):node dist/plugins/agents/claude-code/mcp-approval-server.js
13
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
14
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
15
+ import { z } from 'zod';
16
+ import { createConnection } from 'net';
17
+ import { randomUUID } from 'crypto';
18
+ const SERVER_NAME = 'imhub';
19
+ const TOOL_NAME = 'request';
20
+ class ApprovalClient {
21
+ socketPath;
22
+ runId;
23
+ socket = null;
24
+ buf = '';
25
+ pending = new Map();
26
+ connectErr = null;
27
+ closed = false;
28
+ connectPromise;
29
+ constructor(socketPath, runId) {
30
+ this.socketPath = socketPath;
31
+ this.runId = runId;
32
+ this.connectPromise = this.connect();
33
+ }
34
+ connect() {
35
+ return new Promise((resolve) => {
36
+ const sock = createConnection(this.socketPath);
37
+ sock.setEncoding('utf8');
38
+ const onConnectError = (err) => {
39
+ this.connectErr = err;
40
+ this.closed = true;
41
+ // stderr surfaces inside Claude Code's MCP log
42
+ process.stderr.write(`[mcp-approval-server] connect failed: ${err.message}\n`);
43
+ resolve();
44
+ };
45
+ sock.once('error', onConnectError);
46
+ sock.once('connect', () => {
47
+ sock.removeListener('error', onConnectError);
48
+ sock.on('error', (err) => {
49
+ process.stderr.write(`[mcp-approval-server] socket error: ${err.message}\n`);
50
+ });
51
+ sock.on('data', (chunk) => this.onData(chunk));
52
+ sock.on('close', () => this.onClose());
53
+ this.socket = sock;
54
+ resolve();
55
+ });
56
+ });
57
+ }
58
+ onData(chunk) {
59
+ this.buf += chunk;
60
+ let nl;
61
+ while ((nl = this.buf.indexOf('\n')) !== -1) {
62
+ const line = this.buf.slice(0, nl);
63
+ this.buf = this.buf.slice(nl + 1);
64
+ if (!line)
65
+ continue;
66
+ let msg;
67
+ try {
68
+ msg = JSON.parse(line);
69
+ }
70
+ catch {
71
+ process.stderr.write(`[mcp-approval-server] bad json from bus: ${line.slice(0, 200)}\n`);
72
+ continue;
73
+ }
74
+ this.dispatch(msg);
75
+ }
76
+ }
77
+ dispatch(msg) {
78
+ if (!msg || typeof msg !== 'object')
79
+ return;
80
+ const m = msg;
81
+ if (m.v !== 1 || m.type !== 'decision')
82
+ return;
83
+ const reqId = typeof m.reqId === 'string' ? m.reqId : null;
84
+ if (!reqId)
85
+ return;
86
+ const p = this.pending.get(reqId);
87
+ if (!p)
88
+ return;
89
+ this.pending.delete(reqId);
90
+ if (m.behavior === 'allow') {
91
+ const updatedInput = (m.updatedInput && typeof m.updatedInput === 'object' && !Array.isArray(m.updatedInput))
92
+ ? m.updatedInput
93
+ : p.originalInput; // Claude Code requires updatedInput; echo original
94
+ p.resolve({ behavior: 'allow', updatedInput });
95
+ }
96
+ else {
97
+ const message = typeof m.message === 'string' ? m.message : undefined;
98
+ p.resolve({ behavior: 'deny', ...(message ? { message } : {}) });
99
+ }
100
+ }
101
+ onClose() {
102
+ this.closed = true;
103
+ // Drain pending with deny — claude is left hanging otherwise
104
+ for (const [, p] of this.pending) {
105
+ p.resolve({ behavior: 'deny', message: 'approval bus disconnected' });
106
+ }
107
+ this.pending.clear();
108
+ }
109
+ // request(): see below — request → register pending → write payload
110
+ /**
111
+ * Send an approval request and wait for the decision. If the bus is
112
+ * unreachable or the connection has dropped, returns a deny synchronously.
113
+ */
114
+ async request(args) {
115
+ await this.connectPromise;
116
+ if (this.connectErr || this.closed || !this.socket) {
117
+ return { behavior: 'deny', message: `approval bus unavailable: ${this.connectErr?.message ?? 'closed'}` };
118
+ }
119
+ const reqId = randomUUID();
120
+ const payload = JSON.stringify({
121
+ v: 1,
122
+ type: 'approval',
123
+ runId: this.runId,
124
+ reqId,
125
+ toolName: args.toolName,
126
+ input: args.input,
127
+ toolUseId: args.toolUseId,
128
+ }) + '\n';
129
+ return new Promise((resolve) => {
130
+ this.pending.set(reqId, { resolve, originalInput: args.input });
131
+ this.socket.write(payload, (err) => {
132
+ if (err) {
133
+ this.pending.delete(reqId);
134
+ resolve({ behavior: 'deny', message: `write failed: ${err.message}` });
135
+ }
136
+ });
137
+ });
138
+ }
139
+ async close() {
140
+ this.closed = true;
141
+ if (this.socket && !this.socket.destroyed) {
142
+ await new Promise((resolve) => {
143
+ this.socket.once('close', () => resolve());
144
+ this.socket.end();
145
+ setTimeout(() => { if (this.socket && !this.socket.destroyed)
146
+ this.socket.destroy(); }, 200).unref();
147
+ });
148
+ }
149
+ }
150
+ }
151
+ /**
152
+ * Build the MCP server. Exposed as a function (rather than top-level `await`)
153
+ * so tests can construct it without spinning up stdio.
154
+ */
155
+ export function buildServer(client) {
156
+ const server = new McpServer({
157
+ name: SERVER_NAME,
158
+ version: '0.1.0',
159
+ });
160
+ // Accept both snake_case (what Claude Code sends over the wire) and
161
+ // camelCase (defensive — some forks normalize). passthrough so unknown
162
+ // future fields are not stripped before we see them.
163
+ const inputSchema = {
164
+ tool_name: z.string().optional(),
165
+ toolName: z.string().optional(),
166
+ input: z.record(z.string(), z.unknown()).optional(),
167
+ tool_use_id: z.string().optional(),
168
+ toolUseId: z.string().optional(),
169
+ };
170
+ server.registerTool(TOOL_NAME, {
171
+ title: 'IM hub permission prompt',
172
+ description: 'Routes Claude Code permission prompts to im-hub for human approval over IM. ' +
173
+ 'Returns {behavior: "allow"|"deny", ...} as a JSON-encoded text block.',
174
+ inputSchema,
175
+ }, async (args) => {
176
+ const toolName = args.tool_name ?? args.toolName ?? '<unknown>';
177
+ const input = (args.input ?? {});
178
+ const toolUseId = args.tool_use_id ?? args.toolUseId ?? '';
179
+ const decision = await client.request({ toolName, input, toolUseId });
180
+ return {
181
+ content: [
182
+ { type: 'text', text: JSON.stringify(decision) },
183
+ ],
184
+ };
185
+ });
186
+ return server;
187
+ }
188
+ export { ApprovalClient };
189
+ async function main() {
190
+ const sockPath = process.env.IMHUB_APPROVAL_SOCK;
191
+ const runId = process.env.IMHUB_RUN_ID;
192
+ if (!sockPath || !runId) {
193
+ process.stderr.write('[mcp-approval-server] missing IMHUB_APPROVAL_SOCK or IMHUB_RUN_ID\n');
194
+ process.exit(1);
195
+ }
196
+ const client = new ApprovalClient(sockPath, runId);
197
+ const server = buildServer(client);
198
+ const transport = new StdioServerTransport();
199
+ await server.connect(transport);
200
+ // When stdio closes (claude went away), shut down cleanly.
201
+ const shutdown = async () => {
202
+ try {
203
+ await client.close();
204
+ }
205
+ catch { /* ignore */ }
206
+ try {
207
+ await server.close();
208
+ }
209
+ catch { /* ignore */ }
210
+ process.exit(0);
211
+ };
212
+ process.on('SIGTERM', shutdown);
213
+ process.on('SIGINT', shutdown);
214
+ }
215
+ // Detect "run as script" — when imported by tests we don't want to spin up stdio.
216
+ const isMainModule = (() => {
217
+ if (typeof process === 'undefined' || !process.argv[1])
218
+ return false;
219
+ try {
220
+ const url = new URL(import.meta.url);
221
+ return url.pathname.endsWith(process.argv[1].replace(/^.*?(?=\/|$)/, '')) ||
222
+ url.pathname === process.argv[1] ||
223
+ process.argv[1].endsWith('mcp-approval-server.js');
224
+ }
225
+ catch {
226
+ return false;
227
+ }
228
+ })();
229
+ if (isMainModule) {
230
+ main().catch((err) => {
231
+ process.stderr.write(`[mcp-approval-server] fatal: ${err}\n`);
232
+ process.exit(1);
233
+ });
234
+ }
235
+ //# sourceMappingURL=mcp-approval-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-approval-server.js","sourceRoot":"","sources":["../../../../src/plugins/agents/claude-code/mcp-approval-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mcp-approval-server.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-approval-server.test.d.ts","sourceRoot":"","sources":["../../../../src/plugins/agents/claude-code/mcp-approval-server.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,188 @@
1
+ // mcp-approval-server e2e — 端到端串 ApprovalBus ←→ ApprovalClient ←→ McpServer ←→ MCP Client,
2
+ // 用 InMemoryTransport 替代 stdio,避免依赖 build / 子进程。
3
+ import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
4
+ import { tmpdir } from 'os';
5
+ import { join } from 'path';
6
+ import { randomBytes } from 'crypto';
7
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
8
+ import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
9
+ import { ApprovalBus } from '../../../core/approval-bus.js';
10
+ import { ApprovalClient, buildServer } from './mcp-approval-server.js';
11
+ const RUN_ID = 'run-test-1';
12
+ const RUN_CTX = {
13
+ threadId: 'thread-A',
14
+ platform: 'feishu',
15
+ userId: 'u1',
16
+ channelId: 'c1',
17
+ };
18
+ function uniqueSocketPath() {
19
+ return join(tmpdir(), `imhub-mcp-test-${process.pid}-${randomBytes(4).toString('hex')}.sock`);
20
+ }
21
+ async function setup() {
22
+ const sockPath = uniqueSocketPath();
23
+ const bus = new ApprovalBus({ approvalTimeoutMs: 500 });
24
+ await bus.start(sockPath);
25
+ bus.registerRun(RUN_ID, RUN_CTX);
26
+ const client = new ApprovalClient(sockPath, RUN_ID);
27
+ const server = buildServer(client);
28
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
29
+ await server.connect(serverTransport);
30
+ const mcpClient = new Client({ name: 'test-client', version: '0.0.0' });
31
+ await mcpClient.connect(clientTransport);
32
+ return {
33
+ bus,
34
+ client,
35
+ mcpClient,
36
+ cleanup: async () => {
37
+ await mcpClient.close();
38
+ await server.close();
39
+ await client.close();
40
+ await bus.stop();
41
+ },
42
+ };
43
+ }
44
+ describe('mcp-approval-server', () => {
45
+ let h;
46
+ beforeEach(async () => { h = await setup(); });
47
+ afterEach(async () => { await h.cleanup(); });
48
+ it('exposes a `request` tool', async () => {
49
+ const tools = await h.mcpClient.listTools();
50
+ const names = tools.tools.map((t) => t.name);
51
+ expect(names).toContain('request');
52
+ });
53
+ it('round-trip: tools/call → bus notifier → resolvePending(allow) → MCP result', async () => {
54
+ let captured = null;
55
+ h.bus.setNotifier(async (n) => {
56
+ captured = { toolName: n.toolName, input: n.input };
57
+ // Simulate IM user clicking "approve" by resolving in the next tick
58
+ queueMicrotask(() => {
59
+ h.bus.resolvePending('thread-A', { behavior: 'allow' });
60
+ });
61
+ });
62
+ const result = await h.mcpClient.callTool({
63
+ name: 'request',
64
+ arguments: {
65
+ tool_name: 'Bash',
66
+ input: { command: 'git status' },
67
+ tool_use_id: 'tu-1',
68
+ },
69
+ });
70
+ expect(captured).not.toBeNull();
71
+ expect(captured.toolName).toBe('Bash');
72
+ expect(captured.input).toEqual({ command: 'git status' });
73
+ const content = result.content;
74
+ expect(content[0].type).toBe('text');
75
+ const decision = JSON.parse(content[0].text);
76
+ // When allow has no explicit updatedInput, sidecar echoes the original
77
+ // input back — Claude Code rejects allow without updatedInput.
78
+ expect(decision.behavior).toBe('allow');
79
+ expect(decision.updatedInput).toEqual({ command: 'git status' });
80
+ });
81
+ it('forwards updatedInput on allow', async () => {
82
+ h.bus.setNotifier(async () => {
83
+ queueMicrotask(() => {
84
+ h.bus.resolvePending('thread-A', {
85
+ behavior: 'allow',
86
+ updatedInput: { command: 'echo sandboxed' },
87
+ });
88
+ });
89
+ });
90
+ const result = await h.mcpClient.callTool({
91
+ name: 'request',
92
+ arguments: { tool_name: 'Bash', input: { command: 'echo raw' }, tool_use_id: 'tu' },
93
+ });
94
+ const content = result.content;
95
+ const decision = JSON.parse(content[0].text);
96
+ expect(decision.behavior).toBe('allow');
97
+ expect(decision.updatedInput).toEqual({ command: 'echo sandboxed' });
98
+ });
99
+ it('forwards deny + message', async () => {
100
+ h.bus.setNotifier(async () => {
101
+ queueMicrotask(() => {
102
+ h.bus.resolvePending('thread-A', { behavior: 'deny', message: '用户拒绝' });
103
+ });
104
+ });
105
+ const result = await h.mcpClient.callTool({
106
+ name: 'request',
107
+ arguments: { tool_name: 'Bash', input: {}, tool_use_id: 'tu' },
108
+ });
109
+ const content = result.content;
110
+ const decision = JSON.parse(content[0].text);
111
+ expect(decision).toEqual({ behavior: 'deny', message: '用户拒绝' });
112
+ });
113
+ it('approval timeout (no resolvePending) → MCP returns deny', async () => {
114
+ let notified = false;
115
+ h.bus.setNotifier(async () => { notified = true; /* never resolve */ });
116
+ const result = await h.mcpClient.callTool({
117
+ name: 'request',
118
+ arguments: { tool_name: 'Bash', input: {}, tool_use_id: 'tu' },
119
+ });
120
+ expect(notified).toBe(true);
121
+ const content = result.content;
122
+ const decision = JSON.parse(content[0].text);
123
+ expect(decision.behavior).toBe('deny');
124
+ expect(decision.message).toBe('approval timeout');
125
+ });
126
+ it('also accepts camelCase argument names', async () => {
127
+ let captured = null;
128
+ h.bus.setNotifier(async (n) => {
129
+ captured = n.toolName;
130
+ queueMicrotask(() => {
131
+ h.bus.resolvePending('thread-A', { behavior: 'allow' });
132
+ });
133
+ });
134
+ await h.mcpClient.callTool({
135
+ name: 'request',
136
+ arguments: { toolName: 'Read', input: { file_path: '/etc/hosts' }, toolUseId: 'tu' },
137
+ });
138
+ expect(captured).not.toBeNull();
139
+ expect(captured).toBe('Read');
140
+ });
141
+ it('unknown runId is denied immediately', async () => {
142
+ // Build a fresh client whose runId is never registered with the bus
143
+ const sockPath = h.bus.getSocketPath();
144
+ const orphanClient = new ApprovalClient(sockPath, 'never-registered');
145
+ const orphanServer = buildServer(orphanClient);
146
+ const [ct, st] = InMemoryTransport.createLinkedPair();
147
+ await orphanServer.connect(st);
148
+ const orphanMcp = new Client({ name: 'orphan', version: '0.0.0' });
149
+ await orphanMcp.connect(ct);
150
+ h.bus.setNotifier(async () => { throw new Error('notifier should not be called'); });
151
+ const result = await orphanMcp.callTool({
152
+ name: 'request',
153
+ arguments: { tool_name: 'Bash', input: {}, tool_use_id: 'tu' },
154
+ });
155
+ const content = result.content;
156
+ const decision = JSON.parse(content[0].text);
157
+ expect(decision.behavior).toBe('deny');
158
+ expect(decision.message).toContain('unknown runId');
159
+ await orphanMcp.close();
160
+ await orphanServer.close();
161
+ await orphanClient.close();
162
+ });
163
+ });
164
+ describe('ApprovalClient (without MCP layer)', () => {
165
+ it('returns deny synchronously when bus socket does not exist', async () => {
166
+ const client = new ApprovalClient('/tmp/imhub-nonexistent-socket-xyz', RUN_ID);
167
+ const decision = await client.request({ toolName: 'Bash', input: {}, toolUseId: 'tu' });
168
+ expect(decision.behavior).toBe('deny');
169
+ expect(decision.message).toContain('approval bus unavailable');
170
+ await client.close();
171
+ });
172
+ it('returns deny on all in-flight requests when bus is stopped mid-call', async () => {
173
+ const sockPath = uniqueSocketPath();
174
+ const bus = new ApprovalBus({ approvalTimeoutMs: 5000 });
175
+ await bus.start(sockPath);
176
+ bus.registerRun(RUN_ID, RUN_CTX);
177
+ bus.setNotifier(async () => { });
178
+ const client = new ApprovalClient(sockPath, RUN_ID);
179
+ const inFlight = client.request({ toolName: 'Bash', input: {}, toolUseId: 'tu' });
180
+ // Give the request time to land in pending, then stop the bus
181
+ await new Promise((r) => setTimeout(r, 50));
182
+ await bus.stop();
183
+ const decision = await inFlight;
184
+ expect(decision.behavior).toBe('deny');
185
+ await client.close();
186
+ });
187
+ });
188
+ //# sourceMappingURL=mcp-approval-server.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-approval-server.test.js","sourceRoot":"","sources":["../../../../src/plugins/agents/claude-code/mcp-approval-server.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapter.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.test.d.ts","sourceRoot":"","sources":["../../../../src/plugins/agents/codex/adapter.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,192 @@
1
+ // CodexAdapter — verify session-id capture, exec resume args, text extraction,
2
+ // and usage callbacks. Mirrors the opencode regression net for codex's
3
+ // `--json` event stream (codex 0.128).
4
+ //
5
+ // Reference event shapes (real codex output):
6
+ // {"type":"thread.started","thread_id":"<uuid>"}
7
+ // {"type":"turn.started"}
8
+ // {"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"hi!"}}
9
+ // {"type":"turn.completed","usage":{"input_tokens":13299,"cached_input_tokens":11648,"output_tokens":6,"reasoning_output_tokens":0}}
10
+ import { describe, it, expect } from 'bun:test';
11
+ import { CodexAdapter, _testInternals } from './index.js';
12
+ const { buildArgs, extractText, inspectEvent } = _testInternals;
13
+ describe('CodexAdapter buildArgs', () => {
14
+ it('starts a fresh session when no agentSessionId provided', () => {
15
+ const adapter = new CodexAdapter();
16
+ const args = buildArgs(adapter, 'hello', {});
17
+ expect(args[0]).toBe('exec');
18
+ expect(args).not.toContain('resume');
19
+ expect(args).toContain('--json');
20
+ expect(args[args.length - 1]).toBe('hello');
21
+ });
22
+ it('uses `exec resume <id>` when agentSessionId + agentSessionResume are set', () => {
23
+ const adapter = new CodexAdapter();
24
+ const args = buildArgs(adapter, 'hello', {
25
+ agentSessionId: '019df376-0ec9-77c3-9d7d-1a15fd8cc9c9',
26
+ agentSessionResume: true,
27
+ });
28
+ expect(args[0]).toBe('exec');
29
+ expect(args[1]).toBe('resume');
30
+ expect(args[2]).toBe('019df376-0ec9-77c3-9d7d-1a15fd8cc9c9');
31
+ expect(args).toContain('--json');
32
+ expect(args[args.length - 1]).toBe('hello');
33
+ });
34
+ it('does NOT use resume when agentSessionId is set without agentSessionResume', () => {
35
+ // Defensive: agentSessionId without resume means "we know the id but
36
+ // codex hasn't been told yet" — happens nowhere in practice but we want
37
+ // a deterministic fallback rather than an undefined positional.
38
+ const adapter = new CodexAdapter();
39
+ const args = buildArgs(adapter, 'p', { agentSessionId: 'abc' });
40
+ expect(args).not.toContain('resume');
41
+ expect(args[0]).toBe('exec');
42
+ });
43
+ it('keeps --skip-git-repo-check on every call (post --full-auto removal)', () => {
44
+ // --full-auto was dropped in favor of explicit `-s workspace-write`
45
+ // (without auto-approval) — see codex/index.ts BASE_FLAGS comment.
46
+ const adapter = new CodexAdapter();
47
+ expect(buildArgs(adapter, 'p', {})).toContain('--skip-git-repo-check');
48
+ expect(buildArgs(adapter, 'p', {})).not.toContain('--full-auto');
49
+ expect(buildArgs(adapter, 'p', {
50
+ agentSessionId: 'abc', agentSessionResume: true,
51
+ })).toContain('--skip-git-repo-check');
52
+ });
53
+ it('passes -s workspace-write by default (no plan mode)', () => {
54
+ const adapter = new CodexAdapter();
55
+ const args = buildArgs(adapter, 'p', {});
56
+ expect(args).toContain('-s');
57
+ expect(args).toContain('workspace-write');
58
+ });
59
+ it('passes -s read-only when planMode is true', () => {
60
+ const adapter = new CodexAdapter();
61
+ const args = buildArgs(adapter, 'p', { planMode: true });
62
+ expect(args).toContain('-s');
63
+ expect(args).toContain('read-only');
64
+ expect(args).not.toContain('workspace-write');
65
+ });
66
+ it('passes -s read-only on a resume turn when planMode is set', () => {
67
+ const adapter = new CodexAdapter();
68
+ const args = buildArgs(adapter, 'p', {
69
+ agentSessionId: 'abc', agentSessionResume: true, planMode: true,
70
+ });
71
+ expect(args).toContain('-s');
72
+ expect(args).toContain('read-only');
73
+ });
74
+ });
75
+ describe('CodexAdapter extractText', () => {
76
+ it('extracts text from item.completed agent_message', () => {
77
+ const adapter = new CodexAdapter();
78
+ const text = extractText(adapter, {
79
+ type: 'item.completed',
80
+ item: { id: 'item_0', type: 'agent_message', text: 'hello world' },
81
+ });
82
+ expect(text).toBe('hello world');
83
+ });
84
+ it('returns empty string for non-agent_message item types', () => {
85
+ const adapter = new CodexAdapter();
86
+ expect(extractText(adapter, {
87
+ type: 'item.completed',
88
+ item: { id: 'item_1', type: 'tool_call', text: 'should not surface' },
89
+ })).toBe('');
90
+ });
91
+ it('returns empty for orchestration events (thread.started / turn.*)', () => {
92
+ const adapter = new CodexAdapter();
93
+ expect(extractText(adapter, { type: 'thread.started', thread_id: 'abc' })).toBe('');
94
+ expect(extractText(adapter, { type: 'turn.started' })).toBe('');
95
+ expect(extractText(adapter, { type: 'turn.completed', usage: { input_tokens: 10 } })).toBe('');
96
+ });
97
+ // Regression guard for the v0 adapter that hunted for {type:"message"} —
98
+ // that event shape never fires in real codex 0.128 output.
99
+ it('does NOT match the legacy {type:"message"} shape', () => {
100
+ const adapter = new CodexAdapter();
101
+ expect(extractText(adapter, {
102
+ type: 'message',
103
+ message: { content: [{ type: 'text', text: 'should-not-match' }] },
104
+ })).toBe('');
105
+ });
106
+ });
107
+ describe('CodexAdapter inspectEvent — session id capture', () => {
108
+ it('forwards thread_id from thread.started via opts.onAgentSessionId', () => {
109
+ const adapter = new CodexAdapter();
110
+ const ids = [];
111
+ inspectEvent(adapter, { type: 'thread.started', thread_id: 'uuid-1' }, {
112
+ onAgentSessionId: (id) => ids.push(id),
113
+ });
114
+ expect(ids).toEqual(['uuid-1']);
115
+ });
116
+ it('does not fire for events other than thread.started', () => {
117
+ const adapter = new CodexAdapter();
118
+ const ids = [];
119
+ const opts = { onAgentSessionId: (id) => ids.push(id) };
120
+ inspectEvent(adapter, { type: 'turn.started' }, opts);
121
+ inspectEvent(adapter, {
122
+ type: 'item.completed',
123
+ item: { type: 'agent_message', text: 'hi' },
124
+ }, opts);
125
+ expect(ids.length).toBe(0);
126
+ });
127
+ it('does nothing when callback is absent', () => {
128
+ const adapter = new CodexAdapter();
129
+ inspectEvent(adapter, { type: 'thread.started', thread_id: 'x' }, {});
130
+ // Absence of throw is the assertion.
131
+ expect(true).toBe(true);
132
+ });
133
+ it('survives a callback that throws', () => {
134
+ const adapter = new CodexAdapter();
135
+ inspectEvent(adapter, { type: 'thread.started', thread_id: 'x' }, {
136
+ onAgentSessionId: () => { throw new Error('boom'); },
137
+ });
138
+ expect(true).toBe(true);
139
+ });
140
+ });
141
+ describe('CodexAdapter inspectEvent — usage capture', () => {
142
+ it('forwards input/output tokens from turn.completed.usage', () => {
143
+ const adapter = new CodexAdapter();
144
+ const deltas = [];
145
+ inspectEvent(adapter, {
146
+ type: 'turn.completed',
147
+ usage: {
148
+ input_tokens: 13299,
149
+ cached_input_tokens: 11648,
150
+ output_tokens: 6,
151
+ reasoning_output_tokens: 0,
152
+ },
153
+ }, { onUsage: (d) => deltas.push(d) });
154
+ expect(deltas.length).toBe(1);
155
+ expect(deltas[0].tokensInput).toBe(13299);
156
+ expect(deltas[0].tokensOutput).toBe(6);
157
+ // codex doesn't surface cost — should remain undefined.
158
+ expect(deltas[0].costUsd).toBeUndefined();
159
+ });
160
+ it('does NOT fire onUsage for non-turn.completed events', () => {
161
+ const adapter = new CodexAdapter();
162
+ const deltas = [];
163
+ inspectEvent(adapter, { type: 'turn.started' }, { onUsage: (d) => deltas.push(d) });
164
+ inspectEvent(adapter, {
165
+ type: 'item.completed',
166
+ item: { type: 'agent_message', text: 'hi' },
167
+ }, { onUsage: (d) => deltas.push(d) });
168
+ expect(deltas.length).toBe(0);
169
+ });
170
+ it('skips onUsage when turn.completed carries no usage block', () => {
171
+ const adapter = new CodexAdapter();
172
+ const deltas = [];
173
+ inspectEvent(adapter, { type: 'turn.completed' }, { onUsage: (d) => deltas.push(d) });
174
+ expect(deltas.length).toBe(0);
175
+ });
176
+ });
177
+ describe('CodexAdapter prepareCommand', () => {
178
+ it('does not pin cwd for non-IM calls (no threadId/platform)', async () => {
179
+ const adapter = new CodexAdapter();
180
+ const plan = await _testInternals.prepareCommand(adapter, 'p', {});
181
+ expect(plan.cwd).toBeUndefined();
182
+ });
183
+ it('pins cwd to ~/.im-hub-workspaces/codex when threadId+platform present', async () => {
184
+ const adapter = new CodexAdapter();
185
+ const plan = await _testInternals.prepareCommand(adapter, 'p', {
186
+ threadId: 't1', platform: 'wechat', channelId: 'c1', userId: 'u1',
187
+ });
188
+ expect(plan.cwd).toBeDefined();
189
+ expect(plan.cwd.endsWith('/codex')).toBe(true);
190
+ });
191
+ });
192
+ //# sourceMappingURL=adapter.test.js.map