agim-cli 1.0.1

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 (453) hide show
  1. package/CHANGELOG.md +1234 -0
  2. package/LICENSE +21 -0
  3. package/README.md +422 -0
  4. package/README.zh-CN.md +414 -0
  5. package/dist/cli-ui/cmd-handlers.d.ts +11 -0
  6. package/dist/cli-ui/cmd-handlers.d.ts.map +1 -0
  7. package/dist/cli-ui/cmd-handlers.js +240 -0
  8. package/dist/cli-ui/cmd-handlers.js.map +1 -0
  9. package/dist/cli-ui/config-wizard.d.ts +3 -0
  10. package/dist/cli-ui/config-wizard.d.ts.map +1 -0
  11. package/dist/cli-ui/config-wizard.js +851 -0
  12. package/dist/cli-ui/config-wizard.js.map +1 -0
  13. package/dist/cli-ui/entry-menu.d.ts +28 -0
  14. package/dist/cli-ui/entry-menu.d.ts.map +1 -0
  15. package/dist/cli-ui/entry-menu.js +50 -0
  16. package/dist/cli-ui/entry-menu.js.map +1 -0
  17. package/dist/cli-ui/env-file.d.ts +35 -0
  18. package/dist/cli-ui/env-file.d.ts.map +1 -0
  19. package/dist/cli-ui/env-file.js +163 -0
  20. package/dist/cli-ui/env-file.js.map +1 -0
  21. package/dist/cli-ui/i18n.d.ts +204 -0
  22. package/dist/cli-ui/i18n.d.ts.map +1 -0
  23. package/dist/cli-ui/i18n.js +455 -0
  24. package/dist/cli-ui/i18n.js.map +1 -0
  25. package/dist/cli-ui/lang-picker.d.ts +10 -0
  26. package/dist/cli-ui/lang-picker.d.ts.map +1 -0
  27. package/dist/cli-ui/lang-picker.js +33 -0
  28. package/dist/cli-ui/lang-picker.js.map +1 -0
  29. package/dist/cli-ui/paths.d.ts +4 -0
  30. package/dist/cli-ui/paths.d.ts.map +1 -0
  31. package/dist/cli-ui/paths.js +11 -0
  32. package/dist/cli-ui/paths.js.map +1 -0
  33. package/dist/cli-ui/prompts.d.ts +65 -0
  34. package/dist/cli-ui/prompts.d.ts.map +1 -0
  35. package/dist/cli-ui/prompts.js +125 -0
  36. package/dist/cli-ui/prompts.js.map +1 -0
  37. package/dist/cli-ui/service.d.ts +41 -0
  38. package/dist/cli-ui/service.d.ts.map +1 -0
  39. package/dist/cli-ui/service.js +241 -0
  40. package/dist/cli-ui/service.js.map +1 -0
  41. package/dist/cli.d.ts +3 -0
  42. package/dist/cli.d.ts.map +1 -0
  43. package/dist/cli.js +1143 -0
  44. package/dist/cli.js.map +1 -0
  45. package/dist/core/acp-server.d.ts +8 -0
  46. package/dist/core/acp-server.d.ts.map +1 -0
  47. package/dist/core/acp-server.js +266 -0
  48. package/dist/core/acp-server.js.map +1 -0
  49. package/dist/core/agent-base.d.ts +94 -0
  50. package/dist/core/agent-base.d.ts.map +1 -0
  51. package/dist/core/agent-base.js +373 -0
  52. package/dist/core/agent-base.js.map +1 -0
  53. package/dist/core/agent-cwd.d.ts +48 -0
  54. package/dist/core/agent-cwd.d.ts.map +1 -0
  55. package/dist/core/agent-cwd.js +181 -0
  56. package/dist/core/agent-cwd.js.map +1 -0
  57. package/dist/core/agent-helper.d.ts +65 -0
  58. package/dist/core/agent-helper.d.ts.map +1 -0
  59. package/dist/core/agent-helper.js +150 -0
  60. package/dist/core/agent-helper.js.map +1 -0
  61. package/dist/core/agim-paths.d.ts +10 -0
  62. package/dist/core/agim-paths.d.ts.map +1 -0
  63. package/dist/core/agim-paths.js +64 -0
  64. package/dist/core/agim-paths.js.map +1 -0
  65. package/dist/core/approval-bus.d.ts +300 -0
  66. package/dist/core/approval-bus.d.ts.map +1 -0
  67. package/dist/core/approval-bus.js +990 -0
  68. package/dist/core/approval-bus.js.map +1 -0
  69. package/dist/core/approval-router.d.ts +101 -0
  70. package/dist/core/approval-router.d.ts.map +1 -0
  71. package/dist/core/approval-router.js +540 -0
  72. package/dist/core/approval-router.js.map +1 -0
  73. package/dist/core/audit-log.d.ts +55 -0
  74. package/dist/core/audit-log.d.ts.map +1 -0
  75. package/dist/core/audit-log.js +203 -0
  76. package/dist/core/audit-log.js.map +1 -0
  77. package/dist/core/bgjob-reader.d.ts +65 -0
  78. package/dist/core/bgjob-reader.d.ts.map +1 -0
  79. package/dist/core/bgjob-reader.js +212 -0
  80. package/dist/core/bgjob-reader.js.map +1 -0
  81. package/dist/core/circuit-breaker.d.ts +37 -0
  82. package/dist/core/circuit-breaker.d.ts.map +1 -0
  83. package/dist/core/circuit-breaker.js +115 -0
  84. package/dist/core/circuit-breaker.js.map +1 -0
  85. package/dist/core/commands/agent.d.ts +4 -0
  86. package/dist/core/commands/agent.d.ts.map +1 -0
  87. package/dist/core/commands/agent.js +40 -0
  88. package/dist/core/commands/agent.js.map +1 -0
  89. package/dist/core/commands/approval.d.ts +3 -0
  90. package/dist/core/commands/approval.d.ts.map +1 -0
  91. package/dist/core/commands/approval.js +85 -0
  92. package/dist/core/commands/approval.js.map +1 -0
  93. package/dist/core/commands/audit.d.ts +3 -0
  94. package/dist/core/commands/audit.d.ts.map +1 -0
  95. package/dist/core/commands/audit.js +84 -0
  96. package/dist/core/commands/audit.js.map +1 -0
  97. package/dist/core/commands/builtin.d.ts +3 -0
  98. package/dist/core/commands/builtin.d.ts.map +1 -0
  99. package/dist/core/commands/builtin.js +304 -0
  100. package/dist/core/commands/builtin.js.map +1 -0
  101. package/dist/core/commands/cron.d.ts +3 -0
  102. package/dist/core/commands/cron.d.ts.map +1 -0
  103. package/dist/core/commands/cron.js +128 -0
  104. package/dist/core/commands/cron.js.map +1 -0
  105. package/dist/core/commands/job.d.ts +3 -0
  106. package/dist/core/commands/job.d.ts.map +1 -0
  107. package/dist/core/commands/job.js +195 -0
  108. package/dist/core/commands/job.js.map +1 -0
  109. package/dist/core/commands/memo.d.ts +3 -0
  110. package/dist/core/commands/memo.d.ts.map +1 -0
  111. package/dist/core/commands/memo.js +151 -0
  112. package/dist/core/commands/memo.js.map +1 -0
  113. package/dist/core/commands/model.d.ts +9 -0
  114. package/dist/core/commands/model.d.ts.map +1 -0
  115. package/dist/core/commands/model.js +183 -0
  116. package/dist/core/commands/model.js.map +1 -0
  117. package/dist/core/commands/plan.d.ts +3 -0
  118. package/dist/core/commands/plan.d.ts.map +1 -0
  119. package/dist/core/commands/plan.js +75 -0
  120. package/dist/core/commands/plan.js.map +1 -0
  121. package/dist/core/commands/remind.d.ts +3 -0
  122. package/dist/core/commands/remind.d.ts.map +1 -0
  123. package/dist/core/commands/remind.js +271 -0
  124. package/dist/core/commands/remind.js.map +1 -0
  125. package/dist/core/commands/router.d.ts +3 -0
  126. package/dist/core/commands/router.d.ts.map +1 -0
  127. package/dist/core/commands/router.js +71 -0
  128. package/dist/core/commands/router.js.map +1 -0
  129. package/dist/core/commands/sessions.d.ts +3 -0
  130. package/dist/core/commands/sessions.d.ts.map +1 -0
  131. package/dist/core/commands/sessions.js +88 -0
  132. package/dist/core/commands/sessions.js.map +1 -0
  133. package/dist/core/commands/stats.d.ts +3 -0
  134. package/dist/core/commands/stats.d.ts.map +1 -0
  135. package/dist/core/commands/stats.js +73 -0
  136. package/dist/core/commands/stats.js.map +1 -0
  137. package/dist/core/commands/think.d.ts +3 -0
  138. package/dist/core/commands/think.d.ts.map +1 -0
  139. package/dist/core/commands/think.js +28 -0
  140. package/dist/core/commands/think.js.map +1 -0
  141. package/dist/core/commands/workspaces.d.ts +3 -0
  142. package/dist/core/commands/workspaces.d.ts.map +1 -0
  143. package/dist/core/commands/workspaces.js +47 -0
  144. package/dist/core/commands/workspaces.js.map +1 -0
  145. package/dist/core/config-schema.d.ts +60 -0
  146. package/dist/core/config-schema.d.ts.map +1 -0
  147. package/dist/core/config-schema.js +75 -0
  148. package/dist/core/config-schema.js.map +1 -0
  149. package/dist/core/coord-systems.d.ts +65 -0
  150. package/dist/core/coord-systems.d.ts.map +1 -0
  151. package/dist/core/coord-systems.js +229 -0
  152. package/dist/core/coord-systems.js.map +1 -0
  153. package/dist/core/cron.d.ts +29 -0
  154. package/dist/core/cron.d.ts.map +1 -0
  155. package/dist/core/cron.js +184 -0
  156. package/dist/core/cron.js.map +1 -0
  157. package/dist/core/event-bus.d.ts +80 -0
  158. package/dist/core/event-bus.d.ts.map +1 -0
  159. package/dist/core/event-bus.js +62 -0
  160. package/dist/core/event-bus.js.map +1 -0
  161. package/dist/core/intent-llm.d.ts +27 -0
  162. package/dist/core/intent-llm.d.ts.map +1 -0
  163. package/dist/core/intent-llm.js +170 -0
  164. package/dist/core/intent-llm.js.map +1 -0
  165. package/dist/core/intent.d.ts +12 -0
  166. package/dist/core/intent.d.ts.map +1 -0
  167. package/dist/core/intent.js +187 -0
  168. package/dist/core/intent.js.map +1 -0
  169. package/dist/core/job-board.d.ts +82 -0
  170. package/dist/core/job-board.d.ts.map +1 -0
  171. package/dist/core/job-board.js +379 -0
  172. package/dist/core/job-board.js.map +1 -0
  173. package/dist/core/location-context.d.ts +32 -0
  174. package/dist/core/location-context.d.ts.map +1 -0
  175. package/dist/core/location-context.js +69 -0
  176. package/dist/core/location-context.js.map +1 -0
  177. package/dist/core/location-token.d.ts +57 -0
  178. package/dist/core/location-token.d.ts.map +1 -0
  179. package/dist/core/location-token.js +128 -0
  180. package/dist/core/location-token.js.map +1 -0
  181. package/dist/core/logger.d.ts +6 -0
  182. package/dist/core/logger.d.ts.map +1 -0
  183. package/dist/core/logger.js +54 -0
  184. package/dist/core/logger.js.map +1 -0
  185. package/dist/core/memo-rpc.d.ts +13 -0
  186. package/dist/core/memo-rpc.d.ts.map +1 -0
  187. package/dist/core/memo-rpc.js +288 -0
  188. package/dist/core/memo-rpc.js.map +1 -0
  189. package/dist/core/memos.d.ts +163 -0
  190. package/dist/core/memos.d.ts.map +1 -0
  191. package/dist/core/memos.js +502 -0
  192. package/dist/core/memos.js.map +1 -0
  193. package/dist/core/metrics.d.ts +55 -0
  194. package/dist/core/metrics.d.ts.map +1 -0
  195. package/dist/core/metrics.js +291 -0
  196. package/dist/core/metrics.js.map +1 -0
  197. package/dist/core/onboarding.d.ts +99 -0
  198. package/dist/core/onboarding.d.ts.map +1 -0
  199. package/dist/core/onboarding.js +426 -0
  200. package/dist/core/onboarding.js.map +1 -0
  201. package/dist/core/pending-reminder.d.ts +25 -0
  202. package/dist/core/pending-reminder.d.ts.map +1 -0
  203. package/dist/core/pending-reminder.js +53 -0
  204. package/dist/core/pending-reminder.js.map +1 -0
  205. package/dist/core/rate-limiter.d.ts +44 -0
  206. package/dist/core/rate-limiter.d.ts.map +1 -0
  207. package/dist/core/rate-limiter.js +115 -0
  208. package/dist/core/rate-limiter.js.map +1 -0
  209. package/dist/core/registry.d.ts +32 -0
  210. package/dist/core/registry.d.ts.map +1 -0
  211. package/dist/core/registry.js +126 -0
  212. package/dist/core/registry.js.map +1 -0
  213. package/dist/core/remind-intent.d.ts +25 -0
  214. package/dist/core/remind-intent.d.ts.map +1 -0
  215. package/dist/core/remind-intent.js +196 -0
  216. package/dist/core/remind-intent.js.map +1 -0
  217. package/dist/core/reminder-rpc.d.ts +17 -0
  218. package/dist/core/reminder-rpc.d.ts.map +1 -0
  219. package/dist/core/reminder-rpc.js +169 -0
  220. package/dist/core/reminder-rpc.js.map +1 -0
  221. package/dist/core/reminders.d.ts +159 -0
  222. package/dist/core/reminders.d.ts.map +1 -0
  223. package/dist/core/reminders.js +977 -0
  224. package/dist/core/reminders.js.map +1 -0
  225. package/dist/core/router.d.ts +55 -0
  226. package/dist/core/router.d.ts.map +1 -0
  227. package/dist/core/router.js +497 -0
  228. package/dist/core/router.js.map +1 -0
  229. package/dist/core/schedule.d.ts +65 -0
  230. package/dist/core/schedule.d.ts.map +1 -0
  231. package/dist/core/schedule.js +323 -0
  232. package/dist/core/schedule.js.map +1 -0
  233. package/dist/core/session.d.ts +182 -0
  234. package/dist/core/session.d.ts.map +1 -0
  235. package/dist/core/session.js +807 -0
  236. package/dist/core/session.js.map +1 -0
  237. package/dist/core/sqlite-helper.d.ts +37 -0
  238. package/dist/core/sqlite-helper.d.ts.map +1 -0
  239. package/dist/core/sqlite-helper.js +79 -0
  240. package/dist/core/sqlite-helper.js.map +1 -0
  241. package/dist/core/transcribe.d.ts +25 -0
  242. package/dist/core/transcribe.d.ts.map +1 -0
  243. package/dist/core/transcribe.js +217 -0
  244. package/dist/core/transcribe.js.map +1 -0
  245. package/dist/core/types.d.ts +360 -0
  246. package/dist/core/types.d.ts.map +1 -0
  247. package/dist/core/types.js +3 -0
  248. package/dist/core/types.js.map +1 -0
  249. package/dist/core/workspace.d.ts +67 -0
  250. package/dist/core/workspace.d.ts.map +1 -0
  251. package/dist/core/workspace.js +113 -0
  252. package/dist/core/workspace.js.map +1 -0
  253. package/dist/index.d.ts +5 -0
  254. package/dist/index.d.ts.map +1 -0
  255. package/dist/index.js +6 -0
  256. package/dist/index.js.map +1 -0
  257. package/dist/plugins/agents/acp/acp-adapter.d.ts +16 -0
  258. package/dist/plugins/agents/acp/acp-adapter.d.ts.map +1 -0
  259. package/dist/plugins/agents/acp/acp-adapter.js +49 -0
  260. package/dist/plugins/agents/acp/acp-adapter.js.map +1 -0
  261. package/dist/plugins/agents/acp/acp-client.d.ts +32 -0
  262. package/dist/plugins/agents/acp/acp-client.d.ts.map +1 -0
  263. package/dist/plugins/agents/acp/acp-client.js +177 -0
  264. package/dist/plugins/agents/acp/acp-client.js.map +1 -0
  265. package/dist/plugins/agents/acp/discovery.d.ts +19 -0
  266. package/dist/plugins/agents/acp/discovery.d.ts.map +1 -0
  267. package/dist/plugins/agents/acp/discovery.js +111 -0
  268. package/dist/plugins/agents/acp/discovery.js.map +1 -0
  269. package/dist/plugins/agents/acp/index.d.ts +4 -0
  270. package/dist/plugins/agents/acp/index.d.ts.map +1 -0
  271. package/dist/plugins/agents/acp/index.js +4 -0
  272. package/dist/plugins/agents/acp/index.js.map +1 -0
  273. package/dist/plugins/agents/acp/types.d.ts +62 -0
  274. package/dist/plugins/agents/acp/types.d.ts.map +1 -0
  275. package/dist/plugins/agents/acp/types.js +5 -0
  276. package/dist/plugins/agents/acp/types.js.map +1 -0
  277. package/dist/plugins/agents/claude-code/index.d.ts +25 -0
  278. package/dist/plugins/agents/claude-code/index.d.ts.map +1 -0
  279. package/dist/plugins/agents/claude-code/index.js +184 -0
  280. package/dist/plugins/agents/claude-code/index.js.map +1 -0
  281. package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts +59 -0
  282. package/dist/plugins/agents/claude-code/mcp-approval-server.d.ts.map +1 -0
  283. package/dist/plugins/agents/claude-code/mcp-approval-server.js +645 -0
  284. package/dist/plugins/agents/claude-code/mcp-approval-server.js.map +1 -0
  285. package/dist/plugins/agents/codex/build-mcp-cli-args.d.ts +28 -0
  286. package/dist/plugins/agents/codex/build-mcp-cli-args.d.ts.map +1 -0
  287. package/dist/plugins/agents/codex/build-mcp-cli-args.js +74 -0
  288. package/dist/plugins/agents/codex/build-mcp-cli-args.js.map +1 -0
  289. package/dist/plugins/agents/codex/index.d.ts +53 -0
  290. package/dist/plugins/agents/codex/index.d.ts.map +1 -0
  291. package/dist/plugins/agents/codex/index.js +341 -0
  292. package/dist/plugins/agents/codex/index.js.map +1 -0
  293. package/dist/plugins/agents/copilot/index.d.ts +35 -0
  294. package/dist/plugins/agents/copilot/index.d.ts.map +1 -0
  295. package/dist/plugins/agents/copilot/index.js +182 -0
  296. package/dist/plugins/agents/copilot/index.js.map +1 -0
  297. package/dist/plugins/agents/opencode/ensure-mcp-config.d.ts +11 -0
  298. package/dist/plugins/agents/opencode/ensure-mcp-config.d.ts.map +1 -0
  299. package/dist/plugins/agents/opencode/ensure-mcp-config.js +100 -0
  300. package/dist/plugins/agents/opencode/ensure-mcp-config.js.map +1 -0
  301. package/dist/plugins/agents/opencode/index.d.ts +5 -0
  302. package/dist/plugins/agents/opencode/index.d.ts.map +1 -0
  303. package/dist/plugins/agents/opencode/index.js +30 -0
  304. package/dist/plugins/agents/opencode/index.js.map +1 -0
  305. package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts +166 -0
  306. package/dist/plugins/agents/opencode/opencode-http-adapter.d.ts.map +1 -0
  307. package/dist/plugins/agents/opencode/opencode-http-adapter.js +682 -0
  308. package/dist/plugins/agents/opencode/opencode-http-adapter.js.map +1 -0
  309. package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts +32 -0
  310. package/dist/plugins/agents/opencode/opencode-stdio-adapter.d.ts.map +1 -0
  311. package/dist/plugins/agents/opencode/opencode-stdio-adapter.js +137 -0
  312. package/dist/plugins/agents/opencode/opencode-stdio-adapter.js.map +1 -0
  313. package/dist/plugins/agents/opencode/serve-manager.d.ts +27 -0
  314. package/dist/plugins/agents/opencode/serve-manager.d.ts.map +1 -0
  315. package/dist/plugins/agents/opencode/serve-manager.js +194 -0
  316. package/dist/plugins/agents/opencode/serve-manager.js.map +1 -0
  317. package/dist/plugins/messengers/dingtalk/dingtalk-adapter.d.ts +57 -0
  318. package/dist/plugins/messengers/dingtalk/dingtalk-adapter.d.ts.map +1 -0
  319. package/dist/plugins/messengers/dingtalk/dingtalk-adapter.js +409 -0
  320. package/dist/plugins/messengers/dingtalk/dingtalk-adapter.js.map +1 -0
  321. package/dist/plugins/messengers/dingtalk/dingtalk-client.d.ts +48 -0
  322. package/dist/plugins/messengers/dingtalk/dingtalk-client.d.ts.map +1 -0
  323. package/dist/plugins/messengers/dingtalk/dingtalk-client.js +236 -0
  324. package/dist/plugins/messengers/dingtalk/dingtalk-client.js.map +1 -0
  325. package/dist/plugins/messengers/dingtalk/index.d.ts +3 -0
  326. package/dist/plugins/messengers/dingtalk/index.d.ts.map +1 -0
  327. package/dist/plugins/messengers/dingtalk/index.js +3 -0
  328. package/dist/plugins/messengers/dingtalk/index.js.map +1 -0
  329. package/dist/plugins/messengers/dingtalk/link-coords.d.ts +23 -0
  330. package/dist/plugins/messengers/dingtalk/link-coords.d.ts.map +1 -0
  331. package/dist/plugins/messengers/dingtalk/link-coords.js +89 -0
  332. package/dist/plugins/messengers/dingtalk/link-coords.js.map +1 -0
  333. package/dist/plugins/messengers/dingtalk/media-store.d.ts +16 -0
  334. package/dist/plugins/messengers/dingtalk/media-store.d.ts.map +1 -0
  335. package/dist/plugins/messengers/dingtalk/media-store.js +77 -0
  336. package/dist/plugins/messengers/dingtalk/media-store.js.map +1 -0
  337. package/dist/plugins/messengers/dingtalk/types.d.ts +82 -0
  338. package/dist/plugins/messengers/dingtalk/types.d.ts.map +1 -0
  339. package/dist/plugins/messengers/dingtalk/types.js +14 -0
  340. package/dist/plugins/messengers/dingtalk/types.js.map +1 -0
  341. package/dist/plugins/messengers/discord/discord-adapter.d.ts +21 -0
  342. package/dist/plugins/messengers/discord/discord-adapter.d.ts.map +1 -0
  343. package/dist/plugins/messengers/discord/discord-adapter.js +238 -0
  344. package/dist/plugins/messengers/discord/discord-adapter.js.map +1 -0
  345. package/dist/plugins/messengers/discord/index.d.ts +4 -0
  346. package/dist/plugins/messengers/discord/index.d.ts.map +1 -0
  347. package/dist/plugins/messengers/discord/index.js +4 -0
  348. package/dist/plugins/messengers/discord/index.js.map +1 -0
  349. package/dist/plugins/messengers/discord/markdown-to-discord.d.ts +11 -0
  350. package/dist/plugins/messengers/discord/markdown-to-discord.d.ts.map +1 -0
  351. package/dist/plugins/messengers/discord/markdown-to-discord.js +59 -0
  352. package/dist/plugins/messengers/discord/markdown-to-discord.js.map +1 -0
  353. package/dist/plugins/messengers/discord/types.d.ts +9 -0
  354. package/dist/plugins/messengers/discord/types.d.ts.map +1 -0
  355. package/dist/plugins/messengers/discord/types.js +3 -0
  356. package/dist/plugins/messengers/discord/types.js.map +1 -0
  357. package/dist/plugins/messengers/email/email-adapter.d.ts +33 -0
  358. package/dist/plugins/messengers/email/email-adapter.d.ts.map +1 -0
  359. package/dist/plugins/messengers/email/email-adapter.js +137 -0
  360. package/dist/plugins/messengers/email/email-adapter.js.map +1 -0
  361. package/dist/plugins/messengers/feishu/card-builder.d.ts +23 -0
  362. package/dist/plugins/messengers/feishu/card-builder.d.ts.map +1 -0
  363. package/dist/plugins/messengers/feishu/card-builder.js +89 -0
  364. package/dist/plugins/messengers/feishu/card-builder.js.map +1 -0
  365. package/dist/plugins/messengers/feishu/feishu-adapter.d.ts +23 -0
  366. package/dist/plugins/messengers/feishu/feishu-adapter.d.ts.map +1 -0
  367. package/dist/plugins/messengers/feishu/feishu-adapter.js +250 -0
  368. package/dist/plugins/messengers/feishu/feishu-adapter.js.map +1 -0
  369. package/dist/plugins/messengers/feishu/feishu-client.d.ts +43 -0
  370. package/dist/plugins/messengers/feishu/feishu-client.d.ts.map +1 -0
  371. package/dist/plugins/messengers/feishu/feishu-client.js +118 -0
  372. package/dist/plugins/messengers/feishu/feishu-client.js.map +1 -0
  373. package/dist/plugins/messengers/feishu/index.d.ts +4 -0
  374. package/dist/plugins/messengers/feishu/index.d.ts.map +1 -0
  375. package/dist/plugins/messengers/feishu/index.js +4 -0
  376. package/dist/plugins/messengers/feishu/index.js.map +1 -0
  377. package/dist/plugins/messengers/feishu/types.d.ts +113 -0
  378. package/dist/plugins/messengers/feishu/types.d.ts.map +1 -0
  379. package/dist/plugins/messengers/feishu/types.js +4 -0
  380. package/dist/plugins/messengers/feishu/types.js.map +1 -0
  381. package/dist/plugins/messengers/telegram/index.d.ts +4 -0
  382. package/dist/plugins/messengers/telegram/index.d.ts.map +1 -0
  383. package/dist/plugins/messengers/telegram/index.js +4 -0
  384. package/dist/plugins/messengers/telegram/index.js.map +1 -0
  385. package/dist/plugins/messengers/telegram/markdown-to-html.d.ts +5 -0
  386. package/dist/plugins/messengers/telegram/markdown-to-html.d.ts.map +1 -0
  387. package/dist/plugins/messengers/telegram/markdown-to-html.js +186 -0
  388. package/dist/plugins/messengers/telegram/markdown-to-html.js.map +1 -0
  389. package/dist/plugins/messengers/telegram/media-download.d.ts +59 -0
  390. package/dist/plugins/messengers/telegram/media-download.d.ts.map +1 -0
  391. package/dist/plugins/messengers/telegram/media-download.js +228 -0
  392. package/dist/plugins/messengers/telegram/media-download.js.map +1 -0
  393. package/dist/plugins/messengers/telegram/telegram-adapter.d.ts +77 -0
  394. package/dist/plugins/messengers/telegram/telegram-adapter.d.ts.map +1 -0
  395. package/dist/plugins/messengers/telegram/telegram-adapter.js +880 -0
  396. package/dist/plugins/messengers/telegram/telegram-adapter.js.map +1 -0
  397. package/dist/plugins/messengers/telegram/types.d.ts +47 -0
  398. package/dist/plugins/messengers/telegram/types.d.ts.map +1 -0
  399. package/dist/plugins/messengers/telegram/types.js +3 -0
  400. package/dist/plugins/messengers/telegram/types.js.map +1 -0
  401. package/dist/plugins/messengers/wechat/context-store.d.ts +18 -0
  402. package/dist/plugins/messengers/wechat/context-store.d.ts.map +1 -0
  403. package/dist/plugins/messengers/wechat/context-store.js +105 -0
  404. package/dist/plugins/messengers/wechat/context-store.js.map +1 -0
  405. package/dist/plugins/messengers/wechat/ilink-adapter.d.ts +71 -0
  406. package/dist/plugins/messengers/wechat/ilink-adapter.d.ts.map +1 -0
  407. package/dist/plugins/messengers/wechat/ilink-adapter.js +664 -0
  408. package/dist/plugins/messengers/wechat/ilink-adapter.js.map +1 -0
  409. package/dist/plugins/messengers/wechat/ilink-client.d.ts +75 -0
  410. package/dist/plugins/messengers/wechat/ilink-client.d.ts.map +1 -0
  411. package/dist/plugins/messengers/wechat/ilink-client.js +331 -0
  412. package/dist/plugins/messengers/wechat/ilink-client.js.map +1 -0
  413. package/dist/plugins/messengers/wechat/ilink-types.d.ts +181 -0
  414. package/dist/plugins/messengers/wechat/ilink-types.d.ts.map +1 -0
  415. package/dist/plugins/messengers/wechat/ilink-types.js +22 -0
  416. package/dist/plugins/messengers/wechat/ilink-types.js.map +1 -0
  417. package/dist/plugins/messengers/wechat/media-download.d.ts +32 -0
  418. package/dist/plugins/messengers/wechat/media-download.d.ts.map +1 -0
  419. package/dist/plugins/messengers/wechat/media-download.js +78 -0
  420. package/dist/plugins/messengers/wechat/media-download.js.map +1 -0
  421. package/dist/scripts/migrate-gcj02-to-wgs84.d.ts +3 -0
  422. package/dist/scripts/migrate-gcj02-to-wgs84.d.ts.map +1 -0
  423. package/dist/scripts/migrate-gcj02-to-wgs84.js +52 -0
  424. package/dist/scripts/migrate-gcj02-to-wgs84.js.map +1 -0
  425. package/dist/utils/backoff.d.ts +35 -0
  426. package/dist/utils/backoff.d.ts.map +1 -0
  427. package/dist/utils/backoff.js +59 -0
  428. package/dist/utils/backoff.js.map +1 -0
  429. package/dist/utils/cross-platform.d.ts +26 -0
  430. package/dist/utils/cross-platform.d.ts.map +1 -0
  431. package/dist/utils/cross-platform.js +58 -0
  432. package/dist/utils/cross-platform.js.map +1 -0
  433. package/dist/utils/message-split.d.ts +14 -0
  434. package/dist/utils/message-split.d.ts.map +1 -0
  435. package/dist/utils/message-split.js +65 -0
  436. package/dist/utils/message-split.js.map +1 -0
  437. package/dist/utils/safe-equal.d.ts +2 -0
  438. package/dist/utils/safe-equal.d.ts.map +1 -0
  439. package/dist/utils/safe-equal.js +11 -0
  440. package/dist/utils/safe-equal.js.map +1 -0
  441. package/dist/web/public/_app.js +196 -0
  442. package/dist/web/public/index.html +936 -0
  443. package/dist/web/public/loc.html +305 -0
  444. package/dist/web/public/login.html +106 -0
  445. package/dist/web/public/memos.html +271 -0
  446. package/dist/web/public/reminders.html +234 -0
  447. package/dist/web/public/settings.html +1355 -0
  448. package/dist/web/public/tasks.html +1835 -0
  449. package/dist/web/server.d.ts +12 -0
  450. package/dist/web/server.d.ts.map +1 -0
  451. package/dist/web/server.js +2399 -0
  452. package/dist/web/server.js.map +1 -0
  453. package/package.json +92 -0
