@xopcai/xopc 0.0.82 → 0.0.84

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 (740) hide show
  1. package/README.md +3 -1
  2. package/README.zh-CN.md +3 -1
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +2 -3
  5. package/dist/extensions/feishu/src/outbound/media-load.js.map +1 -1
  6. package/dist/extensions/feishu/src/schema/config-schema.d.ts +6 -6
  7. package/dist/extensions/telegram/src/config-schema.d.ts +6 -6
  8. package/dist/extensions/telegram/src/plugin.d.ts +1 -1
  9. package/dist/extensions/telegram/src/plugin.js +1 -1
  10. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  11. package/dist/extensions/telegram/xopc.extension.json +1 -1
  12. package/dist/extensions/weixin/src/api/api.js +3 -3
  13. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  14. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  15. package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
  16. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  17. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  18. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  19. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  20. package/dist/extensions/weixin/src/plugin.js +1 -1
  21. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  22. package/dist/gateway/static/root/assets/agents-tR-nNP04.js +222 -0
  23. package/dist/gateway/static/root/assets/{apps-page-pJ27dsqn.js → apps-page-BDw6SP-d.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-DEFd-jj1.js +1 -0
  25. package/dist/gateway/static/root/assets/{channels-status-swr-D1KYmOmi.js → channels-status-swr-DI5FHdGe.js} +1 -1
  26. package/dist/gateway/static/root/assets/{cron-api-Y2wfSJVI.js → cron-api-BSqY8LwW.js} +1 -1
  27. package/dist/gateway/static/root/assets/{cron-page-B97KU_RG.js → cron-page-D7lVDjcR.js} +1 -1
  28. package/dist/gateway/static/root/assets/{dist-CboA_Css.js → dist-CqNMNhJM.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-debug-page-DN_zNmpo.js → extension-debug-page-gf2L0kY_.js} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-page-BUXtOzv5.js → extension-page-CQo2Xsmg.js} +1 -1
  31. package/dist/gateway/static/root/assets/{extension-settings-page-C2dX4KCW.js → extension-settings-page-CZf0WoZg.js} +1 -1
  32. package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +3 -0
  33. package/dist/gateway/static/root/assets/{field-primitives-B9rOLqdm.js → field-primitives-DTtlp-l8.js} +1 -1
  34. package/dist/gateway/static/root/assets/{heartbeat-config-api-DvfiRVrc.js → heartbeat-config-api-B0drdQEJ.js} +1 -1
  35. package/dist/gateway/static/root/assets/{index-DQuaMye9.js → index-0Gt3TG4j.js} +94 -85
  36. package/dist/gateway/static/root/assets/index-BuFldCsB.css +1 -0
  37. package/dist/gateway/static/root/assets/{logs-page-BQuBpHcc.js → logs-page-DMuORLfC.js} +1 -1
  38. package/dist/gateway/static/root/assets/sessions-page-_UO8g6NN.js +1 -0
  39. package/dist/gateway/static/root/assets/{settings-form-section-2Yu-FASs.js → settings-form-section-DkmHkknc.js} +1 -1
  40. package/dist/gateway/static/root/assets/settings-page-Cz8FoW_A.js +3 -0
  41. package/dist/gateway/static/root/assets/skills-page-HrUOxF7H.js +2 -0
  42. package/dist/gateway/static/root/assets/{theme-store-DnwYutiX.js → theme-store-D01dJt95.js} +1 -1
  43. package/dist/gateway/static/root/assets/{utils-D2Gn2qod.js → utils-BFwcR6pL.js} +1 -1
  44. package/dist/gateway/static/root/assets/voice-api-key-field-JF8-aqc5.js +1 -0
  45. package/dist/gateway/static/root/index.html +4 -4
  46. package/dist/package.js +1 -1
  47. package/dist/src/agent/agent-instance-gateway.d.ts +50 -0
  48. package/dist/src/agent/agent-instance-gateway.js +1 -0
  49. package/dist/src/agent/agent-manager.d.ts +20 -14
  50. package/dist/src/agent/agent-manager.js +74 -186
  51. package/dist/src/agent/agent-manager.js.map +1 -1
  52. package/dist/src/agent/background-review/coordinator.d.ts +61 -0
  53. package/dist/src/agent/background-review/coordinator.js +120 -0
  54. package/dist/src/agent/background-review/coordinator.js.map +1 -0
  55. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  56. package/dist/src/agent/child-agent-factory.d.ts +14 -0
  57. package/dist/src/agent/child-agent-factory.js +2 -8
  58. package/dist/src/agent/child-agent-factory.js.map +1 -1
  59. package/dist/src/agent/context/workspace-seed.js +3 -3
  60. package/dist/src/agent/embedded/index.d.ts +1 -2
  61. package/dist/src/agent/embedded/index.js +2 -3
  62. package/dist/src/agent/embedded/run-for-session.d.ts +2 -2
  63. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  64. package/dist/src/agent/embedded/runs.d.ts +32 -0
  65. package/dist/src/agent/embedded/runs.js +79 -19
  66. package/dist/src/agent/embedded/runs.js.map +1 -1
  67. package/dist/src/agent/embedded/session-manager-cache.d.ts +14 -0
  68. package/dist/src/agent/embedded/session-manager-cache.js +32 -11
  69. package/dist/src/agent/embedded/session-manager-cache.js.map +1 -1
  70. package/dist/src/agent/embedded/session-runner.d.ts +37 -7
  71. package/dist/src/agent/embedded/session-runner.js +184 -153
  72. package/dist/src/agent/embedded/session-runner.js.map +1 -1
  73. package/dist/src/agent/embedded/session-tool-result-guard.d.ts +57 -9
  74. package/dist/src/agent/embedded/session-tool-result-guard.js +159 -67
  75. package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
  76. package/dist/src/agent/goals/goal-run-store.js +4 -4
  77. package/dist/src/agent/goals/persistent-goal-service.d.ts +84 -0
  78. package/dist/src/agent/goals/persistent-goal-service.js +139 -0
  79. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -0
  80. package/dist/src/agent/goals/post-turn.js +2 -2
  81. package/dist/src/agent/goals/state.d.ts +1 -1
  82. package/dist/src/agent/goals/state.js.map +1 -1
  83. package/dist/src/agent/image/load-image-media.js +1 -1
  84. package/dist/src/agent/inbound/inbound-loop.d.ts +77 -0
  85. package/dist/src/agent/inbound/inbound-loop.js +226 -0
  86. package/dist/src/agent/inbound/inbound-loop.js.map +1 -0
  87. package/dist/src/agent/inbound/turn-dispatcher.d.ts +80 -0
  88. package/dist/src/agent/inbound/turn-dispatcher.js +138 -0
  89. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -0
  90. package/dist/src/agent/ipc/bus.js +1 -1
  91. package/dist/src/agent/ipc/inbox.js +2 -2
  92. package/dist/src/agent/ipc/socket.js +1 -1
  93. package/dist/src/agent/lifecycle/handlers/compaction.d.ts +1 -1
  94. package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
  95. package/dist/src/agent/lifecycle/manager.d.ts +1 -1
  96. package/dist/src/agent/lifecycle/manager.js.map +1 -1
  97. package/dist/src/agent/lifecycle/types.d.ts +1 -1
  98. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  99. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  100. package/dist/src/agent/memory/dreaming/events.js +1 -1
  101. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  102. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  103. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  104. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  105. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  106. package/dist/src/agent/memory/dreaming/utils.d.ts +12 -2
  107. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  108. package/dist/src/agent/memory/dreaming/utils.js.map +1 -1
  109. package/dist/src/agent/memory/index.js +3 -3
  110. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  111. package/dist/src/agent/memory/prefetch-coordinator.d.ts +37 -0
  112. package/dist/src/agent/memory/prefetch-coordinator.js +45 -0
  113. package/dist/src/agent/memory/prefetch-coordinator.js.map +1 -0
  114. package/dist/src/agent/messaging/command-handler.d.ts +5 -1
  115. package/dist/src/agent/messaging/command-handler.js +24 -96
  116. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  117. package/dist/src/agent/messaging/index.d.ts +1 -0
  118. package/dist/src/agent/messaging/index.js +2 -1
  119. package/dist/src/agent/messaging/message-router.d.ts +1 -1
  120. package/dist/src/agent/messaging/message-router.js.map +1 -1
  121. package/dist/src/agent/messaging/outbound-coordinator.d.ts +82 -0
  122. package/dist/src/agent/messaging/outbound-coordinator.js +123 -0
  123. package/dist/src/agent/messaging/outbound-coordinator.js.map +1 -0
  124. package/dist/src/agent/models/manager.js +1 -1
  125. package/dist/src/agent/orchestration/agent-event-handler.d.ts +36 -33
  126. package/dist/src/agent/orchestration/agent-event-handler.js +212 -174
  127. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  128. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +4 -4
  129. package/dist/src/agent/orchestration/agent-orchestrator.js +4 -8
  130. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  131. package/dist/src/agent/orchestration/index.d.ts +1 -1
  132. package/dist/src/agent/orchestration/index.js +2 -2
  133. package/dist/src/agent/prompt/service-prompt-builder.js +4 -4
  134. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  135. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  136. package/dist/src/agent/sandbox/path-policy.js +1 -1
  137. package/dist/src/agent/service/async-queue.d.ts +20 -0
  138. package/dist/src/agent/service/async-queue.js +53 -0
  139. package/dist/src/agent/service/async-queue.js.map +1 -0
  140. package/dist/src/agent/service/build-direct-message-content.d.ts +2 -2
  141. package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
  142. package/dist/src/agent/service/direct-turn-helpers.d.ts +70 -0
  143. package/dist/src/agent/service/direct-turn-helpers.js +90 -0
  144. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -0
  145. package/dist/src/agent/service/process-direct-one-shot.d.ts +3 -3
  146. package/dist/src/agent/service/process-direct-one-shot.js +17 -34
  147. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  148. package/dist/src/agent/service/process-direct-streaming.d.ts +2 -2
  149. package/dist/src/agent/service/process-direct-streaming.js +122 -168
  150. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  151. package/dist/src/agent/service/webchat-tts.d.ts +2 -2
  152. package/dist/src/agent/service/webchat-tts.js +1 -1
  153. package/dist/src/agent/service/webchat-tts.js.map +1 -1
  154. package/dist/src/agent/service.d.ts +62 -167
  155. package/dist/src/agent/service.js +177 -786
  156. package/dist/src/agent/service.js.map +1 -1
  157. package/dist/src/agent/session/index.d.ts +4 -0
  158. package/dist/src/agent/session/index.js +5 -1
  159. package/dist/src/agent/session/session-config-service.d.ts +68 -0
  160. package/dist/src/agent/session/session-config-service.js +172 -0
  161. package/dist/src/agent/session/session-config-service.js.map +1 -0
  162. package/dist/src/agent/session/session-context.d.ts +27 -19
  163. package/dist/src/agent/session/session-context.js +39 -24
  164. package/dist/src/agent/session/session-context.js.map +1 -1
  165. package/dist/src/agent/session/session-hydrator.d.ts +42 -0
  166. package/dist/src/agent/session/session-hydrator.js +66 -0
  167. package/dist/src/agent/session/session-hydrator.js.map +1 -0
  168. package/dist/src/agent/session/session-inspector.d.ts +80 -0
  169. package/dist/src/agent/session/session-inspector.js +119 -0
  170. package/dist/src/agent/session/session-inspector.js.map +1 -0
  171. package/dist/src/agent/session/session-state-bag.d.ts +83 -0
  172. package/dist/src/agent/session/session-state-bag.js +192 -0
  173. package/dist/src/agent/session/session-state-bag.js.map +1 -0
  174. package/dist/src/agent/skills/config.js +1 -1
  175. package/dist/src/agent/skills/hub-hash.js +2 -2
  176. package/dist/src/agent/skills/hub-lock.js +1 -1
  177. package/dist/src/agent/skills/hub-pull.js +2 -2
  178. package/dist/src/agent/skills/index.d.ts +0 -2
  179. package/dist/src/agent/skills/index.js +3 -5
  180. package/dist/src/agent/skills/index.js.map +1 -1
  181. package/dist/src/agent/skills/managed-store.js +1 -1
  182. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +11 -6
  183. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js.map +1 -1
  184. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +35 -7
  185. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
  186. package/dist/src/agent/skills/scanner.js +1 -1
  187. package/dist/src/agent/skills/skill-manage-ops.js +2 -2
  188. package/dist/src/agent/skills/skill-manager.js +1 -1
  189. package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +7 -0
  190. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +37 -0
  191. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  192. package/dist/src/agent/tools/delegate-tool.d.ts +7 -0
  193. package/dist/src/agent/tools/delegate-tool.js +2 -1
  194. package/dist/src/agent/tools/delegate-tool.js.map +1 -1
  195. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  196. package/dist/src/agent/tools/executor.d.ts +34 -15
  197. package/dist/src/agent/tools/executor.js +44 -79
  198. package/dist/src/agent/tools/executor.js.map +1 -1
  199. package/dist/src/agent/tools/factory.d.ts +6 -0
  200. package/dist/src/agent/tools/factory.js +63 -4
  201. package/dist/src/agent/tools/factory.js.map +1 -1
  202. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  203. package/dist/src/agent/tools/send-media.js +1 -1
  204. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  205. package/dist/src/agent/tools/skills-tools.js +1 -1
  206. package/dist/src/agent/tools/tts-tool.js +1 -1
  207. package/dist/src/agent/tools/write.js +1 -1
  208. package/dist/src/agent/workspace-runtime/registry.d.ts +48 -0
  209. package/dist/src/agent/workspace-runtime/registry.js +59 -0
  210. package/dist/src/agent/workspace-runtime/registry.js.map +1 -0
  211. package/dist/src/auth/credentials.js +3 -3
  212. package/dist/src/auth/profiles/store.js +1 -1
  213. package/dist/src/auth/sync-provider-auth.js +1 -1
  214. package/dist/src/browser/cdp-local-launcher.js +4 -3
  215. package/dist/src/browser/cdp-local-launcher.js.map +1 -1
  216. package/dist/src/browser/index.d.ts +1 -0
  217. package/dist/src/browser/index.js +2 -1
  218. package/dist/src/browser/manager.js +3 -2
  219. package/dist/src/browser/manager.js.map +1 -1
  220. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  221. package/dist/src/browser/providers/browser-use.js +2 -1
  222. package/dist/src/browser/providers/browser-use.js.map +1 -1
  223. package/dist/src/browser/providers/browserbase.js +2 -1
  224. package/dist/src/browser/providers/browserbase.js.map +1 -1
  225. package/dist/src/browser/providers/cloakbrowser.js +7 -6
  226. package/dist/src/browser/providers/cloakbrowser.js.map +1 -1
  227. package/dist/src/browser/providers/playwright-doctor.d.ts +2 -0
  228. package/dist/src/browser/providers/playwright-doctor.js +7 -3
  229. package/dist/src/browser/providers/playwright-doctor.js.map +1 -1
  230. package/dist/src/browser/readiness.d.ts +33 -0
  231. package/dist/src/browser/readiness.js +138 -0
  232. package/dist/src/browser/readiness.js.map +1 -0
  233. package/dist/src/browser/stealth.js +2 -2
  234. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  235. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  236. package/dist/src/channels/channel-domain.d.ts +1 -1
  237. package/dist/src/channels/config-helpers.d.ts +1 -1
  238. package/dist/src/channels/config-helpers.js.map +1 -1
  239. package/dist/src/channels/heartbeat-scheduler.d.ts +40 -0
  240. package/dist/src/channels/heartbeat-scheduler.js +94 -0
  241. package/dist/src/channels/heartbeat-scheduler.js.map +1 -0
  242. package/dist/src/channels/lifecycle-supervisor.d.ts +81 -0
  243. package/dist/src/channels/lifecycle-supervisor.js +263 -0
  244. package/dist/src/channels/lifecycle-supervisor.js.map +1 -0
  245. package/dist/src/channels/manager.d.ts +34 -68
  246. package/dist/src/channels/manager.js +107 -477
  247. package/dist/src/channels/manager.js.map +1 -1
  248. package/dist/src/channels/outbound/deliver.d.ts +1 -1
  249. package/dist/src/channels/outbound/deliver.js.map +1 -1
  250. package/dist/src/channels/outbound/persist-store.js +1 -1
  251. package/dist/src/channels/outbound-sender.d.ts +51 -0
  252. package/dist/src/channels/outbound-sender.js +125 -0
  253. package/dist/src/channels/outbound-sender.js.map +1 -0
  254. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  255. package/dist/src/channels/pairing/pairing-service.d.ts +3 -10
  256. package/dist/src/channels/pairing/pairing-service.js.map +1 -1
  257. package/dist/src/channels/pairing/pairing-store.js +2 -2
  258. package/dist/src/channels/pairing/pairing-types.d.ts +15 -0
  259. package/dist/src/channels/pairing/pairing-types.js +1 -0
  260. package/dist/src/channels/plugin-registry.d.ts +22 -0
  261. package/dist/src/channels/plugin-registry.js +44 -0
  262. package/dist/src/channels/plugin-registry.js.map +1 -0
  263. package/dist/src/channels/plugin-types.d.ts +1 -1
  264. package/dist/src/channels/plugins/types.adapters.d.ts +2 -2
  265. package/dist/src/channels/security-helpers.d.ts +1 -1
  266. package/dist/src/channels/security-helpers.js.map +1 -1
  267. package/dist/src/channels/setup-wizard.d.ts +1 -1
  268. package/dist/src/chat-commands/builtins/config.js +2 -2
  269. package/dist/src/chat-commands/context.js +1 -1
  270. package/dist/src/cli/command-catalog.js +110 -8
  271. package/dist/src/cli/command-catalog.js.map +1 -1
  272. package/dist/src/cli/command-loaders.js +2 -0
  273. package/dist/src/cli/command-loaders.js.map +1 -1
  274. package/dist/src/cli/command-manifest.js +9 -1
  275. package/dist/src/cli/command-manifest.js.map +1 -1
  276. package/dist/src/cli/commands/agent/stream-renderer.js +1 -1
  277. package/dist/src/cli/commands/agent/stream-renderer.js.map +1 -1
  278. package/dist/src/cli/commands/agent.js +4 -4
  279. package/dist/src/cli/commands/agent.js.map +1 -1
  280. package/dist/src/cli/commands/browser-cli-helpers.js +2 -1
  281. package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
  282. package/dist/src/cli/commands/config.js +70 -19
  283. package/dist/src/cli/commands/config.js.map +1 -1
  284. package/dist/src/cli/commands/cron-cli.d.ts +2 -0
  285. package/dist/src/cli/commands/cron-cli.js +15 -0
  286. package/dist/src/cli/commands/cron-cli.js.map +1 -0
  287. package/dist/src/cli/commands/cron.d.ts +4 -1
  288. package/dist/src/cli/commands/cron.js +76 -41
  289. package/dist/src/cli/commands/cron.js.map +1 -1
  290. package/dist/src/cli/commands/doctor/checks/channel-config.js +1 -1
  291. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  292. package/dist/src/cli/commands/doctor/checks/config-health.js +2 -2
  293. package/dist/src/cli/commands/doctor/checks/config-health.js.map +1 -1
  294. package/dist/src/cli/commands/doctor/checks/cron-health.js +1 -1
  295. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
  296. package/dist/src/cli/commands/doctor/checks/gateway-health.js +2 -2
  297. package/dist/src/cli/commands/doctor/checks/gateway-health.js.map +1 -1
  298. package/dist/src/cli/commands/doctor/checks/gateway-service.js +2 -2
  299. package/dist/src/cli/commands/doctor/checks/gateway-service.js.map +1 -1
  300. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  301. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  302. package/dist/src/cli/commands/doctor/checks/state-integrity.js +2 -2
  303. package/dist/src/cli/commands/doctor/checks/state-integrity.js.map +1 -1
  304. package/dist/src/cli/commands/doctor/checks/workspace-status.js +4 -4
  305. package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -1
  306. package/dist/src/cli/commands/extension-dev.js +2 -2
  307. package/dist/src/cli/commands/extension-dev.js.map +1 -1
  308. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  309. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  310. package/dist/src/cli/commands/extension-pack.js +1 -1
  311. package/dist/src/cli/commands/gateway/call.js +1 -1
  312. package/dist/src/cli/commands/gateway/call.js.map +1 -1
  313. package/dist/src/cli/commands/gateway/health.js +1 -1
  314. package/dist/src/cli/commands/gateway/health.js.map +1 -1
  315. package/dist/src/cli/commands/gateway/index.d.ts +1 -1
  316. package/dist/src/cli/commands/gateway/index.js +2 -2
  317. package/dist/src/cli/commands/gateway/lifecycle-core.d.ts +31 -12
  318. package/dist/src/cli/commands/gateway/lifecycle-core.js +167 -116
  319. package/dist/src/cli/commands/gateway/lifecycle-core.js.map +1 -1
  320. package/dist/src/cli/commands/gateway/lifecycle.d.ts +11 -0
  321. package/dist/src/cli/commands/gateway/lifecycle.js +102 -0
  322. package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -0
  323. package/dist/src/cli/commands/gateway/logs.js +1 -1
  324. package/dist/src/cli/commands/gateway/logs.js.map +1 -1
  325. package/dist/src/cli/commands/gateway/probe.js +1 -1
  326. package/dist/src/cli/commands/gateway/probe.js.map +1 -1
  327. package/dist/src/cli/commands/gateway/restart-health.d.ts +12 -0
  328. package/dist/src/cli/commands/gateway/restart-health.js +45 -1
  329. package/dist/src/cli/commands/gateway/restart-health.js.map +1 -1
  330. package/dist/src/cli/commands/gateway/restart.js +3 -3
  331. package/dist/src/cli/commands/gateway/restart.js.map +1 -1
  332. package/dist/src/cli/commands/gateway/run-foreground.d.ts +0 -1
  333. package/dist/src/cli/commands/gateway/run-foreground.js +0 -35
  334. package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
  335. package/dist/src/cli/commands/gateway/service.d.ts +4 -0
  336. package/dist/src/cli/commands/gateway/service.js +18 -3
  337. package/dist/src/cli/commands/gateway/service.js.map +1 -1
  338. package/dist/src/cli/commands/gateway/shared.d.ts +3 -0
  339. package/dist/src/cli/commands/gateway/shared.js +54 -0
  340. package/dist/src/cli/commands/gateway/shared.js.map +1 -0
  341. package/dist/src/cli/commands/gateway/status.js +1 -1
  342. package/dist/src/cli/commands/gateway/status.js.map +1 -1
  343. package/dist/src/cli/commands/gateway/stop.js +2 -2
  344. package/dist/src/cli/commands/gateway/stop.js.map +1 -1
  345. package/dist/src/cli/commands/gateway/subcommands.js +1 -4
  346. package/dist/src/cli/commands/gateway/subcommands.js.map +1 -1
  347. package/dist/src/cli/commands/gateway/token.js +1 -1
  348. package/dist/src/cli/commands/gateway/token.js.map +1 -1
  349. package/dist/src/cli/commands/gateway.js +5 -5
  350. package/dist/src/cli/commands/gateway.js.map +1 -1
  351. package/dist/src/cli/commands/image.js +2 -2
  352. package/dist/src/cli/commands/image.js.map +1 -1
  353. package/dist/src/cli/commands/init.js +31 -4
  354. package/dist/src/cli/commands/init.js.map +1 -1
  355. package/dist/src/cli/commands/models.d.ts +4 -1
  356. package/dist/src/cli/commands/models.js +87 -75
  357. package/dist/src/cli/commands/models.js.map +1 -1
  358. package/dist/src/cli/commands/onboard/gateway.d.ts +0 -8
  359. package/dist/src/cli/commands/onboard/gateway.js +48 -49
  360. package/dist/src/cli/commands/onboard/gateway.js.map +1 -1
  361. package/dist/src/cli/commands/onboard.js +11 -64
  362. package/dist/src/cli/commands/onboard.js.map +1 -1
  363. package/dist/src/cli/commands/profile.d.ts +3 -5
  364. package/dist/src/cli/commands/profile.js +31 -31
  365. package/dist/src/cli/commands/profile.js.map +1 -1
  366. package/dist/src/cli/commands/session/utils.js +1 -1
  367. package/dist/src/cli/commands/session/utils.js.map +1 -1
  368. package/dist/src/cli/commands/setup.js +6 -1
  369. package/dist/src/cli/commands/setup.js.map +1 -1
  370. package/dist/src/cli/commands/skills.js +1 -1
  371. package/dist/src/cli/commands/tailscale.js +1 -1
  372. package/dist/src/cli/commands/tailscale.js.map +1 -1
  373. package/dist/src/cli/context.d.ts +20 -0
  374. package/dist/src/cli/context.js +23 -0
  375. package/dist/src/cli/context.js.map +1 -0
  376. package/dist/src/cli/extension-cli-register.js +3 -3
  377. package/dist/src/cli/gateway-run-argv.js +16 -9
  378. package/dist/src/cli/gateway-run-argv.js.map +1 -1
  379. package/dist/src/cli/gateway-run-fast-path.js +1 -1
  380. package/dist/src/cli/gateway-run-fast-path.js.map +1 -1
  381. package/dist/src/cli/index.d.ts +1 -7
  382. package/dist/src/cli/index.js +4 -6
  383. package/dist/src/cli/index.js.map +1 -1
  384. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  385. package/dist/src/config/commands.flags.d.ts +3 -0
  386. package/dist/src/config/commands.flags.js +11 -0
  387. package/dist/src/config/commands.flags.js.map +1 -0
  388. package/dist/src/config/index.d.ts +1 -0
  389. package/dist/src/config/index.js +6 -5
  390. package/dist/src/config/index.js.map +1 -1
  391. package/dist/src/config/loader.js +2 -2
  392. package/dist/src/config/models-json.js +2 -2
  393. package/dist/src/config/profile.js +2 -2
  394. package/dist/src/config/schema.d.ts +11 -4
  395. package/dist/src/config/schema.js +13 -12
  396. package/dist/src/config/schema.js.map +1 -1
  397. package/dist/src/config/workspace-path-helpers.d.ts +15 -0
  398. package/dist/src/config/workspace-path-helpers.js +14 -0
  399. package/dist/src/config/workspace-path-helpers.js.map +1 -0
  400. package/dist/src/cron/executor.js +4 -4
  401. package/dist/src/cron/executor.js.map +1 -1
  402. package/dist/src/cron/persistence.js +1 -1
  403. package/dist/src/cron/run-log-store.js +1 -1
  404. package/dist/src/daemon/index.d.ts +0 -1
  405. package/dist/src/daemon/index.js +1 -2
  406. package/dist/src/daemon/install-plan.js +3 -2
  407. package/dist/src/daemon/install-plan.js.map +1 -1
  408. package/dist/src/daemon/launchd.js +2 -2
  409. package/dist/src/daemon/systemd.js +2 -2
  410. package/dist/src/daemon/types.d.ts +0 -6
  411. package/dist/src/extensions/api.d.ts +1 -1
  412. package/dist/src/extensions/api.js +2 -2
  413. package/dist/src/extensions/api.js.map +1 -1
  414. package/dist/src/extensions/bundle-mcp.js +1 -1
  415. package/dist/src/extensions/discover-extensions.js +1 -1
  416. package/dist/src/extensions/extension-registry-impl.d.ts +51 -0
  417. package/dist/src/extensions/extension-registry-impl.js +117 -0
  418. package/dist/src/extensions/extension-registry-impl.js.map +1 -0
  419. package/dist/src/extensions/health.js +1 -1
  420. package/dist/src/extensions/index.js +3 -2
  421. package/dist/src/extensions/loader.d.ts +3 -43
  422. package/dist/src/extensions/loader.js +3 -110
  423. package/dist/src/extensions/loader.js.map +1 -1
  424. package/dist/src/extensions/lockfile.js +2 -2
  425. package/dist/src/extensions/sdk/index.js +2 -1
  426. package/dist/src/extensions/sdk/index.js.map +1 -1
  427. package/dist/src/extensions/types/events.d.ts +7 -1
  428. package/dist/src/gateway/agents-admin.js +2 -2
  429. package/dist/src/gateway/file-path-classifier.js +2 -2
  430. package/dist/src/gateway/heartbeat/service.js +1 -1
  431. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  432. package/dist/src/gateway/hono/app.js +5 -53
  433. package/dist/src/gateway/hono/app.js.map +1 -1
  434. package/dist/src/gateway/hono/lib/extension-store.js +1 -1
  435. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  436. package/dist/src/gateway/hono/middleware/auth.d.ts +5 -14
  437. package/dist/src/gateway/hono/middleware/auth.js +89 -126
  438. package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
  439. package/dist/src/gateway/hono/middleware/logger.js +1 -1
  440. package/dist/src/gateway/hono/middleware/logger.js.map +1 -1
  441. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +14 -0
  442. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +62 -0
  443. package/dist/src/gateway/hono/middleware/strict-rate-limit.js.map +1 -0
  444. package/dist/src/gateway/hono/oauth.js +1 -1
  445. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +4 -4
  446. package/dist/src/gateway/hono/routes/auth-registry-extensions.js.map +1 -1
  447. package/dist/src/gateway/hono/routes/browser.d.ts +20 -0
  448. package/dist/src/gateway/hono/routes/browser.js +626 -0
  449. package/dist/src/gateway/hono/routes/browser.js.map +1 -0
  450. package/dist/src/gateway/hono/routes/commands-skills.js +13 -13
  451. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  452. package/dist/src/gateway/hono/routes/config-patch/agents.d.ts +18 -0
  453. package/dist/src/gateway/hono/routes/config-patch/agents.js +418 -0
  454. package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -0
  455. package/dist/src/gateway/hono/routes/config-patch/channels.d.ts +12 -0
  456. package/dist/src/gateway/hono/routes/config-patch/channels.js +186 -0
  457. package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -0
  458. package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +18 -0
  459. package/dist/src/gateway/hono/routes/config-patch/gateway.js +264 -0
  460. package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -0
  461. package/dist/src/gateway/hono/routes/config-patch/index.d.ts +9 -0
  462. package/dist/src/gateway/hono/routes/config-patch/index.js +6 -0
  463. package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +23 -0
  464. package/dist/src/gateway/hono/routes/config-patch/misc.js +139 -0
  465. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -0
  466. package/dist/src/gateway/hono/routes/config-patch/result.d.ts +18 -0
  467. package/dist/src/gateway/hono/routes/config-patch/result.js +13 -0
  468. package/dist/src/gateway/hono/routes/config-patch/result.js.map +1 -0
  469. package/dist/src/gateway/hono/routes/config.js +20 -1764
  470. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  471. package/dist/src/gateway/hono/routes/dreaming.js +2 -3
  472. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  473. package/dist/src/gateway/hono/routes/host-fs.js +1 -1
  474. package/dist/src/gateway/hono/routes/lazy-bundles.js +10 -5
  475. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  476. package/dist/src/gateway/hono/routes/mcp.js +1 -2
  477. package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
  478. package/dist/src/gateway/hono/routes/models.js +1 -1
  479. package/dist/src/gateway/hono/routes/sessions.js +32 -32
  480. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  481. package/dist/src/gateway/hono/routes/shares.js +4 -4
  482. package/dist/src/gateway/hono/routes/shares.js.map +1 -1
  483. package/dist/src/gateway/hono/routes/tunnel.js +1 -1
  484. package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
  485. package/dist/src/gateway/hono/routes/workspace.js +6 -7
  486. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  487. package/dist/src/gateway/hono/sse.js +2 -2
  488. package/dist/src/gateway/index.d.ts +1 -1
  489. package/dist/src/gateway/index.js +4 -2
  490. package/dist/src/gateway/lock.js +3 -3
  491. package/dist/src/gateway/rate-limit/auth-policy.d.ts +34 -0
  492. package/dist/src/gateway/rate-limit/auth-policy.js +49 -0
  493. package/dist/src/gateway/rate-limit/auth-policy.js.map +1 -0
  494. package/dist/src/gateway/rate-limit/buckets.d.ts +63 -0
  495. package/dist/src/gateway/rate-limit/buckets.js +143 -0
  496. package/dist/src/gateway/rate-limit/buckets.js.map +1 -0
  497. package/dist/src/gateway/rate-limit/env-flags.d.ts +13 -0
  498. package/dist/src/gateway/rate-limit/env-flags.js +16 -0
  499. package/dist/src/gateway/rate-limit/env-flags.js.map +1 -0
  500. package/dist/src/gateway/rate-limit/index.d.ts +3 -0
  501. package/dist/src/gateway/rate-limit/index.js +4 -0
  502. package/dist/src/gateway/run-loop.d.ts +1 -1
  503. package/dist/src/gateway/run-loop.js +24 -4
  504. package/dist/src/gateway/run-loop.js.map +1 -1
  505. package/dist/src/gateway/runtime-config.js +2 -1
  506. package/dist/src/gateway/runtime-config.js.map +1 -1
  507. package/dist/src/gateway/security/audit.js +2 -1
  508. package/dist/src/gateway/security/audit.js.map +1 -1
  509. package/dist/src/gateway/security/index.d.ts +0 -1
  510. package/dist/src/gateway/security/index.js +1 -2
  511. package/dist/src/gateway/security/loopback.d.ts +13 -0
  512. package/dist/src/gateway/security/loopback.js +45 -0
  513. package/dist/src/gateway/security/loopback.js.map +1 -0
  514. package/dist/src/gateway/service/agent-runner.d.ts +108 -0
  515. package/dist/src/gateway/service/agent-runner.js +184 -0
  516. package/dist/src/gateway/service/agent-runner.js.map +1 -0
  517. package/dist/src/gateway/service/config-coordinator.d.ts +119 -0
  518. package/dist/src/gateway/service/config-coordinator.js +351 -0
  519. package/dist/src/gateway/service/config-coordinator.js.map +1 -0
  520. package/dist/src/gateway/service/marketplace-service.d.ts +85 -0
  521. package/dist/src/gateway/service/marketplace-service.js +239 -0
  522. package/dist/src/gateway/service/marketplace-service.js.map +1 -0
  523. package/dist/src/gateway/service/run-gateway-agent.js +5 -5
  524. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  525. package/dist/src/gateway/service/sessions-api.d.ts +125 -0
  526. package/dist/src/gateway/service/sessions-api.js +135 -0
  527. package/dist/src/gateway/service/sessions-api.js.map +1 -0
  528. package/dist/src/gateway/service.d.ts +30 -360
  529. package/dist/src/gateway/service.js +122 -904
  530. package/dist/src/gateway/service.js.map +1 -1
  531. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  532. package/dist/src/gateway/workspace-heartbeat-path.js +1 -2
  533. package/dist/src/gateway/workspace-heartbeat-path.js.map +1 -1
  534. package/dist/src/infra/gateway-process-argv.d.ts +4 -0
  535. package/dist/src/infra/gateway-process-argv.js +26 -0
  536. package/dist/src/infra/gateway-process-argv.js.map +1 -0
  537. package/dist/src/infra/gateway-processes.d.ts +5 -0
  538. package/dist/src/infra/gateway-processes.js +65 -0
  539. package/dist/src/infra/gateway-processes.js.map +1 -0
  540. package/dist/src/infra/rate-limit/failure-limiter.d.ts +50 -0
  541. package/dist/src/infra/rate-limit/failure-limiter.js +100 -0
  542. package/dist/src/infra/rate-limit/failure-limiter.js.map +1 -0
  543. package/dist/src/infra/rate-limit/index.d.ts +5 -0
  544. package/dist/src/infra/rate-limit/index.js +3 -0
  545. package/dist/src/infra/rate-limit/keyed-store.d.ts +34 -0
  546. package/dist/src/infra/rate-limit/keyed-store.js +44 -0
  547. package/dist/src/infra/rate-limit/keyed-store.js.map +1 -0
  548. package/dist/src/infra/rate-limit/rate-limiter.d.ts +39 -0
  549. package/dist/src/infra/rate-limit/rate-limiter.js +65 -0
  550. package/dist/src/infra/rate-limit/rate-limiter.js.map +1 -0
  551. package/dist/src/infra/restart.d.ts +21 -0
  552. package/dist/src/infra/restart.js +122 -0
  553. package/dist/src/infra/restart.js.map +1 -0
  554. package/dist/src/infra/update-check.js +1 -1
  555. package/dist/src/infra/update-lock.js +3 -3
  556. package/dist/src/infra/update-runner.js +1 -1
  557. package/dist/src/infra/update-startup.js +2 -2
  558. package/dist/src/infra/write-file-atomic.js +2 -2
  559. package/dist/src/mcp/channel-bridge.d.ts +0 -6
  560. package/dist/src/mcp/channel-bridge.js +1 -5
  561. package/dist/src/mcp/channel-bridge.js.map +1 -1
  562. package/dist/src/media-shared/http/ssrf-guard.js +1 -1
  563. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  564. package/dist/src/providers/index.js +2 -2
  565. package/dist/src/providers/model-registry.js +1 -1
  566. package/dist/src/session/config-store.js +2 -2
  567. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  568. package/dist/src/session/parity/sessions-json-file-read.d.ts +2 -1
  569. package/dist/src/session/parity/sessions-json-file-read.js.map +1 -1
  570. package/dist/src/session/parity/sessions-json-file.js +1 -1
  571. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  572. package/dist/src/session/parity/transcript-paths.js +1 -1
  573. package/dist/src/session/search-index-cache.js +1 -1
  574. package/dist/src/session/search-index.js +1 -1
  575. package/dist/src/session/session-title.js +1 -1
  576. package/dist/src/session/store.js +5 -5
  577. package/dist/src/share/share-rate-limit.d.ts +10 -2
  578. package/dist/src/share/share-rate-limit.js +33 -42
  579. package/dist/src/share/share-rate-limit.js.map +1 -1
  580. package/dist/src/share/share-store.js +3 -3
  581. package/dist/src/tui/backends/embedded-backend.js +16 -12
  582. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  583. package/dist/src/tui/clipboard-image.js +2 -2
  584. package/dist/src/tui/extension-host/load-extensions.js +1 -1
  585. package/dist/src/tui/format-tui-hotkeys.js +1 -1
  586. package/dist/src/tui/theme-manager.js +1 -1
  587. package/dist/src/tui/tui-keybindings-file.js +1 -1
  588. package/dist/src/tui/tui-scoped-models.js +1 -1
  589. package/dist/src/tui/tui-settings.js +1 -1
  590. package/dist/src/tui/tui-skills-autocomplete.js +1 -1
  591. package/dist/src/tui/tui.js +1 -2
  592. package/dist/src/tui/tui.js.map +1 -1
  593. package/dist/src/tui/xopc-tui-keybindings.d.ts +0 -1
  594. package/dist/src/tui/xopc-tui-keybindings.js +1 -2
  595. package/dist/src/tui/xopc-tui-keybindings.js.map +1 -1
  596. package/dist/src/tunnel/frpc-binary.js +2 -2
  597. package/dist/src/tunnel/frpc-config.js +1 -1
  598. package/dist/src/tunnel/frpc-extract.js +1 -1
  599. package/dist/src/tunnel/pairing-rate-limit.d.ts +10 -2
  600. package/dist/src/tunnel/pairing-rate-limit.js +19 -15
  601. package/dist/src/tunnel/pairing-rate-limit.js.map +1 -1
  602. package/dist/src/tunnel/tunnel-rate-limit.d.ts +6 -3
  603. package/dist/src/tunnel/tunnel-rate-limit.js +11 -22
  604. package/dist/src/tunnel/tunnel-rate-limit.js.map +1 -1
  605. package/dist/src/tunnel/tunnel-state.js +1 -1
  606. package/dist/src/utils/logger/audit.js +1 -1
  607. package/dist/src/utils/logger/log-store.js +1 -1
  608. package/dist/src/utils/logger/rotation.js +1 -1
  609. package/dist/src/utils/logger/stats.d.ts +1 -1
  610. package/dist/src/voice/tts/audio.js +1 -1
  611. package/dist/src/voice/tts/factory.js +1 -1
  612. package/dist/src/voice/tts/index.js +2 -2
  613. package/dist/src/voice/tts/merge-config.js +1 -1
  614. package/dist/src/voice/tts/providers/edge-speech.js +1 -1
  615. package/dist/src/voice/tts/service.js +1 -1
  616. package/dist/src/voice/tts/service.js.map +1 -1
  617. package/dist/src/voice/tts/speak-core.js +1 -1
  618. package/package.json +10 -5
  619. package/dist/gateway/static/root/assets/agents-Cqh1ts38.js +0 -222
  620. package/dist/gateway/static/root/assets/channels-settings-wTiWStg9.js +0 -1
  621. package/dist/gateway/static/root/assets/fetch-BAAh_kXG.js +0 -3
  622. package/dist/gateway/static/root/assets/index-C8yHX-AA.css +0 -1
  623. package/dist/gateway/static/root/assets/sessions-page-BeiFm0Ms.js +0 -1
  624. package/dist/gateway/static/root/assets/settings-page-RPAz_Wg_.js +0 -3
  625. package/dist/gateway/static/root/assets/skills-page-Wu4aNWDx.js +0 -2
  626. package/dist/gateway/static/root/assets/voice-api-key-field-BxIGhhEL.js +0 -1
  627. package/dist/src/agent/embedded/session-raw-append-message.d.ts +0 -11
  628. package/dist/src/agent/embedded/session-raw-append-message.js +0 -15
  629. package/dist/src/agent/embedded/session-raw-append-message.js.map +0 -1
  630. package/dist/src/agent/embedded/session-tool-result-guard-wrapper.d.ts +0 -15
  631. package/dist/src/agent/embedded/session-tool-result-guard-wrapper.js +0 -24
  632. package/dist/src/agent/embedded/session-tool-result-guard-wrapper.js.map +0 -1
  633. package/dist/src/agent/embedded/session-tool-result-state.d.ts +0 -17
  634. package/dist/src/agent/embedded/session-tool-result-state.js +0 -26
  635. package/dist/src/agent/embedded/session-tool-result-state.js.map +0 -1
  636. package/dist/src/daemon/launchd-restart-handoff.d.ts +0 -25
  637. package/dist/src/daemon/launchd-restart-handoff.js +0 -132
  638. package/dist/src/daemon/launchd-restart-handoff.js.map +0 -1
  639. package/dist/src/gateway/auth-rate-limit.d.ts +0 -71
  640. package/dist/src/gateway/auth-rate-limit.js +0 -192
  641. package/dist/src/gateway/auth-rate-limit.js.map +0 -1
  642. package/dist/src/gateway/restart-handler.d.ts +0 -14
  643. package/dist/src/gateway/restart-handler.js +0 -64
  644. package/dist/src/gateway/restart-handler.js.map +0 -1
  645. package/dist/src/gateway/security/flood-guard.d.ts +0 -28
  646. package/dist/src/gateway/security/flood-guard.js +0 -42
  647. package/dist/src/gateway/security/flood-guard.js.map +0 -1
  648. package/dist/src/infra/rate-limit.d.ts +0 -38
  649. package/dist/src/infra/rate-limit.js +0 -60
  650. package/dist/src/infra/rate-limit.js.map +0 -1
  651. package/dist/src/infra/restart-intent.d.ts +0 -13
  652. package/dist/src/infra/restart-intent.js +0 -40
  653. package/dist/src/infra/restart-intent.js.map +0 -1
  654. package/dist/src/infra/restart-sentinel.d.ts +0 -23
  655. package/dist/src/infra/restart-sentinel.js +0 -75
  656. package/dist/src/infra/restart-sentinel.js.map +0 -1
  657. package/skills/creative/canvas-design/LICENSE.txt +0 -202
  658. package/skills/creative/canvas-design/SKILL-zh.md +0 -130
  659. package/skills/creative/canvas-design/SKILL.md +0 -130
  660. package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +0 -93
  661. package/skills/creative/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  662. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  663. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-OFL.txt +0 -93
  664. package/skills/creative/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  665. package/skills/creative/canvas-design/canvas-fonts/Boldonse-OFL.txt +0 -93
  666. package/skills/creative/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  667. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  668. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -93
  669. package/skills/creative/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  670. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  671. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  672. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +0 -93
  673. package/skills/creative/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  674. package/skills/creative/canvas-design/canvas-fonts/DMMono-OFL.txt +0 -93
  675. package/skills/creative/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  676. package/skills/creative/canvas-design/canvas-fonts/EricaOne-OFL.txt +0 -94
  677. package/skills/creative/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  678. package/skills/creative/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  679. package/skills/creative/canvas-design/canvas-fonts/GeistMono-OFL.txt +0 -93
  680. package/skills/creative/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  681. package/skills/creative/canvas-design/canvas-fonts/Gloock-OFL.txt +0 -93
  682. package/skills/creative/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  683. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  684. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +0 -93
  685. package/skills/creative/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  686. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  687. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  688. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  689. package/skills/creative/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  690. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  691. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  692. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  693. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -93
  694. package/skills/creative/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  695. package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  696. package/skills/creative/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  697. package/skills/creative/canvas-design/canvas-fonts/Italiana-OFL.txt +0 -93
  698. package/skills/creative/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  699. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  700. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -93
  701. package/skills/creative/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  702. package/skills/creative/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  703. package/skills/creative/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  704. package/skills/creative/canvas-design/canvas-fonts/Jura-OFL.txt +0 -93
  705. package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +0 -93
  706. package/skills/creative/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  707. package/skills/creative/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  708. package/skills/creative/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  709. package/skills/creative/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  710. package/skills/creative/canvas-design/canvas-fonts/Lora-OFL.txt +0 -93
  711. package/skills/creative/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  712. package/skills/creative/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  713. package/skills/creative/canvas-design/canvas-fonts/NationalPark-OFL.txt +0 -93
  714. package/skills/creative/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  715. package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -93
  716. package/skills/creative/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  717. package/skills/creative/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  718. package/skills/creative/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -93
  719. package/skills/creative/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  720. package/skills/creative/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  721. package/skills/creative/canvas-design/canvas-fonts/PixelifySans-OFL.txt +0 -93
  722. package/skills/creative/canvas-design/canvas-fonts/PoiretOne-OFL.txt +0 -93
  723. package/skills/creative/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  724. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  725. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-OFL.txt +0 -93
  726. package/skills/creative/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  727. package/skills/creative/canvas-design/canvas-fonts/Silkscreen-OFL.txt +0 -93
  728. package/skills/creative/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  729. package/skills/creative/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  730. package/skills/creative/canvas-design/canvas-fonts/SmoochSans-OFL.txt +0 -93
  731. package/skills/creative/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  732. package/skills/creative/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -93
  733. package/skills/creative/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  734. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  735. package/skills/creative/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  736. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  737. package/skills/creative/canvas-design/canvas-fonts/WorkSans-OFL.txt +0 -93
  738. package/skills/creative/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  739. package/skills/creative/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -93
  740. package/skills/creative/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
