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,851 @@
1
+ // cli-ui/config-wizard.ts — interactive `agim config` flow.
2
+ //
3
+ // Top-level menu has 5 sections:
4
+ // 1. Messengers — list-of-channels; each opens its own sub-menu
5
+ // (WeChat QR scan / Telegram & Feishu & Discord
6
+ // credential prompts / Email toggle)
7
+ // 2. Agents — list-of-agents with live CLI install detection;
8
+ // per-agent sub-menu lets you enable/disable, see
9
+ // install / auth instructions, set as default
10
+ // 3. Remote ACP — list / add / edit / remove
11
+ // 4. SMTP — Edit / Disable / Back; preset picker → host/port/
12
+ // user/pass/from/secure (writes to ENV_FILE)
13
+ // 5. Baidu Maps AK — Set / Clear / Back (writes IMHUB_BAIDU_MAP_AK)
14
+ //
15
+ // Design rule: every sub-menu has a ← Back entry. The wizard never
16
+ // requires Ctrl-C to escape (first-time users don't know it works).
17
+ //
18
+ // Edits land in the in-memory Config object until "Done — save and exit".
19
+ // SMTP / Baidu writes are immediate to env-file.ts so a crash mid-wizard
20
+ // doesn't lose the secrets the user already typed.
21
+ import { crossSpawn } from '../utils/cross-platform.js';
22
+ import { menu, inputText, inputSecret, yesNo, BACK, UserAbortError, } from './prompts.js';
23
+ import { t } from './i18n.js';
24
+ import { loadConfig, saveConfig } from '../core/onboarding.js';
25
+ import { CONFIG_DIR } from './paths.js';
26
+ import { ENV_FILE, readEffectiveEnv, updateEnvFile, unsetEnvKey, hasProcessEnvOverride } from './env-file.js';
27
+ /** Probe whether a CLI command exists on PATH. Mirrors the `--version`
28
+ * spawn check the legacy `config <agent>` flow used. Resolves quickly:
29
+ * most install probes finish in <200ms, missing binaries return
30
+ * ENOENT immediately. */
31
+ function cliAvailable(cmd) {
32
+ return new Promise((resolve) => {
33
+ const proc = crossSpawn(cmd, ['--version'], { stdio: 'ignore' });
34
+ proc.on('close', (code) => resolve(code === 0));
35
+ proc.on('error', () => resolve(false));
36
+ });
37
+ }
38
+ export async function runConfigWizard(lang) {
39
+ let config = await loadConfig();
40
+ console.log();
41
+ console.log(t(lang, 'config.title'));
42
+ console.log(t(lang, 'config.subtitle'));
43
+ console.log();
44
+ while (true) {
45
+ let picked;
46
+ try {
47
+ picked = (await menu({
48
+ lang,
49
+ message: t(lang, 'menu.subtitle'),
50
+ choices: [
51
+ { value: 'messengers', name: t(lang, 'config.section.messengers') },
52
+ { value: 'agents', name: t(lang, 'config.section.agents') },
53
+ { value: 'acp', name: t(lang, 'config.section.acp') },
54
+ { value: 'smtp', name: t(lang, 'config.section.smtp') },
55
+ { value: 'baidu', name: t(lang, 'config.section.baidu') },
56
+ { value: 'done', name: t(lang, 'config.section.done'), separatorBefore: true },
57
+ ],
58
+ }));
59
+ }
60
+ catch (err) {
61
+ if (err instanceof UserAbortError)
62
+ return;
63
+ throw err;
64
+ }
65
+ if (picked === BACK || picked === 'done')
66
+ break;
67
+ try {
68
+ if (picked === 'messengers')
69
+ config = await sectionMessengers(lang, config);
70
+ else if (picked === 'agents')
71
+ config = await sectionAgents(lang, config);
72
+ else if (picked === 'acp')
73
+ config = await sectionAcp(lang, config);
74
+ else if (picked === 'smtp')
75
+ await sectionSmtp(lang);
76
+ else if (picked === 'baidu')
77
+ await sectionBaidu(lang);
78
+ }
79
+ catch (err) {
80
+ if (err instanceof UserAbortError)
81
+ continue; // Ctrl-C inside a section → bounce back to the top menu
82
+ throw err;
83
+ }
84
+ }
85
+ await saveConfig(config);
86
+ console.log();
87
+ console.log(t(lang, 'config.saved', { file: `${CONFIG_DIR}/config.json` }));
88
+ }
89
+ const MESSENGER_SPECS = [
90
+ { id: 'wechat-ilink', labelKey: 'messengers.label.wechat', hasCreds: false },
91
+ { id: 'telegram', labelKey: 'messengers.label.telegram', hasCreds: true },
92
+ { id: 'feishu', labelKey: 'messengers.label.feishu', hasCreds: true },
93
+ { id: 'dingtalk', labelKey: 'messengers.label.dingtalk', hasCreds: true },
94
+ { id: 'discord', labelKey: 'messengers.label.discord', hasCreds: true },
95
+ { id: 'email', labelKey: 'messengers.label.email', hasCreds: false },
96
+ ];
97
+ /** Return the localized one-line status (enabled / enabled-no-creds /
98
+ * not configured) for a messenger. Used in the top-level list. */
99
+ function messengerStatus(lang, spec, cfg) {
100
+ const enabled = (cfg.messengers || []).includes(spec.id);
101
+ if (!enabled)
102
+ return t(lang, 'messengers.status.disabled');
103
+ if (spec.id === 'telegram' && !cfg.telegram?.botToken) {
104
+ return t(lang, 'messengers.status.enabled_no_creds');
105
+ }
106
+ if (spec.id === 'feishu' && !(cfg.feishu?.appId && cfg.feishu?.appSecret)) {
107
+ return t(lang, 'messengers.status.enabled_no_creds');
108
+ }
109
+ if (spec.id === 'dingtalk' && !(cfg.dingtalk?.clientId && cfg.dingtalk?.clientSecret)) {
110
+ return t(lang, 'messengers.status.enabled_no_creds');
111
+ }
112
+ if (spec.id === 'discord' && !cfg.discord?.botToken) {
113
+ return t(lang, 'messengers.status.enabled_no_creds');
114
+ }
115
+ return t(lang, 'messengers.status.enabled');
116
+ }
117
+ async function sectionMessengers(lang, cfg) {
118
+ let config = cfg;
119
+ while (true) {
120
+ console.log();
121
+ console.log(t(lang, 'messengers.title'));
122
+ console.log(t(lang, 'messengers.subtitle'));
123
+ console.log();
124
+ const choices = MESSENGER_SPECS.map(spec => ({
125
+ value: spec.id,
126
+ name: t(lang, 'messengers.row', {
127
+ label: t(lang, spec.labelKey),
128
+ status: messengerStatus(lang, spec, config),
129
+ }),
130
+ }));
131
+ const picked = await menu({
132
+ lang,
133
+ message: t(lang, 'menu.subtitle'),
134
+ choices,
135
+ back: 'messengers.action.back',
136
+ });
137
+ if (picked === BACK)
138
+ return config;
139
+ const spec = MESSENGER_SPECS.find(s => s.id === picked);
140
+ config = await messengerSubMenu(lang, config, spec);
141
+ }
142
+ }
143
+ /** Per-messenger sub-menu: shows current state, lets user configure,
144
+ * re-configure, or remove (and for email just enable/disable). All
145
+ * paths land back here so user can keep editing; ← Back returns to the
146
+ * list above. */
147
+ async function messengerSubMenu(lang, cfg, spec) {
148
+ let config = cfg;
149
+ while (true) {
150
+ const enabled = (config.messengers || []).includes(spec.id);
151
+ console.log();
152
+ console.log(t(lang, spec.labelKey) + ' — ' + messengerStatus(lang, spec, config));
153
+ console.log();
154
+ const choices = [];
155
+ if (spec.id === 'email') {
156
+ // Email is just a toggle — SMTP creds live in env file, not config.
157
+ if (!enabled) {
158
+ choices.push({ value: 'enable_email', name: t(lang, 'messengers.action.enable_email') });
159
+ }
160
+ else {
161
+ choices.push({ value: 'disable_email', name: t(lang, 'messengers.action.disable_email') });
162
+ }
163
+ }
164
+ else if (spec.id === 'wechat-ilink') {
165
+ // WeChat: configure = scan QR.
166
+ choices.push({
167
+ value: 'configure',
168
+ name: enabled
169
+ ? t(lang, 'messengers.action.reconfigure')
170
+ : t(lang, 'messengers.action.configure'),
171
+ });
172
+ if (enabled) {
173
+ choices.push({ value: 'remove', name: t(lang, 'messengers.action.remove') });
174
+ }
175
+ }
176
+ else {
177
+ // Telegram / Feishu / Discord — prompt for credentials.
178
+ choices.push({
179
+ value: 'configure',
180
+ name: enabled
181
+ ? t(lang, 'messengers.action.reconfigure')
182
+ : t(lang, 'messengers.action.configure'),
183
+ });
184
+ if (enabled) {
185
+ choices.push({ value: 'remove', name: t(lang, 'messengers.action.remove') });
186
+ }
187
+ }
188
+ const action = await menu({
189
+ lang,
190
+ message: t(lang, 'menu.subtitle'),
191
+ choices,
192
+ back: 'messengers.action.back',
193
+ });
194
+ if (action === BACK)
195
+ return config;
196
+ try {
197
+ if (action === 'enable_email' || action === 'disable_email') {
198
+ config = toggleEmail(config, action === 'enable_email');
199
+ if (action === 'enable_email') {
200
+ console.log(t(lang, 'messengers.smtp_hint'));
201
+ console.log(t(lang, 'messengers.enabled', { label: t(lang, spec.labelKey) }));
202
+ }
203
+ else {
204
+ console.log(t(lang, 'messengers.removed', { label: t(lang, spec.labelKey) }));
205
+ }
206
+ }
207
+ else if (action === 'remove') {
208
+ config = removeMessenger(config, spec.id);
209
+ console.log(t(lang, 'messengers.removed', { label: t(lang, spec.labelKey) }));
210
+ }
211
+ else if (action === 'configure') {
212
+ if (spec.id === 'wechat-ilink')
213
+ config = await configureWechat(lang, config);
214
+ else if (spec.id === 'telegram')
215
+ config = await configureTelegram(lang, config);
216
+ else if (spec.id === 'feishu')
217
+ config = await configureFeishu(lang, config);
218
+ else if (spec.id === 'dingtalk')
219
+ config = await configureDingtalk(lang, config);
220
+ else if (spec.id === 'discord')
221
+ config = await configureDiscord(lang, config);
222
+ }
223
+ }
224
+ catch (err) {
225
+ if (err instanceof UserAbortError)
226
+ continue; // Ctrl-C inside a sub-flow → bounce back to this menu
227
+ throw err;
228
+ }
229
+ }
230
+ }
231
+ function removeMessenger(cfg, id) {
232
+ const messengers = (cfg.messengers || []).filter(m => m !== id);
233
+ const next = { ...cfg, messengers };
234
+ if (id === 'telegram')
235
+ delete next.telegram;
236
+ if (id === 'feishu')
237
+ delete next.feishu;
238
+ if (id === 'dingtalk')
239
+ delete next.dingtalk;
240
+ if (id === 'discord')
241
+ delete next.discord;
242
+ return next;
243
+ }
244
+ function toggleEmail(cfg, enable) {
245
+ const current = new Set(cfg.messengers || []);
246
+ if (enable)
247
+ current.add('email');
248
+ else
249
+ current.delete('email');
250
+ return { ...cfg, messengers: Array.from(current) };
251
+ }
252
+ async function configureWechat(lang, cfg) {
253
+ console.log(t(lang, 'wechat.fetching'));
254
+ const { ILinkWeChatAdapter } = await import('../plugins/messengers/wechat/ilink-adapter.js');
255
+ const adapter = new ILinkWeChatAdapter();
256
+ try {
257
+ const { qrUrl, qrToken } = await adapter.startQRLogin();
258
+ console.log();
259
+ console.log(t(lang, 'wechat.scan'));
260
+ console.log(qrUrl);
261
+ console.log();
262
+ console.log(t(lang, 'wechat.waiting'));
263
+ const credentials = await adapter.waitForQRLogin(qrToken, (status) => {
264
+ console.log(`[${new Date().toLocaleTimeString()}] ${status}`);
265
+ });
266
+ if (!credentials) {
267
+ console.log(t(lang, 'wechat.failed'));
268
+ return cfg;
269
+ }
270
+ console.log(t(lang, 'wechat.logged_in', { user: credentials.userId ?? '', bot: credentials.accountId ?? '' }));
271
+ const messengers = new Set(cfg.messengers || []);
272
+ messengers.add('wechat-ilink');
273
+ return { ...cfg, messengers: Array.from(messengers) };
274
+ }
275
+ catch (err) {
276
+ const msg = err instanceof Error ? err.message : String(err);
277
+ console.log(`❌ ${msg}`);
278
+ return cfg;
279
+ }
280
+ }
281
+ /** Mask a secret so we can show "(current: ...XYZ)" without leaking the
282
+ * whole token. Keeps the last 4 chars; pads with • for the prefix so the
283
+ * visible chunk looks roughly the right shape. */
284
+ function maskSecret(s) {
285
+ if (!s)
286
+ return '(empty)';
287
+ if (s.length <= 6)
288
+ return '•'.repeat(s.length);
289
+ return '•'.repeat(Math.min(8, s.length - 4)) + s.slice(-4);
290
+ }
291
+ async function configureTelegram(lang, cfg) {
292
+ console.log();
293
+ console.log(t(lang, 'tg.docs'));
294
+ console.log();
295
+ const current = cfg.telegram;
296
+ const tokenLabel = current?.botToken
297
+ ? t(lang, 'tg.field.token_keep', { hint: maskSecret(current.botToken) })
298
+ : t(lang, 'tg.field.token');
299
+ const tokenIn = await inputSecret({
300
+ message: tokenLabel,
301
+ required: !current?.botToken,
302
+ });
303
+ const token = tokenIn || current?.botToken || '';
304
+ const channelId = await inputText({
305
+ message: t(lang, 'tg.field.channel'),
306
+ default: current?.channelId ?? 'default',
307
+ });
308
+ const messengers = new Set(cfg.messengers || []);
309
+ messengers.add('telegram');
310
+ return {
311
+ ...cfg,
312
+ messengers: Array.from(messengers),
313
+ telegram: { botToken: token, channelId: channelId || 'default' },
314
+ };
315
+ }
316
+ async function configureFeishu(lang, cfg) {
317
+ console.log();
318
+ console.log(t(lang, 'feishu.docs'));
319
+ console.log();
320
+ const current = cfg.feishu;
321
+ const appId = await inputText({
322
+ message: t(lang, 'feishu.field.app_id'),
323
+ default: current?.appId,
324
+ required: true,
325
+ });
326
+ const secretLabel = current?.appSecret
327
+ ? t(lang, 'feishu.field.app_secret_keep')
328
+ : t(lang, 'feishu.field.app_secret');
329
+ const secretIn = await inputSecret({
330
+ message: secretLabel,
331
+ required: !current?.appSecret,
332
+ });
333
+ const appSecret = secretIn || current?.appSecret || '';
334
+ const messengers = new Set(cfg.messengers || []);
335
+ messengers.add('feishu');
336
+ return {
337
+ ...cfg,
338
+ messengers: Array.from(messengers),
339
+ feishu: { appId, appSecret, channelId: current?.channelId },
340
+ };
341
+ }
342
+ async function configureDingtalk(lang, cfg) {
343
+ console.log();
344
+ console.log(t(lang, 'dingtalk.docs'));
345
+ console.log();
346
+ const current = cfg.dingtalk;
347
+ const clientId = await inputText({
348
+ message: t(lang, 'dingtalk.field.client_id'),
349
+ default: current?.clientId,
350
+ required: true,
351
+ });
352
+ const secretLabel = current?.clientSecret
353
+ ? t(lang, 'dingtalk.field.client_secret_keep')
354
+ : t(lang, 'dingtalk.field.client_secret');
355
+ const secretIn = await inputSecret({
356
+ message: secretLabel,
357
+ required: !current?.clientSecret,
358
+ });
359
+ const clientSecret = secretIn || current?.clientSecret || '';
360
+ const messengers = new Set(cfg.messengers || []);
361
+ messengers.add('dingtalk');
362
+ return {
363
+ ...cfg,
364
+ messengers: Array.from(messengers),
365
+ dingtalk: { clientId, clientSecret, channelId: current?.channelId },
366
+ };
367
+ }
368
+ async function configureDiscord(lang, cfg) {
369
+ console.log();
370
+ console.log(t(lang, 'discord.docs'));
371
+ console.log();
372
+ const current = cfg.discord;
373
+ const tokenLabel = current?.botToken
374
+ ? t(lang, 'discord.field.token_keep')
375
+ : t(lang, 'discord.field.token');
376
+ const tokenIn = await inputSecret({
377
+ message: tokenLabel,
378
+ required: !current?.botToken,
379
+ });
380
+ const token = tokenIn || current?.botToken || '';
381
+ const channelId = await inputText({
382
+ message: t(lang, 'discord.field.channel'),
383
+ default: current?.channelId ?? 'default',
384
+ });
385
+ const guildsRaw = await inputText({
386
+ message: t(lang, 'discord.field.guilds'),
387
+ default: (current?.allowedGuilds ?? []).join(','),
388
+ });
389
+ const channelsRaw = await inputText({
390
+ message: t(lang, 'discord.field.channels'),
391
+ default: (current?.allowedChannels ?? []).join(','),
392
+ });
393
+ const messengers = new Set(cfg.messengers || []);
394
+ messengers.add('discord');
395
+ return {
396
+ ...cfg,
397
+ messengers: Array.from(messengers),
398
+ discord: {
399
+ botToken: token,
400
+ channelId: channelId || 'default',
401
+ allowedGuilds: guildsRaw ? guildsRaw.split(',').map(s => s.trim()).filter(Boolean) : undefined,
402
+ allowedChannels: channelsRaw ? channelsRaw.split(',').map(s => s.trim()).filter(Boolean) : undefined,
403
+ },
404
+ };
405
+ }
406
+ const AGENT_SPECS = [
407
+ { id: 'claude-code', cmd: 'claude' },
408
+ { id: 'opencode', cmd: 'opencode', authHintKey: 'agents.auth_hint.opencode' },
409
+ { id: 'codex', cmd: 'codex', authHintKey: 'agents.auth_hint.codex' },
410
+ { id: 'copilot', cmd: 'copilot' },
411
+ ];
412
+ /** Detect install state once per sectionAgents() call, but always
413
+ * re-detect after the user picks "Re-check". */
414
+ async function detectAgentInstalls() {
415
+ const out = new Map();
416
+ await Promise.all(AGENT_SPECS.map(async (spec) => {
417
+ if (spec.id === 'copilot') {
418
+ // Copilot has multiple install paths; use the plugin's own check
419
+ // which knows about VSCode extension / gh-copilot extension / etc.
420
+ try {
421
+ const { copilotAdapter } = await import('../plugins/agents/copilot/index.js');
422
+ out.set(spec.id, await copilotAdapter.isAvailable());
423
+ }
424
+ catch {
425
+ out.set(spec.id, false);
426
+ }
427
+ }
428
+ else {
429
+ out.set(spec.id, await cliAvailable(spec.cmd));
430
+ }
431
+ }));
432
+ return out;
433
+ }
434
+ function agentStatus(lang, id, enabled, installed) {
435
+ if (enabled && installed)
436
+ return t(lang, 'agents.status.enabled_installed');
437
+ if (enabled && !installed)
438
+ return t(lang, 'agents.status.enabled_missing');
439
+ if (!enabled && installed)
440
+ return t(lang, 'agents.status.disabled_installed');
441
+ return t(lang, 'agents.status.disabled_missing');
442
+ }
443
+ async function sectionAgents(lang, cfg) {
444
+ let config = cfg;
445
+ let installs = await detectAgentInstalls();
446
+ while (true) {
447
+ // Effective enabled list: union of cfg.agents + cfg.defaultAgent.
448
+ // Historical configs can drift into `agents: []` + a non-empty
449
+ // `defaultAgent` from the legacy `config <agent>` flow.
450
+ const validIds = new Set(AGENT_SPECS.map(s => s.id));
451
+ const effective = new Set([
452
+ ...((config.agents || []).filter(a => validIds.has(a))),
453
+ ...(config.defaultAgent && validIds.has(config.defaultAgent) ? [config.defaultAgent] : []),
454
+ ]);
455
+ console.log();
456
+ console.log(t(lang, 'agents.title'));
457
+ console.log(t(lang, 'agents.subtitle'));
458
+ console.log();
459
+ const choices = [];
460
+ for (const spec of AGENT_SPECS) {
461
+ const enabled = effective.has(spec.id);
462
+ const installed = installs.get(spec.id) ?? false;
463
+ choices.push({
464
+ value: spec.id,
465
+ name: t(lang, 'agents.row', {
466
+ label: t(lang, ('agents.label.' + spec.id)),
467
+ status: agentStatus(lang, spec.id, enabled, installed),
468
+ }),
469
+ });
470
+ }
471
+ if (effective.size > 0) {
472
+ choices.push({
473
+ value: '__set_default__',
474
+ name: t(lang, 'agents.set_default_action'),
475
+ separatorBefore: true,
476
+ });
477
+ }
478
+ choices.push({
479
+ value: '__recheck__',
480
+ name: t(lang, 'agents.action.recheck'),
481
+ separatorBefore: effective.size === 0,
482
+ });
483
+ const picked = await menu({
484
+ lang,
485
+ message: t(lang, 'menu.subtitle'),
486
+ choices,
487
+ back: 'agents.action.back',
488
+ });
489
+ if (picked === BACK)
490
+ return config;
491
+ if (picked === '__recheck__') {
492
+ installs = await detectAgentInstalls();
493
+ console.log('🔄 Re-checked all agents.');
494
+ continue;
495
+ }
496
+ if (picked === '__set_default__') {
497
+ const enabledIds = Array.from(effective);
498
+ const def = await menu({
499
+ lang,
500
+ message: t(lang, 'agents.default_picker'),
501
+ choices: enabledIds.map(id => ({
502
+ value: id,
503
+ name: t(lang, ('agents.label.' + id)),
504
+ })),
505
+ default: enabledIds.includes(config.defaultAgent) ? config.defaultAgent : enabledIds[0],
506
+ back: 'agents.action.back',
507
+ });
508
+ if (def === BACK)
509
+ continue;
510
+ // Also ensure the picked default is in agents[] (it must be for
511
+ // routing to work).
512
+ const agents = new Set(config.agents || []);
513
+ agents.add(def);
514
+ config = { ...config, agents: Array.from(agents), defaultAgent: def };
515
+ console.log(t(lang, 'agents.default_set', { label: t(lang, ('agents.label.' + def)) }));
516
+ continue;
517
+ }
518
+ const spec = AGENT_SPECS.find(s => s.id === picked);
519
+ try {
520
+ config = await agentSubMenu(lang, config, spec, installs, effective.has(spec.id));
521
+ }
522
+ catch (err) {
523
+ if (err instanceof UserAbortError)
524
+ continue;
525
+ throw err;
526
+ }
527
+ }
528
+ }
529
+ async function agentSubMenu(lang, cfg, spec, installs, enabled) {
530
+ let config = cfg;
531
+ let isEnabled = enabled;
532
+ while (true) {
533
+ const installed = installs.get(spec.id) ?? false;
534
+ const label = t(lang, ('agents.label.' + spec.id));
535
+ console.log();
536
+ console.log(label + ' — ' + agentStatus(lang, spec.id, isEnabled, installed));
537
+ console.log(installed
538
+ ? t(lang, 'agents.installed_msg', { label })
539
+ : t(lang, 'agents.missing_msg', { label }));
540
+ if (spec.authHintKey)
541
+ console.log(t(lang, spec.authHintKey));
542
+ console.log();
543
+ const choices = [];
544
+ if (!isEnabled) {
545
+ choices.push({ value: 'enable', name: t(lang, 'agents.action.enable') });
546
+ }
547
+ else {
548
+ choices.push({ value: 'set_default', name: t(lang, 'agents.action.set_default') });
549
+ choices.push({ value: 'disable', name: t(lang, 'agents.action.disable') });
550
+ }
551
+ choices.push({ value: 'install_hint', name: t(lang, 'agents.action.install_hint') });
552
+ choices.push({ value: 'recheck', name: t(lang, 'agents.action.recheck') });
553
+ const action = await menu({
554
+ lang,
555
+ message: t(lang, 'menu.subtitle'),
556
+ choices,
557
+ back: 'agents.action.back',
558
+ });
559
+ if (action === BACK)
560
+ return config;
561
+ if (action === 'enable') {
562
+ const agents = new Set(config.agents || []);
563
+ agents.add(spec.id);
564
+ // If there's no default yet, this agent becomes the default.
565
+ const alsoDefault = !config.defaultAgent;
566
+ const next = {
567
+ ...config,
568
+ agents: Array.from(agents),
569
+ defaultAgent: alsoDefault ? spec.id : config.defaultAgent,
570
+ };
571
+ config = next;
572
+ isEnabled = true;
573
+ console.log(t(lang, 'agents.enabled', {
574
+ label,
575
+ also_default: alsoDefault ? t(lang, 'agents.also_default') : '',
576
+ }));
577
+ }
578
+ else if (action === 'disable') {
579
+ const agents = (config.agents || []).filter(a => a !== spec.id);
580
+ let defaultAgent = config.defaultAgent;
581
+ if (defaultAgent === spec.id) {
582
+ // Promote the next enabled agent (or empty).
583
+ defaultAgent = agents[0] ?? '';
584
+ }
585
+ config = { ...config, agents, defaultAgent };
586
+ isEnabled = false;
587
+ console.log(t(lang, 'agents.removed', { label }));
588
+ }
589
+ else if (action === 'set_default') {
590
+ const agents = new Set(config.agents || []);
591
+ agents.add(spec.id);
592
+ config = { ...config, agents: Array.from(agents), defaultAgent: spec.id };
593
+ console.log(t(lang, 'agents.default_set', { label }));
594
+ }
595
+ else if (action === 'install_hint') {
596
+ console.log();
597
+ console.log(t(lang, ('agents.install_hint.' + spec.id)));
598
+ if (spec.authHintKey)
599
+ console.log(t(lang, spec.authHintKey));
600
+ console.log();
601
+ }
602
+ else if (action === 'recheck') {
603
+ const newInstalls = await detectAgentInstalls();
604
+ installs.set(spec.id, newInstalls.get(spec.id) ?? false);
605
+ console.log('🔄 Re-checked.');
606
+ }
607
+ }
608
+ }
609
+ // ─── ACP section ───────────────────────────────────────────────────────
610
+ async function sectionAcp(lang, cfg) {
611
+ let agents = [...(cfg.acpAgents ?? [])];
612
+ while (true) {
613
+ const choices = [];
614
+ choices.push({ value: '__add__', name: t(lang, 'acp.action.add') });
615
+ for (const a of agents) {
616
+ choices.push({ value: `edit:${a.name}`, name: t(lang, 'acp.action.edit', { name: a.name }) });
617
+ choices.push({ value: `remove:${a.name}`, name: t(lang, 'acp.action.remove', { name: a.name }) });
618
+ }
619
+ const picked = (await menu({
620
+ lang,
621
+ message: t(lang, 'acp.subtitle'),
622
+ choices,
623
+ back: 'acp.action.back',
624
+ }));
625
+ if (picked === BACK)
626
+ break;
627
+ if (picked === '__add__') {
628
+ const a = await promptAcpAgent(lang);
629
+ if (a)
630
+ agents.push(a);
631
+ }
632
+ else if (picked.startsWith('remove:')) {
633
+ const name = picked.slice('remove:'.length);
634
+ agents = agents.filter(x => x.name !== name);
635
+ console.log(t(lang, 'acp.removed', { name }));
636
+ }
637
+ else if (picked.startsWith('edit:')) {
638
+ const name = picked.slice('edit:'.length);
639
+ const idx = agents.findIndex(x => x.name === name);
640
+ if (idx >= 0) {
641
+ const updated = await promptAcpAgent(lang, agents[idx]);
642
+ if (updated)
643
+ agents[idx] = updated;
644
+ }
645
+ }
646
+ }
647
+ return { ...cfg, acpAgents: agents };
648
+ }
649
+ async function promptAcpAgent(lang, existing) {
650
+ const name = await inputText({
651
+ message: t(lang, 'acp.field.name'),
652
+ default: existing?.name,
653
+ required: true,
654
+ });
655
+ const endpoint = await inputText({
656
+ message: t(lang, 'acp.field.endpoint'),
657
+ default: existing?.endpoint,
658
+ required: true,
659
+ validate: v => /^https?:\/\//.test(v) || 'must start with http:// or https://',
660
+ });
661
+ const authType = (await menu({
662
+ lang,
663
+ message: t(lang, 'acp.field.auth_type'),
664
+ choices: [
665
+ { value: 'none', name: t(lang, 'acp.auth.none') },
666
+ { value: 'bearer', name: t(lang, 'acp.auth.bearer') },
667
+ ],
668
+ default: (existing?.auth?.type === 'bearer' ? 'bearer' : 'none'),
669
+ }));
670
+ let token;
671
+ if (authType === 'bearer') {
672
+ token = await inputSecret({
673
+ message: t(lang, 'acp.field.auth_token'),
674
+ required: true,
675
+ });
676
+ }
677
+ console.log(t(lang, 'acp.added', { name }));
678
+ return {
679
+ name,
680
+ endpoint,
681
+ auth: authType === 'none' ? { type: 'none' } : { type: 'bearer', token },
682
+ enabled: true,
683
+ };
684
+ }
685
+ const SMTP_PRESETS = [
686
+ { id: 'gmail', host: 'smtp.gmail.com', port: 465, secure: 'true' },
687
+ { id: 'outlook', host: 'smtp.office365.com', port: 587, secure: 'false' },
688
+ { id: 'qq', host: 'smtp.qq.com', port: 465, secure: 'true' },
689
+ { id: '163', host: 'smtp.163.com', port: 465, secure: 'true' },
690
+ { id: 'custom' },
691
+ { id: 'skip' },
692
+ ];
693
+ async function sectionSmtp(lang) {
694
+ console.log();
695
+ console.log(t(lang, 'smtp.title'));
696
+ console.log(t(lang, 'smtp.subtitle', { envFile: ENV_FILE }));
697
+ // Use the effective env (env file + process.env fallback) so SMTP keys
698
+ // set via the systemd unit's Environment= lines also show up in the
699
+ // prefill — historical installs put them there directly.
700
+ const current = readEffectiveEnv();
701
+ const hasExisting = Boolean(current.IMHUB_SMTP_HOST && current.IMHUB_SMTP_USER);
702
+ console.log(hasExisting
703
+ ? t(lang, 'smtp.current_set', {
704
+ user: current.IMHUB_SMTP_USER ?? '',
705
+ host: current.IMHUB_SMTP_HOST ?? '',
706
+ port: current.IMHUB_SMTP_PORT ?? '?',
707
+ })
708
+ : t(lang, 'smtp.current_unset'));
709
+ console.log();
710
+ const action = (await menu({
711
+ lang,
712
+ message: t(lang, 'menu.subtitle'),
713
+ choices: [
714
+ { value: 'edit', name: t(lang, 'smtp.action.edit') },
715
+ { value: 'disable', name: t(lang, 'smtp.action.disable'), disabled: !hasExisting },
716
+ ],
717
+ back: 'smtp.action.back',
718
+ }));
719
+ if (action === BACK)
720
+ return;
721
+ if (action === 'disable') {
722
+ for (const k of ['IMHUB_SMTP_HOST', 'IMHUB_SMTP_PORT', 'IMHUB_SMTP_USER', 'IMHUB_SMTP_PASS', 'IMHUB_SMTP_FROM', 'IMHUB_SMTP_SECURE']) {
723
+ unsetEnvKey(k);
724
+ }
725
+ console.log(t(lang, 'smtp.cleared', { file: ENV_FILE }));
726
+ return;
727
+ }
728
+ const presetId = (await menu({
729
+ lang,
730
+ message: t(lang, 'smtp.preset'),
731
+ choices: SMTP_PRESETS.filter(p => p.id !== 'skip').map(p => ({
732
+ value: p.id,
733
+ name: t(lang, `smtp.preset.${p.id}`),
734
+ })),
735
+ back: 'smtp.action.back',
736
+ }));
737
+ if (presetId === BACK)
738
+ return;
739
+ const preset = SMTP_PRESETS.find(p => p.id === presetId);
740
+ // Prefill priority: existing user value first, then preset default.
741
+ // Picking a known preset (gmail/qq/etc) while already-configured shouldn't
742
+ // erase the user's working host — they probably picked it just to grab the
743
+ // suggested port/TLS pair.
744
+ const host = await inputText({
745
+ message: t(lang, 'smtp.field.host'),
746
+ default: current.IMHUB_SMTP_HOST ?? preset.host,
747
+ required: true,
748
+ });
749
+ const port = await inputText({
750
+ message: t(lang, 'smtp.field.port'),
751
+ default: String(current.IMHUB_SMTP_PORT ?? preset.port ?? 465),
752
+ required: true,
753
+ validate: v => /^\d+$/.test(v) && Number(v) > 0 && Number(v) < 65536 || '1..65535',
754
+ });
755
+ const user = await inputText({
756
+ message: t(lang, 'smtp.field.user'),
757
+ default: current.IMHUB_SMTP_USER,
758
+ required: true,
759
+ });
760
+ // Password: never prefill literally (leaks via scrollback). Empty input
761
+ // means "keep what's stored". When nothing is stored yet, require it.
762
+ const passInput = await inputSecret({
763
+ message: t(lang, current.IMHUB_SMTP_PASS ? 'smtp.field.pass_keep' : 'smtp.field.pass'),
764
+ required: !current.IMHUB_SMTP_PASS,
765
+ });
766
+ const pass = passInput || current.IMHUB_SMTP_PASS || '';
767
+ const from = await inputText({
768
+ message: t(lang, 'smtp.field.from'),
769
+ default: current.IMHUB_SMTP_FROM || user,
770
+ });
771
+ let secure = preset.secure ?? current.IMHUB_SMTP_SECURE ?? 'auto';
772
+ if (presetId === 'custom') {
773
+ secure = (await menu({
774
+ lang,
775
+ message: t(lang, 'smtp.field.secure'),
776
+ choices: [
777
+ { value: 'auto', name: t(lang, 'smtp.secure.auto') },
778
+ { value: 'true', name: t(lang, 'smtp.secure.true') },
779
+ { value: 'false', name: t(lang, 'smtp.secure.false') },
780
+ ],
781
+ default: secure,
782
+ }));
783
+ }
784
+ updateEnvFile({
785
+ IMHUB_SMTP_HOST: host,
786
+ IMHUB_SMTP_PORT: port,
787
+ IMHUB_SMTP_USER: user,
788
+ IMHUB_SMTP_PASS: pass,
789
+ IMHUB_SMTP_FROM: from,
790
+ IMHUB_SMTP_SECURE: secure,
791
+ });
792
+ console.log(t(lang, 'smtp.saved', { file: ENV_FILE }));
793
+ // Warn if any wizard-managed SMTP key is also set by the running env
794
+ // (most commonly: systemd unit's `Environment=` lines). Writing the
795
+ // env file alone won't change the active value in that case.
796
+ for (const k of ['IMHUB_SMTP_HOST', 'IMHUB_SMTP_PORT', 'IMHUB_SMTP_USER', 'IMHUB_SMTP_PASS', 'IMHUB_SMTP_FROM']) {
797
+ if (hasProcessEnvOverride(k)) {
798
+ console.log(t(lang, 'env.shadowed_warn', { key: k, file: ENV_FILE }));
799
+ break; // one warning is enough; user gets the picture
800
+ }
801
+ }
802
+ }
803
+ // ─── Baidu Maps section ────────────────────────────────────────────────
804
+ async function sectionBaidu(lang) {
805
+ while (true) {
806
+ console.log();
807
+ console.log(t(lang, 'baidu.title'));
808
+ console.log(t(lang, 'baidu.subtitle'));
809
+ console.log(t(lang, 'baidu.howto'));
810
+ console.log();
811
+ // Effective env so a key set via the systemd unit / shell export
812
+ // still shows up here, not just keys written into ~/.im-hub/env.
813
+ const current = readEffectiveEnv().IMHUB_BAIDU_MAP_AK;
814
+ const status = current ? `${current.slice(0, 6)}…${current.slice(-4)} (set)` : '(unset)';
815
+ const action = (await menu({
816
+ lang,
817
+ message: `current: ${status}`,
818
+ choices: [
819
+ { value: 'set', name: t(lang, 'baidu.action.set') },
820
+ { value: 'clear', name: t(lang, 'baidu.action.clear'), disabled: !current },
821
+ ],
822
+ back: 'baidu.action.back',
823
+ }));
824
+ if (action === BACK)
825
+ return;
826
+ if (action === 'clear') {
827
+ unsetEnvKey('IMHUB_BAIDU_MAP_AK');
828
+ console.log(t(lang, 'baidu.cleared'));
829
+ continue;
830
+ }
831
+ const ak = await inputText({
832
+ message: t(lang, 'baidu.input'),
833
+ default: current,
834
+ validate: v => {
835
+ if (!v)
836
+ return 'Required (or pick ← Back)';
837
+ if (v.length < 24 || v.length > 64)
838
+ return 'AK length looks wrong (expected ~32 chars)';
839
+ return true;
840
+ },
841
+ });
842
+ updateEnvFile({ IMHUB_BAIDU_MAP_AK: ak });
843
+ console.log(t(lang, 'baidu.saved', { file: ENV_FILE }));
844
+ if (hasProcessEnvOverride('IMHUB_BAIDU_MAP_AK')) {
845
+ console.log(t(lang, 'env.shadowed_warn', { key: 'IMHUB_BAIDU_MAP_AK', file: ENV_FILE }));
846
+ }
847
+ }
848
+ }
849
+ // Suppress an unused-import warning for yesNo — exposed for future sections.
850
+ void yesNo;
851
+ //# sourceMappingURL=config-wizard.js.map