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,236 @@
1
+ // DingTalk Bot client — wraps the official `dingtalk-stream` SDK for
2
+ // inbound messages (WebSocket Stream mode) and uses DingTalk's REST
3
+ // OpenAPI for outbound messages.
4
+ //
5
+ // Architecture matches the Feishu client:
6
+ // * Inbound goes through TOPIC_ROBOT callback registered with DWClient
7
+ // * Outbound uses access-token-authed POST to api.dingtalk.com
8
+ // * The SDK manages WebSocket reconnect (1s-60s exponential), heartbeat,
9
+ // and access-token refresh — we just call getAccessToken() before
10
+ // each OpenAPI send and the SDK caches/refreshes as needed.
11
+ //
12
+ // Why not sessionWebhook (the temporary 30s URL each inbound message
13
+ // carries)? Because im-hub's primary use case is multi-minute agent
14
+ // runs and the sessionWebhook is always stale by the time the agent
15
+ // finishes. OpenAPI works for any send regardless of elapsed time.
16
+ import { DWClient, TOPIC_ROBOT } from 'dingtalk-stream';
17
+ import { logger as rootLogger } from '../../../core/logger.js';
18
+ const log = rootLogger.child({ component: 'dingtalk-client' });
19
+ const API_BASE = 'https://api.dingtalk.com';
20
+ const URL_1V1 = `${API_BASE}/v1.0/robot/oToMessages/batchSend`;
21
+ const URL_GROUP = `${API_BASE}/v1.0/robot/groupMessages/send`;
22
+ const URL_MEDIA_DL = `${API_BASE}/v1.0/robot/messageFiles/download`;
23
+ /** Hard cap on a single inbound media download. DingTalk caps voice at
24
+ * ~2 MB and images at ~10 MB on the consumer client; 20 MB gives us
25
+ * headroom for files without letting a runaway upload fill the disk. */
26
+ const MAX_MEDIA_BYTES = 20 * 1024 * 1024;
27
+ function parseThreadId(threadId) {
28
+ if (threadId.startsWith('user:')) {
29
+ return { kind: 'user', id: threadId.slice('user:'.length) };
30
+ }
31
+ if (threadId.startsWith('group:')) {
32
+ return { kind: 'group', id: threadId.slice('group:'.length) };
33
+ }
34
+ return null;
35
+ }
36
+ export class DingTalkClient {
37
+ dw;
38
+ config;
39
+ messageHandler;
40
+ /** Cached robotCode from the most recent inbound (== clientId for
41
+ * stream-mode internal apps, but we read it from messages so we're
42
+ * tolerant of multi-bot setups in one app). */
43
+ lastSeenRobotCode;
44
+ constructor(config) {
45
+ this.config = config;
46
+ this.lastSeenRobotCode = config.clientId; // sensible default
47
+ this.dw = new DWClient({
48
+ clientId: config.clientId,
49
+ clientSecret: config.clientSecret,
50
+ // DWClient defaults: autoReconnect=true, debug=false, keepAlive=false.
51
+ // Reconnect strategy is 1s → 60s exponential, heartbeat 8s — already
52
+ // matches our needs.
53
+ });
54
+ }
55
+ onMessage(handler) {
56
+ this.messageHandler = handler;
57
+ }
58
+ async start() {
59
+ this.dw.registerCallbackListener(TOPIC_ROBOT, async (res) => {
60
+ let msg;
61
+ try {
62
+ msg = JSON.parse(res.data);
63
+ }
64
+ catch (err) {
65
+ log.warn({ err: err instanceof Error ? err.message : String(err), data: res.data?.slice?.(0, 200) }, 'failed to parse TOPIC_ROBOT data');
66
+ return;
67
+ }
68
+ if (msg.robotCode)
69
+ this.lastSeenRobotCode = msg.robotCode;
70
+ if (this.messageHandler) {
71
+ try {
72
+ await this.messageHandler(msg);
73
+ }
74
+ catch (err) {
75
+ log.error({ err: err instanceof Error ? err.message : String(err) }, 'message handler threw');
76
+ }
77
+ }
78
+ // ack so the gateway doesn't redeliver. We're swallowing the
79
+ // response payload here intentionally — DingTalk gives 60s before
80
+ // it retries; our agent flow may exceed that and that's fine,
81
+ // the user gets the eventual reply via OpenAPI.
82
+ this.dw.socketCallBackResponse(res.headers.messageId, { status: 'SUCCESS' });
83
+ });
84
+ await this.dw.connect();
85
+ log.info({ event: 'dingtalk.client.connected' }, 'WebSocket connected');
86
+ }
87
+ async stop() {
88
+ try {
89
+ this.dw.disconnect();
90
+ }
91
+ catch (err) {
92
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, 'error during dingtalk disconnect (ignored)');
93
+ }
94
+ }
95
+ /** Send a plain-text message to a thread we previously received from
96
+ * (encoded as `user:<staffId>` for 1:1, `group:<convId>` for groups).
97
+ * Uses OpenAPI under the bot's access token. */
98
+ async sendMessage(threadId, text) {
99
+ await this.sendTemplated(threadId, 'sampleText', { content: text });
100
+ }
101
+ /** Send a markdown-formatted message. DingTalk's `sampleMarkdown` only
102
+ * takes `title` + `text`; we derive title from the first line so the
103
+ * user sees something meaningful in the notification preview. */
104
+ async sendMarkdown(threadId, text, title) {
105
+ const firstLine = text.split('\n', 1)[0]?.replace(/^[#*\-\s>]+/, '').slice(0, 32) || 'Message';
106
+ await this.sendTemplated(threadId, 'sampleMarkdown', {
107
+ title: title ?? firstLine,
108
+ text,
109
+ });
110
+ }
111
+ /** Download an inbound image / voice / file message's binary payload.
112
+ *
113
+ * DingTalk hands the bot a short-lived `downloadCode` in each media
114
+ * inbound; we trade it (plus our robotCode) for a presigned downloadUrl
115
+ * on alibaba CDN, then GET that URL and return the bytes.
116
+ *
117
+ * Returns null on any error (caller surfaces a "[download failed:...]"
118
+ * marker instead of silently dropping the user's message). MAX cap is
119
+ * enforced; oversize payloads throw before allocating the buffer.
120
+ *
121
+ * Reference: POST /v1.0/robot/messageFiles/download
122
+ * { downloadCode, robotCode }
123
+ * header: x-acs-dingtalk-access-token
124
+ * response: { downloadUrl } (sometimes nested under .data)
125
+ */
126
+ async downloadMessageFile(downloadCode) {
127
+ if (!downloadCode)
128
+ return null;
129
+ let accessToken;
130
+ try {
131
+ accessToken = await this.dw.getAccessToken();
132
+ }
133
+ catch (err) {
134
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, 'dingtalk: getAccessToken failed before media download');
135
+ return null;
136
+ }
137
+ if (!accessToken)
138
+ return null;
139
+ // Step 1: exchange downloadCode for a CDN URL.
140
+ let downloadUrl = null;
141
+ try {
142
+ const res = await fetch(URL_MEDIA_DL, {
143
+ method: 'POST',
144
+ headers: {
145
+ 'Content-Type': 'application/json',
146
+ 'x-acs-dingtalk-access-token': String(accessToken),
147
+ },
148
+ body: JSON.stringify({ downloadCode, robotCode: this.lastSeenRobotCode }),
149
+ });
150
+ if (!res.ok) {
151
+ const txt = await res.text().catch(() => '');
152
+ log.warn({
153
+ status: res.status,
154
+ body: txt.slice(0, 200),
155
+ event: 'dingtalk.media.exchange_failed',
156
+ }, 'messageFiles/download API rejected the downloadCode exchange');
157
+ return null;
158
+ }
159
+ const payload = await res.json().catch(() => null);
160
+ downloadUrl = payload?.downloadUrl ?? payload?.data?.downloadUrl ?? null;
161
+ if (!downloadUrl) {
162
+ log.warn({ event: 'dingtalk.media.no_url_in_response', payload }, 'exchange succeeded but response had no downloadUrl');
163
+ return null;
164
+ }
165
+ }
166
+ catch (err) {
167
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, 'dingtalk: downloadCode exchange threw');
168
+ return null;
169
+ }
170
+ // Step 2: GET the CDN URL. DingTalk's CDN may be on different alibaba
171
+ // hosts depending on the file type / region; no host restriction here.
172
+ try {
173
+ const res = await fetch(downloadUrl);
174
+ if (!res.ok) {
175
+ log.warn({ status: res.status, event: 'dingtalk.media.cdn_get_failed' }, 'CDN refused the download');
176
+ return null;
177
+ }
178
+ const contentLength = parseInt(res.headers.get('content-length') ?? '0', 10);
179
+ if (Number.isFinite(contentLength) && contentLength > MAX_MEDIA_BYTES) {
180
+ log.warn({ contentLength, max: MAX_MEDIA_BYTES, event: 'dingtalk.media.too_large' }, 'media exceeds size cap; refusing to download');
181
+ return null;
182
+ }
183
+ const arr = await res.arrayBuffer();
184
+ if (arr.byteLength > MAX_MEDIA_BYTES) {
185
+ log.warn({ bytes: arr.byteLength, max: MAX_MEDIA_BYTES, event: 'dingtalk.media.too_large' }, 'media bytes exceed size cap after download');
186
+ return null;
187
+ }
188
+ const contentType = res.headers.get('content-type') ?? 'application/octet-stream';
189
+ return { buffer: Buffer.from(arr), contentType };
190
+ }
191
+ catch (err) {
192
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, 'dingtalk: CDN GET threw');
193
+ return null;
194
+ }
195
+ }
196
+ /** Shared POST path. msgKey + msgParam (stringified inner object) is
197
+ * DingTalk's "templated message" convention — covers text, markdown,
198
+ * cards via the same endpoint. */
199
+ async sendTemplated(threadId, msgKey, inner) {
200
+ const target = parseThreadId(threadId);
201
+ if (!target) {
202
+ throw new Error(`dingtalk: unrecognised threadId "${threadId}" (expected user:<id> or group:<id>)`);
203
+ }
204
+ const accessToken = await this.dw.getAccessToken();
205
+ if (!accessToken) {
206
+ throw new Error('dingtalk: getAccessToken() returned empty token');
207
+ }
208
+ const body = target.kind === 'user'
209
+ ? {
210
+ robotCode: this.lastSeenRobotCode,
211
+ userIds: [target.id],
212
+ msgKey,
213
+ msgParam: JSON.stringify(inner),
214
+ }
215
+ : {
216
+ robotCode: this.lastSeenRobotCode,
217
+ openConversationId: target.id,
218
+ msgKey,
219
+ msgParam: JSON.stringify(inner),
220
+ };
221
+ const url = target.kind === 'user' ? URL_1V1 : URL_GROUP;
222
+ const res = await fetch(url, {
223
+ method: 'POST',
224
+ headers: {
225
+ 'Content-Type': 'application/json',
226
+ 'x-acs-dingtalk-access-token': String(accessToken),
227
+ },
228
+ body: JSON.stringify(body),
229
+ });
230
+ if (!res.ok) {
231
+ const txt = await res.text().catch(() => '');
232
+ throw new Error(`dingtalk: ${target.kind} send failed: ${res.status} ${res.statusText} ${txt.slice(0, 200)}`);
233
+ }
234
+ }
235
+ }
236
+ //# sourceMappingURL=dingtalk-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dingtalk-client.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/dingtalk-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { dingtalkAdapter, DingTalkAdapter } from './dingtalk-adapter.js';
2
+ export type { DingTalkConfig, DingTalkInboundMessage } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACxE,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,3 @@
1
+ // DingTalk (钉钉) Stream-mode messenger adapter.
2
+ export { dingtalkAdapter, DingTalkAdapter } from './dingtalk-adapter.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA"}
@@ -0,0 +1,23 @@
1
+ /** What coord system the URL's host implies. Drives which conversion
2
+ * `normalizeIncomingCoords` applies on the extracted lat/lng. */
3
+ export type MapUrlSource = 'dingtalk-link-amap' | 'dingtalk-link-tencent' | 'dingtalk-link-baidu' | 'dingtalk-link-unknown';
4
+ /** Best-effort lat/lng extraction from common map URLs.
5
+ *
6
+ * Returns null if the URL doesn't look like a map share. On hit, also
7
+ * returns the `source` so the caller can route through
8
+ * `normalizeIncomingCoords()` for the right coord-system conversion:
9
+ * - Amap / Gaode → GCJ-02
10
+ * - Tencent (map.qq) → GCJ-02
11
+ * - Baidu Maps → BD-09
12
+ * - Anything else → pass-through (we don't guess for unknown hosts)
13
+ *
14
+ * Parses these URL shapes:
15
+ * - Amap: `uri.amap.com/marker?position=lng,lat`
16
+ * - Tencent: `apis.map.qq.com/uri/v1/marker?marker=coord:lat,lng`
17
+ * - Generic: `?location=lat,lng`, `?latlng=lat,lng`, `?lat=…&lng=…` */
18
+ export declare function tryExtractLatLng(url: string): {
19
+ lat: number;
20
+ lng: number;
21
+ source: MapUrlSource;
22
+ } | null;
23
+ //# sourceMappingURL=link-coords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-coords.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/link-coords.ts"],"names":[],"mappings":"AASA;kEACkE;AAClE,MAAM,MAAM,YAAY,GACpB,oBAAoB,GACpB,uBAAuB,GACvB,qBAAqB,GACrB,uBAAuB,CAAA;AAmB3B;;;;;;;;;;;;;yEAayE;AACzE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAAG,IAAI,CA+CvG"}
@@ -0,0 +1,89 @@
1
+ // Map-URL coordinate extraction for DingTalk `link` msgtype payloads.
2
+ //
3
+ // Kept in a separate file (rather than inline in dingtalk-adapter.ts)
4
+ // because the adapter pulls in heavy modules — `media-store.ts`,
5
+ // `dingtalk-stream`, the transcribe / location-context machinery — that
6
+ // each can have side effects at import time (env-var capture, file
7
+ // handles, etc.). Tests for the URL classifier should not pay that cost
8
+ // or risk pulling in process-wide state.
9
+ function classifyHost(host) {
10
+ const h = host.toLowerCase();
11
+ if (h.endsWith('.amap.com') || h === 'amap.com' || h.endsWith('.gaode.com') || h === 'gaode.com') {
12
+ return 'dingtalk-link-amap';
13
+ }
14
+ if (h.endsWith('.qq.com') || h === 'qq.com') {
15
+ // Tencent's map endpoints: map.qq.com, apis.map.qq.com, lbs.qq.com.
16
+ // Other *.qq.com URLs (chat / mail) shouldn't legitimately carry
17
+ // map coords; if they do, GCJ-02 is the safe assumption.
18
+ return 'dingtalk-link-tencent';
19
+ }
20
+ if (h.endsWith('.baidu.com') || h === 'baidu.com') {
21
+ return 'dingtalk-link-baidu';
22
+ }
23
+ return 'dingtalk-link-unknown';
24
+ }
25
+ /** Best-effort lat/lng extraction from common map URLs.
26
+ *
27
+ * Returns null if the URL doesn't look like a map share. On hit, also
28
+ * returns the `source` so the caller can route through
29
+ * `normalizeIncomingCoords()` for the right coord-system conversion:
30
+ * - Amap / Gaode → GCJ-02
31
+ * - Tencent (map.qq) → GCJ-02
32
+ * - Baidu Maps → BD-09
33
+ * - Anything else → pass-through (we don't guess for unknown hosts)
34
+ *
35
+ * Parses these URL shapes:
36
+ * - Amap: `uri.amap.com/marker?position=lng,lat`
37
+ * - Tencent: `apis.map.qq.com/uri/v1/marker?marker=coord:lat,lng`
38
+ * - Generic: `?location=lat,lng`, `?latlng=lat,lng`, `?lat=…&lng=…` */
39
+ export function tryExtractLatLng(url) {
40
+ if (!url || typeof url !== 'string')
41
+ return null;
42
+ try {
43
+ const u = new URL(url);
44
+ const source = classifyHost(u.hostname);
45
+ const params = u.searchParams;
46
+ // Amap: ?position=lng,lat
47
+ const position = params.get('position');
48
+ if (position) {
49
+ const [lngStr, latStr] = position.split(',');
50
+ const lng = parseFloat(lngStr);
51
+ const lat = parseFloat(latStr);
52
+ if (Number.isFinite(lat) && Number.isFinite(lng))
53
+ return { lat, lng, source };
54
+ }
55
+ // Tencent: ?marker=coord:lat,lng;title:...
56
+ const marker = params.get('marker');
57
+ if (marker?.startsWith('coord:')) {
58
+ const coord = marker.slice('coord:'.length).split(';')[0];
59
+ const [latStr, lngStr] = coord.split(',');
60
+ const lat = parseFloat(latStr);
61
+ const lng = parseFloat(lngStr);
62
+ if (Number.isFinite(lat) && Number.isFinite(lng))
63
+ return { lat, lng, source };
64
+ }
65
+ // Generic ?location=lat,lng OR ?latlng=lat,lng
66
+ const loc = params.get('location') ?? params.get('latlng');
67
+ if (loc) {
68
+ const [latStr, lngStr] = loc.split(',');
69
+ const lat = parseFloat(latStr);
70
+ const lng = parseFloat(lngStr);
71
+ if (Number.isFinite(lat) && Number.isFinite(lng))
72
+ return { lat, lng, source };
73
+ }
74
+ // Separate ?lat=...&lng=... (or &lon=...)
75
+ const latParam = params.get('lat') ?? params.get('latitude');
76
+ const lngParam = params.get('lng') ?? params.get('lon') ?? params.get('longitude');
77
+ if (latParam && lngParam) {
78
+ const lat = parseFloat(latParam);
79
+ const lng = parseFloat(lngParam);
80
+ if (Number.isFinite(lat) && Number.isFinite(lng))
81
+ return { lat, lng, source };
82
+ }
83
+ }
84
+ catch {
85
+ /* URL didn't parse — not a map share we can read. */
86
+ }
87
+ return null;
88
+ }
89
+ //# sourceMappingURL=link-coords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-coords.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/link-coords.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /** Pick a sensible extension for a buffer based on (in order):
2
+ * 1. content-type header from the CDN response
3
+ * 2. the original filename (for msgtype='file') if it has one
4
+ * 3. fallback 'bin' so the file is always inspectable on disk
5
+ *
6
+ * Same map shape as telegram's pickExtension but DingTalk also delivers
7
+ * voice as audio/amr — distinct from anything telegram sees. */
8
+ export declare function pickDingTalkExtension(contentType: string | undefined, originalFilename: string | undefined): string;
9
+ /** Write `buffer` to `<MEDIA_ROOT>/dingtalk/<subPath>/<filename>` and
10
+ * return the absolute path. Refuses path-traversal in filename / subPath
11
+ * (segments containing `/`, `\`, or `..` are rejected before mkdir).
12
+ *
13
+ * Caller is responsible for the size cap — `dingtalk-client.ts`
14
+ * already enforces MAX_MEDIA_BYTES before handing us the buffer. */
15
+ export declare function saveDingTalkMedia(buffer: Buffer, subPath: string, filename: string): Promise<string>;
16
+ //# sourceMappingURL=media-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-store.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/media-store.ts"],"names":[],"mappings":"AAgBA;;;;;;iEAMiE;AACjE,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,CA2BR;AAED;;;;;qEAKqE;AACrE,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAiBjB"}
@@ -0,0 +1,77 @@
1
+ // DingTalk inbound media → local disk.
2
+ //
3
+ // We piggyback on telegram's MEDIA_ROOT so both adapters land their
4
+ // attachments in the same ~/.im-hub/media/<platform>/<thread>/ tree.
5
+ // That keeps `cleanupOldMedia` (running on the telegram side) covering
6
+ // everything, and matches how claude-code's Read tool already expects
7
+ // to find adjuncts referenced by `[图片附件:…]` markers.
8
+ //
9
+ // Why a separate file from `dingtalk-client.ts`? The client's job is the
10
+ // network round-trip; the on-disk format and path-injection guards live
11
+ // here so they can be unit-tested without spinning up a DWClient.
12
+ import { mkdir, writeFile } from 'node:fs/promises';
13
+ import { resolve } from 'node:path';
14
+ import { MEDIA_ROOT } from '../telegram/media-download.js';
15
+ /** Pick a sensible extension for a buffer based on (in order):
16
+ * 1. content-type header from the CDN response
17
+ * 2. the original filename (for msgtype='file') if it has one
18
+ * 3. fallback 'bin' so the file is always inspectable on disk
19
+ *
20
+ * Same map shape as telegram's pickExtension but DingTalk also delivers
21
+ * voice as audio/amr — distinct from anything telegram sees. */
22
+ export function pickDingTalkExtension(contentType, originalFilename) {
23
+ if (originalFilename) {
24
+ const m = /\.([a-z0-9]+)$/i.exec(originalFilename);
25
+ if (m)
26
+ return m[1].toLowerCase();
27
+ }
28
+ if (contentType) {
29
+ const map = {
30
+ 'image/jpeg': 'jpg',
31
+ 'image/jpg': 'jpg',
32
+ 'image/png': 'png',
33
+ 'image/gif': 'gif',
34
+ 'image/webp': 'webp',
35
+ 'image/heic': 'heic',
36
+ 'audio/amr': 'amr',
37
+ 'audio/x-amr': 'amr',
38
+ 'audio/mpeg': 'mp3',
39
+ 'audio/mp4': 'm4a',
40
+ 'audio/ogg': 'ogg',
41
+ 'audio/wav': 'wav',
42
+ 'application/pdf': 'pdf',
43
+ };
44
+ const ct = contentType.toLowerCase().split(';')[0].trim();
45
+ if (map[ct])
46
+ return map[ct];
47
+ const m = /\/([a-z0-9]+)$/i.exec(ct);
48
+ if (m)
49
+ return m[1].toLowerCase();
50
+ }
51
+ return 'bin';
52
+ }
53
+ /** Write `buffer` to `<MEDIA_ROOT>/dingtalk/<subPath>/<filename>` and
54
+ * return the absolute path. Refuses path-traversal in filename / subPath
55
+ * (segments containing `/`, `\`, or `..` are rejected before mkdir).
56
+ *
57
+ * Caller is responsible for the size cap — `dingtalk-client.ts`
58
+ * already enforces MAX_MEDIA_BYTES before handing us the buffer. */
59
+ export async function saveDingTalkMedia(buffer, subPath, filename) {
60
+ for (const piece of [subPath, filename]) {
61
+ if (piece.includes('..') || piece.includes('\\')) {
62
+ throw new Error(`unsafe path piece: ${piece}`);
63
+ }
64
+ }
65
+ if (filename.includes('/')) {
66
+ throw new Error(`unsafe filename: ${filename}`);
67
+ }
68
+ const dir = resolve(MEDIA_ROOT, 'dingtalk', subPath);
69
+ const path = resolve(dir, filename);
70
+ if (!path.startsWith(`${MEDIA_ROOT}/`)) {
71
+ throw new Error(`destination escapes MEDIA_ROOT: ${path}`);
72
+ }
73
+ await mkdir(dir, { recursive: true });
74
+ await writeFile(path, buffer);
75
+ return path;
76
+ }
77
+ //# sourceMappingURL=media-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-store.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/media-store.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,oEAAoE;AACpE,qEAAqE;AACrE,uEAAuE;AACvE,sEAAsE;AACtE,qDAAqD;AACrD,EAAE;AACF,yEAAyE;AACzE,wEAAwE;AACxE,kEAAkE;AAElE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE1D;;;;;;iEAMiE;AACjE,MAAM,UAAU,qBAAqB,CACnC,WAA+B,EAC/B,gBAAoC;IAEpC,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAClD,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAClC,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,GAAG,GAA2B;YAClC,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,MAAM;YACpB,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE,KAAK;YACpB,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,iBAAiB,EAAE,KAAK;SACzB,CAAA;QACD,MAAM,EAAE,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QACzD,IAAI,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAA;QAC3B,MAAM,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACpC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAClC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;qEAKqE;AACrE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,OAAe,EACf,QAAgB;IAEhB,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;QACxC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAA;QAChD,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAA;IACjD,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAA;IACpD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IACnC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC;IACD,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACrC,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC7B,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,82 @@
1
+ export interface DingTalkConfig {
2
+ /** AppKey from the DingTalk developer console (also serves as robotCode). */
3
+ clientId: string;
4
+ /** AppSecret — used by the SDK to obtain access tokens automatically. */
5
+ clientSecret: string;
6
+ /** Optional channel id (forwarded to MessageContext); we don't drive
7
+ * routing on it but a few downstream consumers tag logs by it. */
8
+ channelId?: string;
9
+ }
10
+ /** Inbound message payload from the Stream SDK's TOPIC_ROBOT callback.
11
+ * Empirically observed msgtype values (community docs say `image`/`voice`
12
+ * but DingTalk actually wire-formats them as `picture`/`audio`):
13
+ * 'text' | 'picture' | 'audio' | 'file' | 'link' | 'markdown' | 'action_card'
14
+ * The official Node SDK only types `text`; we keep msgtype as a loose
15
+ * string and snapshot known shapes for the rest. Unknown shapes fall
16
+ * through to a debug-logging path that dumps the full payload — that's
17
+ * how we discovered the `picture`/`audio` naming + the `content` block
18
+ * shape (community docs document those fields under `msg.picture` etc.,
19
+ * but real deliveries put them inside a single `content` object). */
20
+ export interface DingTalkInboundMessage {
21
+ /** Unique message id for dedup. */
22
+ msgId: string;
23
+ /** One of the empirically-confirmed msgtype values, or something else. */
24
+ msgtype: string;
25
+ /** Present on msgtype='text'. */
26
+ text?: {
27
+ content: string;
28
+ };
29
+ /** Present on msgtype='link'. picUrl is the thumbnail; messageUrl is
30
+ * the deep link / URL the user actually shared. Title/text are
31
+ * display preview. */
32
+ link?: {
33
+ title?: string;
34
+ text?: string;
35
+ picUrl?: string;
36
+ messageUrl?: string;
37
+ };
38
+ /** Catch-all `content` block — used by every non-text/non-link msgtype.
39
+ * Different msgtype values use different subsets of the fields below:
40
+ * picture: { pictureDownloadCode (full), downloadCode (thumb) }
41
+ * audio: { downloadCode, recognition (DingTalk's server-side ASR!) }
42
+ * file: { downloadCode, fileName } (best-effort from docs)
43
+ * markdown / action_card: { text, title } (best-effort) */
44
+ content?: {
45
+ pictureDownloadCode?: string;
46
+ downloadCode?: string;
47
+ /** DingTalk's built-in voice-to-text for `audio` messages. Prefer
48
+ * this over running whisper.cpp locally — it's typically more
49
+ * accurate for Mandarin and zero-cost on our side. */
50
+ recognition?: string;
51
+ title?: string;
52
+ text?: string;
53
+ fileName?: string;
54
+ duration?: string | number;
55
+ };
56
+ /** Conversation id in OpenAPI's `openConversationId` shape — usable
57
+ * directly when calling /v1.0/robot/groupMessages/send. */
58
+ conversationId: string;
59
+ /** '1' = single chat (1:1), '2' = group chat. */
60
+ conversationType: '1' | '2' | string;
61
+ /** Internal staff id of the message sender (use in 1:1 send userIds). */
62
+ senderStaffId: string;
63
+ senderNick?: string;
64
+ senderCorpId?: string;
65
+ /** Bot's own ids (chatbotUserId = robot's user id inside the corp). */
66
+ chatbotUserId?: string;
67
+ chatbotCorpId?: string;
68
+ /** The bot's robotCode — same value as the configured AppKey/clientId
69
+ * for stream-mode internal apps, but we read it from the message so
70
+ * we don't have to hard-code the relationship. */
71
+ robotCode: string;
72
+ /** Temporary webhook URL the bot can POST to without an access token,
73
+ * valid until `sessionWebhookExpiredTime` (ms epoch). 30s in practice. */
74
+ sessionWebhook?: string;
75
+ sessionWebhookExpiredTime?: number;
76
+ createAt?: number;
77
+ isAdmin?: boolean;
78
+ /** Catch-all for unknown fields — we never index this in code, but
79
+ * preserving it lets the debug-log path dump the full payload. */
80
+ [extra: string]: unknown;
81
+ }
82
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/types.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,cAAc;IAC7B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAA;IAChB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAA;IACpB;uEACmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;sEASsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAA;IACf,iCAAiC;IACjC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1B;;2BAEuB;IACvB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9E;;;;;kEAK8D;IAC9D,OAAO,CAAC,EAAE;QACR,mBAAmB,CAAC,EAAE,MAAM,CAAA;QAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB;;+DAEuD;QACvD,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAC3B,CAAA;IACD;gEAC4D;IAC5D,cAAc,EAAE,MAAM,CAAA;IACtB,iDAAiD;IACjD,gBAAgB,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,CAAA;IACpC,yEAAyE;IACzE,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;uDAEmD;IACnD,SAAS,EAAE,MAAM,CAAA;IACjB;+EAC2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;uEACmE;IACnE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB"}
@@ -0,0 +1,14 @@
1
+ // DingTalk (钉钉) Bot — Stream-mode messenger types
2
+ //
3
+ // Reference:
4
+ // * SDK: https://github.com/open-dingtalk/dingtalk-stream-sdk-nodejs
5
+ // * Stream mode protocol: https://open.dingtalk.com/document/direction/stream-mode-protocol-access-description
6
+ // * 1:1 send: POST /v1.0/robot/oToMessages/batchSend
7
+ // * Group send: POST /v1.0/robot/groupMessages/send
8
+ //
9
+ // Note: the SDK's RobotTextMessage type covers only `msgtype: 'text'`, but
10
+ // inbound payloads carry conversationType / robotCode / sessionWebhook
11
+ // that we need for routing — restate the full shape here so the adapter
12
+ // can switch on conversationType without fighting the SDK union.
13
+ export {};
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/plugins/messengers/dingtalk/types.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,aAAa;AACb,uEAAuE;AACvE,iHAAiH;AACjH,uDAAuD;AACvD,sDAAsD;AACtD,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,wEAAwE;AACxE,iEAAiE"}
@@ -0,0 +1,21 @@
1
+ import type { MessengerAdapter, MessageContext } from '../../../core/types.js';
2
+ export declare class DiscordAdapter implements MessengerAdapter {
3
+ readonly name = "discord";
4
+ private client;
5
+ private config;
6
+ private messageHandler?;
7
+ private typingIntervals;
8
+ /** L7: companion AbortController per typing thread. Lets the periodic
9
+ * refresh callback bail BEFORE invoking sendTyping when stop() has
10
+ * fired, instead of racing against client.destroy(). */
11
+ private typingAbortControllers;
12
+ start(): Promise<void>;
13
+ stop(): Promise<void>;
14
+ onMessage(handler: (ctx: MessageContext) => Promise<void>): void;
15
+ sendMessage(threadId: string, text: string): Promise<void>;
16
+ sendTyping(threadId: string, isTyping: boolean): Promise<void>;
17
+ private fetchSendableChannel;
18
+ private handleDiscordMessage;
19
+ }
20
+ export declare const discordAdapter: DiscordAdapter;
21
+ //# sourceMappingURL=discord-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord-adapter.d.ts","sourceRoot":"","sources":["../../../../src/plugins/messengers/discord/discord-adapter.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAW,MAAM,wBAAwB,CAAA;AAWvF,qBAAa,cAAe,YAAW,gBAAgB;IACrD,QAAQ,CAAC,IAAI,aAAY;IACzB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,cAAc,CAAC,CAAwC;IAC/D,OAAO,CAAC,eAAe,CAAoD;IAC3E;;6DAEyD;IACzD,OAAO,CAAC,sBAAsB,CAAqC;IAE7D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA0DtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI1D,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB1D,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;YA4DtD,oBAAoB;YAcpB,oBAAoB;CAyDnC;AAGD,eAAO,MAAM,cAAc,gBAAuB,CAAA"}