@@ -0,0 +1,229 @@
1
+ // coord-systems.ts — every coordinate-system conversion + the
2
+ // "normalize an incoming location" policy that adapters route through.
3
+ //
4
+ // Why this module exists (incident background, 2026-05-12):
5
+ // The old behavior was "treat every incoming lat/lng as GCJ-02 if it
6
+ // falls inside the China bbox" — true for iOS Core Location and
7
+ // Apple/Google GMS-with-China-region, FALSE for the WeChat X5
8
+ // webview, raw Android Chrome, Telegram Desktop, and other paths
9
+ // where the JS / IM payload is already WGS-84.
10
+ //
11
+ // The user observed wrong markers in WeChat — `/memo here` H5 capture
12
+ // landed coords ~500m–1km off on both 高德 and 百度 maps. Root cause:
13
+ // X5 webview hands the page genuine WGS-84, but server.ts applied an
14
+ // inverse GCJ→WGS offset on top, so the stored value was *anti-shifted*
15
+ // and every downstream map URL re-shifted it back the wrong way.
16
+ //
17
+ // Per-platform reality (empirically known as of 2026-05):
18
+ //
19
+ // | Source | Coord system |
20
+ // |---------------------------------------|-----------------|
21
+ // | Telegram native location (iOS in China) | GCJ-02 |
22
+ // | Telegram native location (iOS outside China) | WGS-84 |
23
+ // | Telegram native location (Telegram Desktop) | WGS-84 |
24
+ // | Telegram native location (most Android cases) | WGS-84 |
25
+ // | Feishu native location | GCJ-02 (mandated) |
26
+ // | DingTalk native location | n/a (not delivered to bots) |
27
+ // | DingTalk link msgtype → Amap/Tencent URL | GCJ-02 |
28
+ // | DingTalk link msgtype → Baidu Maps URL | BD-09 |
29
+ // | H5 `navigator.geolocation` in iOS Safari (CN) | GCJ-02 |
30
+ // | H5 `navigator.geolocation` in WeChat X5 / Chrome| WGS-84 |
31
+ //
32
+ // There is no reliable server-side way to know which of the two
33
+ // ambiguous paths produced any given coord, so we ship sensible
34
+ // defaults + env-var overrides for the edge cases.
35
+ import { logger as rootLogger } from './logger.js';
36
+ const log = rootLogger.child({ component: 'coord-systems' });
37
+ /**
38
+ * Convert any incoming (lat, lng) to WGS-84 based on what we know about
39
+ * the source. Adapters route every native coord through this. Defaults
40
+ * favor "trust the payload as WGS-84" because that's the safer assumption
41
+ * when the source is ambiguous — applying an inverse GCJ offset to a
42
+ * value that's actually already WGS produces a 500m-1km error, while
43
+ * pass-through on actual GCJ leaves the user with the same ~1km error
44
+ * but in a recoverable direction. Both error modes get the user roughly
45
+ * the right country / city; an `IMHUB_*_COORDS_GCJ02=1` env flag flips
46
+ * the default for any source whose users tell us their device DOES apply
47
+ * the offset (Apple devices in China + Chinese region most often).
48
+ */
49
+ export function normalizeIncomingCoords(source, lat, lng) {
50
+ if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
51
+ return { lat, lng, applied: 'none', outOfChina: true };
52
+ }
53
+ if (outOfChina(lat, lng)) {
54
+ return { lat, lng, applied: 'none', outOfChina: true };
55
+ }
56
+ // Per-source policy. The flag-overrideable defaults reflect the empirical
57
+ // table at the top of this file. See env table at the bottom.
58
+ const treatAsGcj = (() => {
59
+ switch (source) {
60
+ case 'telegram-native':
61
+ // Default WGS-84 (covers Telegram Desktop + non-Apple in-China +
62
+ // anyone outside China). User can flip with the env flag if their
63
+ // Telegram is on Apple-zh-CN where Core Location applies the offset.
64
+ return process.env.IMHUB_TELEGRAM_COORDS_GCJ02 === '1';
65
+ case 'feishu-native':
66
+ // Feishu is mandated GCJ-02 server-side, no override expected.
67
+ return true;
68
+ case 'dingtalk-link-amap':
69
+ case 'dingtalk-link-tencent':
70
+ return true;
71
+ case 'dingtalk-link-baidu':
72
+ return false; // BD-09, handled below
73
+ case 'dingtalk-link-unknown':
74
+ return false; // pass-through; don't guess
75
+ case 'h5-browser-geolocation':
76
+ // Default WGS-84. THIS IS THE INCIDENT FIX (2026-05-12): WeChat
77
+ // X5 + Android Chrome without GMS hand the page raw WGS-84 and
78
+ // the old "always GCJ" assumption put markers ~1km off in WeChat.
79
+ // iOS Safari users in China can flip the flag to restore the old
80
+ // GCJ→WGS path.
81
+ return process.env.IMHUB_H5_COORDS_GCJ02 === '1';
82
+ case 'web-admin':
83
+ // Developer-facing console; PC browser is overwhelmingly WGS-84.
84
+ return false;
85
+ }
86
+ })();
87
+ if (source === 'dingtalk-link-baidu') {
88
+ const wgs = bd09ToWgs84(lat, lng);
89
+ log.debug({
90
+ event: 'coord.normalized',
91
+ source,
92
+ raw_lat: lat, raw_lng: lng,
93
+ wgs_lat: wgs.lat, wgs_lng: wgs.lng,
94
+ applied: 'bd09-to-wgs84',
95
+ });
96
+ return { lat: wgs.lat, lng: wgs.lng, applied: 'bd09-to-wgs84', outOfChina: false };
97
+ }
98
+ if (treatAsGcj) {
99
+ const wgs = gcj02ToWgs84(lat, lng);
100
+ log.debug({
101
+ event: 'coord.normalized',
102
+ source,
103
+ raw_lat: lat, raw_lng: lng,
104
+ wgs_lat: wgs.lat, wgs_lng: wgs.lng,
105
+ applied: 'gcj02-to-wgs84',
106
+ });
107
+ return { lat: wgs.lat, lng: wgs.lng, applied: 'gcj02-to-wgs84', outOfChina: false };
108
+ }
109
+ log.debug({
110
+ event: 'coord.normalized',
111
+ source,
112
+ raw_lat: lat, raw_lng: lng,
113
+ wgs_lat: lat, wgs_lng: lng,
114
+ applied: 'none',
115
+ });
116
+ return { lat, lng, applied: 'none', outOfChina: false };
117
+ }
118
+ // ─── coord-system math ──────────────────────────────────────────────
119
+ // We keep the GCJ pair in this file alongside BD-09 (rather than
120
+ // re-exporting from memos.ts) so all coord math lives in one place.
121
+ // The originals in memos.ts are still exported for backwards-compat;
122
+ // new code should import from here.
123
+ const A = 6378245.0;
124
+ const EE = 0.006693421622965943;
125
+ const PI = Math.PI;
126
+ /** WGS-84 → GCJ-02. */
127
+ export function wgs84ToGcj02(lat, lng) {
128
+ if (outOfChina(lat, lng))
129
+ return { lat, lng };
130
+ let dLat = transformLat(lng - 105.0, lat - 35.0);
131
+ let dLng = transformLng(lng - 105.0, lat - 35.0);
132
+ const radLat = (lat / 180.0) * PI;
133
+ let magic = Math.sin(radLat);
134
+ magic = 1 - EE * magic * magic;
135
+ const sqrtMagic = Math.sqrt(magic);
136
+ dLat = (dLat * 180.0) / (((A * (1 - EE)) / (magic * sqrtMagic)) * PI);
137
+ dLng = (dLng * 180.0) / ((A / sqrtMagic) * Math.cos(radLat) * PI);
138
+ return { lat: lat + dLat, lng: lng + dLng };
139
+ }
140
+ /** GCJ-02 → WGS-84 (Newton iteration; converges to sub-meter in 3 passes). */
141
+ export function gcj02ToWgs84(lat, lng) {
142
+ if (outOfChina(lat, lng))
143
+ return { lat, lng };
144
+ let wgsLat = lat;
145
+ let wgsLng = lng;
146
+ for (let i = 0; i < 3; i++) {
147
+ const forward = wgs84ToGcj02(wgsLat, wgsLng);
148
+ wgsLat = lat - (forward.lat - wgsLat);
149
+ wgsLng = lng - (forward.lng - wgsLng);
150
+ }
151
+ return { lat: wgsLat, lng: wgsLng };
152
+ }
153
+ /**
154
+ * Baidu BD-09 → GCJ-02. BD-09 is GCJ-02 plus an additional radial offset
155
+ * applied by Baidu. The math is well-known (cf. open-source `coordtransform`
156
+ * libraries); we lift the formula verbatim and add a comment so the next
157
+ * reader doesn't have to derive it.
158
+ */
159
+ export function bd09ToGcj02(lat, lng) {
160
+ if (outOfChina(lat, lng))
161
+ return { lat, lng };
162
+ const X_PI = (PI * 3000.0) / 180.0;
163
+ const x = lng - 0.0065;
164
+ const y = lat - 0.006;
165
+ const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
166
+ const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
167
+ return { lat: z * Math.sin(theta), lng: z * Math.cos(theta) };
168
+ }
169
+ /** GCJ-02 → Baidu BD-09 (forward; closed form). */
170
+ export function gcj02ToBd09(lat, lng) {
171
+ if (outOfChina(lat, lng))
172
+ return { lat, lng };
173
+ const X_PI = (PI * 3000.0) / 180.0;
174
+ const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI);
175
+ const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI);
176
+ return { lat: z * Math.sin(theta) + 0.006, lng: z * Math.cos(theta) + 0.0065 };
177
+ }
178
+ /** BD-09 → WGS-84 via GCJ-02 intermediate. */
179
+ export function bd09ToWgs84(lat, lng) {
180
+ if (outOfChina(lat, lng))
181
+ return { lat, lng };
182
+ const gcj = bd09ToGcj02(lat, lng);
183
+ return gcj02ToWgs84(gcj.lat, gcj.lng);
184
+ }
185
+ /** WGS-84 → BD-09 via GCJ-02 intermediate. Useful for building Baidu
186
+ * Maps URLs from our WGS-stored coords. */
187
+ export function wgs84ToBd09(lat, lng) {
188
+ if (outOfChina(lat, lng))
189
+ return { lat, lng };
190
+ const gcj = wgs84ToGcj02(lat, lng);
191
+ return gcj02ToBd09(gcj.lat, gcj.lng);
192
+ }
193
+ // ─── internals ──────────────────────────────────────────────────────
194
+ /** GCJ-02 offset is only defined for mainland China + the bbox below.
195
+ * Outside, every conversion in this module is a no-op pass-through. */
196
+ export function outOfChina(lat, lng) {
197
+ return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271;
198
+ }
199
+ function transformLat(x, y) {
200
+ let r = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
201
+ r += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
202
+ r += ((20.0 * Math.sin(y * PI) + 40.0 * Math.sin((y / 3.0) * PI)) * 2.0) / 3.0;
203
+ r += ((160.0 * Math.sin((y / 12.0) * PI) + 320 * Math.sin((y * PI) / 30.0)) * 2.0) / 3.0;
204
+ return r;
205
+ }
206
+ function transformLng(x, y) {
207
+ let r = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
208
+ r += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
209
+ r += ((20.0 * Math.sin(x * PI) + 40.0 * Math.sin((x / 3.0) * PI)) * 2.0) / 3.0;
210
+ r += ((150.0 * Math.sin((x / 12.0) * PI) + 300.0 * Math.sin((x / 30.0) * PI)) * 2.0) / 3.0;
211
+ return r;
212
+ }
213
+ // ─── env vars exposed by this module ────────────────────────────────
214
+ //
215
+ // IMHUB_TELEGRAM_COORDS_GCJ02=1
216
+ // Apply GCJ-02 → WGS-84 to Telegram native location/venue messages.
217
+ // Default off (WGS pass-through). Turn ON if your Telegram clients are
218
+ // Apple devices in China (iOS Core Location applies the offset).
219
+ //
220
+ // IMHUB_H5_COORDS_GCJ02=1
221
+ // Apply GCJ-02 → WGS-84 to coordinates POSTed from the /memo here H5
222
+ // capture page. Default off (WGS pass-through). Turn ON if your users
223
+ // open the H5 link in iOS Safari / iOS WebKit in mainland China —
224
+ // navigator.geolocation respects Apple's GCJ offset there.
225
+ //
226
+ // (Feishu always GCJ→WGS, DingTalk amap/qmap always GCJ→WGS,
227
+ // DingTalk baidu always BD-09→WGS — those are server-mandated and
228
+ // don't need overrides.)
229
+ //# sourceMappingURL=coord-systems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coord-systems.js","sourceRoot":"","sources":["../../src/core/coord-systems.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ interface FieldSpec {
2
+ raw: string;
3
+ values: Set<number>;
4
+ min: number;
5
+ max: number;
6
+ }
7
+ export interface CronSpec {
8
+ minute: FieldSpec;
9
+ hour: FieldSpec;
10
+ day: FieldSpec;
11
+ month: FieldSpec;
12
+ dow: FieldSpec;
13
+ }
14
+ export declare function parseCron(expr: string): CronSpec;
15
+ /**
16
+ * Next firing strictly after `from`, found by field-level
17
+ * fast-forwarding. For "yearly at midnight Jan 1" (`0 0 1 1 *`) this
18
+ * converges in at most 4-5 jumps, vs ~525_000 minute increments under
19
+ * the previous brute-force loop.
20
+ *
21
+ * The loop walks fields outermost (month) → innermost (minute). On a
22
+ * mismatch we set the field to its ceiling (next valid value) and reset
23
+ * everything inside it. If no ceiling exists in the current scope we
24
+ * step one unit up in the parent field. JavaScript Date handles
25
+ * carries (month=12 → next year, hour=24 → next day) natively.
26
+ */
27
+ export declare function nextOccurrence(spec: CronSpec, from?: Date): Date | null;
28
+ export {};
29
+ //# sourceMappingURL=cron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/core/cron.ts"],"names":[],"mappings":"AAgBA,UAAU,SAAS;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;CACZ;AA2DD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,SAAS,CAAA;IACf,GAAG,EAAE,SAAS,CAAA;IACd,KAAK,EAAE,SAAS,CAAA;IAChB,GAAG,EAAE,SAAS,CAAA;CACf;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAYhD;AAgCD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAE,IAAiB,GAAG,IAAI,GAAG,IAAI,CA2DnF"}
@@ -0,0 +1,184 @@
1
+ // Minimal POSIX-flavored cron parser (5 fields: minute hour day month dow).
2
+ //
3
+ // Supported syntax per field:
4
+ // * wildcard
5
+ // N single integer
6
+ // N,M,O comma list
7
+ // N-M inclusive range
8
+ // *\/K step (e.g. */5 = every 5 minutes)
9
+ // N-M/K stepped range
10
+ //
11
+ // Day-of-week: 0 or 7 = Sunday, 1 = Monday … 6 = Saturday.
12
+ //
13
+ // nextOccurrence() returns the next Date strictly greater than `from`.
14
+ // Returns null only on bogus expressions; a valid expression always has
15
+ // a future occurrence within ~6 years (the search loop bails after that).
16
+ const FIELD_BOUNDS = [
17
+ { name: 'minute', min: 0, max: 59 },
18
+ { name: 'hour', min: 0, max: 23 },
19
+ { name: 'day', min: 1, max: 31 },
20
+ { name: 'month', min: 1, max: 12 },
21
+ { name: 'dow', min: 0, max: 6 }, // 7 normalized to 0
22
+ ];
23
+ function parseField(raw, min, max, fieldName) {
24
+ const out = new Set();
25
+ for (const piece of raw.split(',')) {
26
+ const stepMatch = piece.match(/^(.+)\/(\d+)$/);
27
+ let body = piece;
28
+ let step = 1;
29
+ if (stepMatch) {
30
+ body = stepMatch[1];
31
+ step = parseInt(stepMatch[2], 10);
32
+ if (!Number.isFinite(step) || step <= 0) {
33
+ throw new Error(`Invalid step in ${fieldName}: ${piece}`);
34
+ }
35
+ }
36
+ let lo;
37
+ let hi;
38
+ if (body === '*') {
39
+ lo = min;
40
+ hi = max;
41
+ }
42
+ else {
43
+ const range = body.match(/^(\d+)-(\d+)$/);
44
+ if (range) {
45
+ lo = parseInt(range[1], 10);
46
+ hi = parseInt(range[2], 10);
47
+ }
48
+ else {
49
+ const single = parseInt(body, 10);
50
+ if (!Number.isFinite(single)) {
51
+ throw new Error(`Invalid value in ${fieldName}: ${piece}`);
52
+ }
53
+ lo = single;
54
+ hi = single;
55
+ }
56
+ }
57
+ if (fieldName === 'dow') {
58
+ if (lo === 7)
59
+ lo = 0;
60
+ if (hi === 7)
61
+ hi = 0;
62
+ }
63
+ if (lo < min || hi > max || lo > hi) {
64
+ throw new Error(`Out-of-range value in ${fieldName}: ${piece}`);
65
+ }
66
+ for (let v = lo; v <= hi; v += step)
67
+ out.add(v);
68
+ }
69
+ return { raw, values: out, min, max };
70
+ }
71
+ export function parseCron(expr) {
72
+ const parts = expr.trim().split(/\s+/);
73
+ if (parts.length !== 5) {
74
+ throw new Error(`Expected 5 fields (minute hour day month dow), got ${parts.length}`);
75
+ }
76
+ return {
77
+ minute: parseField(parts[0], FIELD_BOUNDS[0].min, FIELD_BOUNDS[0].max, FIELD_BOUNDS[0].name),
78
+ hour: parseField(parts[1], FIELD_BOUNDS[1].min, FIELD_BOUNDS[1].max, FIELD_BOUNDS[1].name),
79
+ day: parseField(parts[2], FIELD_BOUNDS[2].min, FIELD_BOUNDS[2].max, FIELD_BOUNDS[2].name),
80
+ month: parseField(parts[3], FIELD_BOUNDS[3].min, FIELD_BOUNDS[3].max, FIELD_BOUNDS[3].name),
81
+ dow: parseField(parts[4], FIELD_BOUNDS[4].min, FIELD_BOUNDS[4].max, FIELD_BOUNDS[4].name),
82
+ };
83
+ }
84
+ /**
85
+ * Smallest value in `values` that is ≥ target, or null if none.
86
+ * The set is iterated linearly; sizes are tiny (≤ 60) so the cost is
87
+ * negligible vs the surrounding work.
88
+ */
89
+ function ceilingIn(values, target) {
90
+ let best = null;
91
+ for (const v of values) {
92
+ if (v >= target && (best === null || v < best))
93
+ best = v;
94
+ }
95
+ return best;
96
+ }
97
+ function firstIn(values) {
98
+ let best = Infinity;
99
+ for (const v of values)
100
+ if (v < best)
101
+ best = v;
102
+ return best;
103
+ }
104
+ function dayMatches(spec, d) {
105
+ const dayWild = spec.day.raw === '*';
106
+ const dowWild = spec.dow.raw === '*';
107
+ const dayOk = spec.day.values.has(d.getDate());
108
+ const dowOk = spec.dow.values.has(d.getDay());
109
+ if (dayWild && dowWild)
110
+ return true;
111
+ if (!dayWild && dowWild)
112
+ return dayOk;
113
+ if (dayWild && !dowWild)
114
+ return dowOk;
115
+ return dayOk || dowOk;
116
+ }
117
+ /**
118
+ * Next firing strictly after `from`, found by field-level
119
+ * fast-forwarding. For "yearly at midnight Jan 1" (`0 0 1 1 *`) this
120
+ * converges in at most 4-5 jumps, vs ~525_000 minute increments under
121
+ * the previous brute-force loop.
122
+ *
123
+ * The loop walks fields outermost (month) → innermost (minute). On a
124
+ * mismatch we set the field to its ceiling (next valid value) and reset
125
+ * everything inside it. If no ceiling exists in the current scope we
126
+ * step one unit up in the parent field. JavaScript Date handles
127
+ * carries (month=12 → next year, hour=24 → next day) natively.
128
+ */
129
+ export function nextOccurrence(spec, from = new Date()) {
130
+ const cur = new Date(from);
131
+ cur.setSeconds(0, 0);
132
+ cur.setMinutes(cur.getMinutes() + 1);
133
+ // Sane upper bound: 1000 field jumps will resolve any 5-field spec —
134
+ // crontab can't repeat itself within that many adjustments.
135
+ for (let i = 0; i < 1000; i++) {
136
+ // 1) Month
137
+ const mthIdx = cur.getMonth() + 1; // 1-indexed
138
+ const mthCeil = ceilingIn(spec.month.values, mthIdx);
139
+ if (mthCeil === null) {
140
+ // No matching month this year — roll to next year's first valid month.
141
+ cur.setFullYear(cur.getFullYear() + 1, firstIn(spec.month.values) - 1, 1);
142
+ cur.setHours(0, 0, 0, 0);
143
+ continue;
144
+ }
145
+ if (mthCeil !== mthIdx) {
146
+ cur.setMonth(mthCeil - 1, 1);
147
+ cur.setHours(0, 0, 0, 0);
148
+ continue;
149
+ }
150
+ // 2) Day (handle the day-OR-dow quirk through dayMatches)
151
+ if (!dayMatches(spec, cur)) {
152
+ cur.setDate(cur.getDate() + 1);
153
+ cur.setHours(0, 0, 0, 0);
154
+ continue;
155
+ }
156
+ // 3) Hour
157
+ const hr = cur.getHours();
158
+ const hrCeil = ceilingIn(spec.hour.values, hr);
159
+ if (hrCeil === null) {
160
+ cur.setDate(cur.getDate() + 1);
161
+ cur.setHours(0, 0, 0, 0);
162
+ continue;
163
+ }
164
+ if (hrCeil !== hr) {
165
+ cur.setHours(hrCeil, 0, 0, 0);
166
+ continue;
167
+ }
168
+ // 4) Minute
169
+ const mn = cur.getMinutes();
170
+ const mnCeil = ceilingIn(spec.minute.values, mn);
171
+ if (mnCeil === null) {
172
+ cur.setHours(cur.getHours() + 1, 0, 0, 0);
173
+ continue;
174
+ }
175
+ if (mnCeil !== mn) {
176
+ cur.setMinutes(mnCeil, 0, 0);
177
+ continue;
178
+ }
179
+ // All four fields are valid simultaneously — done.
180
+ return new Date(cur);
181
+ }
182
+ return null;
183
+ }
184
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/core/cron.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,8BAA8B;AAC9B,yBAAyB;AACzB,+BAA+B;AAC/B,2BAA2B;AAC3B,gCAAgC;AAChC,kDAAkD;AAClD,8BAA8B;AAC9B,EAAE;AACF,2DAA2D;AAC3D,EAAE;AACF,uEAAuE;AACvE,wEAAwE;AACxE,0EAA0E;AAS1E,MAAM,YAAY,GAAG;IACnB,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IACnC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IACjC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IAChC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IAClC,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAG,oBAAoB;CAC9C,CAAA;AAEV,SAAS,UAAU,CAAC,GAAW,EAAE,GAAW,EAAE,GAAW,EAAE,SAAiB;IAC1E,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAE7B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QAC9C,IAAI,IAAI,GAAG,KAAK,CAAA;QAChB,IAAI,IAAI,GAAG,CAAC,CAAA;QACZ,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;YACnB,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,mBAAmB,SAAS,KAAK,KAAK,EAAE,CAAC,CAAA;YAC3D,CAAC;QACH,CAAC;QAED,IAAI,EAAU,CAAA;QACd,IAAI,EAAU,CAAA;QACd,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,EAAE,GAAG,GAAG,CAAA;YACR,EAAE,GAAG,GAAG,CAAA;QACV,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;YACzC,IAAI,KAAK,EAAE,CAAC;gBACV,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;gBAC3B,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YAC7B,CAAC;iBAAM,CAAC;gBACN,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;gBACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC7B,MAAM,IAAI,KAAK,CAAC,oBAAoB,SAAS,KAAK,KAAK,EAAE,CAAC,CAAA;gBAC5D,CAAC;gBACD,EAAE,GAAG,MAAM,CAAA;gBACX,EAAE,GAAG,MAAM,CAAA;YACb,CAAC;QACH,CAAC;QAED,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;YACxB,IAAI,EAAE,KAAK,CAAC;gBAAE,EAAE,GAAG,CAAC,CAAA;YACpB,IAAI,EAAE,KAAK,CAAC;gBAAE,EAAE,GAAG,CAAC,CAAA;QACtB,CAAC;QACD,IAAI,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,yBAAyB,SAAS,KAAK,KAAK,EAAE,CAAC,CAAA;QACjE,CAAC;QAED,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI;YAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACjD,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;AACvC,CAAC;AAUD,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,sDAAsD,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IACvF,CAAC;IACD,OAAO;QACL,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5F,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1F,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzF,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3F,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;KAC1F,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,MAAmB,EAAE,MAAc;IACpD,IAAI,IAAI,GAAkB,IAAI,CAAA;IAC9B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC;YAAE,IAAI,GAAG,CAAC,CAAA;IAC1D,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,OAAO,CAAC,MAAmB;IAClC,IAAI,IAAI,GAAG,QAAQ,CAAA;IACnB,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,IAAI,CAAC,GAAG,IAAI;YAAE,IAAI,GAAG,CAAC,CAAA;IAC9C,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,UAAU,CAAC,IAAc,EAAE,CAAO;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,CAAA;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,CAAA;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;IAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;IAC7C,IAAI,OAAO,IAAI,OAAO;QAAE,OAAO,IAAI,CAAA;IACnC,IAAI,CAAC,OAAO,IAAI,OAAO;QAAE,OAAO,KAAK,CAAA;IACrC,IAAI,OAAO,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IACrC,OAAO,KAAK,IAAI,KAAK,CAAA;AACvB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,OAAa,IAAI,IAAI,EAAE;IACpE,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1B,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACpB,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAA;IAEpC,qEAAqE;IACrE,4DAA4D;IAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,WAAW;QACX,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA,CAAE,YAAY;QAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QACpD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,uEAAuE;YACvE,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;YACzE,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACxB,SAAQ;QACV,CAAC;QACD,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACvB,GAAG,CAAC,QAAQ,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;YAC5B,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACxB,SAAQ;QACV,CAAC;QAED,0DAA0D;QAC1D,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAA;YAC9B,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACxB,SAAQ;QACV,CAAC;QAED,UAAU;QACV,MAAM,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAA;QACzB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAC9C,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAA;YAC9B,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACxB,SAAQ;QACV,CAAC;QACD,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YAClB,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YAC7B,SAAQ;QACV,CAAC;QAED,YAAY;QACZ,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,EAAE,CAAA;QAC3B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAChD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACzC,SAAQ;QACV,CAAC;QACD,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YAClB,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YAC5B,SAAQ;QACV,CAAC;QAED,mDAAmD;QACnD,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;IACtB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { EventEmitter } from 'node:events';
2
+ /** Fired by audit-log.logInvocation after a successful (or failed) agent
3
+ * invocation has been recorded. Mirrors the shape audit-log already
4
+ * builds, plus a `ts` ISO string for client-side sorting. */
5
+ export interface AuditEvent {
6
+ type: 'audit';
7
+ ts: string;
8
+ agent: string;
9
+ intent: string;
10
+ platform: string;
11
+ durationMs: number;
12
+ cost: number;
13
+ success: boolean;
14
+ traceId: string;
15
+ userId: string;
16
+ }
17
+ /** Fired when approval-bus enqueues a new pending or resolves one. The
18
+ * /api/approvals snapshot is still authoritative; this event lets the
19
+ * UI refresh that tab (and the in-chat card) without waiting on the
20
+ * 3 s poll. */
21
+ export interface ApprovalEvent {
22
+ type: 'approval';
23
+ phase: 'requested' | 'resolved';
24
+ reqId: string;
25
+ threadId: string;
26
+ platform: string;
27
+ toolName: string;
28
+ /** Present on resolved events — 'allow' / 'deny' / 'timeout' from the
29
+ * bus's metrics buckets. Absent on `requested`. */
30
+ outcome?: 'allow' | 'deny' | 'timeout';
31
+ }
32
+ /** Fired on job-board state transitions. The dashboard subscribes to
33
+ * refresh the Jobs tab without polling. */
34
+ export interface JobEvent {
35
+ type: 'job';
36
+ phase: 'created' | 'started' | 'completed' | 'failed' | 'cancelled';
37
+ jobId: number;
38
+ agent: string;
39
+ }
40
+ /** Periodic metrics tick. Different from individual audit events: this
41
+ * is a snapshot of the full per-agent state (counters + latency
42
+ * quantiles) so the Health tab's sparkline doesn't have to derive
43
+ * everything from raw audits. Emitted by an internal interval, not by
44
+ * any specific call site. */
45
+ export interface MetricsEvent {
46
+ type: 'metrics';
47
+ ts: string;
48
+ agents: Array<{
49
+ agent: string;
50
+ total: number;
51
+ success: number;
52
+ failure: number;
53
+ p50Ms: number;
54
+ p95Ms: number;
55
+ p99Ms: number;
56
+ }>;
57
+ }
58
+ export type ImhubEvent = AuditEvent | ApprovalEvent | JobEvent | MetricsEvent;
59
+ declare class ImhubEventBus extends EventEmitter {
60
+ /** Bounded recent-event log so a freshly-connected SSE client can
61
+ * catch up on what happened in the last few seconds without needing
62
+ * a separate REST poll. Cap at 200 entries — enough for the dashboard
63
+ * to show a meaningful "what just happened" feed without bloating
64
+ * process memory. */
65
+ private recent;
66
+ private static readonly RECENT_CAP;
67
+ constructor();
68
+ /**
69
+ * Publish a typed event. Listeners are called synchronously inside
70
+ * EventEmitter.emit; errors thrown from a listener are caught here so
71
+ * a bad subscriber can't break audit-log / approval-bus / job-board.
72
+ */
73
+ publish(event: ImhubEvent): void;
74
+ /** Snapshot of the recent ring buffer. Used by SSE handler on
75
+ * connection to replay the last N events to a fresh client. */
76
+ getRecent(): ImhubEvent[];
77
+ }
78
+ export declare const eventBus: ImhubEventBus;
79
+ export {};
80
+ //# sourceMappingURL=event-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/core/event-bus.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C;;8DAE8D;AAC9D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;gBAGgB;AAChB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,WAAW,GAAG,UAAU,CAAA;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB;wDACoD;IACpD,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAA;CACvC;AAED;4CAC4C;AAC5C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAA;IACnE,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;8BAI8B;AAC9B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;KACd,CAAC,CAAA;CACH;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,aAAa,GAAG,QAAQ,GAAG,YAAY,CAAA;AAE7E,cAAM,aAAc,SAAQ,YAAY;IACtC;;;;0BAIsB;IACtB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAM;;IAUxC;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAUhC;oEACgE;IAChE,SAAS,IAAI,UAAU,EAAE;CAG1B;AAED,eAAO,MAAM,QAAQ,eAAsB,CAAA"}
@@ -0,0 +1,62 @@
1
+ // im-hub event bus — fan-out for cross-cutting state changes that the
2
+ // dashboard / future plugins want to observe in real time.
3
+ //
4
+ // Why a dedicated bus instead of just exposing each module's
5
+ // EventEmitter?
6
+ //
7
+ // 1. Type uniformity. Subscribers want to handle *any* event with one
8
+ // handler shape; otherwise tasks.html ends up wiring six different
9
+ // EventEmitters by hand.
10
+ // 2. Cross-module decoupling. audit-log / approval-bus / job-board
11
+ // should not know that a Web SSE consumer exists. They emit on the
12
+ // bus; whoever wants to listen does.
13
+ // 3. Backpressure / fan-out. The /events SSE endpoint multiplexes a
14
+ // single bus subscription out to N browser clients. If a single
15
+ // client is slow we don't want to drag the entire process; the bus
16
+ // only does fan-out, per-connection write-buffering is the SSE
17
+ // handler's responsibility.
18
+ //
19
+ // IMPORTANT: emit is best-effort. Never throw out of an emit() — the
20
+ // caller (audit-log.logInvocation, approvalBus.handleApproval, etc.) is
21
+ // in a hot path. We swallow listener errors here so a buggy subscriber
22
+ // can't break the originating action.
23
+ import { EventEmitter } from 'node:events';
24
+ class ImhubEventBus extends EventEmitter {
25
+ /** Bounded recent-event log so a freshly-connected SSE client can
26
+ * catch up on what happened in the last few seconds without needing
27
+ * a separate REST poll. Cap at 200 entries — enough for the dashboard
28
+ * to show a meaningful "what just happened" feed without bloating
29
+ * process memory. */
30
+ recent = [];
31
+ static RECENT_CAP = 200;
32
+ constructor() {
33
+ super();
34
+ // EventEmitter defaults to 10 listeners before warning; we expect one
35
+ // handler per SSE connection plus a few internal subscribers, so 100
36
+ // is a comfortable cap that still flags accidental leaks.
37
+ this.setMaxListeners(100);
38
+ }
39
+ /**
40
+ * Publish a typed event. Listeners are called synchronously inside
41
+ * EventEmitter.emit; errors thrown from a listener are caught here so
42
+ * a bad subscriber can't break audit-log / approval-bus / job-board.
43
+ */
44
+ publish(event) {
45
+ this.recent.push(event);
46
+ while (this.recent.length > ImhubEventBus.RECENT_CAP)
47
+ this.recent.shift();
48
+ try {
49
+ this.emit('event', event);
50
+ }
51
+ catch {
52
+ // EventEmitter normally rethrows — caller is in a hot path so we swallow.
53
+ }
54
+ }
55
+ /** Snapshot of the recent ring buffer. Used by SSE handler on
56
+ * connection to replay the last N events to a fresh client. */
57
+ getRecent() {
58
+ return this.recent.slice();
59
+ }
60
+ }
61
+ export const eventBus = new ImhubEventBus();
62
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/core/event-bus.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,2DAA2D;AAC3D,EAAE;AACF,6DAA6D;AAC7D,gBAAgB;AAChB,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,8BAA8B;AAC9B,qEAAqE;AACrE,wEAAwE;AACxE,0CAA0C;AAC1C,sEAAsE;AACtE,qEAAqE;AACrE,wEAAwE;AACxE,oEAAoE;AACpE,iCAAiC;AACjC,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,uEAAuE;AACvE,sCAAsC;AAEtC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAgE1C,MAAM,aAAc,SAAQ,YAAY;IACtC;;;;0BAIsB;IACd,MAAM,GAAiB,EAAE,CAAA;IACzB,MAAM,CAAU,UAAU,GAAG,GAAG,CAAA;IAExC;QACE,KAAK,EAAE,CAAA;QACP,sEAAsE;QACtE,qEAAqE;QACrE,0DAA0D;QAC1D,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,KAAiB;QACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,aAAa,CAAC,UAAU;YAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACzE,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;QAC5E,CAAC;IACH,CAAC;IAED;oEACgE;IAChE,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IAC5B,CAAC;;AAGH,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAA"}
@@ -0,0 +1,27 @@
1
+ import type { AgentAdapter } from './types.js';
2
+ export interface LLMJudgeConfig {
3
+ /** Agent name used as the judge. Must already be registered. */
4
+ agentName: string;
5
+ /** Score threshold below which the LLM is consulted (default 1.0). */
6
+ threshold?: number;
7
+ /** Override the default 5s response timeout. */
8
+ timeoutMs?: number;
9
+ }
10
+ export declare function configureLLMJudge(cfg: LLMJudgeConfig | null): void;
11
+ /** Read the judge configuration. Used by classifyIntent to know whether
12
+ * to attempt a fallback at all. */
13
+ export declare function getLLMJudge(): LLMJudgeConfig | null;
14
+ /**
15
+ * Ask the judge agent which candidate to use. Returns null on any
16
+ * failure path (timeout, judge unavailable, malformed response) so
17
+ * the caller can keep its rule-based decision.
18
+ */
19
+ export declare function classifyWithLLM(text: string, candidates: string[], resolveAgent: (name: string) => AgentAdapter | undefined): Promise<{
20
+ agent: string;
21
+ reason: string;
22
+ } | null>;
23
+ /** Test-only: clear cache so memoization doesn't leak between cases. */
24
+ export declare function _clearLLMCache(): void;
25
+ /** Test/diagnostic: current cache size. */
26
+ export declare function _cacheSize(): number;
27
+ //# sourceMappingURL=intent-llm.d.ts.map