@@ -1,10 +1,13 @@
1
1
  import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
+ import { ConfigSchema, init_schema } from "../../config/schema.js";
2
3
  import { formatExamples, register } from "../registry.js";
3
4
  import { resolveGatewayLocalClientHost } from "../../config/gateway-bind.js";
4
- import { existsSync } from "fs";
5
+ import { existsSync, readFileSync } from "fs";
5
6
  import { Command } from "commander";
6
7
  //#region src/cli/commands/config.ts
7
8
  init_write_file_atomic();
9
+ init_schema();
10
+ const MISSING_CONFIG_HINT = "Run: xopc setup, xopc onboard, or xopc init";
8
11
  async function loadConfigDeps() {
9
12
  const [{ loadConfig }, { createLogger }] = await Promise.all([import("../../config/index.js"), import("../../utils/logger.js")]);
10
13
  return {
@@ -12,6 +15,49 @@ async function loadConfigDeps() {
12
15
  log: createLogger("ConfigCommand")
13
16
  };
14
17
  }
18
+ async function runConfigShow(configPath) {
19
+ const { loadConfig, log } = await loadConfigDeps();
20
+ if (!existsSync(configPath)) {
21
+ log.warn(`No config file found. ${MISSING_CONFIG_HINT}`);
22
+ return;
23
+ }
24
+ const config = loadConfig(configPath);
25
+ const maskedConfig = JSON.stringify(config, (key, value) => {
26
+ if (key === "api_key" || key === "token") return value ? "********" : value;
27
+ return value;
28
+ }, 2);
29
+ console.log(maskedConfig);
30
+ }
31
+ async function runConfigValidate(configPath) {
32
+ const { log } = await loadConfigDeps();
33
+ if (!existsSync(configPath)) {
34
+ log.error("Config file not found. Run: xopc onboard");
35
+ return false;
36
+ }
37
+ let json;
38
+ try {
39
+ json = JSON.parse(readFileSync(configPath, "utf-8"));
40
+ } catch {
41
+ log.error("Config file is not valid JSON.");
42
+ return false;
43
+ }
44
+ const parsed = ConfigSchema.safeParse(json);
45
+ if (!parsed.success) {
46
+ log.error("Config does not match the expected schema.");
47
+ for (const issue of parsed.error.issues) console.error(` - ${issue.path.join(".") || "(root)"}: ${issue.message}`);
48
+ return false;
49
+ }
50
+ const { validateChannelPluginConfigs } = await import("../../config/validate-channel-configs.js");
51
+ const channelErrors = validateChannelPluginConfigs(parsed.data);
52
+ if (channelErrors.length > 0) {
53
+ log.error("Channel configuration failed validation.");
54
+ for (const err of channelErrors) console.error(` - ${err}`);
55
+ return false;
56
+ }
57
+ log.info({ path: configPath }, "Config is valid");
58
+ console.log("✅ Configuration is valid");
59
+ return true;
60
+ }
15
61
  function getNestedValue(obj, path) {
16
62
  return path.split(".").reduce((current, key) => {
17
63
  if (current && typeof current === "object" && key in current) return current[key];
@@ -28,19 +74,30 @@ function setNestedValue(obj, path, value) {
28
74
  return obj;
29
75
  }
30
76
  function createConfigCommand(ctx) {
31
- const cmd = new Command("config").description("View and edit configuration").addHelpText("after", formatExamples([
77
+ const cmd = new Command("config").description("View and edit configuration").option("--show", "Show full configuration (alias for `config show`)").option("--validate", "Validate configuration file (alias for `config validate`)").addHelpText("after", formatExamples([
32
78
  "xopc config get agents.defaults.model",
33
79
  "xopc config set agents.defaults.temperature 0.8",
34
80
  "xopc config unset agents.defaults.max_tokens",
35
81
  "xopc config show",
82
+ "xopc config validate",
36
83
  "xopc config token # Show gateway token info",
37
84
  "xopc config token --show # Show full token",
38
85
  "xopc config token --generate # Generate new token"
39
- ]));
86
+ ])).action(async (options) => {
87
+ if (options.show) {
88
+ await runConfigShow(ctx.configPath);
89
+ return;
90
+ }
91
+ if (options.validate) {
92
+ if (!await runConfigValidate(ctx.configPath)) process.exit(1);
93
+ return;
94
+ }
95
+ cmd.outputHelp();
96
+ });
40
97
  cmd.command("get <path>").description("Get a config value by dot path").action(async (path) => {
41
98
  const { loadConfig, log } = await loadConfigDeps();
42
99
  if (!existsSync(ctx.configPath)) {
43
- log.error("Config file not found. Run: xopc onboard");
100
+ log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
44
101
  process.exit(1);
45
102
  }
46
103
  const value = getNestedValue(loadConfig(ctx.configPath), path);
@@ -53,7 +110,7 @@ function createConfigCommand(ctx) {
53
110
  cmd.command("set <path> <value>").description("Set a config value by dot path").action(async (path, value) => {
54
111
  const { loadConfig, log } = await loadConfigDeps();
55
112
  if (!existsSync(ctx.configPath)) {
56
- log.error("Config file not found. Run: xopc onboard");
113
+ log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
57
114
  process.exit(1);
58
115
  }
59
116
  let parsedValue;
@@ -70,7 +127,7 @@ function createConfigCommand(ctx) {
70
127
  cmd.command("unset <path>").description("Remove a config value by dot path").action(async (path) => {
71
128
  const { loadConfig, log } = await loadConfigDeps();
72
129
  if (!existsSync(ctx.configPath)) {
73
- log.error("Config file not found. Run: xopc onboard");
130
+ log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
74
131
  process.exit(1);
75
132
  }
76
133
  const config = loadConfig(ctx.configPath);
@@ -89,22 +146,15 @@ function createConfigCommand(ctx) {
89
146
  }
90
147
  });
91
148
  cmd.command("show").description("Show full configuration (sensitive values masked)").action(async () => {
92
- const { loadConfig, log } = await loadConfigDeps();
93
- if (!existsSync(ctx.configPath)) {
94
- log.warn("No config file found. Run: xopc onboard");
95
- return;
96
- }
97
- const config = loadConfig(ctx.configPath);
98
- const maskedConfig = JSON.stringify(config, (key, value) => {
99
- if (key === "api_key" || key === "token") return value ? "********" : value;
100
- return value;
101
- }, 2);
102
- console.log(maskedConfig);
149
+ await runConfigShow(ctx.configPath);
150
+ });
151
+ cmd.command("validate").description("Validate configuration file against schema and channel plugins").action(async () => {
152
+ if (!await runConfigValidate(ctx.configPath)) process.exit(1);
103
153
  });
104
154
  cmd.command("token").description("Generate or view the gateway auth token").option("--generate", "Generate a new token").option("--show", "Show the current token (unmasked)").action(async (options) => {
105
155
  const { loadConfig, log } = await loadConfigDeps();
106
156
  if (!existsSync(ctx.configPath)) {
107
- log.error("Config file not found. Run: xopc onboard");
157
+ log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);
108
158
  process.exit(1);
109
159
  }
110
160
  const config = loadConfig(ctx.configPath);
@@ -140,7 +190,7 @@ function createConfigCommand(ctx) {
140
190
  console.log(` Token: ${token.slice(0, 8)}...${token.slice(-8)}`);
141
191
  console.log("\nUse \"xopc config token --show\" to view the full token");
142
192
  console.log("Use \"xopc config token --generate\" to generate a new token");
143
- } else if (mode === "token") console.log(" Token: not set (will be auto-generated on first gateway start)");
193
+ } else if (mode === "token") console.log(" Token: not set (will be auto-generated on first `xopc gateway` run)");
144
194
  });
145
195
  cmd.command("path").description("Show configuration file path").action(() => {
146
196
  console.log(ctx.configPath);
@@ -158,6 +208,7 @@ register({
158
208
  "xopc config get agents.defaults.model",
159
209
  "xopc config set agents.defaults.temperature 0.8",
160
210
  "xopc config show",
211
+ "xopc config validate",
161
212
  "xopc config token",
162
213
  "xopc config token --show",
163
214
  "xopc config token --generate"
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../../src/cli/commands/config.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nasync function loadConfigDeps() {\n const [{ loadConfig }, { createLogger }] = await Promise.all([\n import('../../config/index.js'),\n import('../../utils/logger.js'),\n ]);\n return { loadConfig, log: createLogger('ConfigCommand') };\n}\n\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current: any, key: string) => {\n if (current && typeof current === 'object' && key in current) {\n return current[key];\n }\n return undefined;\n }, obj);\n}\n\nfunction setNestedValue(obj: any, path: string, value: any): any {\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n const target = keys.reduce((current: any, key: string) => {\n if (!current[key] || typeof current[key] !== 'object') {\n current[key] = {};\n }\n return current[key];\n }, obj);\n target[lastKey] = value;\n return obj;\n}\n\nfunction createConfigCommand(ctx: CLIContext): Command {\n const cmd = new Command('config')\n .description('View and edit configuration')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc config get agents.defaults.model',\n 'xopc config set agents.defaults.temperature 0.8',\n 'xopc config unset agents.defaults.max_tokens',\n 'xopc config show',\n 'xopc config token # Show gateway token info',\n 'xopc config token --show # Show full token',\n 'xopc config token --generate # Generate new token',\n ])\n );\n\n cmd\n .command('get <path>')\n .description('Get a config value by dot path')\n .action(async (path: string) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error('Config file not found. Run: xopc onboard');\n process.exit(1);\n }\n\n const config = loadConfig(ctx.configPath);\n const value = getNestedValue(config, path);\n\n if (value === undefined) {\n log.error({ path }, `Config path not found`);\n process.exit(1);\n }\n\n console.log(typeof value === 'object' ? JSON.stringify(value, null, 2) : value);\n });\n\n cmd\n .command('set <path> <value>')\n .description('Set a config value by dot path')\n .action(async (path: string, value: string) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error('Config file not found. Run: xopc onboard');\n process.exit(1);\n }\n\n let parsedValue: any;\n try {\n parsedValue = JSON.parse(value);\n } catch {\n parsedValue = value;\n }\n\n const config = loadConfig(ctx.configPath);\n setNestedValue(config, path, parsedValue);\n\n await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));\n\n log.info({ path }, `Config updated`);\n });\n\n cmd\n .command('unset <path>')\n .description('Remove a config value by dot path')\n .action(async (path: string) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error('Config file not found. Run: xopc onboard');\n process.exit(1);\n }\n\n const config = loadConfig(ctx.configPath);\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n const target = keys.reduce((current: any, key: string) => {\n return current && current[key];\n }, config);\n\n if (target && typeof target === 'object' && lastKey in target) {\n delete target[lastKey];\n await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));\n log.info({ path }, `Config removed`);\n } else {\n log.error({ path }, `Config path not found`);\n process.exit(1);\n }\n });\n\n cmd\n .command('show')\n .description('Show full configuration (sensitive values masked)')\n .action(async () => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.warn('No config file found. Run: xopc onboard');\n return;\n }\n\n const config = loadConfig(ctx.configPath);\n\n const maskedConfig = JSON.stringify(config, (key, value) => {\n if (key === 'api_key' || key === 'token') {\n return value ? '********' : value;\n }\n return value;\n }, 2);\n\n console.log(maskedConfig);\n });\n\n cmd\n .command('token')\n .description('Generate or view the gateway auth token')\n .option('--generate', 'Generate a new token')\n .option('--show', 'Show the current token (unmasked)')\n .action(async (options) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error('Config file not found. Run: xopc onboard');\n process.exit(1);\n }\n\n const config = loadConfig(ctx.configPath);\n\n if (options.show) {\n const token = config?.gateway?.auth?.token;\n if (token) {\n console.log(token);\n } else {\n console.log('No token configured. Gateway auth mode:', config?.gateway?.auth?.mode || 'not set');\n }\n return;\n }\n\n if (options.generate) {\n const crypto = await import('crypto');\n const newToken = crypto.randomBytes(24).toString('hex');\n\n config.gateway = config.gateway || {};\n config.gateway.auth = {\n mode: 'token',\n token: newToken,\n };\n\n await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));\n log.info('New gateway token generated');\n console.log(`Token: ${newToken.slice(0, 8)}...${newToken.slice(-8)}`);\n console.log('\\nUse \"xopc config token --show\" to view the full token');\n return;\n }\n\n // Default: show masked token info\n const token = config?.gateway?.auth?.token;\n const mode = config?.gateway?.auth?.mode;\n const bind = config?.gateway?.bind ?? 'loopback';\n const port = config?.gateway?.port || 18790;\n const clientHost = config ? resolveGatewayLocalClientHost(config) : '127.0.0.1';\n\n console.log('Gateway Configuration:');\n console.log(` Bind: ${bind}`);\n console.log(` Local URL: http://${clientHost}:${port}`);\n console.log(` Auth Mode: ${mode || 'not set'}`);\n if (token) {\n console.log(` Token: ${token.slice(0, 8)}...${token.slice(-8)}`);\n console.log('\\nUse \"xopc config token --show\" to view the full token');\n console.log('Use \"xopc config token --generate\" to generate a new token');\n } else if (mode === 'token') {\n console.log(' Token: not set (will be auto-generated on first gateway start)');\n }\n });\n\n cmd\n .command('path')\n .description('Show configuration file path')\n .action(() => {\n console.log(ctx.configPath);\n });\n\n return cmd;\n}\n\nregister({\n id: 'config',\n name: 'config',\n description: 'View and edit configuration',\n factory: createConfigCommand,\n metadata: {\n category: 'utility',\n examples: [\n 'xopc config get agents.defaults.model',\n 'xopc config set agents.defaults.temperature 0.8',\n 'xopc config show',\n 'xopc config token',\n 'xopc config token --show',\n 'xopc config token --generate',\n ],\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../../src/cli/commands/config.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { existsSync, readFileSync } from 'fs';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { ConfigSchema } from '../../config/schema.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nconst MISSING_CONFIG_HINT = 'Run: xopc setup, xopc onboard, or xopc init';\n\nasync function loadConfigDeps() {\n const [{ loadConfig }, { createLogger }] = await Promise.all([\n import('../../config/index.js'),\n import('../../utils/logger.js'),\n ]);\n return { loadConfig, log: createLogger('ConfigCommand') };\n}\n\nasync function runConfigShow(configPath: string): Promise<void> {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(configPath)) {\n log.warn(`No config file found. ${MISSING_CONFIG_HINT}`);\n return;\n }\n\n const config = loadConfig(configPath);\n const maskedConfig = JSON.stringify(\n config,\n (key, value) => {\n if (key === 'api_key' || key === 'token') {\n return value ? '********' : value;\n }\n return value;\n },\n 2,\n );\n console.log(maskedConfig);\n}\n\nasync function runConfigValidate(configPath: string): Promise<boolean> {\n const { log } = await loadConfigDeps();\n if (!existsSync(configPath)) {\n log.error('Config file not found. Run: xopc onboard');\n return false;\n }\n\n let json: unknown;\n try {\n json = JSON.parse(readFileSync(configPath, 'utf-8'));\n } catch {\n log.error('Config file is not valid JSON.');\n return false;\n }\n\n const parsed = ConfigSchema.safeParse(json);\n if (!parsed.success) {\n log.error('Config does not match the expected schema.');\n for (const issue of parsed.error.issues) {\n console.error(` - ${issue.path.join('.') || '(root)'}: ${issue.message}`);\n }\n return false;\n }\n\n const { validateChannelPluginConfigs } = await import('../../config/validate-channel-configs.js');\n const channelErrors = validateChannelPluginConfigs(parsed.data);\n if (channelErrors.length > 0) {\n log.error('Channel configuration failed validation.');\n for (const err of channelErrors) {\n console.error(` - ${err}`);\n }\n return false;\n }\n\n log.info({ path: configPath }, 'Config is valid');\n console.log('✅ Configuration is valid');\n return true;\n}\n\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current: any, key: string) => {\n if (current && typeof current === 'object' && key in current) {\n return current[key];\n }\n return undefined;\n }, obj);\n}\n\nfunction setNestedValue(obj: any, path: string, value: any): any {\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n const target = keys.reduce((current: any, key: string) => {\n if (!current[key] || typeof current[key] !== 'object') {\n current[key] = {};\n }\n return current[key];\n }, obj);\n target[lastKey] = value;\n return obj;\n}\n\nfunction createConfigCommand(ctx: CLIContext): Command {\n const cmd = new Command('config')\n .description('View and edit configuration')\n .option('--show', 'Show full configuration (alias for `config show`)')\n .option('--validate', 'Validate configuration file (alias for `config validate`)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc config get agents.defaults.model',\n 'xopc config set agents.defaults.temperature 0.8',\n 'xopc config unset agents.defaults.max_tokens',\n 'xopc config show',\n 'xopc config validate',\n 'xopc config token # Show gateway token info',\n 'xopc config token --show # Show full token',\n 'xopc config token --generate # Generate new token',\n ]),\n )\n .action(async (options) => {\n if (options.show) {\n await runConfigShow(ctx.configPath);\n return;\n }\n if (options.validate) {\n const ok = await runConfigValidate(ctx.configPath);\n if (!ok) {\n process.exit(1);\n }\n return;\n }\n cmd.outputHelp();\n });\n\n cmd\n .command('get <path>')\n .description('Get a config value by dot path')\n .action(async (path: string) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);\n process.exit(1);\n }\n\n const config = loadConfig(ctx.configPath);\n const value = getNestedValue(config, path);\n\n if (value === undefined) {\n log.error({ path }, `Config path not found`);\n process.exit(1);\n }\n\n console.log(typeof value === 'object' ? JSON.stringify(value, null, 2) : value);\n });\n\n cmd\n .command('set <path> <value>')\n .description('Set a config value by dot path')\n .action(async (path: string, value: string) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);\n process.exit(1);\n }\n\n let parsedValue: any;\n try {\n parsedValue = JSON.parse(value);\n } catch {\n parsedValue = value;\n }\n\n const config = loadConfig(ctx.configPath);\n setNestedValue(config, path, parsedValue);\n\n await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));\n\n log.info({ path }, `Config updated`);\n });\n\n cmd\n .command('unset <path>')\n .description('Remove a config value by dot path')\n .action(async (path: string) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);\n process.exit(1);\n }\n\n const config = loadConfig(ctx.configPath);\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n const target = keys.reduce((current: any, key: string) => {\n return current && current[key];\n }, config);\n\n if (target && typeof target === 'object' && lastKey in target) {\n delete target[lastKey];\n await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));\n log.info({ path }, `Config removed`);\n } else {\n log.error({ path }, `Config path not found`);\n process.exit(1);\n }\n });\n\n cmd\n .command('show')\n .description('Show full configuration (sensitive values masked)')\n .action(async () => {\n await runConfigShow(ctx.configPath);\n });\n\n cmd\n .command('validate')\n .description('Validate configuration file against schema and channel plugins')\n .action(async () => {\n const ok = await runConfigValidate(ctx.configPath);\n if (!ok) {\n process.exit(1);\n }\n });\n\n cmd\n .command('token')\n .description('Generate or view the gateway auth token')\n .option('--generate', 'Generate a new token')\n .option('--show', 'Show the current token (unmasked)')\n .action(async (options) => {\n const { loadConfig, log } = await loadConfigDeps();\n if (!existsSync(ctx.configPath)) {\n log.error(`Config file not found. ${MISSING_CONFIG_HINT}`);\n process.exit(1);\n }\n\n const config = loadConfig(ctx.configPath);\n\n if (options.show) {\n const token = config?.gateway?.auth?.token;\n if (token) {\n console.log(token);\n } else {\n console.log('No token configured. Gateway auth mode:', config?.gateway?.auth?.mode || 'not set');\n }\n return;\n }\n\n if (options.generate) {\n const crypto = await import('crypto');\n const newToken = crypto.randomBytes(24).toString('hex');\n\n config.gateway = config.gateway || {};\n config.gateway.auth = {\n mode: 'token',\n token: newToken,\n };\n\n await writeTextAtomic(ctx.configPath, JSON.stringify(config, null, 2));\n log.info('New gateway token generated');\n console.log(`Token: ${newToken.slice(0, 8)}...${newToken.slice(-8)}`);\n console.log('\\nUse \"xopc config token --show\" to view the full token');\n return;\n }\n\n // Default: show masked token info\n const token = config?.gateway?.auth?.token;\n const mode = config?.gateway?.auth?.mode;\n const bind = config?.gateway?.bind ?? 'loopback';\n const port = config?.gateway?.port || 18790;\n const clientHost = config ? resolveGatewayLocalClientHost(config) : '127.0.0.1';\n\n console.log('Gateway Configuration:');\n console.log(` Bind: ${bind}`);\n console.log(` Local URL: http://${clientHost}:${port}`);\n console.log(` Auth Mode: ${mode || 'not set'}`);\n if (token) {\n console.log(` Token: ${token.slice(0, 8)}...${token.slice(-8)}`);\n console.log('\\nUse \"xopc config token --show\" to view the full token');\n console.log('Use \"xopc config token --generate\" to generate a new token');\n } else if (mode === 'token') {\n console.log(' Token: not set (will be auto-generated on first `xopc gateway` run)');\n }\n });\n\n cmd\n .command('path')\n .description('Show configuration file path')\n .action(() => {\n console.log(ctx.configPath);\n });\n\n return cmd;\n}\n\nregister({\n id: 'config',\n name: 'config',\n description: 'View and edit configuration',\n factory: createConfigCommand,\n metadata: {\n category: 'utility',\n examples: [\n 'xopc config get agents.defaults.model',\n 'xopc config set agents.defaults.temperature 0.8',\n 'xopc config show',\n 'xopc config validate',\n 'xopc config token',\n 'xopc config token --show',\n 'xopc config token --generate',\n ],\n },\n});\n"],"mappings":";;;;;;;wBAGmE;aACb;AAGtD,MAAM,sBAAsB;AAE5B,eAAe,iBAAiB;CAC9B,MAAM,CAAC,EAAE,cAAc,EAAE,kBAAkB,MAAM,QAAQ,IAAI,CAC3D,OAAO,0BACP,OAAO,yBACR,CAAC;AACF,QAAO;EAAE;EAAY,KAAK,aAAa,gBAAgB;EAAE;;AAG3D,eAAe,cAAc,YAAmC;CAC9D,MAAM,EAAE,YAAY,QAAQ,MAAM,gBAAgB;AAClD,KAAI,CAAC,WAAW,WAAW,EAAE;AAC3B,MAAI,KAAK,yBAAyB,sBAAsB;AACxD;;CAGF,MAAM,SAAS,WAAW,WAAW;CACrC,MAAM,eAAe,KAAK,UACxB,SACC,KAAK,UAAU;AACd,MAAI,QAAQ,aAAa,QAAQ,QAC/B,QAAO,QAAQ,aAAa;AAE9B,SAAO;IAET,EACD;AACD,SAAQ,IAAI,aAAa;;AAG3B,eAAe,kBAAkB,YAAsC;CACrE,MAAM,EAAE,QAAQ,MAAM,gBAAgB;AACtC,KAAI,CAAC,WAAW,WAAW,EAAE;AAC3B,MAAI,MAAM,2CAA2C;AACrD,SAAO;;CAGT,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,aAAa,YAAY,QAAQ,CAAC;SAC9C;AACN,MAAI,MAAM,iCAAiC;AAC3C,SAAO;;CAGT,MAAM,SAAS,aAAa,UAAU,KAAK;AAC3C,KAAI,CAAC,OAAO,SAAS;AACnB,MAAI,MAAM,6CAA6C;AACvD,OAAK,MAAM,SAAS,OAAO,MAAM,OAC/B,SAAQ,MAAM,OAAO,MAAM,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,MAAM,UAAU;AAE5E,SAAO;;CAGT,MAAM,EAAE,iCAAiC,MAAM,OAAO;CACtD,MAAM,gBAAgB,6BAA6B,OAAO,KAAK;AAC/D,KAAI,cAAc,SAAS,GAAG;AAC5B,MAAI,MAAM,2CAA2C;AACrD,OAAK,MAAM,OAAO,cAChB,SAAQ,MAAM,OAAO,MAAM;AAE7B,SAAO;;AAGT,KAAI,KAAK,EAAE,MAAM,YAAY,EAAE,kBAAkB;AACjD,SAAQ,IAAI,2BAA2B;AACvC,QAAO;;AAGT,SAAS,eAAe,KAAU,MAAmB;AACnD,QAAO,KAAK,MAAM,IAAI,CAAC,QAAQ,SAAc,QAAgB;AAC3D,MAAI,WAAW,OAAO,YAAY,YAAY,OAAO,QACnD,QAAO,QAAQ;IAGhB,IAAI;;AAGT,SAAS,eAAe,KAAU,MAAc,OAAiB;CAC/D,MAAM,OAAO,KAAK,MAAM,IAAI;CAC5B,MAAM,UAAU,KAAK,KAAK;CAC1B,MAAM,SAAS,KAAK,QAAQ,SAAc,QAAgB;AACxD,MAAI,CAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,SAC3C,SAAQ,OAAO,EAAE;AAEnB,SAAO,QAAQ;IACd,IAAI;AACP,QAAO,WAAW;AAClB,QAAO;;AAGT,SAAS,oBAAoB,KAA0B;CACrD,MAAM,MAAM,IAAI,QAAQ,SAAS,CAC9B,YAAY,8BAA8B,CAC1C,OAAO,UAAU,oDAAoD,CACrE,OAAO,cAAc,4DAA4D,CACjF,YACC,SACA,eAAe;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CACH,CACA,OAAO,OAAO,YAAY;AACzB,MAAI,QAAQ,MAAM;AAChB,SAAM,cAAc,IAAI,WAAW;AACnC;;AAEF,MAAI,QAAQ,UAAU;AAEpB,OAAI,CAAC,MADY,kBAAkB,IAAI,WAAW,CAEhD,SAAQ,KAAK,EAAE;AAEjB;;AAEF,MAAI,YAAY;GAChB;AAEJ,KACG,QAAQ,aAAa,CACrB,YAAY,iCAAiC,CAC7C,OAAO,OAAO,SAAiB;EAC9B,MAAM,EAAE,YAAY,QAAQ,MAAM,gBAAgB;AAClD,MAAI,CAAC,WAAW,IAAI,WAAW,EAAE;AAC/B,OAAI,MAAM,0BAA0B,sBAAsB;AAC1D,WAAQ,KAAK,EAAE;;EAIjB,MAAM,QAAQ,eADC,WAAW,IAAI,WACK,EAAE,KAAK;AAE1C,MAAI,UAAU,KAAA,GAAW;AACvB,OAAI,MAAM,EAAE,MAAM,EAAE,wBAAwB;AAC5C,WAAQ,KAAK,EAAE;;AAGjB,UAAQ,IAAI,OAAO,UAAU,WAAW,KAAK,UAAU,OAAO,MAAM,EAAE,GAAG,MAAM;GAC/E;AAEJ,KACG,QAAQ,qBAAqB,CAC7B,YAAY,iCAAiC,CAC7C,OAAO,OAAO,MAAc,UAAkB;EAC7C,MAAM,EAAE,YAAY,QAAQ,MAAM,gBAAgB;AAClD,MAAI,CAAC,WAAW,IAAI,WAAW,EAAE;AAC/B,OAAI,MAAM,0BAA0B,sBAAsB;AAC1D,WAAQ,KAAK,EAAE;;EAGjB,IAAI;AACJ,MAAI;AACF,iBAAc,KAAK,MAAM,MAAM;UACzB;AACN,iBAAc;;EAGhB,MAAM,SAAS,WAAW,IAAI,WAAW;AACzC,iBAAe,QAAQ,MAAM,YAAY;AAEzC,QAAM,gBAAgB,IAAI,YAAY,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAEtE,MAAI,KAAK,EAAE,MAAM,EAAE,iBAAiB;GACpC;AAEJ,KACG,QAAQ,eAAe,CACvB,YAAY,oCAAoC,CAChD,OAAO,OAAO,SAAiB;EAC9B,MAAM,EAAE,YAAY,QAAQ,MAAM,gBAAgB;AAClD,MAAI,CAAC,WAAW,IAAI,WAAW,EAAE;AAC/B,OAAI,MAAM,0BAA0B,sBAAsB;AAC1D,WAAQ,KAAK,EAAE;;EAGjB,MAAM,SAAS,WAAW,IAAI,WAAW;EACzC,MAAM,OAAO,KAAK,MAAM,IAAI;EAC5B,MAAM,UAAU,KAAK,KAAK;EAC1B,MAAM,SAAS,KAAK,QAAQ,SAAc,QAAgB;AACxD,UAAO,WAAW,QAAQ;KACzB,OAAO;AAEV,MAAI,UAAU,OAAO,WAAW,YAAY,WAAW,QAAQ;AAC7D,UAAO,OAAO;AACd,SAAM,gBAAgB,IAAI,YAAY,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AACtE,OAAI,KAAK,EAAE,MAAM,EAAE,iBAAiB;SAC/B;AACL,OAAI,MAAM,EAAE,MAAM,EAAE,wBAAwB;AAC5C,WAAQ,KAAK,EAAE;;GAEjB;AAEJ,KACG,QAAQ,OAAO,CACf,YAAY,oDAAoD,CAChE,OAAO,YAAY;AAClB,QAAM,cAAc,IAAI,WAAW;GACnC;AAEJ,KACG,QAAQ,WAAW,CACnB,YAAY,iEAAiE,CAC7E,OAAO,YAAY;AAElB,MAAI,CAAC,MADY,kBAAkB,IAAI,WAAW,CAEhD,SAAQ,KAAK,EAAE;GAEjB;AAEJ,KACG,QAAQ,QAAQ,CAChB,YAAY,0CAA0C,CACtD,OAAO,cAAc,uBAAuB,CAC5C,OAAO,UAAU,oCAAoC,CACrD,OAAO,OAAO,YAAY;EACzB,MAAM,EAAE,YAAY,QAAQ,MAAM,gBAAgB;AAClD,MAAI,CAAC,WAAW,IAAI,WAAW,EAAE;AAC/B,OAAI,MAAM,0BAA0B,sBAAsB;AAC1D,WAAQ,KAAK,EAAE;;EAGjB,MAAM,SAAS,WAAW,IAAI,WAAW;AAEzC,MAAI,QAAQ,MAAM;GAChB,MAAM,QAAQ,QAAQ,SAAS,MAAM;AACrC,OAAI,MACF,SAAQ,IAAI,MAAM;OAElB,SAAQ,IAAI,2CAA2C,QAAQ,SAAS,MAAM,QAAQ,UAAU;AAElG;;AAGF,MAAI,QAAQ,UAAU;GAEpB,MAAM,YAAW,MADI,OAAO,WACJ,YAAY,GAAG,CAAC,SAAS,MAAM;AAEvD,UAAO,UAAU,OAAO,WAAW,EAAE;AACrC,UAAO,QAAQ,OAAO;IACpB,MAAM;IACN,OAAO;IACR;AAED,SAAM,gBAAgB,IAAI,YAAY,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AACtE,OAAI,KAAK,8BAA8B;AACvC,WAAQ,IAAI,UAAU,SAAS,MAAM,GAAG,EAAE,CAAC,KAAK,SAAS,MAAM,GAAG,GAAG;AACrE,WAAQ,IAAI,4DAA0D;AACtE;;EAIF,MAAM,QAAQ,QAAQ,SAAS,MAAM;EACrC,MAAM,OAAO,QAAQ,SAAS,MAAM;EACpC,MAAM,OAAO,QAAQ,SAAS,QAAQ;EACtC,MAAM,OAAO,QAAQ,SAAS,QAAQ;EACtC,MAAM,aAAa,SAAS,8BAA8B,OAAO,GAAG;AAEpE,UAAQ,IAAI,yBAAyB;AACrC,UAAQ,IAAI,WAAW,OAAO;AAC9B,UAAQ,IAAI,uBAAuB,WAAW,GAAG,OAAO;AACxD,UAAQ,IAAI,gBAAgB,QAAQ,YAAY;AAChD,MAAI,OAAO;AACT,WAAQ,IAAI,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM,MAAM,GAAG,GAAG;AACjE,WAAQ,IAAI,4DAA0D;AACtE,WAAQ,IAAI,+DAA6D;aAChE,SAAS,QAClB,SAAQ,IAAI,wEAAwE;GAEtF;AAEJ,KACG,QAAQ,OAAO,CACf,YAAY,+BAA+B,CAC3C,aAAa;AACZ,UAAQ,IAAI,IAAI,WAAW;GAC3B;AAEJ,QAAO;;AAGT,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU;GACR;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACF;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { CronService } from '../../cron/service.js';
2
+ export declare function withCronService<T>(fn: (service: CronService) => Promise<T>): Promise<T>;
@@ -0,0 +1,15 @@
1
+ //#region src/cli/commands/cron-cli.ts
2
+ async function withCronService(fn) {
3
+ const { CronService } = await import("../../cron/index.js");
4
+ const cronService = new CronService();
5
+ await cronService.initialize();
6
+ try {
7
+ return await fn(cronService);
8
+ } finally {
9
+ await cronService.stop();
10
+ }
11
+ }
12
+ //#endregion
13
+ export { withCronService };
14
+
15
+ //# sourceMappingURL=cron-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-cli.js","names":[],"sources":["../../../../src/cli/commands/cron-cli.ts"],"sourcesContent":["import type { CronService } from '../../cron/service.js';\n\nexport async function withCronService<T>(fn: (service: CronService) => Promise<T>): Promise<T> {\n const { CronService } = await import('../../cron/index.js');\n const cronService = new CronService();\n await cronService.initialize();\n try {\n return await fn(cronService);\n } finally {\n await cronService.stop();\n }\n}\n"],"mappings":";AAEA,eAAsB,gBAAmB,IAAsD;CAC7F,MAAM,EAAE,gBAAgB,MAAM,OAAO;CACrC,MAAM,cAAc,IAAI,aAAa;AACrC,OAAM,YAAY,YAAY;AAC9B,KAAI;AACF,SAAO,MAAM,GAAG,YAAY;WACpB;AACR,QAAM,YAAY,MAAM"}
@@ -1 +1,4 @@
1
- export {};
1
+ import { Command } from 'commander';
2
+ import type { CLIContext } from '../registry.js';
3
+ declare function createCronCommand(_ctx: CLIContext): Command;
4
+ export { createCronCommand };
@@ -1,62 +1,92 @@
1
1
  import { formatExamples, register } from "../registry.js";
2
+ import { withCronService } from "./cron-cli.js";
2
3
  import { Command } from "commander";
3
4
  //#region src/cli/commands/cron.ts
4
5
  function createCronCommand(_ctx) {
5
6
  const cmd = new Command("cron").description("Manage scheduled tasks").addHelpText("after", formatExamples([
6
7
  "xopc cron list # List all tasks",
7
8
  "xopc cron add --schedule \"0 9 * * *\" --message \"Good morning\"",
9
+ "xopc cron enable <job-id> # Enable a task",
10
+ "xopc cron disable <job-id> # Disable a task",
11
+ "xopc cron run <job-id> # Run a task now",
8
12
  "xopc cron remove <job-id> # Remove a task"
9
13
  ]));
10
14
  cmd.addCommand(new Command("list").description("List all scheduled tasks").action(async () => {
11
- const { CronService } = await import("../../cron/index.js");
12
- const cronService = new CronService();
13
- await cronService.initialize();
14
- const jobs = await cronService.listJobs();
15
- if (jobs.length === 0) {
16
- console.log("No scheduled tasks.");
17
- return;
18
- }
19
- console.log("Scheduled Tasks:\n");
20
- const { getCronPayloadText } = await import("../../cron/job-content.js");
21
- for (const job of jobs) {
22
- console.log(` ${job.id} - ${job.schedule}`);
23
- console.log(` ${getCronPayloadText({ payload: job.payload })}`);
24
- console.log(` Next: ${job.next_run || "N/A"}`);
25
- console.log();
26
- }
27
- await cronService.stop();
15
+ await withCronService(async (cronService) => {
16
+ const jobs = await cronService.listJobs();
17
+ if (jobs.length === 0) {
18
+ console.log("No scheduled tasks.");
19
+ return;
20
+ }
21
+ console.log("Scheduled Tasks:\n");
22
+ const { getCronPayloadText } = await import("../../cron/job-content.js");
23
+ for (const job of jobs) {
24
+ const state = job.enabled ? "enabled " : "disabled";
25
+ console.log(` ${job.id} [${state}] - ${job.schedule}`);
26
+ console.log(` ${getCronPayloadText({ payload: job.payload })}`);
27
+ console.log(` Next: ${job.next_run || "N/A"}`);
28
+ console.log();
29
+ }
30
+ });
28
31
  }));
29
32
  cmd.addCommand(new Command("add").description("Add a scheduled task").option("--name <text>", "Task name").option("--schedule <cron>", "Cron expression (e.g., \"0 9 * * *\")").option("--message <text>", "Message to send").action(async (options) => {
30
33
  if (!options.schedule || !options.message) {
31
34
  console.error("Error: --schedule and --message are required");
32
35
  process.exit(1);
33
36
  }
34
- const { CronService } = await import("../../cron/index.js");
35
- const cronService = new CronService();
36
- await cronService.initialize();
37
- const result = await cronService.addJob(options.schedule, {
38
- name: options.name,
39
- payload: {
40
- kind: "systemEvent",
41
- text: options.message
42
- }
37
+ await withCronService(async (cronService) => {
38
+ const result = await cronService.addJob(options.schedule, {
39
+ name: options.name,
40
+ payload: {
41
+ kind: "systemEvent",
42
+ text: options.message
43
+ }
44
+ });
45
+ console.log(`✅ Added job ${result.id}`);
46
+ console.log(` Schedule: ${result.schedule}`);
43
47
  });
44
- console.log(`✅ Added job ${result.id}`);
45
- console.log(` Schedule: ${result.schedule}`);
46
- await cronService.stop();
47
48
  }));
48
49
  cmd.addCommand(new Command("remove").description("Remove a scheduled task").argument("<id>", "Job ID").action(async (id) => {
49
- const { CronService } = await import("../../cron/index.js");
50
- const cronService = new CronService();
51
- await cronService.initialize();
52
- const success = await cronService.removeJob(id);
53
- await cronService.stop();
54
- if (success) console.log(`✅ Removed job ${id}`);
55
- else {
56
- console.error(`Job ${id} not found`);
57
- process.exit(1);
58
- }
50
+ await withCronService(async (cronService) => {
51
+ if (await cronService.removeJob(id)) console.log(`✅ Removed job ${id}`);
52
+ else {
53
+ console.error(`Job ${id} not found`);
54
+ process.exit(1);
55
+ }
56
+ });
59
57
  }));
58
+ cmd.addCommand(new Command("enable").description("Enable a scheduled task").argument("<id>", "Job ID").action(async (id) => {
59
+ await withCronService(async (cronService) => {
60
+ if (await cronService.toggleJob(id, true)) console.log(`✅ Enabled job ${id}`);
61
+ else {
62
+ console.error(`Job ${id} not found`);
63
+ process.exit(1);
64
+ }
65
+ });
66
+ }));
67
+ cmd.addCommand(new Command("disable").description("Disable a scheduled task").argument("<id>", "Job ID").action(async (id) => {
68
+ await withCronService(async (cronService) => {
69
+ if (await cronService.toggleJob(id, false)) console.log(`✅ Disabled job ${id}`);
70
+ else {
71
+ console.error(`Job ${id} not found`);
72
+ process.exit(1);
73
+ }
74
+ });
75
+ }));
76
+ const runNowAction = async (id) => {
77
+ await withCronService(async (cronService) => {
78
+ try {
79
+ await cronService.runJobNow(id);
80
+ console.log(`✅ Triggered job ${id}`);
81
+ } catch (err) {
82
+ const message = err instanceof Error ? err.message : String(err);
83
+ console.error(message);
84
+ process.exit(1);
85
+ }
86
+ });
87
+ };
88
+ cmd.addCommand(new Command("run").description("Run a scheduled task immediately").argument("<id>", "Job ID").action(runNowAction));
89
+ cmd.addCommand(new Command("trigger").description("Alias for `cron run`").argument("<id>", "Job ID").action(runNowAction));
60
90
  return cmd;
61
91
  }
62
92
  register({
@@ -66,10 +96,15 @@ register({
66
96
  factory: createCronCommand,
67
97
  metadata: {
68
98
  category: "utility",
69
- examples: ["xopc cron list", "xopc cron add --schedule \"0 9 * * *\" --message \"Hello\""]
99
+ examples: [
100
+ "xopc cron list",
101
+ "xopc cron add --schedule \"0 9 * * *\" --message \"Hello\"",
102
+ "xopc cron enable abc12345",
103
+ "xopc cron run abc12345"
104
+ ]
70
105
  }
71
106
  });
72
107
  //#endregion
73
- export {};
108
+ export { createCronCommand };
74
109
 
75
110
  //# sourceMappingURL=cron.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cron.js","names":[],"sources":["../../../../src/cli/commands/cron.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\n\nfunction createCronCommand(_ctx: CLIContext): Command {\n const cmd = new Command('cron')\n .description('Manage scheduled tasks')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc cron list # List all tasks',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Good morning\"',\n 'xopc cron remove <job-id> # Remove a task',\n ])\n );\n\n cmd.addCommand(\n new Command('list')\n .description('List all scheduled tasks')\n .action(async () => {\n const { CronService } = await import('../../cron/index.js');\n \n const cronService = new CronService();\n await cronService.initialize();\n \n const jobs = await cronService.listJobs();\n \n if (jobs.length === 0) {\n console.log('No scheduled tasks.');\n return;\n }\n \n console.log('Scheduled Tasks:\\n');\n const { getCronPayloadText } = await import('../../cron/job-content.js');\n for (const job of jobs) {\n console.log(` ${job.id} - ${job.schedule}`);\n console.log(` ${getCronPayloadText({ payload: job.payload })}`);\n console.log(` Next: ${job.next_run || 'N/A'}`);\n console.log();\n }\n \n await cronService.stop();\n })\n );\n\n cmd.addCommand(\n new Command('add')\n .description('Add a scheduled task')\n .option('--name <text>', 'Task name')\n .option('--schedule <cron>', 'Cron expression (e.g., \"0 9 * * *\")')\n .option('--message <text>', 'Message to send')\n .action(async (options) => {\n if (!options.schedule || !options.message) {\n console.error('Error: --schedule and --message are required');\n process.exit(1);\n }\n \n const { CronService } = await import('../../cron/index.js');\n const cronService = new CronService();\n await cronService.initialize();\n \n const result = await cronService.addJob(options.schedule, {\n name: options.name,\n payload: { kind: 'systemEvent', text: options.message },\n });\n \n console.log(`✅ Added job ${result.id}`);\n console.log(` Schedule: ${result.schedule}`);\n \n await cronService.stop();\n })\n );\n\n cmd.addCommand(\n new Command('remove')\n .description('Remove a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n const { CronService } = await import('../../cron/index.js');\n const cronService = new CronService();\n await cronService.initialize();\n \n const success = await cronService.removeJob(id);\n \n await cronService.stop();\n \n if (success) {\n console.log(`✅ Removed job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n })\n );\n\n return cmd;\n}\n\nregister({\n id: 'cron',\n name: 'cron',\n description: 'Manage scheduled tasks',\n factory: createCronCommand,\n metadata: {\n category: 'utility',\n examples: [\n 'xopc cron list',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Hello\"',\n ],\n },\n});\n"],"mappings":";;;AAIA,SAAS,kBAAkB,MAA2B;CACpD,MAAM,MAAM,IAAI,QAAQ,OAAO,CAC5B,YAAY,yBAAyB,CACrC,YACC,SACA,eAAe;EACb;EACA;EACA;EACD,CAAC,CACH;AAEH,KAAI,WACF,IAAI,QAAQ,OAAO,CAChB,YAAY,2BAA2B,CACvC,OAAO,YAAY;EAClB,MAAM,EAAE,gBAAgB,MAAM,OAAO;EAErC,MAAM,cAAc,IAAI,aAAa;AACrC,QAAM,YAAY,YAAY;EAE9B,MAAM,OAAO,MAAM,YAAY,UAAU;AAEzC,MAAI,KAAK,WAAW,GAAG;AACrB,WAAQ,IAAI,sBAAsB;AAClC;;AAGF,UAAQ,IAAI,qBAAqB;EACjC,MAAM,EAAE,uBAAuB,MAAM,OAAO;AAC5C,OAAK,MAAM,OAAO,MAAM;AACtB,WAAQ,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,WAAW;AAC5C,WAAQ,IAAI,QAAQ,mBAAmB,EAAE,SAAS,IAAI,SAAS,CAAC,GAAG;AACnE,WAAQ,IAAI,cAAc,IAAI,YAAY,QAAQ;AAClD,WAAQ,KAAK;;AAGf,QAAM,YAAY,MAAM;GACxB,CACL;AAED,KAAI,WACF,IAAI,QAAQ,MAAM,CACf,YAAY,uBAAuB,CACnC,OAAO,iBAAiB,YAAY,CACpC,OAAO,qBAAqB,wCAAsC,CAClE,OAAO,oBAAoB,kBAAkB,CAC7C,OAAO,OAAO,YAAY;AACzB,MAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,SAAS;AACzC,WAAQ,MAAM,+CAA+C;AAC7D,WAAQ,KAAK,EAAE;;EAGjB,MAAM,EAAE,gBAAgB,MAAM,OAAO;EACrC,MAAM,cAAc,IAAI,aAAa;AACrC,QAAM,YAAY,YAAY;EAE9B,MAAM,SAAS,MAAM,YAAY,OAAO,QAAQ,UAAU;GACxD,MAAM,QAAQ;GACd,SAAS;IAAE,MAAM;IAAe,MAAM,QAAQ;IAAS;GACxD,CAAC;AAEF,UAAQ,IAAI,eAAe,OAAO,KAAK;AACvC,UAAQ,IAAI,gBAAgB,OAAO,WAAW;AAE9C,QAAM,YAAY,MAAM;GACxB,CACL;AAED,KAAI,WACF,IAAI,QAAQ,SAAS,CAClB,YAAY,0BAA0B,CACtC,SAAS,QAAQ,SAAS,CAC1B,OAAO,OAAO,OAAO;EACpB,MAAM,EAAE,gBAAgB,MAAM,OAAO;EACrC,MAAM,cAAc,IAAI,aAAa;AACrC,QAAM,YAAY,YAAY;EAE9B,MAAM,UAAU,MAAM,YAAY,UAAU,GAAG;AAE/C,QAAM,YAAY,MAAM;AAExB,MAAI,QACF,SAAQ,IAAI,iBAAiB,KAAK;OAC7B;AACL,WAAQ,MAAM,OAAO,GAAG,YAAY;AACpC,WAAQ,KAAK,EAAE;;GAEjB,CACL;AAED,QAAO;;AAGT,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU,CACR,kBACA,6DACD;EACF;CACF,CAAC"}
1
+ {"version":3,"file":"cron.js","names":[],"sources":["../../../../src/cli/commands/cron.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport { withCronService } from './cron-cli.js';\n\nfunction createCronCommand(_ctx: CLIContext): Command {\n const cmd = new Command('cron')\n .description('Manage scheduled tasks')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc cron list # List all tasks',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Good morning\"',\n 'xopc cron enable <job-id> # Enable a task',\n 'xopc cron disable <job-id> # Disable a task',\n 'xopc cron run <job-id> # Run a task now',\n 'xopc cron remove <job-id> # Remove a task',\n ]),\n );\n\n cmd.addCommand(\n new Command('list')\n .description('List all scheduled tasks')\n .action(async () => {\n await withCronService(async (cronService) => {\n const jobs = await cronService.listJobs();\n\n if (jobs.length === 0) {\n console.log('No scheduled tasks.');\n return;\n }\n\n console.log('Scheduled Tasks:\\n');\n const { getCronPayloadText } = await import('../../cron/job-content.js');\n for (const job of jobs) {\n const state = job.enabled ? 'enabled ' : 'disabled';\n console.log(` ${job.id} [${state}] - ${job.schedule}`);\n console.log(` ${getCronPayloadText({ payload: job.payload })}`);\n console.log(` Next: ${job.next_run || 'N/A'}`);\n console.log();\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('add')\n .description('Add a scheduled task')\n .option('--name <text>', 'Task name')\n .option('--schedule <cron>', 'Cron expression (e.g., \"0 9 * * *\")')\n .option('--message <text>', 'Message to send')\n .action(async (options) => {\n if (!options.schedule || !options.message) {\n console.error('Error: --schedule and --message are required');\n process.exit(1);\n }\n\n await withCronService(async (cronService) => {\n const result = await cronService.addJob(options.schedule, {\n name: options.name,\n payload: { kind: 'systemEvent', text: options.message },\n });\n\n console.log(`✅ Added job ${result.id}`);\n console.log(` Schedule: ${result.schedule}`);\n });\n }),\n );\n\n cmd.addCommand(\n new Command('remove')\n .description('Remove a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.removeJob(id);\n if (success) {\n console.log(`✅ Removed job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('enable')\n .description('Enable a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.toggleJob(id, true);\n if (success) {\n console.log(`✅ Enabled job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('disable')\n .description('Disable a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.toggleJob(id, false);\n if (success) {\n console.log(`✅ Disabled job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n const runNowAction = async (id: string) => {\n await withCronService(async (cronService) => {\n try {\n await cronService.runJobNow(id);\n console.log(`✅ Triggered job ${id}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(message);\n process.exit(1);\n }\n });\n };\n\n cmd.addCommand(\n new Command('run')\n .description('Run a scheduled task immediately')\n .argument('<id>', 'Job ID')\n .action(runNowAction),\n );\n\n cmd.addCommand(\n new Command('trigger')\n .description('Alias for `cron run`')\n .argument('<id>', 'Job ID')\n .action(runNowAction),\n );\n\n return cmd;\n}\n\nregister({\n id: 'cron',\n name: 'cron',\n description: 'Manage scheduled tasks',\n factory: createCronCommand,\n metadata: {\n category: 'utility',\n examples: [\n 'xopc cron list',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Hello\"',\n 'xopc cron enable abc12345',\n 'xopc cron run abc12345',\n ],\n },\n});\n\nexport { createCronCommand };\n"],"mappings":"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"}
@@ -50,7 +50,7 @@ function checkWeixin(cfg) {
50
50
  const hints = [];
51
51
  if ((wx.accounts ? Object.keys(wx.accounts).filter((k) => k.trim()) : []).length === 0) {
52
52
  messages.push("Weixin is enabled but no accounts are defined in config.");
53
- hints.push("Run: xopc channels weixin login (or add channels.weixin.accounts).");
53
+ hints.push("Run: xopc channels login --channel weixin (or add channels.weixin.accounts).");
54
54
  }
55
55
  return {
56
56
  ok: messages.length === 0,
@@ -1 +1 @@
1
- {"version":3,"file":"channel-config.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/channel-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\ntype TelegramCfg = {\n enabled?: boolean;\n accounts?: Record<string, { botToken?: string; dmPolicy?: string; enabled?: boolean }>;\n dmPolicy?: string;\n};\n\ntype WeixinCfg = {\n enabled?: boolean;\n accounts?: Record<string, unknown>;\n};\n\nfunction checkTelegram(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const tg = cfg.channels?.telegram as TelegramCfg | undefined;\n if (!tg) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const defaultAcc = tg.accounts?.default;\n const token = defaultAcc?.botToken?.trim() ?? '';\n const enabled = tg.enabled === true || token.length > 0;\n\n if (!enabled) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n\n if (!token) {\n messages.push('Telegram is enabled but no bot token is set.');\n hints.push('Set channels.telegram.accounts.default.botToken.');\n }\n\n const dm = (defaultAcc?.dmPolicy ?? tg.dmPolicy) || 'pairing';\n if (!['pairing', 'allowlist', 'open', 'disabled'].includes(dm)) {\n messages.push(`Telegram dmPolicy \"${dm}\" is not valid.`);\n }\n if (dm === 'open') {\n messages.push('Telegram DM policy is \"open\" (any user can message the bot).');\n hints.push('Consider \"pairing\" or \"allowlist\" for stricter access.');\n }\n\n return {\n ok: messages.length === 0,\n messages,\n hints,\n };\n}\n\nfunction checkWeixin(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const wx = cfg.channels?.weixin as WeixinCfg | undefined;\n if (!wx || wx.enabled !== true) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n const accountKeys = wx.accounts ? Object.keys(wx.accounts).filter((k) => k.trim()) : [];\n if (accountKeys.length === 0) {\n messages.push('Weixin is enabled but no accounts are defined in config.');\n hints.push('Run: xopc channels weixin login (or add channels.weixin.accounts).');\n }\n\n return { ok: messages.length === 0, messages, hints };\n}\n\nexport async function checkChannelConfig(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const tg = checkTelegram(cfg);\n const wx = checkWeixin(cfg);\n const allMsg = [...tg.messages, ...wx.messages];\n const allHints = [...tg.hints, ...wx.hints];\n\n const tgEnabled =\n (cfg.channels?.telegram as TelegramCfg | undefined)?.enabled === true ||\n Boolean((cfg.channels?.telegram as TelegramCfg | undefined)?.accounts?.default?.botToken?.trim());\n const wxOn = (cfg.channels?.weixin as WeixinCfg | undefined)?.enabled === true;\n if (!tgEnabled && !wxOn) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'No channels enabled; skipped.',\n hints: [],\n };\n }\n\n if (allMsg.length === 0) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'pass',\n message: 'Enabled channel configuration looks valid.',\n hints: [],\n };\n }\n\n const hasFail = allMsg.some((m) => m.includes('no bot token') || m.includes('no accounts'));\n return {\n id: 'channel-config',\n label: 'Channels',\n status: hasFail ? 'fail' : 'warn',\n message: allMsg.join(' '),\n hints: allHints,\n };\n}\n"],"mappings":";;;aAE0D;AAe1D,SAAS,cAAc,KAAmE;CACxF,MAAM,KAAK,IAAI,UAAU;AACzB,KAAI,CAAC,GACH,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,aAAa,GAAG,UAAU;CAChC,MAAM,QAAQ,YAAY,UAAU,MAAM,IAAI;AAG9C,KAAI,EAFY,GAAG,YAAY,QAAQ,MAAM,SAAS,GAGpD,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,WAAqB,EAAE;CAC7B,MAAM,QAAkB,EAAE;AAE1B,KAAI,CAAC,OAAO;AACV,WAAS,KAAK,+CAA+C;AAC7D,QAAM,KAAK,mDAAmD;;CAGhE,MAAM,MAAM,YAAY,YAAY,GAAG,aAAa;AACpD,KAAI,CAAC;EAAC;EAAW;EAAa;EAAQ;EAAW,CAAC,SAAS,GAAG,CAC5D,UAAS,KAAK,sBAAsB,GAAG,iBAAiB;AAE1D,KAAI,OAAO,QAAQ;AACjB,WAAS,KAAK,iEAA+D;AAC7E,QAAM,KAAK,6DAAyD;;AAGtE,QAAO;EACL,IAAI,SAAS,WAAW;EACxB;EACA;EACD;;AAGH,SAAS,YAAY,KAAmE;CACtF,MAAM,KAAK,IAAI,UAAU;AACzB,KAAI,CAAC,MAAM,GAAG,YAAY,KACxB,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,WAAqB,EAAE;CAC7B,MAAM,QAAkB,EAAE;AAE1B,MADoB,GAAG,WAAW,OAAO,KAAK,GAAG,SAAS,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,EACvE,WAAW,GAAG;AAC5B,WAAS,KAAK,2DAA2D;AACzE,QAAM,KAAK,qEAAqE;;AAGlF,QAAO;EAAE,IAAI,SAAS,WAAW;EAAG;EAAU;EAAO;;AAGvD,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,KAAK,cAAc,IAAI;CAC7B,MAAM,KAAK,YAAY,IAAI;CAC3B,MAAM,SAAS,CAAC,GAAG,GAAG,UAAU,GAAG,GAAG,SAAS;CAC/C,MAAM,WAAW,CAAC,GAAG,GAAG,OAAO,GAAG,GAAG,MAAM;CAE3C,MAAM,aACH,IAAI,UAAU,WAAsC,YAAY,QACjE,SAAS,IAAI,UAAU,WAAsC,UAAU,SAAS,UAAU,MAAM,CAAC;CACnG,MAAM,QAAQ,IAAI,UAAU,SAAkC,YAAY;AAC1E,KAAI,CAAC,aAAa,CAAC,KACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAGH,KAAI,OAAO,WAAW,EACpB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAIH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAJc,OAAO,MAAM,MAAM,EAAE,SAAS,eAAe,IAAI,EAAE,SAAS,cAAc,CAIzE,GAAG,SAAS;EAC3B,SAAS,OAAO,KAAK,IAAI;EACzB,OAAO;EACR"}
1
+ {"version":3,"file":"channel-config.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/channel-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\ntype TelegramCfg = {\n enabled?: boolean;\n accounts?: Record<string, { botToken?: string; dmPolicy?: string; enabled?: boolean }>;\n dmPolicy?: string;\n};\n\ntype WeixinCfg = {\n enabled?: boolean;\n accounts?: Record<string, unknown>;\n};\n\nfunction checkTelegram(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const tg = cfg.channels?.telegram as TelegramCfg | undefined;\n if (!tg) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const defaultAcc = tg.accounts?.default;\n const token = defaultAcc?.botToken?.trim() ?? '';\n const enabled = tg.enabled === true || token.length > 0;\n\n if (!enabled) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n\n if (!token) {\n messages.push('Telegram is enabled but no bot token is set.');\n hints.push('Set channels.telegram.accounts.default.botToken.');\n }\n\n const dm = (defaultAcc?.dmPolicy ?? tg.dmPolicy) || 'pairing';\n if (!['pairing', 'allowlist', 'open', 'disabled'].includes(dm)) {\n messages.push(`Telegram dmPolicy \"${dm}\" is not valid.`);\n }\n if (dm === 'open') {\n messages.push('Telegram DM policy is \"open\" (any user can message the bot).');\n hints.push('Consider \"pairing\" or \"allowlist\" for stricter access.');\n }\n\n return {\n ok: messages.length === 0,\n messages,\n hints,\n };\n}\n\nfunction checkWeixin(cfg: Config): { ok: boolean; messages: string[]; hints: string[] } {\n const wx = cfg.channels?.weixin as WeixinCfg | undefined;\n if (!wx || wx.enabled !== true) {\n return { ok: true, messages: [], hints: [] };\n }\n\n const messages: string[] = [];\n const hints: string[] = [];\n const accountKeys = wx.accounts ? Object.keys(wx.accounts).filter((k) => k.trim()) : [];\n if (accountKeys.length === 0) {\n messages.push('Weixin is enabled but no accounts are defined in config.');\n hints.push('Run: xopc channels login --channel weixin (or add channels.weixin.accounts).');\n }\n\n return { ok: messages.length === 0, messages, hints };\n}\n\nexport async function checkChannelConfig(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const tg = checkTelegram(cfg);\n const wx = checkWeixin(cfg);\n const allMsg = [...tg.messages, ...wx.messages];\n const allHints = [...tg.hints, ...wx.hints];\n\n const tgEnabled =\n (cfg.channels?.telegram as TelegramCfg | undefined)?.enabled === true ||\n Boolean((cfg.channels?.telegram as TelegramCfg | undefined)?.accounts?.default?.botToken?.trim());\n const wxOn = (cfg.channels?.weixin as WeixinCfg | undefined)?.enabled === true;\n if (!tgEnabled && !wxOn) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'skip',\n message: 'No channels enabled; skipped.',\n hints: [],\n };\n }\n\n if (allMsg.length === 0) {\n return {\n id: 'channel-config',\n label: 'Channels',\n status: 'pass',\n message: 'Enabled channel configuration looks valid.',\n hints: [],\n };\n }\n\n const hasFail = allMsg.some((m) => m.includes('no bot token') || m.includes('no accounts'));\n return {\n id: 'channel-config',\n label: 'Channels',\n status: hasFail ? 'fail' : 'warn',\n message: allMsg.join(' '),\n hints: allHints,\n };\n}\n"],"mappings":";;;aAE0D;AAe1D,SAAS,cAAc,KAAmE;CACxF,MAAM,KAAK,IAAI,UAAU;AACzB,KAAI,CAAC,GACH,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,aAAa,GAAG,UAAU;CAChC,MAAM,QAAQ,YAAY,UAAU,MAAM,IAAI;AAG9C,KAAI,EAFY,GAAG,YAAY,QAAQ,MAAM,SAAS,GAGpD,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,WAAqB,EAAE;CAC7B,MAAM,QAAkB,EAAE;AAE1B,KAAI,CAAC,OAAO;AACV,WAAS,KAAK,+CAA+C;AAC7D,QAAM,KAAK,mDAAmD;;CAGhE,MAAM,MAAM,YAAY,YAAY,GAAG,aAAa;AACpD,KAAI,CAAC;EAAC;EAAW;EAAa;EAAQ;EAAW,CAAC,SAAS,GAAG,CAC5D,UAAS,KAAK,sBAAsB,GAAG,iBAAiB;AAE1D,KAAI,OAAO,QAAQ;AACjB,WAAS,KAAK,iEAA+D;AAC7E,QAAM,KAAK,6DAAyD;;AAGtE,QAAO;EACL,IAAI,SAAS,WAAW;EACxB;EACA;EACD;;AAGH,SAAS,YAAY,KAAmE;CACtF,MAAM,KAAK,IAAI,UAAU;AACzB,KAAI,CAAC,MAAM,GAAG,YAAY,KACxB,QAAO;EAAE,IAAI;EAAM,UAAU,EAAE;EAAE,OAAO,EAAE;EAAE;CAG9C,MAAM,WAAqB,EAAE;CAC7B,MAAM,QAAkB,EAAE;AAE1B,MADoB,GAAG,WAAW,OAAO,KAAK,GAAG,SAAS,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC,GAAG,EAAE,EACvE,WAAW,GAAG;AAC5B,WAAS,KAAK,2DAA2D;AACzE,QAAM,KAAK,+EAA+E;;AAG5F,QAAO;EAAE,IAAI,SAAS,WAAW;EAAG;EAAU;EAAO;;AAGvD,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,KAAK,cAAc,IAAI;CAC7B,MAAM,KAAK,YAAY,IAAI;CAC3B,MAAM,SAAS,CAAC,GAAG,GAAG,UAAU,GAAG,GAAG,SAAS;CAC/C,MAAM,WAAW,CAAC,GAAG,GAAG,OAAO,GAAG,GAAG,MAAM;CAE3C,MAAM,aACH,IAAI,UAAU,WAAsC,YAAY,QACjE,SAAS,IAAI,UAAU,WAAsC,UAAU,SAAS,UAAU,MAAM,CAAC;CACnG,MAAM,QAAQ,IAAI,UAAU,SAAkC,YAAY;AAC1E,KAAI,CAAC,aAAa,CAAC,KACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAGH,KAAI,OAAO,WAAW,EACpB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAIH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAJc,OAAO,MAAM,MAAM,EAAE,SAAS,eAAe,IAAI,EAAE,SAAS,cAAc,CAIzE,GAAG,SAAS;EAC3B,SAAS,OAAO,KAAK,IAAI;EACzB,OAAO;EACR"}
@@ -1,7 +1,7 @@
1
1
  import { ConfigSchema, init_schema } from "../../../../config/schema.js";
2
2
  import { init_loader, loadConfig, saveConfig } from "../../../../config/loader.js";
3
- import { dirname } from "node:path";
4
3
  import { existsSync, mkdirSync, readFileSync } from "node:fs";
4
+ import { dirname } from "node:path";
5
5
  //#region src/cli/commands/doctor/checks/config-health.ts
6
6
  init_loader();
7
7
  init_schema();
@@ -33,7 +33,7 @@ async function checkConfigHealth(ctx) {
33
33
  label: "Config",
34
34
  status: "fail",
35
35
  message: "Config file not found.",
36
- hints: [`Run: xopc init`, `Or: xopc doctor --fix`]
36
+ hints: [`Run: xopc init (or xopc setup)`, `Or: xopc doctor --fix`]
37
37
  };
38
38
  }
39
39
  let raw;
@@ -1 +1 @@
1
- {"version":3,"file":"config-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/config-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { mkdirSync } from 'node:fs';\n\nimport { loadConfig, saveConfig } from '../../../../config/loader.js';\nimport { ConfigSchema } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkConfigHealth(ctx: DoctorContext): Promise<CheckResult> {\n const path = ctx.configPath;\n\n if (!existsSync(path)) {\n if (ctx.options.fix) {\n try {\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const defaults = loadConfig(path);\n await saveConfig(defaults, path);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Created default config file.',\n hints: [path],\n fixed: true,\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Config file missing and could not create default: ${msg}`,\n hints: [path],\n };\n }\n }\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file not found.',\n hints: [`Run: xopc init`, `Or: xopc doctor --fix`],\n };\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf-8');\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Cannot read config file: ${msg}`,\n hints: [path],\n };\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file is not valid JSON.',\n hints: ['Fix syntax or restore from backup (.bak).', path],\n };\n }\n\n const parsed = ConfigSchema.safeParse(json);\n if (!parsed.success) {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config does not match the expected schema.',\n hints: parsed.error.issues.slice(0, 5).map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`),\n };\n }\n\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Config file exists and validates.',\n hints: [path],\n };\n}\n"],"mappings":";;;;;aAIsE;aACV;AAG5D,eAAsB,kBAAkB,KAA0C;CAChF,MAAM,OAAO,IAAI;AAEjB,KAAI,CAAC,WAAW,KAAK,EAAE;AACrB,MAAI,IAAI,QAAQ,IACd,KAAI;AAEF,aADY,QAAQ,KACP,EAAE,EAAE,WAAW,MAAM,CAAC;AAEnC,SAAM,WADW,WAAW,KACH,EAAE,KAAK;AAChC,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,KAAK;IACb,OAAO;IACR;WACM,GAAG;AAEV,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,qDALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IAMpD,OAAO,CAAC,KAAK;IACd;;AAGL,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,kBAAkB,wBAAwB;GACnD;;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,aAAa,MAAM,QAAQ;UAC1B,GAAG;AAEV,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,4BALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;GAMpD,OAAO,CAAC,KAAK;GACd;;CAGH,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,6CAA6C,KAAK;GAC3D;;CAGH,MAAM,SAAS,aAAa,UAAU,KAAK;AAC3C,KAAI,CAAC,OAAO,QACV,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,OAAO,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,EAAE,UAAU;EACnG;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,KAAK;EACd"}
1
+ {"version":3,"file":"config-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/config-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { mkdirSync } from 'node:fs';\n\nimport { loadConfig, saveConfig } from '../../../../config/loader.js';\nimport { ConfigSchema } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkConfigHealth(ctx: DoctorContext): Promise<CheckResult> {\n const path = ctx.configPath;\n\n if (!existsSync(path)) {\n if (ctx.options.fix) {\n try {\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const defaults = loadConfig(path);\n await saveConfig(defaults, path);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Created default config file.',\n hints: [path],\n fixed: true,\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Config file missing and could not create default: ${msg}`,\n hints: [path],\n };\n }\n }\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file not found.',\n hints: [`Run: xopc init (or xopc setup)`, `Or: xopc doctor --fix`],\n };\n }\n\n let raw: string;\n try {\n raw = readFileSync(path, 'utf-8');\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: `Cannot read config file: ${msg}`,\n hints: [path],\n };\n }\n\n let json: unknown;\n try {\n json = JSON.parse(raw);\n } catch {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config file is not valid JSON.',\n hints: ['Fix syntax or restore from backup (.bak).', path],\n };\n }\n\n const parsed = ConfigSchema.safeParse(json);\n if (!parsed.success) {\n return {\n id: 'config-health',\n label: 'Config',\n status: 'fail',\n message: 'Config does not match the expected schema.',\n hints: parsed.error.issues.slice(0, 5).map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`),\n };\n }\n\n return {\n id: 'config-health',\n label: 'Config',\n status: 'pass',\n message: 'Config file exists and validates.',\n hints: [path],\n };\n}\n"],"mappings":";;;;;aAIsE;aACV;AAG5D,eAAsB,kBAAkB,KAA0C;CAChF,MAAM,OAAO,IAAI;AAEjB,KAAI,CAAC,WAAW,KAAK,EAAE;AACrB,MAAI,IAAI,QAAQ,IACd,KAAI;AAEF,aADY,QAAQ,KACP,EAAE,EAAE,WAAW,MAAM,CAAC;AAEnC,SAAM,WADW,WAAW,KACH,EAAE,KAAK;AAChC,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,KAAK;IACb,OAAO;IACR;WACM,GAAG;AAEV,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,qDALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IAMpD,OAAO,CAAC,KAAK;IACd;;AAGL,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,kCAAkC,wBAAwB;GACnE;;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,aAAa,MAAM,QAAQ;UAC1B,GAAG;AAEV,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,4BALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;GAMpD,OAAO,CAAC,KAAK;GACd;;CAGH,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,IAAI;SAChB;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,6CAA6C,KAAK;GAC3D;;CAGH,MAAM,SAAS,aAAa,UAAU,KAAK;AAC3C,KAAI,CAAC,OAAO,QACV,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,OAAO,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,IAAI,IAAI,SAAS,IAAI,EAAE,UAAU;EACnG;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,KAAK;EACd"}
@@ -38,7 +38,7 @@ async function checkCronHealth(ctx) {
38
38
  label: "Cron",
39
39
  status: "warn",
40
40
  message: "Cron directory does not exist.",
41
- hints: [cronDir, "Run: xopc init"]
41
+ hints: [cronDir, "Run: xopc init (creates cron directory)"]
42
42
  };
43
43
  const jobsPath = resolveCronJobsPath();
44
44
  if (!existsSync(jobsPath)) return {
@@ -1 +1 @@
1
- {"version":3,"file":"cron-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/cron-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport { resolveCronDir, resolveCronJobsPath } from '../../../../config/paths.js';\nimport { JobDataSchema } from '../../../../cron/validation.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkCronHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n if (cfg.cron?.enabled === false) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Cron is disabled in config; skipped.',\n hints: [],\n };\n }\n\n const cronDir = resolveCronDir();\n if (!existsSync(cronDir)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron directory does not exist.',\n hints: [cronDir, 'Run: xopc init'],\n };\n }\n\n const jobsPath = resolveCronJobsPath();\n if (!existsSync(jobsPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is missing.',\n hints: [jobsPath],\n };\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(jobsPath, 'utf-8'));\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is not valid JSON.',\n hints: [jobsPath],\n };\n }\n\n if (!raw || typeof raw !== 'object' || !('jobs' in raw) || !Array.isArray((raw as { jobs: unknown }).jobs)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file has invalid structure (expected { jobs: [] }).',\n hints: [jobsPath],\n };\n }\n\n const jobs = (raw as { jobs: unknown[] }).jobs;\n const hints: string[] = [];\n let valid = 0;\n let enabled = 0;\n let scheduleMissing = 0;\n\n for (const j of jobs) {\n const r = JobDataSchema.safeParse(j);\n if (r.success) {\n valid++;\n if (r.data.enabled) {\n enabled++;\n const sched = r.data.schedule?.trim();\n if (!sched) {\n scheduleMissing++;\n hints.push(`Job \"${r.data.name || r.data.id}\" is enabled but has no schedule.`);\n }\n }\n } else {\n hints.push('One or more job entries failed validation (check jobs.json).');\n break;\n }\n }\n\n if (valid !== jobs.length) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Some cron jobs are invalid or could not be validated.',\n hints: hints.length ? hints.slice(0, 5) : [jobsPath],\n };\n }\n\n if (scheduleMissing > 0) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: `${scheduleMissing} enabled job(s) are missing a schedule.`,\n hints: hints.slice(0, 5),\n };\n }\n\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'pass',\n message: `Cron jobs file is valid (${enabled} enabled, ${jobs.length} total).`,\n hints: [jobsPath],\n };\n}\n"],"mappings":";;;;;aAE0D;YAEwB;AAIlF,eAAsB,gBAAgB,KAA0C;AAC9E,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;AAGH,KAAI,IAAI,MAAM,YAAY,MACxB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,MAAM,UAAU,gBAAgB;AAChC,KAAI,CAAC,WAAW,QAAQ,CACtB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS,iBAAiB;EACnC;CAGH,MAAM,WAAW,qBAAqB;AACtC,KAAI,CAAC,WAAW,SAAS,CACvB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS;EAClB;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,KAAK,MAAM,aAAa,UAAU,QAAQ,CAAC;SAC3C;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,SAAS;GAClB;;AAGH,KAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,EAAE,UAAU,QAAQ,CAAC,MAAM,QAAS,IAA0B,KAAK,CACxG,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS;EAClB;CAGH,MAAM,OAAQ,IAA4B;CAC1C,MAAM,QAAkB,EAAE;CAC1B,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,kBAAkB;AAEtB,MAAK,MAAM,KAAK,MAAM;EACpB,MAAM,IAAI,cAAc,UAAU,EAAE;AACpC,MAAI,EAAE,SAAS;AACb;AACA,OAAI,EAAE,KAAK,SAAS;AAClB;AAEA,QAAI,CADU,EAAE,KAAK,UAAU,MAAM,EACzB;AACV;AACA,WAAM,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,GAAG,mCAAmC;;;SAG9E;AACL,SAAM,KAAK,+DAA+D;AAC1E;;;AAIJ,KAAI,UAAU,KAAK,OACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,MAAM,SAAS,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,SAAS;EACrD;AAGH,KAAI,kBAAkB,EACpB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,GAAG,gBAAgB;EAC5B,OAAO,MAAM,MAAM,GAAG,EAAE;EACzB;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,4BAA4B,QAAQ,YAAY,KAAK,OAAO;EACrE,OAAO,CAAC,SAAS;EAClB"}
1
+ {"version":3,"file":"cron-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/cron-health.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport { resolveCronDir, resolveCronJobsPath } from '../../../../config/paths.js';\nimport { JobDataSchema } from '../../../../cron/validation.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkCronHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n if (cfg.cron?.enabled === false) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'skip',\n message: 'Cron is disabled in config; skipped.',\n hints: [],\n };\n }\n\n const cronDir = resolveCronDir();\n if (!existsSync(cronDir)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron directory does not exist.',\n hints: [cronDir, 'Run: xopc init (creates cron directory)'],\n };\n }\n\n const jobsPath = resolveCronJobsPath();\n if (!existsSync(jobsPath)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is missing.',\n hints: [jobsPath],\n };\n }\n\n let raw: unknown;\n try {\n raw = JSON.parse(readFileSync(jobsPath, 'utf-8'));\n } catch {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file is not valid JSON.',\n hints: [jobsPath],\n };\n }\n\n if (!raw || typeof raw !== 'object' || !('jobs' in raw) || !Array.isArray((raw as { jobs: unknown }).jobs)) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Cron jobs file has invalid structure (expected { jobs: [] }).',\n hints: [jobsPath],\n };\n }\n\n const jobs = (raw as { jobs: unknown[] }).jobs;\n const hints: string[] = [];\n let valid = 0;\n let enabled = 0;\n let scheduleMissing = 0;\n\n for (const j of jobs) {\n const r = JobDataSchema.safeParse(j);\n if (r.success) {\n valid++;\n if (r.data.enabled) {\n enabled++;\n const sched = r.data.schedule?.trim();\n if (!sched) {\n scheduleMissing++;\n hints.push(`Job \"${r.data.name || r.data.id}\" is enabled but has no schedule.`);\n }\n }\n } else {\n hints.push('One or more job entries failed validation (check jobs.json).');\n break;\n }\n }\n\n if (valid !== jobs.length) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: 'Some cron jobs are invalid or could not be validated.',\n hints: hints.length ? hints.slice(0, 5) : [jobsPath],\n };\n }\n\n if (scheduleMissing > 0) {\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'warn',\n message: `${scheduleMissing} enabled job(s) are missing a schedule.`,\n hints: hints.slice(0, 5),\n };\n }\n\n return {\n id: 'cron-health',\n label: 'Cron',\n status: 'pass',\n message: `Cron jobs file is valid (${enabled} enabled, ${jobs.length} total).`,\n hints: [jobsPath],\n };\n}\n"],"mappings":";;;;;aAE0D;YAEwB;AAIlF,eAAsB,gBAAgB,KAA0C;AAC9E,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;AAGH,KAAI,IAAI,MAAM,YAAY,MACxB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,MAAM,UAAU,gBAAgB;AAChC,KAAI,CAAC,WAAW,QAAQ,CACtB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS,0CAA0C;EAC5D;CAGH,MAAM,WAAW,qBAAqB;AACtC,KAAI,CAAC,WAAW,SAAS,CACvB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS;EAClB;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,KAAK,MAAM,aAAa,UAAU,QAAQ,CAAC;SAC3C;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,SAAS;GAClB;;AAGH,KAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,EAAE,UAAU,QAAQ,CAAC,MAAM,QAAS,IAA0B,KAAK,CACxG,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,SAAS;EAClB;CAGH,MAAM,OAAQ,IAA4B;CAC1C,MAAM,QAAkB,EAAE;CAC1B,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,kBAAkB;AAEtB,MAAK,MAAM,KAAK,MAAM;EACpB,MAAM,IAAI,cAAc,UAAU,EAAE;AACpC,MAAI,EAAE,SAAS;AACb;AACA,OAAI,EAAE,KAAK,SAAS;AAClB;AAEA,QAAI,CADU,EAAE,KAAK,UAAU,MAAM,EACzB;AACV;AACA,WAAM,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,GAAG,mCAAmC;;;SAG9E;AACL,SAAM,KAAK,+DAA+D;AAC1E;;;AAIJ,KAAI,UAAU,KAAK,OACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,MAAM,SAAS,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,SAAS;EACrD;AAGH,KAAI,kBAAkB,EACpB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,GAAG,gBAAgB;EAC5B,OAAO,MAAM,MAAM,GAAG,EAAE;EACzB;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,4BAA4B,QAAQ,YAAY,KAAK,OAAO;EACrE,OAAO,CAAC,SAAS;EAClB"}
@@ -46,7 +46,7 @@ async function checkGatewayHealth(ctx) {
46
46
  label: "Gateway HTTP",
47
47
  status: "warn",
48
48
  message: `Gateway returned HTTP ${res.status} at ${url}.`,
49
- hints: ["Start the gateway: xopc gateway start"]
49
+ hints: ["Start the gateway: xopc gateway service start (or xopc gateway for foreground)"]
50
50
  };
51
51
  } catch (e) {
52
52
  clearTimeout(timer);
@@ -55,7 +55,7 @@ async function checkGatewayHealth(ctx) {
55
55
  label: "Gateway HTTP",
56
56
  status: "warn",
57
57
  message: e instanceof Error && e.name === "AbortError" ? `Gateway did not respond within ${FETCH_TIMEOUT_MS / 1e3}s (${url}).` : `Gateway not reachable (${url}).`,
58
- hints: ["Start the gateway: xopc gateway start", `Configured base: ${base}`]
58
+ hints: ["Start the gateway: xopc gateway service start (or xopc gateway for foreground)", `Configured base: ${base}`]
59
59
  };
60
60
  }
61
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/gateway-health.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport { resolveGatewayLocalClientHost } from '../../../../config/gateway-bind.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction resolveGatewayBaseUrl(cfg: Config): string {\n const host = resolveGatewayLocalClientHost(cfg);\n const port = cfg.gateway?.port ?? 18790;\n return `http://${host}:${port}`;\n}\n\nconst FETCH_TIMEOUT_MS = 5000;\n\nexport async function checkGatewayHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const base = resolveGatewayBaseUrl(cfg);\n const url = `${base.replace(/\\/$/, '')}/health`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n try {\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timer);\n if (res.ok) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'pass',\n message: `Gateway responded OK at ${url}.`,\n hints: [],\n };\n }\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: `Gateway returned HTTP ${res.status} at ${url}.`,\n hints: ['Start the gateway: xopc gateway start'],\n };\n } catch (e) {\n clearTimeout(timer);\n const isAbort = e instanceof Error && e.name === 'AbortError';\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: isAbort\n ? `Gateway did not respond within ${FETCH_TIMEOUT_MS / 1000}s (${url}).`\n : `Gateway not reachable (${url}).`,\n hints: ['Start the gateway: xopc gateway start', `Configured base: ${base}`],\n };\n }\n}\n"],"mappings":";;;;aAE0D;AAK1D,SAAS,sBAAsB,KAAqB;AAGlD,QAAO,UAFM,8BAA8B,IAEtB,CAAC,GADT,IAAI,SAAS,QAAQ;;AAIpC,MAAM,mBAAmB;AAEzB,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,OAAO,sBAAsB,IAAI;CACvC,MAAM,MAAM,GAAG,KAAK,QAAQ,OAAO,GAAG,CAAC;CACvC,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,iBAAiB;AAEpE,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,WAAW,QAAQ,CAAC;AAC3D,eAAa,MAAM;AACnB,MAAI,IAAI,GACN,QAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,2BAA2B,IAAI;GACxC,OAAO,EAAE;GACV;AAEH,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,yBAAyB,IAAI,OAAO,MAAM,IAAI;GACvD,OAAO,CAAC,wCAAwC;GACjD;UACM,GAAG;AACV,eAAa,MAAM;AAEnB,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SALc,aAAa,SAAS,EAAE,SAAS,eAM3C,kCAAkC,mBAAmB,IAAK,KAAK,IAAI,MACnE,0BAA0B,IAAI;GAClC,OAAO,CAAC,yCAAyC,oBAAoB,OAAO;GAC7E"}
1
+ {"version":3,"file":"gateway-health.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/gateway-health.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport { resolveGatewayLocalClientHost } from '../../../../config/gateway-bind.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction resolveGatewayBaseUrl(cfg: Config): string {\n const host = resolveGatewayLocalClientHost(cfg);\n const port = cfg.gateway?.port ?? 18790;\n return `http://${host}:${port}`;\n}\n\nconst FETCH_TIMEOUT_MS = 5000;\n\nexport async function checkGatewayHealth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const base = resolveGatewayBaseUrl(cfg);\n const url = `${base.replace(/\\/$/, '')}/health`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n\n try {\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(timer);\n if (res.ok) {\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'pass',\n message: `Gateway responded OK at ${url}.`,\n hints: [],\n };\n }\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: `Gateway returned HTTP ${res.status} at ${url}.`,\n hints: ['Start the gateway: xopc gateway service start (or xopc gateway for foreground)'],\n };\n } catch (e) {\n clearTimeout(timer);\n const isAbort = e instanceof Error && e.name === 'AbortError';\n return {\n id: 'gateway-health',\n label: 'Gateway HTTP',\n status: 'warn',\n message: isAbort\n ? `Gateway did not respond within ${FETCH_TIMEOUT_MS / 1000}s (${url}).`\n : `Gateway not reachable (${url}).`,\n hints: ['Start the gateway: xopc gateway service start (or xopc gateway for foreground)', `Configured base: ${base}`],\n };\n }\n}\n"],"mappings":";;;;aAE0D;AAK1D,SAAS,sBAAsB,KAAqB;AAGlD,QAAO,UAFM,8BAA8B,IAEtB,CAAC,GADT,IAAI,SAAS,QAAQ;;AAIpC,MAAM,mBAAmB;AAEzB,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,OAAO,sBAAsB,IAAI;CACvC,MAAM,MAAM,GAAG,KAAK,QAAQ,OAAO,GAAG,CAAC;CACvC,MAAM,aAAa,IAAI,iBAAiB;CACxC,MAAM,QAAQ,iBAAiB,WAAW,OAAO,EAAE,iBAAiB;AAEpE,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,WAAW,QAAQ,CAAC;AAC3D,eAAa,MAAM;AACnB,MAAI,IAAI,GACN,QAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,2BAA2B,IAAI;GACxC,OAAO,EAAE;GACV;AAEH,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,yBAAyB,IAAI,OAAO,MAAM,IAAI;GACvD,OAAO,CAAC,iFAAiF;GAC1F;UACM,GAAG;AACV,eAAa,MAAM;AAEnB,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SALc,aAAa,SAAS,EAAE,SAAS,eAM3C,kCAAkC,mBAAmB,IAAK,KAAK,IAAI,MACnE,0BAA0B,IAAI;GAClC,OAAO,CAAC,kFAAkF,oBAAoB,OAAO;GACtH"}