@xopcai/xopc 0.0.86 → 0.0.88

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 (658) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/adapters/cli-login.js +3 -3
  3. package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/delivery-chat-id.d.ts +1 -1
  7. package/dist/extensions/telegram/src/delivery-chat-id.js +1 -1
  8. package/dist/extensions/telegram/src/delivery-chat-id.js.map +1 -1
  9. package/dist/extensions/telegram/src/plugin.js +1 -1
  10. package/dist/extensions/telegram/src/routing-integration.js +3 -2
  11. package/dist/extensions/telegram/src/routing-integration.js.map +1 -1
  12. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  13. package/dist/extensions/telegram/xopc.extension.json +1 -1
  14. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +2 -2
  15. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -1
  16. package/dist/extensions/weixin/src/api/api.js +3 -3
  17. package/dist/extensions/weixin/src/api/api.js.map +1 -1
  18. package/dist/extensions/weixin/src/auth/accounts.js +12 -12
  19. package/dist/extensions/weixin/src/auth/accounts.js.map +1 -1
  20. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  21. package/dist/extensions/weixin/src/delivery-to.js +2 -2
  22. package/dist/extensions/weixin/src/delivery-to.js.map +1 -1
  23. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  24. package/dist/extensions/weixin/src/messaging/debug-mode.js +5 -5
  25. package/dist/extensions/weixin/src/messaging/debug-mode.js.map +1 -1
  26. package/dist/extensions/weixin/src/messaging/inbound.js +11 -11
  27. package/dist/extensions/weixin/src/messaging/inbound.js.map +1 -1
  28. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  29. package/dist/extensions/weixin/src/plugin.js +1 -1
  30. package/dist/extensions/weixin/src/storage/sync-buf.js +4 -4
  31. package/dist/extensions/weixin/src/storage/sync-buf.js.map +1 -1
  32. package/dist/extensions/weixin/src/workflow-progress.d.ts +1 -1
  33. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  34. package/dist/extensions/weixin/src/workflow-progress.js.map +1 -1
  35. package/dist/gateway/static/root/assets/agents-CRxETUZx.js +222 -0
  36. package/dist/gateway/static/root/assets/{apps-page-DrfytjOb.js → apps-page-wKWf3l57.js} +1 -1
  37. package/dist/gateway/static/root/assets/channels-settings-DDbqVNkx.js +1 -0
  38. package/dist/gateway/static/root/assets/{channels-status-swr-Bs5kMCMI.js → channels-status-swr-DIsl75Y3.js} +1 -1
  39. package/dist/gateway/static/root/assets/copy-SxMW6Xpc.js +1 -0
  40. package/dist/gateway/static/root/assets/{cron-api-BuVcZ5zR.js → cron-api-N9hvuRrn.js} +1 -1
  41. package/dist/gateway/static/root/assets/{cron-page-BMrloeFH.js → cron-page-tlNGNxhP.js} +1 -1
  42. package/dist/gateway/static/root/assets/{dist-CKU1OOTf.js → dist-CJwfHYvT.js} +1 -1
  43. package/dist/gateway/static/root/assets/{extension-debug-page-BdW_46sN.js → extension-debug-page-BVJohZoZ.js} +1 -1
  44. package/dist/gateway/static/root/assets/{extension-page-DW47KI82.js → extension-page-BT2tmElC.js} +1 -1
  45. package/dist/gateway/static/root/assets/extension-settings-page-BSS47c2j.js +1 -0
  46. package/dist/gateway/static/root/assets/{fetch-B2MYHbWg.js → fetch-BaFNUtkE.js} +1 -1
  47. package/dist/gateway/static/root/assets/{field-primitives-DPG-oJmx.js → field-primitives-QwYEq6Hz.js} +1 -1
  48. package/dist/gateway/static/root/assets/{heartbeat-config-api-C8dNts9i.js → heartbeat-config-api-BVSidEDJ.js} +1 -1
  49. package/dist/gateway/static/root/assets/index-CqZzHNEg.css +1 -0
  50. package/dist/gateway/static/root/assets/{index-BmVYculr.js → index-qNrVJp-y.js} +97 -95
  51. package/dist/gateway/static/root/assets/{logs-page-sTsVWz0X.js → logs-page-DDonPVLn.js} +1 -1
  52. package/dist/gateway/static/root/assets/sessions-page-DKt-Wmib.js +1 -0
  53. package/dist/gateway/static/root/assets/{settings-form-section-DuvRQW--.js → settings-form-section-B8N3A3Zo.js} +1 -1
  54. package/dist/gateway/static/root/assets/settings-page-DcJjvvw4.js +3 -0
  55. package/dist/gateway/static/root/assets/{share-preview-page-BtG2kLDh.js → share-preview-page-Q7KqkO-u.js} +1 -1
  56. package/dist/gateway/static/root/assets/skills-page-DuJ4BTO3.js +2 -0
  57. package/dist/gateway/static/root/assets/{theme-store-DryYl3qD.js → theme-store-BbRc5ugR.js} +1 -1
  58. package/dist/gateway/static/root/assets/url-D6jvVYIA.js +7 -0
  59. package/dist/gateway/static/root/assets/{utils-BY7bU1DT.js → utils-CxDGduqK.js} +1 -1
  60. package/dist/gateway/static/root/assets/voice-api-key-field-CTyHz7L_.js +1 -0
  61. package/dist/gateway/static/root/assets/workflows-page-GacJ41Fv.js +27 -0
  62. package/dist/gateway/static/root/index.html +6 -5
  63. package/dist/package.js +1 -1
  64. package/dist/src/agent/agent-manager.js +7 -7
  65. package/dist/src/agent/agent-scope.d.ts +4 -0
  66. package/dist/src/agent/agent-scope.js +53 -10
  67. package/dist/src/agent/agent-scope.js.map +1 -1
  68. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +2 -1
  69. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  70. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  71. package/dist/src/agent/child-agent-factory.d.ts +15 -0
  72. package/dist/src/agent/child-agent-factory.js +35 -2
  73. package/dist/src/agent/child-agent-factory.js.map +1 -1
  74. package/dist/src/agent/client-error-format.d.ts +20 -0
  75. package/dist/src/agent/client-error-format.js +97 -0
  76. package/dist/src/agent/client-error-format.js.map +1 -0
  77. package/dist/src/agent/context/workspace-seed.js +2 -2
  78. package/dist/src/agent/embedded/run-turn.js +23 -4
  79. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  80. package/dist/src/agent/embedded/session-tool-result-guard.js +2 -1
  81. package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
  82. package/dist/src/agent/embedded/tool-result-truncation.js +2 -1
  83. package/dist/src/agent/embedded/tool-result-truncation.js.map +1 -1
  84. package/dist/src/agent/fallback/candidates.js +2 -2
  85. package/dist/src/agent/fallback/candidates.js.map +1 -1
  86. package/dist/src/agent/goals/goal-locale.d.ts +1 -1
  87. package/dist/src/agent/goals/goal-run-store.js +4 -4
  88. package/dist/src/agent/goals/persistent-goal-apis.d.ts +0 -2
  89. package/dist/src/agent/goals/persistent-goal-service.js +1 -2
  90. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  91. package/dist/src/agent/goals/post-turn.js +2 -2
  92. package/dist/src/agent/image/generation/normalization.js +2 -12
  93. package/dist/src/agent/image/generation/normalization.js.map +1 -1
  94. package/dist/src/agent/image/generation/provider-registry.d.ts +4 -8
  95. package/dist/src/agent/image/generation/provider-registry.js.map +1 -1
  96. package/dist/src/agent/image/generation/runtime.d.ts +2 -2
  97. package/dist/src/agent/image/generation/runtime.js.map +1 -1
  98. package/dist/src/agent/image/generation/types.d.ts +0 -18
  99. package/dist/src/agent/image/image-helpers.js +6 -1
  100. package/dist/src/agent/image/image-helpers.js.map +1 -1
  101. package/dist/src/agent/image/index.d.ts +1 -1
  102. package/dist/src/agent/image/load-image-media.js +2 -2
  103. package/dist/src/agent/inbound/inbound-loop.d.ts +5 -0
  104. package/dist/src/agent/inbound/inbound-loop.js +41 -10
  105. package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
  106. package/dist/src/agent/inbound/turn-dispatcher.d.ts +4 -0
  107. package/dist/src/agent/inbound/turn-dispatcher.js +7 -5
  108. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  109. package/dist/src/agent/ipc/bus.js +1 -1
  110. package/dist/src/agent/ipc/inbox.js +2 -2
  111. package/dist/src/agent/ipc/socket.js +1 -1
  112. package/dist/src/agent/mcp/bundle-mcp-materialize.js +2 -1
  113. package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
  114. package/dist/src/agent/mcp/bundle-mcp-names.js +2 -1
  115. package/dist/src/agent/mcp/bundle-mcp-names.js.map +1 -1
  116. package/dist/src/agent/mcp/bundle-mcp-runtime.js +2 -1
  117. package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
  118. package/dist/src/agent/mcp/mcp-transport-config.js +2 -1
  119. package/dist/src/agent/mcp/mcp-transport-config.js.map +1 -1
  120. package/dist/src/agent/mcp/mcp-transport.js +2 -1
  121. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  122. package/dist/src/agent/media-generation/runtime-shared.js +2 -9
  123. package/dist/src/agent/media-generation/runtime-shared.js.map +1 -1
  124. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  125. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  126. package/dist/src/agent/memory/dreaming/events.js +1 -1
  127. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  128. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  129. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  130. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  131. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  132. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  133. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  134. package/dist/src/agent/messaging/command-handler.d.ts +6 -0
  135. package/dist/src/agent/messaging/command-handler.js +5 -0
  136. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  137. package/dist/src/agent/models/manager.js +1 -1
  138. package/dist/src/agent/orchestration/llm-turn-retry.d.ts +2 -0
  139. package/dist/src/agent/orchestration/llm-turn-retry.js +9 -1
  140. package/dist/src/agent/orchestration/llm-turn-retry.js.map +1 -1
  141. package/dist/src/agent/prompt/safety.d.ts +0 -7
  142. package/dist/src/agent/prompt/safety.js +1 -20
  143. package/dist/src/agent/prompt/safety.js.map +1 -1
  144. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  145. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  146. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  147. package/dist/src/agent/sandbox/path-policy.js +2 -2
  148. package/dist/src/agent/service/build-direct-message-content.js +2 -2
  149. package/dist/src/agent/service/build-direct-message-content.js.map +1 -1
  150. package/dist/src/agent/service/direct-turn-helpers.d.ts +3 -1
  151. package/dist/src/agent/service/direct-turn-helpers.js +6 -1
  152. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  153. package/dist/src/agent/service/process-direct-one-shot.d.ts +4 -0
  154. package/dist/src/agent/service/process-direct-one-shot.js +15 -2
  155. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  156. package/dist/src/agent/service/process-direct-streaming.d.ts +4 -0
  157. package/dist/src/agent/service/process-direct-streaming.js +53 -7
  158. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  159. package/dist/src/agent/service/webchat-tts.d.ts +1 -2
  160. package/dist/src/agent/service/webchat-tts.js +2 -2
  161. package/dist/src/agent/service/webchat-tts.js.map +1 -1
  162. package/dist/src/agent/service.d.ts +8 -0
  163. package/dist/src/agent/service.js +25 -5
  164. package/dist/src/agent/service.js.map +1 -1
  165. package/dist/src/agent/session/session-inspector.js +1 -1
  166. package/dist/src/agent/skills/config.js +1 -1
  167. package/dist/src/agent/skills/hub-hash.js +2 -2
  168. package/dist/src/agent/skills/hub-lock.js +1 -1
  169. package/dist/src/agent/skills/hub-pull.js +2 -2
  170. package/dist/src/agent/skills/index.js +1 -1
  171. package/dist/src/agent/skills/managed-store.js +1 -1
  172. package/dist/src/agent/skills/scanner.js +1 -1
  173. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  174. package/dist/src/agent/skills/skill-manager.js +1 -1
  175. package/dist/src/agent/tools/create-share-tool.js +27 -20
  176. package/dist/src/agent/tools/create-share-tool.js.map +1 -1
  177. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  178. package/dist/src/agent/tools/factory.js +2 -2
  179. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  180. package/dist/src/agent/tools/index.d.ts +0 -1
  181. package/dist/src/agent/tools/index.js +4 -5
  182. package/dist/src/agent/tools/send-media.js +1 -1
  183. package/dist/src/agent/tools/shell.js +0 -13
  184. package/dist/src/agent/tools/shell.js.map +1 -1
  185. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  186. package/dist/src/agent/tools/workflow-tool.js +70 -16
  187. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  188. package/dist/src/agent/tools/write.js +1 -1
  189. package/dist/src/agent/workflow/agent-progress.d.ts +5 -0
  190. package/dist/src/agent/workflow/agent-progress.js +65 -0
  191. package/dist/src/agent/workflow/agent-progress.js.map +1 -0
  192. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +1 -1
  193. package/dist/src/agent/workflow/builtins/audit-repo.js +14 -0
  194. package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -1
  195. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +1 -1
  196. package/dist/src/agent/workflow/builtins/debug-incident.js +14 -0
  197. package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -1
  198. package/dist/src/agent/workflow/builtins/implementation-plan.d.ts +12 -0
  199. package/dist/src/agent/workflow/builtins/implementation-plan.js +175 -0
  200. package/dist/src/agent/workflow/builtins/implementation-plan.js.map +1 -0
  201. package/dist/src/agent/workflow/builtins/index.d.ts +3 -1
  202. package/dist/src/agent/workflow/builtins/index.js +11 -1
  203. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  204. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +1 -1
  205. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +14 -0
  206. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -1
  207. package/dist/src/agent/workflow/builtins/pr-review.d.ts +1 -1
  208. package/dist/src/agent/workflow/builtins/pr-review.js +14 -0
  209. package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -1
  210. package/dist/src/agent/workflow/builtins/release-check.d.ts +11 -0
  211. package/dist/src/agent/workflow/builtins/release-check.js +165 -0
  212. package/dist/src/agent/workflow/builtins/release-check.js.map +1 -0
  213. package/dist/src/agent/workflow/builtins/research.d.ts +1 -1
  214. package/dist/src/agent/workflow/builtins/research.js +14 -0
  215. package/dist/src/agent/workflow/builtins/research.js.map +1 -1
  216. package/dist/src/agent/workflow/catalog.js +1 -1
  217. package/dist/src/agent/workflow/channel-capability.d.ts +3 -3
  218. package/dist/src/agent/workflow/index.d.ts +2 -1
  219. package/dist/src/agent/workflow/index.js +3 -2
  220. package/dist/src/agent/workflow/lint.d.ts +38 -0
  221. package/dist/src/agent/workflow/lint.js +74 -0
  222. package/dist/src/agent/workflow/lint.js.map +1 -0
  223. package/dist/src/agent/workflow/meta-locale.d.ts +12 -0
  224. package/dist/src/agent/workflow/meta-locale.js +62 -0
  225. package/dist/src/agent/workflow/meta-locale.js.map +1 -0
  226. package/dist/src/agent/workflow/parser.js +7 -1
  227. package/dist/src/agent/workflow/parser.js.map +1 -1
  228. package/dist/src/agent/workflow/runtime.d.ts +4 -1
  229. package/dist/src/agent/workflow/runtime.js +88 -8
  230. package/dist/src/agent/workflow/runtime.js.map +1 -1
  231. package/dist/src/agent/workflow/snapshot.js +2 -12
  232. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  233. package/dist/src/agent/workflow/step-labels.d.ts +8 -0
  234. package/dist/src/agent/workflow/step-labels.js +48 -0
  235. package/dist/src/agent/workflow/step-labels.js.map +1 -0
  236. package/dist/src/agent/workflow/subagent-runner.js +46 -1
  237. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  238. package/dist/src/agent/workflow/types.d.ts +76 -1
  239. package/dist/src/auth/credentials.d.ts +5 -0
  240. package/dist/src/auth/credentials.js +12 -3
  241. package/dist/src/auth/credentials.js.map +1 -1
  242. package/dist/src/auth/profiles/store.js +1 -1
  243. package/dist/src/auth/sync-provider-auth.js +1 -1
  244. package/dist/src/browser/cache-dir-policy.js +1 -1
  245. package/dist/src/browser/cdp-local-launcher.js +2 -2
  246. package/dist/src/browser/index.js +4 -4
  247. package/dist/src/browser/manager.d.ts +1 -3
  248. package/dist/src/browser/manager.js +0 -6
  249. package/dist/src/browser/manager.js.map +1 -1
  250. package/dist/src/browser/providers/browser-ext-install.d.ts +4 -4
  251. package/dist/src/browser/providers/browser-ext-install.js +41 -88
  252. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  253. package/dist/src/browser/providers/cloakbrowser.d.ts +0 -5
  254. package/dist/src/browser/providers/cloakbrowser.js +6 -59
  255. package/dist/src/browser/providers/cloakbrowser.js.map +1 -1
  256. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  257. package/dist/src/browser/stealth.js +1 -1
  258. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  259. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  260. package/dist/src/channels/attachments/voice-stt-webchat.js +10 -8
  261. package/dist/src/channels/attachments/voice-stt-webchat.js.map +1 -1
  262. package/dist/src/channels/outbound/persist-store.js +1 -1
  263. package/dist/src/channels/pairing/allow-from-file.js +9 -9
  264. package/dist/src/channels/pairing/allow-from-file.js.map +1 -1
  265. package/dist/src/channels/pairing/pairing-store.js +7 -7
  266. package/dist/src/channels/pairing/pairing-store.js.map +1 -1
  267. package/dist/src/chat-commands/builtins/config.js +2 -2
  268. package/dist/src/chat-commands/builtins/session.js +1 -1
  269. package/dist/src/chat-commands/builtins/session.js.map +1 -1
  270. package/dist/src/chat-commands/builtins/tts.js +2 -2
  271. package/dist/src/chat-commands/builtins/tts.js.map +1 -1
  272. package/dist/src/chat-commands/context.d.ts +3 -0
  273. package/dist/src/chat-commands/context.js +22 -4
  274. package/dist/src/chat-commands/context.js.map +1 -1
  275. package/dist/src/chat-commands/session-key.d.ts +4 -37
  276. package/dist/src/chat-commands/session-key.js +49 -85
  277. package/dist/src/chat-commands/session-key.js.map +1 -1
  278. package/dist/src/chat-commands/types.d.ts +2 -0
  279. package/dist/src/cli/commands/agent/interactive.js +2 -2
  280. package/dist/src/cli/commands/agent/interactive.js.map +1 -1
  281. package/dist/src/cli/commands/agent/sessions.js +2 -2
  282. package/dist/src/cli/commands/agent/sessions.js.map +1 -1
  283. package/dist/src/cli/commands/agent.js +4 -5
  284. package/dist/src/cli/commands/agent.js.map +1 -1
  285. package/dist/src/cli/commands/channels.js +1 -5
  286. package/dist/src/cli/commands/channels.js.map +1 -1
  287. package/dist/src/cli/commands/config.js +1 -1
  288. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  289. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  290. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  291. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  292. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  293. package/dist/src/cli/commands/extension-dev.js +1 -1
  294. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  295. package/dist/src/cli/commands/extension-pack.js +1 -1
  296. package/dist/src/cli/commands/gateway/lifecycle-core.js +1 -1
  297. package/dist/src/cli/commands/gateway/lifecycle-core.js.map +1 -1
  298. package/dist/src/cli/commands/gateway/logs.d.ts +9 -0
  299. package/dist/src/cli/commands/gateway/logs.js +50 -17
  300. package/dist/src/cli/commands/gateway/logs.js.map +1 -1
  301. package/dist/src/cli/commands/image.js +23 -22
  302. package/dist/src/cli/commands/image.js.map +1 -1
  303. package/dist/src/cli/commands/init.js +4 -4
  304. package/dist/src/cli/commands/onboard.js +1 -1
  305. package/dist/src/cli/commands/session/utils.js +2 -2
  306. package/dist/src/cli/commands/session/utils.js.map +1 -1
  307. package/dist/src/cli/commands/update.js +26 -46
  308. package/dist/src/cli/commands/update.js.map +1 -1
  309. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  310. package/dist/src/cli/utils/session.d.ts +0 -5
  311. package/dist/src/cli/utils/session.js +1 -6
  312. package/dist/src/cli/utils/session.js.map +1 -1
  313. package/dist/src/commands/agents.config.js +1 -1
  314. package/dist/src/commands/agents.config.js.map +1 -1
  315. package/dist/src/config/agent-profile.js +6 -28
  316. package/dist/src/config/agent-profile.js.map +1 -1
  317. package/dist/src/config/agent-typed-models.d.ts +18 -0
  318. package/dist/src/config/agent-typed-models.js +53 -0
  319. package/dist/src/config/agent-typed-models.js.map +1 -0
  320. package/dist/src/config/gateway-bind.js +1 -1
  321. package/dist/src/config/index.js +6 -6
  322. package/dist/src/config/loader.js +2 -2
  323. package/dist/src/config/model-input.js +2 -5
  324. package/dist/src/config/model-input.js.map +1 -1
  325. package/dist/src/config/models-json.js +2 -2
  326. package/dist/src/config/paths-state.js +1 -1
  327. package/dist/src/config/profile.js +2 -2
  328. package/dist/src/config/schema.d.ts +253 -217
  329. package/dist/src/config/schema.js +91 -40
  330. package/dist/src/config/schema.js.map +1 -1
  331. package/dist/src/config/voice.d.ts +3 -28
  332. package/dist/src/config/voice.js +27 -261
  333. package/dist/src/config/voice.js.map +1 -1
  334. package/dist/src/config/workspace-path-helpers.d.ts +1 -2
  335. package/dist/src/config/workspace-path-helpers.js.map +1 -1
  336. package/dist/src/config/workspace-path.js +1 -1
  337. package/dist/src/cron/executor.js +2 -2
  338. package/dist/src/cron/persistence.js +1 -1
  339. package/dist/src/cron/run-log-store.js +1 -1
  340. package/dist/src/daemon/constants.js +1 -1
  341. package/dist/src/daemon/install-plan.js +27 -3
  342. package/dist/src/daemon/install-plan.js.map +1 -1
  343. package/dist/src/daemon/launchd.d.ts +8 -0
  344. package/dist/src/daemon/launchd.js +7 -14
  345. package/dist/src/daemon/launchd.js.map +1 -1
  346. package/dist/src/daemon/schtasks.d.ts +25 -0
  347. package/dist/src/daemon/schtasks.js +168 -48
  348. package/dist/src/daemon/schtasks.js.map +1 -1
  349. package/dist/src/daemon/service.js +5 -4
  350. package/dist/src/daemon/service.js.map +1 -1
  351. package/dist/src/daemon/systemd.d.ts +6 -0
  352. package/dist/src/daemon/systemd.js +20 -5
  353. package/dist/src/daemon/systemd.js.map +1 -1
  354. package/dist/src/extensions/activation-context.js +0 -1
  355. package/dist/src/extensions/activation-context.js.map +1 -1
  356. package/dist/src/extensions/bundle-mcp.js +1 -1
  357. package/dist/src/extensions/discover-extensions.js +1 -1
  358. package/dist/src/extensions/health.js +1 -1
  359. package/dist/src/extensions/loader.js +1 -1
  360. package/dist/src/extensions/lockfile.js +2 -2
  361. package/dist/src/extensions/normalize-manifest.js +0 -1
  362. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  363. package/dist/src/extensions/types/manifest.d.ts +0 -2
  364. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  365. package/dist/src/gateway/agent-builtin-tools.js +1 -0
  366. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  367. package/dist/src/gateway/agents-admin.d.ts +9 -0
  368. package/dist/src/gateway/agents-admin.js +28 -4
  369. package/dist/src/gateway/agents-admin.js.map +1 -1
  370. package/dist/src/gateway/config-tools-web.js +3 -2
  371. package/dist/src/gateway/config-tools-web.js.map +1 -1
  372. package/dist/src/gateway/file-path-classifier.js +2 -2
  373. package/dist/src/gateway/heartbeat/service.js +2 -2
  374. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  375. package/dist/src/gateway/hono/app.js +1 -1
  376. package/dist/src/gateway/hono/lib/agent-model.d.ts +25 -10
  377. package/dist/src/gateway/hono/lib/agent-model.js +60 -36
  378. package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
  379. package/dist/src/gateway/hono/lib/config-payload.js +29 -6
  380. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  381. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  382. package/dist/src/gateway/hono/lib/mask-secret-length.d.ts +6 -0
  383. package/dist/src/gateway/hono/lib/mask-secret-length.js +16 -0
  384. package/dist/src/gateway/hono/lib/mask-secret-length.js.map +1 -0
  385. package/dist/src/gateway/hono/lib/safe-providers-config.d.ts +1 -1
  386. package/dist/src/gateway/hono/lib/safe-providers-config.js +2 -1
  387. package/dist/src/gateway/hono/lib/safe-providers-config.js.map +1 -1
  388. package/dist/src/gateway/hono/lib/safe-voice-config.js +16 -54
  389. package/dist/src/gateway/hono/lib/safe-voice-config.js.map +1 -1
  390. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  391. package/dist/src/gateway/hono/oauth.js +1 -1
  392. package/dist/src/gateway/hono/routes/agents.js +2 -2
  393. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  394. package/dist/src/gateway/hono/routes/config-patch/agents.js +25 -7
  395. package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
  396. package/dist/src/gateway/hono/routes/config-patch/channels.js +0 -11
  397. package/dist/src/gateway/hono/routes/config-patch/channels.js.map +1 -1
  398. package/dist/src/gateway/hono/routes/config-patch/gateway.js +3 -2
  399. package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
  400. package/dist/src/gateway/hono/routes/config-patch/misc.js +8 -3
  401. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  402. package/dist/src/gateway/hono/routes/config.js +59 -0
  403. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  404. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  405. package/dist/src/gateway/hono/routes/goals.js +1 -1
  406. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  407. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  408. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  409. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  410. package/dist/src/gateway/hono/routes/models.js +75 -12
  411. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  412. package/dist/src/gateway/hono/routes/sessions.js +28 -7
  413. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  414. package/dist/src/gateway/hono/routes/shares.js +15 -13
  415. package/dist/src/gateway/hono/routes/shares.js.map +1 -1
  416. package/dist/src/gateway/hono/routes/tunnel.js +1 -1
  417. package/dist/src/gateway/hono/routes/update.js +4 -2
  418. package/dist/src/gateway/hono/routes/update.js.map +1 -1
  419. package/dist/src/gateway/hono/routes/voice.js +75 -0
  420. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  421. package/dist/src/gateway/hono/routes/workflows.d.ts +3 -0
  422. package/dist/src/gateway/hono/routes/workflows.js +347 -0
  423. package/dist/src/gateway/hono/routes/workflows.js.map +1 -0
  424. package/dist/src/gateway/hono/routes/workspace.js +4 -4
  425. package/dist/src/gateway/hono/sse.js +16 -33
  426. package/dist/src/gateway/hono/sse.js.map +1 -1
  427. package/dist/src/gateway/lock.js +11 -11
  428. package/dist/src/gateway/lock.js.map +1 -1
  429. package/dist/src/gateway/ports.js +6 -6
  430. package/dist/src/gateway/ports.js.map +1 -1
  431. package/dist/src/gateway/resolve-webchat-session-key.d.ts +19 -0
  432. package/dist/src/gateway/resolve-webchat-session-key.js +46 -0
  433. package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -0
  434. package/dist/src/gateway/service/agent-runner.js +2 -2
  435. package/dist/src/gateway/service/marketplace-service.js +2 -2
  436. package/dist/src/gateway/service/run-gateway-agent.js +9 -11
  437. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  438. package/dist/src/gateway/service/sessions-api.d.ts +3 -0
  439. package/dist/src/gateway/service/sessions-api.js +8 -0
  440. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  441. package/dist/src/gateway/service.d.ts +3 -2
  442. package/dist/src/gateway/service.js +9 -8
  443. package/dist/src/gateway/service.js.map +1 -1
  444. package/dist/src/gateway/session-reset-service.d.ts +20 -0
  445. package/dist/src/gateway/session-reset-service.js +54 -0
  446. package/dist/src/gateway/session-reset-service.js.map +1 -0
  447. package/dist/src/gateway/startup-readiness.d.ts +1 -1
  448. package/dist/src/gateway/startup-readiness.js +1 -0
  449. package/dist/src/gateway/startup-readiness.js.map +1 -1
  450. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  451. package/dist/src/heartbeat/index.js +1 -1
  452. package/dist/src/infra/gateway-processes.js +2 -2
  453. package/dist/src/infra/gateway-processes.js.map +1 -1
  454. package/dist/src/infra/restart.js +2 -2
  455. package/dist/src/infra/run-command.d.ts +16 -0
  456. package/dist/src/infra/run-command.js +67 -0
  457. package/dist/src/infra/run-command.js.map +1 -0
  458. package/dist/src/infra/update-check.js +1 -1
  459. package/dist/src/infra/update-global.d.ts +45 -0
  460. package/dist/src/infra/update-global.js +224 -0
  461. package/dist/src/infra/update-global.js.map +1 -0
  462. package/dist/src/infra/update-lock.js +3 -3
  463. package/dist/src/infra/update-runner.js +1 -1
  464. package/dist/src/infra/update-startup.js +2 -2
  465. package/dist/src/infra/write-file-atomic.js +2 -2
  466. package/dist/src/mcp/channel-shared.js +2 -1
  467. package/dist/src/mcp/channel-shared.js.map +1 -1
  468. package/dist/src/providers/auth-runtime/auth-profile-store.js +2 -2
  469. package/dist/src/providers/auth-runtime/auth-profile-store.js.map +1 -1
  470. package/dist/src/providers/auth-runtime/resolve-auth.js +1 -12
  471. package/dist/src/providers/auth-runtime/resolve-auth.js.map +1 -1
  472. package/dist/src/providers/auth-runtime/types.d.ts +6 -12
  473. package/dist/src/providers/index.js +2 -2
  474. package/dist/src/providers/model-registry.js +1 -1
  475. package/dist/src/routing/agent-session-key.d.ts +58 -0
  476. package/dist/src/routing/agent-session-key.js +164 -0
  477. package/dist/src/routing/agent-session-key.js.map +1 -0
  478. package/dist/src/routing/index.d.ts +1 -1
  479. package/dist/src/routing/index.js +4 -2
  480. package/dist/src/routing/index.js.map +1 -1
  481. package/dist/src/routing/resolve-route.d.ts +15 -0
  482. package/dist/src/routing/resolve-route.js +41 -20
  483. package/dist/src/routing/resolve-route.js.map +1 -1
  484. package/dist/src/routing/resolve-tui-session-key.d.ts +25 -0
  485. package/dist/src/routing/resolve-tui-session-key.js +54 -0
  486. package/dist/src/routing/resolve-tui-session-key.js.map +1 -0
  487. package/dist/src/routing/session-key-utils.d.ts +24 -0
  488. package/dist/src/routing/session-key-utils.js +92 -0
  489. package/dist/src/routing/session-key-utils.js.map +1 -0
  490. package/dist/src/routing/session-key.d.ts +19 -49
  491. package/dist/src/routing/session-key.js +143 -116
  492. package/dist/src/routing/session-key.js.map +1 -1
  493. package/dist/src/session/config-store.js +2 -2
  494. package/dist/src/session/index.d.ts +6 -0
  495. package/dist/src/session/index.js +7 -1
  496. package/dist/src/session/init-session-turn.d.ts +30 -0
  497. package/dist/src/session/init-session-turn.js +102 -0
  498. package/dist/src/session/init-session-turn.js.map +1 -0
  499. package/dist/src/session/lifecycle-timestamps.d.ts +8 -0
  500. package/dist/src/session/lifecycle-timestamps.js +16 -0
  501. package/dist/src/session/lifecycle-timestamps.js.map +1 -0
  502. package/dist/src/session/manager.d.ts +7 -1
  503. package/dist/src/session/manager.js +8 -1
  504. package/dist/src/session/manager.js.map +1 -1
  505. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  506. package/dist/src/session/parity/sessions-json-file.js +1 -1
  507. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  508. package/dist/src/session/parity/transcript-paths.js +2 -2
  509. package/dist/src/session/parity/transcript-paths.js.map +1 -1
  510. package/dist/src/session/parity/xopc-session-disk-entry.d.ts +6 -0
  511. package/dist/src/session/reset-policy.d.ts +32 -0
  512. package/dist/src/session/reset-policy.js +65 -0
  513. package/dist/src/session/reset-policy.js.map +1 -0
  514. package/dist/src/session/reset-triggers.d.ts +20 -0
  515. package/dist/src/session/reset-triggers.js +63 -0
  516. package/dist/src/session/reset-triggers.js.map +1 -0
  517. package/dist/src/session/reset-type.d.ts +12 -0
  518. package/dist/src/session/reset-type.js +25 -0
  519. package/dist/src/session/reset-type.js.map +1 -0
  520. package/dist/src/session/resolve-session.d.ts +30 -0
  521. package/dist/src/session/resolve-session.js +93 -0
  522. package/dist/src/session/resolve-session.js.map +1 -0
  523. package/dist/src/session/search-index-cache.js +1 -1
  524. package/dist/src/session/search-index.js +1 -1
  525. package/dist/src/session/session-title.js +3 -2
  526. package/dist/src/session/session-title.js.map +1 -1
  527. package/dist/src/session/store.d.ts +11 -4
  528. package/dist/src/session/store.js +62 -11
  529. package/dist/src/session/store.js.map +1 -1
  530. package/dist/src/session/transcript-events.js +2 -1
  531. package/dist/src/session/transcript-events.js.map +1 -1
  532. package/dist/src/share/share-auto.js +2 -2
  533. package/dist/src/share/share-store.js +3 -3
  534. package/dist/src/share/share-thumbnail.js +2 -2
  535. package/dist/src/share/share-url.d.ts +33 -0
  536. package/dist/src/share/share-url.js +56 -14
  537. package/dist/src/share/share-url.js.map +1 -1
  538. package/dist/src/share/share-zip.js +1 -1
  539. package/dist/src/share/site-share-store.js +3 -3
  540. package/dist/src/share/site-static-serve.js +1 -1
  541. package/dist/src/tui/backends/embedded-backend.js +4 -9
  542. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  543. package/dist/src/tui/backends/gateway-sse-backend.js +1 -1
  544. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  545. package/dist/src/tui/clipboard-image.js +3 -3
  546. package/dist/src/tui/components/chat-log.js +3 -3
  547. package/dist/src/tui/components/chat-log.js.map +1 -1
  548. package/dist/src/tui/theme-manager.js +1 -1
  549. package/dist/src/tui/theme.d.ts +0 -2
  550. package/dist/src/tui/theme.js +1 -3
  551. package/dist/src/tui/theme.js.map +1 -1
  552. package/dist/src/tui/tui-agent-events.js +2 -1
  553. package/dist/src/tui/tui-agent-events.js.map +1 -1
  554. package/dist/src/tui/tui-commands.d.ts +3 -0
  555. package/dist/src/tui/tui-commands.js +45 -10
  556. package/dist/src/tui/tui-commands.js.map +1 -1
  557. package/dist/src/tui/tui-keybindings-file.js +2 -22
  558. package/dist/src/tui/tui-keybindings-file.js.map +1 -1
  559. package/dist/src/tui/tui-scoped-models.js +2 -2
  560. package/dist/src/tui/tui-session-actions.d.ts +28 -0
  561. package/dist/src/tui/tui-session-actions.js +88 -0
  562. package/dist/src/tui/tui-session-actions.js.map +1 -0
  563. package/dist/src/tui/tui-settings.js +1 -1
  564. package/dist/src/tui/tui.js +54 -49
  565. package/dist/src/tui/tui.js.map +1 -1
  566. package/dist/src/tunnel/frpc-binary.js +3 -3
  567. package/dist/src/tunnel/frpc-config.js +1 -1
  568. package/dist/src/tunnel/frpc-extract.js +1 -1
  569. package/dist/src/tunnel/tunnel-state.js +1 -1
  570. package/dist/src/utils/logger/audit.js +1 -1
  571. package/dist/src/utils/logger/log-store.js +1 -1
  572. package/dist/src/utils/logger/rotation.js +1 -1
  573. package/dist/src/utils/string-coerce.d.ts +2 -0
  574. package/dist/src/utils/string-coerce.js +10 -1
  575. package/dist/src/utils/string-coerce.js.map +1 -1
  576. package/dist/src/voice/metadata/builtin.d.ts +2 -0
  577. package/dist/src/voice/metadata/builtin.js +420 -0
  578. package/dist/src/voice/metadata/builtin.js.map +1 -0
  579. package/dist/src/voice/metadata/index.d.ts +4 -0
  580. package/dist/src/voice/metadata/index.js +3 -0
  581. package/dist/src/voice/metadata/registry.d.ts +5 -0
  582. package/dist/src/voice/metadata/registry.js +34 -0
  583. package/dist/src/voice/metadata/registry.js.map +1 -0
  584. package/dist/src/voice/metadata/types.d.ts +41 -0
  585. package/dist/src/voice/metadata/types.js +1 -0
  586. package/dist/src/voice/stt/config-slice.d.ts +2 -5
  587. package/dist/src/voice/stt/config-slice.js +5 -26
  588. package/dist/src/voice/stt/config-slice.js.map +1 -1
  589. package/dist/src/voice/stt/list-providers.d.ts +3 -3
  590. package/dist/src/voice/stt/list-providers.js +41 -6
  591. package/dist/src/voice/stt/list-providers.js.map +1 -1
  592. package/dist/src/voice/stt/types.d.ts +1 -18
  593. package/dist/src/voice/stt/types.js +4 -2
  594. package/dist/src/voice/stt/types.js.map +1 -1
  595. package/dist/src/voice/tts/audio.js +1 -1
  596. package/dist/src/voice/tts/config-slice.d.ts +3 -7
  597. package/dist/src/voice/tts/config-slice.js +7 -38
  598. package/dist/src/voice/tts/config-slice.js.map +1 -1
  599. package/dist/src/voice/tts/list-providers.d.ts +3 -3
  600. package/dist/src/voice/tts/list-providers.js +41 -6
  601. package/dist/src/voice/tts/list-providers.js.map +1 -1
  602. package/dist/src/voice/tts/merge-config.js +2 -48
  603. package/dist/src/voice/tts/merge-config.js.map +1 -1
  604. package/dist/src/voice/tts/providers/alibaba-speech.js +1 -1
  605. package/dist/src/voice/tts/providers/alibaba-speech.js.map +1 -1
  606. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  607. package/dist/src/voice/tts/types.d.ts +1 -29
  608. package/dist/src/voice/tts/types.js +19 -17
  609. package/dist/src/voice/tts/types.js.map +1 -1
  610. package/dist/src/workflows/domain/command.d.ts +18 -0
  611. package/dist/src/workflows/domain/command.js +1 -0
  612. package/dist/src/workflows/domain/definition.d.ts +62 -0
  613. package/dist/src/workflows/domain/definition.js +1 -0
  614. package/dist/src/workflows/domain/event.d.ts +67 -0
  615. package/dist/src/workflows/domain/event.js +1 -0
  616. package/dist/src/workflows/domain/index.d.ts +5 -0
  617. package/dist/src/workflows/domain/index.js +2 -0
  618. package/dist/src/workflows/domain/result.d.ts +65 -0
  619. package/dist/src/workflows/domain/result.js +1 -0
  620. package/dist/src/workflows/domain/run.d.ts +120 -0
  621. package/dist/src/workflows/domain/run.js +14 -0
  622. package/dist/src/workflows/domain/run.js.map +1 -0
  623. package/dist/src/workflows/engine/index.d.ts +2 -0
  624. package/dist/src/workflows/engine/index.js +3 -0
  625. package/dist/src/workflows/engine/projector.d.ts +3 -0
  626. package/dist/src/workflows/engine/projector.js +205 -0
  627. package/dist/src/workflows/engine/projector.js.map +1 -0
  628. package/dist/src/workflows/engine/workflow-engine.d.ts +31 -0
  629. package/dist/src/workflows/engine/workflow-engine.js +188 -0
  630. package/dist/src/workflows/engine/workflow-engine.js.map +1 -0
  631. package/dist/src/workflows/index.d.ts +6 -0
  632. package/dist/src/workflows/index.js +11 -0
  633. package/dist/src/workflows/runtime/index.d.ts +1 -0
  634. package/dist/src/workflows/runtime/index.js +4 -0
  635. package/dist/src/workflows/runtime/script-runtime.d.ts +3 -0
  636. package/dist/src/workflows/runtime/script-runtime.js +3 -0
  637. package/dist/src/workflows/store/event-store.d.ts +17 -0
  638. package/dist/src/workflows/store/event-store.js +83 -0
  639. package/dist/src/workflows/store/event-store.js.map +1 -0
  640. package/dist/src/workflows/store/paths.d.ts +7 -0
  641. package/dist/src/workflows/store/paths.js +26 -0
  642. package/dist/src/workflows/store/paths.js.map +1 -0
  643. package/dist/src/workflows/store/run-store.d.ts +13 -0
  644. package/dist/src/workflows/store/run-store.js +68 -0
  645. package/dist/src/workflows/store/run-store.js.map +1 -0
  646. package/package.json +5 -8
  647. package/dist/gateway/static/root/assets/agents-mS3_HpRI.js +0 -222
  648. package/dist/gateway/static/root/assets/channels-settings-BG6b9KrW.js +0 -1
  649. package/dist/gateway/static/root/assets/extension-settings-page-B-W4x2xP.js +0 -1
  650. package/dist/gateway/static/root/assets/index-ew_2L2We.css +0 -1
  651. package/dist/gateway/static/root/assets/sessions-page-FaG_Vlkb.js +0 -1
  652. package/dist/gateway/static/root/assets/settings-page-Bet1OerL.js +0 -3
  653. package/dist/gateway/static/root/assets/skills-page-DhUO235y.js +0 -2
  654. package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +0 -3
  655. package/dist/gateway/static/root/assets/voice-api-key-field-CGEydndO.js +0 -1
  656. package/dist/src/agent/tools/browser-legacy-tools.d.ts +0 -17
  657. package/dist/src/agent/tools/browser-legacy-tools.js +0 -766
  658. package/dist/src/agent/tools/browser-legacy-tools.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"channels.js","names":[],"sources":["../../../../src/cli/commands/channels.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { approveChannelPairingFromCli, type PairingCliChannel } from '../../channels/pairing/index.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport {\n getChannelPlugin,\n listChannelPlugins,\n syncChannelPluginsFromManager,\n} from '../../channels/plugins/registry.js';\nimport { bundledChannelPlugins } from '../../generated/bundled-channel-plugins.js';\nimport { loadConfig } from '../../config/loader.js';\nimport type { Config } from '../../config/schema.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { colors } from '../utils/colors.js';\n\nimport {\n SETUP_EXIT,\n SetupValidationError,\n emitOutcome,\n isPromptCancelled,\n promptSecret,\n runSetup,\n type SetupOutcome,\n} from './setup-shared/index.js';\n\nfunction ensureChannelRegistryForCli(): void {\n if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\n}\n\nfunction resolveConfigPathFromCommand(command: Command): string {\n const root =\n command.parent?.parent && command.parent.parent instanceof Command\n ? command.parent.parent\n : command.parent && command.parent instanceof Command\n ? command.parent\n : null;\n const globalOpts = (root && typeof root.opts === 'function'\n ? (root.opts() as { config?: string })\n : {}) as { config?: string };\n return (\n globalOpts.config?.trim() ||\n process.env.XOPC_CONFIG_PATH?.trim() ||\n process.env.XOPC_CONFIG?.trim() ||\n resolveConfigPath()\n );\n}\n\nfunction createChannelsCommand(ctx: CLIContext): Command {\n const cmd = new Command('channels')\n .description('Messaging channel login and credentials')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc channels login',\n 'xopc channels login --channel weixin',\n 'xopc channels login --channel feishu',\n 'xopc channels login --account my-bot-id',\n 'xopc channels pairing approve --channel telegram ABC12XYZ',\n ]),\n );\n\n const PAIRING_CHANNELS = new Set<PairingCliChannel>(['telegram', 'feishu', 'weixin']);\n\n cmd\n .command('login')\n .description('Log in with QR code or channel-specific credentials flow')\n .option(\n '--channel <id>',\n 'Channel id (auto-detected when only one login-capable channel is registered)',\n )\n .option('--account <id>', 'Optional account id when re-logging an existing bot')\n .option('--timeout <ms>', 'Max wait for scan (default 480000)', '480000')\n .option('--credentials-only', 'Only save token files; do not update xopc.json')\n .action(async (options, command) => {\n ensureChannelRegistryForCli();\n const explicitChannel = options.channel?.trim?.();\n let channelId: string;\n if (explicitChannel) {\n channelId = explicitChannel;\n } else {\n const loginCapable = listChannelPlugins().filter((p) => p.cliLogin);\n if (loginCapable.length === 1) {\n channelId = loginCapable[0].id;\n console.log(`Auto-detected channel: ${channelId}`);\n } else if (loginCapable.length === 0) {\n console.error('No channels with login support found.');\n process.exitCode = 1;\n return;\n } else {\n console.error(\n `Multiple channels support login: ${loginCapable.map((p) => p.id).join(', ')}. ` +\n 'Use --channel <id> to specify.',\n );\n process.exitCode = 1;\n return;\n }\n }\n const plugin = getChannelPlugin(channelId);\n if (!plugin?.cliLogin) {\n console.error(`Channel \"${channelId}\" does not support CLI login.`);\n const capable = listChannelPlugins()\n .filter((p) => p.cliLogin)\n .map((p) => p.id);\n if (capable.length > 0) {\n console.error(`Channels with login support: ${capable.join(', ')}`);\n }\n process.exitCode = 1;\n return;\n }\n\n const configPath = resolveConfigPathFromCommand(command);\n const timeoutMs = Math.max(60_000, Number.parseInt(String(options.timeout), 10) || 480_000);\n const verbose = ctx.isVerbose;\n\n const result = await plugin.cliLogin.runLogin({\n configPath,\n verbose,\n timeoutMs,\n accountId: options.account?.trim() || undefined,\n writeConfig: !options.credentialsOnly,\n });\n\n if (!result.ok) {\n if (result.cancelled) {\n process.exitCode = 130;\n return;\n }\n console.error(result.message || 'Login failed');\n process.exitCode = 1;\n }\n });\n\n cmd\n .command('list')\n .description('List configured channels and their account status')\n .option('--json', 'Output as JSON for agents/UIs', false)\n .action((opts: { json?: boolean }) => {\n ensureChannelRegistryForCli();\n const cfg = loadConfig(resolveConfigPathFromCommand(cmd));\n const channelsCfg = (cfg.channels ?? {}) as Record<string, Record<string, unknown>>;\n const entries = listChannelPlugins().map((plugin) => {\n const raw = channelsCfg[plugin.id] ?? {};\n const enabled = raw.enabled === true;\n const accounts = (raw.accounts ?? {}) as Record<string, Record<string, unknown>>;\n const accountSummaries = Object.entries(accounts).map(([id, acct]) => ({\n accountId: id,\n enabled: acct.enabled !== false,\n configured: typeof acct.botToken === 'string'\n ? Boolean((acct.botToken as string).trim())\n : false,\n }));\n return {\n id: plugin.id,\n name: plugin.meta?.label ?? plugin.id,\n enabled,\n hasLogin: Boolean(plugin.cliLogin),\n accountCount: accountSummaries.length,\n accounts: accountSummaries,\n };\n });\n if (opts.json) {\n process.stdout.write(JSON.stringify({ ok: true, channels: entries }) + '\\n');\n return;\n }\n console.log('');\n console.log(colors.bold('CHANNELS'));\n const idWidth = Math.max(...entries.map((e) => e.id.length));\n for (const e of entries) {\n const status = e.enabled\n ? colors.green('● enabled')\n : colors.gray('○ disabled');\n const accts = e.accountCount > 0 ? colors.gray(` (${e.accountCount} accounts)`) : '';\n console.log(` ${e.id.padEnd(idWidth)} ${status} ${colors.gray(e.name)}${accts}`);\n }\n console.log('');\n console.log(colors.gray('Use: xopc channels add <id> [--token <token>]'));\n });\n\n cmd\n .command('add <channel>')\n .description('Add or update a channel account (currently: telegram)')\n .option('--token <value>', 'Bot token (Telegram). Prompts securely if omitted.')\n .option('--account <id>', 'Account id (default: \"default\")')\n .option('--enable', 'Enable the channel after writing (default: true)', true)\n .option('--dry-run', 'Show the change without writing', false)\n .option('--json', 'Emit a single JSON outcome line', false)\n .action(\n async (\n channel: string,\n opts: {\n token?: string;\n account?: string;\n enable?: boolean;\n dryRun?: boolean;\n json?: boolean;\n },\n ) => {\n const channelId = channel.trim().toLowerCase();\n const accountId = opts.account?.trim() || 'default';\n const dryRun = Boolean(opts.dryRun);\n const json = Boolean(opts.json);\n\n if (channelId === 'feishu' || channelId === 'weixin') {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: `channels.${channelId}`,\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [\n {\n message:\n channelId === 'weixin'\n ? 'Weixin uses interactive QR login. Run: xopc channels login --channel weixin'\n : 'Feishu add via CLI is not yet implemented. Edit `~/.xopc/xopc.json` (channels.feishu) or run: xopc onboard --channels',\n },\n ],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.ERROR;\n return;\n }\n\n if (channelId !== 'telegram') {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: `channels.${channelId}`,\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [{ message: `Unknown channel \"${channelId}\". Try: xopc channels list` }],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.ERROR;\n return;\n }\n\n let token = opts.token?.trim();\n if (!token) {\n token = process.env.TELEGRAM_BOT_TOKEN?.trim();\n }\n if (!token) {\n try {\n token = await promptSecret('Telegram bot token (from @BotFather):');\n } catch (error) {\n if (isPromptCancelled(error)) {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: 'channels.telegram',\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [{ message: 'Cancelled by user' }],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.CANCELLED;\n return;\n }\n throw error;\n }\n }\n\n if (!validateTelegramToken(token)) {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: 'channels.telegram',\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [{ path: 'token', message: 'Token does not look like a Telegram bot token (expected `<digits>:<35+ chars>`).' }],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.ERROR;\n return;\n }\n\n await runSetup({\n configPath: resolveConfigPathFromCommand(cmd),\n options: { dryRun, json },\n mutator: {\n domain: 'channels.telegram',\n target: accountId,\n action: 'add',\n mutate(config) {\n return applyTelegramAccount(config, accountId, token!, opts.enable !== false);\n },\n resultValue: () => ({\n channel: 'telegram',\n accountId,\n tokenMask: maskToken(token!),\n }),\n notes: () => [\n opts.enable !== false\n ? 'Telegram channel enabled. Restart the gateway for the new bot to come online.'\n : 'Telegram credentials saved (channel disabled). Use `--enable` to start it.',\n ],\n },\n });\n },\n );\n\n cmd\n .command('remove <channel>')\n .description('Remove a channel account')\n .option('--account <id>', 'Account id (default: \"default\")')\n .option('--dry-run', 'Show the change without writing', false)\n .option('--json', 'Emit a single JSON outcome line', false)\n .action(\n async (\n channel: string,\n opts: { account?: string; dryRun?: boolean; json?: boolean },\n ) => {\n const channelId = channel.trim().toLowerCase();\n const accountId = opts.account?.trim() || 'default';\n const dryRun = Boolean(opts.dryRun);\n const json = Boolean(opts.json);\n\n await runSetup({\n configPath: resolveConfigPathFromCommand(cmd),\n options: { dryRun, json },\n mutator: {\n domain: `channels.${channelId}`,\n target: accountId,\n action: 'remove',\n mutate(config) {\n return removeChannelAccount(config, channelId, accountId);\n },\n },\n });\n },\n );\n\n cmd\n .command('schema [channel]')\n .description('Print credential schemas for channels (for agents / UIs)')\n .option('--json', 'JSON output (default human-readable JSON)', false)\n .action((channel: string | undefined, opts: { json?: boolean }) => {\n ensureChannelRegistryForCli();\n const all = listChannelPlugins().map((p) => ({\n id: p.id,\n name: p.meta?.label ?? p.id,\n hasLogin: Boolean(p.cliLogin),\n configSchema: p.configSchema?.schema,\n }));\n const payload = {\n ok: true,\n channels: channel ? all.filter((c) => c.id === channel) : all,\n };\n if (opts.json) {\n process.stdout.write(JSON.stringify(payload) + '\\n');\n } else {\n console.log(JSON.stringify(payload, null, 2));\n }\n });\n\n cmd\n .command('pairing')\n .description('Approve DM pairing requests (updates channel allowFrom credential files)')\n .addCommand(\n new Command('approve')\n .description('Approve a pairing code shown to the user in Telegram / Feishu / Weixin DMs')\n .requiredOption('--channel <id>', 'telegram | feishu | weixin')\n .option('--account <id>', 'Bot account id from config', 'default')\n .argument('<code>', 'Pairing code from the user message')\n .action((code: string, options: { channel?: string; account?: string }) => {\n const ch = (options.channel ?? '').trim().toLowerCase() as PairingCliChannel;\n if (!PAIRING_CHANNELS.has(ch)) {\n console.error('Invalid --channel. Use: telegram, feishu, or weixin.');\n process.exitCode = 1;\n return;\n }\n const accountId = (options.account ?? 'default').trim() || 'default';\n const result = approveChannelPairingFromCli({\n channel: ch,\n accountId,\n code: String(code ?? '').trim(),\n });\n if (result.ok === false) {\n console.error(result.error);\n process.exitCode = 1;\n return;\n }\n console.log(`Approved. Sender id added to allowFrom store: ${result.senderId}`);\n }),\n );\n\n return cmd;\n}\n\n// ---------- helpers ----------\n\nconst TELEGRAM_TOKEN_PATTERN = /^\\d{5,}:[A-Za-z0-9_-]{30,}$/;\n\nexport function validateTelegramToken(token: string): boolean {\n return TELEGRAM_TOKEN_PATTERN.test(token.trim());\n}\n\nexport function maskToken(token: string): string {\n const t = token.trim();\n if (t.length <= 8) return '*'.repeat(t.length);\n return `${t.slice(0, 4)}…${t.slice(-4)}`;\n}\n\nexport function applyTelegramAccount(\n cfg: Config,\n accountId: string,\n botToken: string,\n enable: boolean,\n): Config {\n const channels = { ...((cfg.channels ?? {}) as Record<string, unknown>) };\n const tg = { ...((channels.telegram ?? {}) as Record<string, unknown>) };\n if (enable) tg.enabled = true;\n // Preserve the legacy single-account top-level field for backwards\n // compatibility with older config readers.\n tg.botToken = botToken;\n const accounts = { ...((tg.accounts ?? {}) as Record<string, Record<string, unknown>>) };\n accounts[accountId] = {\n ...(accounts[accountId] ?? {}),\n accountId,\n enabled: true,\n botToken,\n };\n tg.accounts = accounts;\n channels.telegram = tg;\n return { ...cfg, channels } as Config;\n}\n\nexport function removeChannelAccount(\n cfg: Config,\n channelId: string,\n accountId: string,\n): Config {\n if (channelId === 'feishu' || channelId === 'weixin' || channelId === 'telegram') {\n const channels = { ...((cfg.channels ?? {}) as Record<string, unknown>) };\n const ch = { ...((channels[channelId] ?? {}) as Record<string, unknown>) };\n const accounts = { ...((ch.accounts ?? {}) as Record<string, unknown>) };\n if (!(accountId in accounts)) {\n throw new SetupValidationError([\n { message: `No account \"${accountId}\" on channel \"${channelId}\".` },\n ]);\n }\n delete accounts[accountId];\n ch.accounts = accounts;\n if (Object.keys(accounts).length === 0) {\n ch.enabled = false;\n // Drop legacy top-level token alongside the last removed account.\n if (channelId === 'telegram') {\n delete ch.botToken;\n }\n }\n channels[channelId] = ch;\n return { ...cfg, channels } as Config;\n }\n throw new SetupValidationError([\n { message: `Unknown channel \"${channelId}\". Try: xopc channels list` },\n ]);\n}\n\nregister({\n id: 'channels',\n name: 'channels',\n description: 'Messaging channel login',\n factory: createChannelsCommand,\n metadata: {\n category: 'setup',\n examples: [\n 'xopc channels list',\n 'xopc channels add telegram --token 123456:ABC...',\n 'xopc channels remove telegram',\n 'xopc channels login',\n 'xopc channels pairing approve --channel feishu --account default ABC12XYZ',\n ],\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"channels.js","names":[],"sources":["../../../../src/cli/commands/channels.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { approveChannelPairingFromCli, type PairingCliChannel } from '../../channels/pairing/index.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport {\n getChannelPlugin,\n listChannelPlugins,\n syncChannelPluginsFromManager,\n} from '../../channels/plugins/registry.js';\nimport { bundledChannelPlugins } from '../../generated/bundled-channel-plugins.js';\nimport { loadConfig } from '../../config/loader.js';\nimport type { Config } from '../../config/schema.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { colors } from '../utils/colors.js';\n\nimport {\n SETUP_EXIT,\n SetupValidationError,\n emitOutcome,\n isPromptCancelled,\n promptSecret,\n runSetup,\n type SetupOutcome,\n} from './setup-shared/index.js';\n\nfunction ensureChannelRegistryForCli(): void {\n if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\n}\n\nfunction resolveConfigPathFromCommand(command: Command): string {\n const root =\n command.parent?.parent && command.parent.parent instanceof Command\n ? command.parent.parent\n : command.parent && command.parent instanceof Command\n ? command.parent\n : null;\n const globalOpts = (root && typeof root.opts === 'function'\n ? (root.opts() as { config?: string })\n : {}) as { config?: string };\n return (\n globalOpts.config?.trim() ||\n process.env.XOPC_CONFIG_PATH?.trim() ||\n process.env.XOPC_CONFIG?.trim() ||\n resolveConfigPath()\n );\n}\n\nfunction createChannelsCommand(ctx: CLIContext): Command {\n const cmd = new Command('channels')\n .description('Messaging channel login and credentials')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc channels login',\n 'xopc channels login --channel weixin',\n 'xopc channels login --channel feishu',\n 'xopc channels login --account my-bot-id',\n 'xopc channels pairing approve --channel telegram ABC12XYZ',\n ]),\n );\n\n const PAIRING_CHANNELS = new Set<PairingCliChannel>(['telegram', 'feishu', 'weixin']);\n\n cmd\n .command('login')\n .description('Log in with QR code or channel-specific credentials flow')\n .option(\n '--channel <id>',\n 'Channel id (auto-detected when only one login-capable channel is registered)',\n )\n .option('--account <id>', 'Optional account id when re-logging an existing bot')\n .option('--timeout <ms>', 'Max wait for scan (default 480000)', '480000')\n .option('--credentials-only', 'Only save token files; do not update xopc.json')\n .action(async (options, command) => {\n ensureChannelRegistryForCli();\n const explicitChannel = options.channel?.trim?.();\n let channelId: string;\n if (explicitChannel) {\n channelId = explicitChannel;\n } else {\n const loginCapable = listChannelPlugins().filter((p) => p.cliLogin);\n if (loginCapable.length === 1) {\n channelId = loginCapable[0].id;\n console.log(`Auto-detected channel: ${channelId}`);\n } else if (loginCapable.length === 0) {\n console.error('No channels with login support found.');\n process.exitCode = 1;\n return;\n } else {\n console.error(\n `Multiple channels support login: ${loginCapable.map((p) => p.id).join(', ')}. ` +\n 'Use --channel <id> to specify.',\n );\n process.exitCode = 1;\n return;\n }\n }\n const plugin = getChannelPlugin(channelId);\n if (!plugin?.cliLogin) {\n console.error(`Channel \"${channelId}\" does not support CLI login.`);\n const capable = listChannelPlugins()\n .filter((p) => p.cliLogin)\n .map((p) => p.id);\n if (capable.length > 0) {\n console.error(`Channels with login support: ${capable.join(', ')}`);\n }\n process.exitCode = 1;\n return;\n }\n\n const configPath = resolveConfigPathFromCommand(command);\n const timeoutMs = Math.max(60_000, Number.parseInt(String(options.timeout), 10) || 480_000);\n const verbose = ctx.isVerbose;\n\n const result = await plugin.cliLogin.runLogin({\n configPath,\n verbose,\n timeoutMs,\n accountId: options.account?.trim() || undefined,\n writeConfig: !options.credentialsOnly,\n });\n\n if (!result.ok) {\n if (result.cancelled) {\n process.exitCode = 130;\n return;\n }\n console.error(result.message || 'Login failed');\n process.exitCode = 1;\n }\n });\n\n cmd\n .command('list')\n .description('List configured channels and their account status')\n .option('--json', 'Output as JSON for agents/UIs', false)\n .action((opts: { json?: boolean }) => {\n ensureChannelRegistryForCli();\n const cfg = loadConfig(resolveConfigPathFromCommand(cmd));\n const channelsCfg = (cfg.channels ?? {}) as Record<string, Record<string, unknown>>;\n const entries = listChannelPlugins().map((plugin) => {\n const raw = channelsCfg[plugin.id] ?? {};\n const enabled = raw.enabled === true;\n const accounts = (raw.accounts ?? {}) as Record<string, Record<string, unknown>>;\n const accountSummaries = Object.entries(accounts).map(([id, acct]) => ({\n accountId: id,\n enabled: acct.enabled !== false,\n configured: typeof acct.botToken === 'string'\n ? Boolean((acct.botToken as string).trim())\n : false,\n }));\n return {\n id: plugin.id,\n name: plugin.meta?.label ?? plugin.id,\n enabled,\n hasLogin: Boolean(plugin.cliLogin),\n accountCount: accountSummaries.length,\n accounts: accountSummaries,\n };\n });\n if (opts.json) {\n process.stdout.write(JSON.stringify({ ok: true, channels: entries }) + '\\n');\n return;\n }\n console.log('');\n console.log(colors.bold('CHANNELS'));\n const idWidth = Math.max(...entries.map((e) => e.id.length));\n for (const e of entries) {\n const status = e.enabled\n ? colors.green('● enabled')\n : colors.gray('○ disabled');\n const accts = e.accountCount > 0 ? colors.gray(` (${e.accountCount} accounts)`) : '';\n console.log(` ${e.id.padEnd(idWidth)} ${status} ${colors.gray(e.name)}${accts}`);\n }\n console.log('');\n console.log(colors.gray('Use: xopc channels add <id> [--token <token>]'));\n });\n\n cmd\n .command('add <channel>')\n .description('Add or update a channel account (currently: telegram)')\n .option('--token <value>', 'Bot token (Telegram). Prompts securely if omitted.')\n .option('--account <id>', 'Account id (default: \"default\")')\n .option('--enable', 'Enable the channel after writing (default: true)', true)\n .option('--dry-run', 'Show the change without writing', false)\n .option('--json', 'Emit a single JSON outcome line', false)\n .action(\n async (\n channel: string,\n opts: {\n token?: string;\n account?: string;\n enable?: boolean;\n dryRun?: boolean;\n json?: boolean;\n },\n ) => {\n const channelId = channel.trim().toLowerCase();\n const accountId = opts.account?.trim() || 'default';\n const dryRun = Boolean(opts.dryRun);\n const json = Boolean(opts.json);\n\n if (channelId === 'feishu' || channelId === 'weixin') {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: `channels.${channelId}`,\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [\n {\n message:\n channelId === 'weixin'\n ? 'Weixin uses interactive QR login. Run: xopc channels login --channel weixin'\n : 'Feishu add via CLI is not yet implemented. Edit `~/.xopc/xopc.json` (channels.feishu) or run: xopc onboard --channels',\n },\n ],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.ERROR;\n return;\n }\n\n if (channelId !== 'telegram') {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: `channels.${channelId}`,\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [{ message: `Unknown channel \"${channelId}\". Try: xopc channels list` }],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.ERROR;\n return;\n }\n\n let token = opts.token?.trim();\n if (!token) {\n token = process.env.TELEGRAM_BOT_TOKEN?.trim();\n }\n if (!token) {\n try {\n token = await promptSecret('Telegram bot token (from @BotFather):');\n } catch (error) {\n if (isPromptCancelled(error)) {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: 'channels.telegram',\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [{ message: 'Cancelled by user' }],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.CANCELLED;\n return;\n }\n throw error;\n }\n }\n\n if (!validateTelegramToken(token)) {\n const outcome: SetupOutcome = {\n ok: false,\n action: 'add',\n domain: 'channels.telegram',\n target: accountId,\n changedPaths: [],\n dryRun,\n errors: [{ path: 'token', message: 'Token does not look like a Telegram bot token (expected `<digits>:<35+ chars>`).' }],\n };\n emitOutcome(outcome, json);\n process.exitCode = SETUP_EXIT.ERROR;\n return;\n }\n\n await runSetup({\n configPath: resolveConfigPathFromCommand(cmd),\n options: { dryRun, json },\n mutator: {\n domain: 'channels.telegram',\n target: accountId,\n action: 'add',\n mutate(config) {\n return applyTelegramAccount(config, accountId, token!, opts.enable !== false);\n },\n resultValue: () => ({\n channel: 'telegram',\n accountId,\n tokenMask: maskToken(token!),\n }),\n notes: () => [\n opts.enable !== false\n ? 'Telegram channel enabled. Restart the gateway for the new bot to come online.'\n : 'Telegram credentials saved (channel disabled). Use `--enable` to start it.',\n ],\n },\n });\n },\n );\n\n cmd\n .command('remove <channel>')\n .description('Remove a channel account')\n .option('--account <id>', 'Account id (default: \"default\")')\n .option('--dry-run', 'Show the change without writing', false)\n .option('--json', 'Emit a single JSON outcome line', false)\n .action(\n async (\n channel: string,\n opts: { account?: string; dryRun?: boolean; json?: boolean },\n ) => {\n const channelId = channel.trim().toLowerCase();\n const accountId = opts.account?.trim() || 'default';\n const dryRun = Boolean(opts.dryRun);\n const json = Boolean(opts.json);\n\n await runSetup({\n configPath: resolveConfigPathFromCommand(cmd),\n options: { dryRun, json },\n mutator: {\n domain: `channels.${channelId}`,\n target: accountId,\n action: 'remove',\n mutate(config) {\n return removeChannelAccount(config, channelId, accountId);\n },\n },\n });\n },\n );\n\n cmd\n .command('schema [channel]')\n .description('Print credential schemas for channels (for agents / UIs)')\n .option('--json', 'JSON output (default human-readable JSON)', false)\n .action((channel: string | undefined, opts: { json?: boolean }) => {\n ensureChannelRegistryForCli();\n const all = listChannelPlugins().map((p) => ({\n id: p.id,\n name: p.meta?.label ?? p.id,\n hasLogin: Boolean(p.cliLogin),\n configSchema: p.configSchema?.schema,\n }));\n const payload = {\n ok: true,\n channels: channel ? all.filter((c) => c.id === channel) : all,\n };\n if (opts.json) {\n process.stdout.write(JSON.stringify(payload) + '\\n');\n } else {\n console.log(JSON.stringify(payload, null, 2));\n }\n });\n\n cmd\n .command('pairing')\n .description('Approve DM pairing requests (updates channel allowFrom credential files)')\n .addCommand(\n new Command('approve')\n .description('Approve a pairing code shown to the user in Telegram / Feishu / Weixin DMs')\n .requiredOption('--channel <id>', 'telegram | feishu | weixin')\n .option('--account <id>', 'Bot account id from config', 'default')\n .argument('<code>', 'Pairing code from the user message')\n .action((code: string, options: { channel?: string; account?: string }) => {\n const ch = (options.channel ?? '').trim().toLowerCase() as PairingCliChannel;\n if (!PAIRING_CHANNELS.has(ch)) {\n console.error('Invalid --channel. Use: telegram, feishu, or weixin.');\n process.exitCode = 1;\n return;\n }\n const accountId = (options.account ?? 'default').trim() || 'default';\n const result = approveChannelPairingFromCli({\n channel: ch,\n accountId,\n code: String(code ?? '').trim(),\n });\n if (result.ok === false) {\n console.error(result.error);\n process.exitCode = 1;\n return;\n }\n console.log(`Approved. Sender id added to allowFrom store: ${result.senderId}`);\n }),\n );\n\n return cmd;\n}\n\n// ---------- helpers ----------\n\nconst TELEGRAM_TOKEN_PATTERN = /^\\d{5,}:[A-Za-z0-9_-]{30,}$/;\n\nexport function validateTelegramToken(token: string): boolean {\n return TELEGRAM_TOKEN_PATTERN.test(token.trim());\n}\n\nexport function maskToken(token: string): string {\n const t = token.trim();\n if (t.length <= 8) return '*'.repeat(t.length);\n return `${t.slice(0, 4)}…${t.slice(-4)}`;\n}\n\nexport function applyTelegramAccount(\n cfg: Config,\n accountId: string,\n botToken: string,\n enable: boolean,\n): Config {\n const channels = { ...((cfg.channels ?? {}) as Record<string, unknown>) };\n const tg = { ...((channels.telegram ?? {}) as Record<string, unknown>) };\n if (enable) tg.enabled = true;\n const accounts = { ...((tg.accounts ?? {}) as Record<string, Record<string, unknown>>) };\n accounts[accountId] = {\n ...(accounts[accountId] ?? {}),\n accountId,\n enabled: true,\n botToken,\n };\n tg.accounts = accounts;\n channels.telegram = tg;\n return { ...cfg, channels } as Config;\n}\n\nexport function removeChannelAccount(\n cfg: Config,\n channelId: string,\n accountId: string,\n): Config {\n if (channelId === 'feishu' || channelId === 'weixin' || channelId === 'telegram') {\n const channels = { ...((cfg.channels ?? {}) as Record<string, unknown>) };\n const ch = { ...((channels[channelId] ?? {}) as Record<string, unknown>) };\n const accounts = { ...((ch.accounts ?? {}) as Record<string, unknown>) };\n if (!(accountId in accounts)) {\n throw new SetupValidationError([\n { message: `No account \"${accountId}\" on channel \"${channelId}\".` },\n ]);\n }\n delete accounts[accountId];\n ch.accounts = accounts;\n if (Object.keys(accounts).length === 0) {\n ch.enabled = false;\n }\n channels[channelId] = ch;\n return { ...cfg, channels } as Config;\n }\n throw new SetupValidationError([\n { message: `Unknown channel \"${channelId}\". Try: xopc channels list` },\n ]);\n}\n\nregister({\n id: 'channels',\n name: 'channels',\n description: 'Messaging channel login',\n factory: createChannelsCommand,\n metadata: {\n category: 'setup',\n examples: [\n 'xopc channels list',\n 'xopc channels add telegram --token 123456:ABC...',\n 'xopc channels remove telegram',\n 'xopc channels login',\n 'xopc channels pairing approve --channel feishu --account default ABC12XYZ',\n ],\n },\n});\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { ConfigSchema, init_schema } from "../../config/schema.js";
2
1
  import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
+ import { ConfigSchema, init_schema } from "../../config/schema.js";
3
3
  import { resolveGatewayLocalClientHost } from "../../config/gateway-bind.js";
4
4
  import { formatExamples, register } from "../registry.js";
5
5
  import { existsSync, readFileSync } from "fs";
@@ -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();
@@ -1,6 +1,6 @@
1
+ import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
1
2
  import { getAgentDefaultModelRef, init_schema, parseModelRef } from "../../../../config/schema.js";
2
3
  import { init_loader, loadConfig } from "../../../../config/loader.js";
3
- import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
4
4
  import { existsSync } from "node:fs";
5
5
  //#region src/cli/commands/doctor/checks/provider-auth.ts
6
6
  init_loader();
@@ -2,8 +2,8 @@ import { init_agent_scope, resolveDefaultAgentId } from "../../../../agent/agent
2
2
  import { init_transcript_paths, resolveSessionFilePath } from "../../../../session/parity/transcript-paths.js";
3
3
  import { FILENAMES, init_paths, resolveSessionsDir } from "../../../../config/paths.js";
4
4
  import { init_loader, loadConfig } from "../../../../config/loader.js";
5
- import { join } from "node:path";
6
5
  import { existsSync, readFileSync } from "node:fs";
6
+ import { join } from "node:path";
7
7
  //#region src/cli/commands/doctor/checks/session-integrity.ts
8
8
  init_agent_scope();
9
9
  init_loader();
@@ -1,5 +1,5 @@
1
- import { join } from "node:path";
2
1
  import { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
2
+ import { join } from "node:path";
3
3
  //#region src/cli/commands/doctor/checks/state-integrity.ts
4
4
  function isWritable(dir) {
5
5
  try {
@@ -1,8 +1,8 @@
1
1
  import { init_agent_scope, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../../../agent/agent-scope.js";
2
2
  import { WORKSPACE_FILES, init_paths } from "../../../../config/paths.js";
3
3
  import { init_loader, loadConfig } from "../../../../config/loader.js";
4
- import { join } from "node:path";
5
4
  import { existsSync } from "node:fs";
5
+ import { join } from "node:path";
6
6
  //#region src/cli/commands/doctor/checks/workspace-status.ts
7
7
  init_agent_scope();
8
8
  init_loader();
@@ -12,8 +12,8 @@ import { runGatewayLoop } from "../../gateway/run-loop.js";
12
12
  import "../../gateway/index.js";
13
13
  import { colors } from "../utils/colors.js";
14
14
  import { initWorkspace } from "../utils/init-workspace.js";
15
- import { join, resolve } from "node:path";
16
15
  import { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, watch } from "node:fs";
16
+ import { join, resolve } from "node:path";
17
17
  import { Command } from "commander";
18
18
  //#region src/cli/commands/extension-dev.ts
19
19
  init_loader();
@@ -7,8 +7,8 @@ import { installExtensionFromStoreZip, installFromLocal, installFromNpm, peekExt
7
7
  import { fetchRegistry, findExtension, getExtensionMarketplaceStoreBaseUrl, listExtensions, searchExtensions } from "../../extensions/marketplace.js";
8
8
  import { downloadExtensionStoreZipBuffer, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl } from "../../agent/skills/marketplace/adapters/store/store-api-client.js";
9
9
  import { colors } from "../utils/colors.js";
10
- import { join, resolve } from "node:path";
11
10
  import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
11
+ import { join, resolve } from "node:path";
12
12
  import { execSync } from "node:child_process";
13
13
  import { Command } from "commander";
14
14
  import semver from "semver";
@@ -4,8 +4,8 @@ import { init_logger } from "../../utils/logger.js";
4
4
  import { normalizeExtensionManifest } from "../../extensions/normalize-manifest.js";
5
5
  import { checkEngineCompatibility } from "../../extensions/engine-check.js";
6
6
  import { colors } from "../utils/colors.js";
7
- import { isAbsolute, join, resolve } from "node:path";
8
7
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
8
+ import { isAbsolute, join, resolve } from "node:path";
9
9
  import { execSync } from "node:child_process";
10
10
  import { Command } from "commander";
11
11
  //#region src/cli/commands/extension-pack.ts
@@ -99,7 +99,7 @@ async function runServiceStop(params) {
99
99
  emitResult(options, {
100
100
  ok: true,
101
101
  result: "stopped",
102
- message: options.disable ? "Gateway stopped and disabled (will not respawn)." : "Gateway stop signal sent."
102
+ message: options.disable ? "Gateway stopped and disabled (will not respawn)." : "Gateway stopped."
103
103
  });
104
104
  } catch (err) {
105
105
  log.error({ err }, "Failed to stop gateway");
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle-core.js","names":[],"sources":["../../../../../src/cli/commands/gateway/lifecycle-core.ts"],"sourcesContent":["/**\n * Daemon lifecycle core — OpenClaw-aligned service start/stop/restart with onNotLoaded fallback.\n */\n\nimport { createLogger } from '../../../utils/logger.js';\nimport type {\n DaemonLifecycleOptions,\n GatewayService,\n} from '../../../daemon/types.js';\nimport {\n clearGatewayRestartIntentSync,\n writeGatewayRestartIntentSync,\n} from '../../../infra/restart.js';\n\nconst log = createLogger('DaemonLifecycle');\n\nexport type ServiceRecoveryResult = {\n result: 'started' | 'stopped' | 'restarted';\n message?: string;\n warnings?: string[];\n loaded?: boolean;\n};\n\ntype ServiceRecoveryContext = {\n json: boolean;\n fail: (message: string, hints?: string[], diagnostics?: string[], options?: DaemonLifecycleOptions) => void;\n};\n\ntype RestartPostCheckContext = {\n options: DaemonLifecycleOptions;\n fail: (message: string, hints?: string[], diagnostics?: string[], options?: DaemonLifecycleOptions) => void;\n};\n\nfunction emitResult(\n options: DaemonLifecycleOptions,\n payload: {\n ok: boolean;\n result?: string;\n message?: string;\n error?: string;\n hints?: string[];\n warnings?: string[];\n },\n): void {\n if (options.json) {\n console.log(JSON.stringify(payload, null, 2));\n return;\n }\n if (payload.ok) {\n if (payload.message) {\n console.log(`✅ ${payload.message}`);\n }\n for (const warning of payload.warnings ?? []) {\n console.warn(`⚠️ ${warning}`);\n }\n return;\n }\n if (payload.error) {\n console.error(`❌ ${payload.error}`);\n }\n for (const hint of payload.hints ?? []) {\n console.log(`💡 ${hint}`);\n }\n}\n\nfunction createFail(options: DaemonLifecycleOptions) {\n return (\n message: string,\n hints?: string[],\n diagnostics?: string[],\n opts: DaemonLifecycleOptions = options,\n ) => {\n emitResult(opts, { ok: false, error: message, hints });\n for (const line of diagnostics ?? []) {\n if (!opts.json) {\n console.log(` ${line}`);\n }\n }\n process.exit(1);\n };\n}\n\nasync function resolveServiceLoadedOrFail(\n service: GatewayService,\n fail: ServiceRecoveryContext['fail'],\n): Promise<boolean | null> {\n try {\n return await service.isLoaded({ env: process.env });\n } catch (err) {\n fail(`Gateway service check failed: ${String(err)}`);\n return null;\n }\n}\n\nasync function handleServiceNotLoaded(params: {\n service: GatewayService;\n renderStartHints: () => string[];\n options: DaemonLifecycleOptions;\n}): Promise<void> {\n emitResult(params.options, {\n ok: true,\n result: 'not-loaded',\n message: `Gateway service ${params.service.notLoadedText}.`,\n hints: params.renderStartHints(),\n });\n}\n\nasync function checkAndWarnTokenDrift(\n service: GatewayService,\n options: DaemonLifecycleOptions,\n): Promise<string[]> {\n const warnings: string[] = [];\n try {\n const command = await service.readCommand(process.env);\n const serviceToken = command?.environment?.XOPC_GATEWAY_TOKEN;\n if (!serviceToken) {\n return warnings;\n }\n const { loadConfig } = await import('../../../config/index.js');\n const { resolveConfigPath } = await import('../../../config/paths.js');\n const config = loadConfig(resolveConfigPath());\n const configToken = config?.gateway?.auth?.token;\n if (configToken && serviceToken !== configToken) {\n const warning =\n 'Token drift detected: service token differs from config. Run `xopc gateway service install --force` to sync.';\n warnings.push(warning);\n if (!options.json) {\n console.warn(`⚠️ ${warning}`);\n }\n }\n } catch {\n // Best-effort\n }\n return warnings;\n}\n\nexport async function runServiceStop(params: {\n service: GatewayService;\n opts?: DaemonLifecycleOptions;\n onNotLoaded?: (ctx: ServiceRecoveryContext) => Promise<ServiceRecoveryResult | null>;\n}): Promise<void> {\n const options = params.opts ?? {};\n const fail = createFail(options);\n const loaded = await resolveServiceLoadedOrFail(params.service, fail);\n if (loaded === null) {\n return;\n }\n\n if (!loaded) {\n try {\n const handled = await params.onNotLoaded?.({ json: Boolean(options.json), fail });\n if (handled) {\n emitResult(options, {\n ok: true,\n result: handled.result,\n message: handled.message,\n warnings: handled.warnings,\n });\n return;\n }\n } catch (err) {\n fail(`Gateway stop failed: ${String(err)}`);\n return;\n }\n await handleServiceNotLoaded({\n service: params.service,\n renderStartHints: () => ['xopc gateway service install', 'xopc gateway'],\n options,\n });\n return;\n }\n\n try {\n await params.service.stop({ env: process.env, disable: options.disable });\n emitResult(options, {\n ok: true,\n result: 'stopped',\n message: options.disable\n ? 'Gateway stopped and disabled (will not respawn).'\n : 'Gateway stop signal sent.',\n });\n } catch (err) {\n log.error({ err }, 'Failed to stop gateway');\n fail(`Gateway stop failed: ${String(err)}`);\n }\n}\n\nexport async function runServiceRestart(params: {\n service: GatewayService;\n opts?: DaemonLifecycleOptions;\n renderStartHints: () => string[];\n checkTokenDrift?: boolean;\n onNotLoaded?: (ctx: ServiceRecoveryContext) => Promise<ServiceRecoveryResult | null>;\n postRestartCheck?: (ctx: RestartPostCheckContext) => Promise<void>;\n}): Promise<void> {\n const options = params.opts ?? {};\n const fail = createFail(options);\n const warnings: string[] = [];\n let handledRecovery: ServiceRecoveryResult | null = null;\n\n const loaded = await resolveServiceLoadedOrFail(params.service, fail);\n if (loaded === null) {\n return;\n }\n\n if (!loaded) {\n try {\n handledRecovery = (await params.onNotLoaded?.({ json: Boolean(options.json), fail })) ?? null;\n } catch (err) {\n fail(`Gateway restart failed: ${String(err)}`);\n return;\n }\n if (!handledRecovery) {\n await handleServiceNotLoaded({\n service: params.service,\n renderStartHints: params.renderStartHints,\n options,\n });\n return;\n }\n if (handledRecovery.warnings?.length) {\n warnings.push(...handledRecovery.warnings);\n }\n }\n\n if (loaded && params.checkTokenDrift) {\n warnings.push(...(await checkAndWarnTokenDrift(params.service, options)));\n }\n\n try {\n if (loaded) {\n let wroteRestartIntent = false;\n const runtime = await params.service.readRuntime(process.env).catch(() => null);\n wroteRestartIntent = writeGatewayRestartIntentSync({ targetPid: runtime?.pid });\n try {\n await params.service.restart({ env: process.env });\n } catch (err) {\n if (wroteRestartIntent) {\n clearGatewayRestartIntentSync();\n }\n throw err;\n }\n }\n\n if (params.postRestartCheck) {\n await params.postRestartCheck({ options, fail });\n }\n\n if (options.wait) {\n const timeoutMs = parseWaitTimeout(options.wait);\n const { loadConfig } = await import('../../../config/index.js');\n const { resolveConfigPath } = await import('../../../config/paths.js');\n const config = loadConfig(resolveConfigPath());\n const port = typeof config.gateway?.port === 'number' ? config.gateway.port : 18790;\n const { waitForRestartHealth } = await import('./restart-health.js');\n const snapshot = await waitForRestartHealth({\n service: params.service,\n port,\n timeoutMs,\n onProgress: () => {\n if (!options.json) {\n process.stdout.write('.');\n }\n },\n });\n if (!options.json) {\n process.stdout.write('\\n');\n }\n if (!snapshot.healthy) {\n fail(`Restart health check failed: ${snapshot.waitOutcome ?? 'timeout'}`, [\n 'xopc gateway logs',\n ]);\n return;\n }\n emitResult(options, {\n ok: true,\n result: 'healthy',\n message: `Gateway restarted and healthy (pid ${snapshot.runtime?.pid ?? 'unknown'}, ${snapshot.elapsedMs ?? 0}ms).`,\n warnings: warnings.length ? warnings : undefined,\n });\n return;\n }\n\n emitResult(options, {\n ok: true,\n result: 'restarted',\n message: handledRecovery?.message ?? 'Gateway restart completed.',\n warnings: warnings.length ? warnings : undefined,\n });\n } catch (err) {\n log.error({ err }, 'Failed to restart gateway');\n fail(`Gateway restart failed: ${String(err)}`, params.renderStartHints());\n } finally {\n clearGatewayRestartIntentSync();\n }\n}\n\nexport async function executeDaemonUninstall(options: DaemonLifecycleOptions = {}): Promise<void> {\n const { resolveGatewayService, isDaemonAvailableAsync } = await import('../../../daemon/service.js');\n const available = await isDaemonAvailableAsync();\n if (!available) {\n emitResult(options, { ok: false, error: 'Daemon service not available on this platform' });\n process.exit(1);\n }\n const service = await resolveGatewayService();\n const loaded = await service.isLoaded({ env: process.env }).catch(() => false);\n if (loaded) {\n try {\n await service.stop({ env: process.env });\n } catch {\n // Best-effort\n }\n }\n try {\n await service.uninstall({ env: process.env });\n emitResult(options, { ok: true, result: 'uninstalled', message: 'Gateway service uninstalled.' });\n } catch (err) {\n log.error({ err }, 'Failed to uninstall gateway service');\n emitResult(options, { ok: false, error: `Failed to uninstall: ${String(err)}` });\n process.exit(1);\n }\n}\n\nfunction parseWaitTimeout(wait: string): number {\n const match = wait.match(/^(\\d+)(s|m|ms)?$/);\n if (!match) return 60_000;\n const value = parseInt(match[1], 10);\n const unit = match[2] || 's';\n switch (unit) {\n case 'ms':\n return value;\n case 'm':\n return value * 60_000;\n case 's':\n default:\n return value * 1000;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycle-core.js","names":[],"sources":["../../../../../src/cli/commands/gateway/lifecycle-core.ts"],"sourcesContent":["/**\n * Daemon lifecycle core — OpenClaw-aligned service start/stop/restart with onNotLoaded fallback.\n */\n\nimport { createLogger } from '../../../utils/logger.js';\nimport type {\n DaemonLifecycleOptions,\n GatewayService,\n} from '../../../daemon/types.js';\nimport {\n clearGatewayRestartIntentSync,\n writeGatewayRestartIntentSync,\n} from '../../../infra/restart.js';\n\nconst log = createLogger('DaemonLifecycle');\n\nexport type ServiceRecoveryResult = {\n result: 'started' | 'stopped' | 'restarted';\n message?: string;\n warnings?: string[];\n loaded?: boolean;\n};\n\ntype ServiceRecoveryContext = {\n json: boolean;\n fail: (message: string, hints?: string[], diagnostics?: string[], options?: DaemonLifecycleOptions) => void;\n};\n\ntype RestartPostCheckContext = {\n options: DaemonLifecycleOptions;\n fail: (message: string, hints?: string[], diagnostics?: string[], options?: DaemonLifecycleOptions) => void;\n};\n\nfunction emitResult(\n options: DaemonLifecycleOptions,\n payload: {\n ok: boolean;\n result?: string;\n message?: string;\n error?: string;\n hints?: string[];\n warnings?: string[];\n },\n): void {\n if (options.json) {\n console.log(JSON.stringify(payload, null, 2));\n return;\n }\n if (payload.ok) {\n if (payload.message) {\n console.log(`✅ ${payload.message}`);\n }\n for (const warning of payload.warnings ?? []) {\n console.warn(`⚠️ ${warning}`);\n }\n return;\n }\n if (payload.error) {\n console.error(`❌ ${payload.error}`);\n }\n for (const hint of payload.hints ?? []) {\n console.log(`💡 ${hint}`);\n }\n}\n\nfunction createFail(options: DaemonLifecycleOptions) {\n return (\n message: string,\n hints?: string[],\n diagnostics?: string[],\n opts: DaemonLifecycleOptions = options,\n ) => {\n emitResult(opts, { ok: false, error: message, hints });\n for (const line of diagnostics ?? []) {\n if (!opts.json) {\n console.log(` ${line}`);\n }\n }\n process.exit(1);\n };\n}\n\nasync function resolveServiceLoadedOrFail(\n service: GatewayService,\n fail: ServiceRecoveryContext['fail'],\n): Promise<boolean | null> {\n try {\n return await service.isLoaded({ env: process.env });\n } catch (err) {\n fail(`Gateway service check failed: ${String(err)}`);\n return null;\n }\n}\n\nasync function handleServiceNotLoaded(params: {\n service: GatewayService;\n renderStartHints: () => string[];\n options: DaemonLifecycleOptions;\n}): Promise<void> {\n emitResult(params.options, {\n ok: true,\n result: 'not-loaded',\n message: `Gateway service ${params.service.notLoadedText}.`,\n hints: params.renderStartHints(),\n });\n}\n\nasync function checkAndWarnTokenDrift(\n service: GatewayService,\n options: DaemonLifecycleOptions,\n): Promise<string[]> {\n const warnings: string[] = [];\n try {\n const command = await service.readCommand(process.env);\n const serviceToken = command?.environment?.XOPC_GATEWAY_TOKEN;\n if (!serviceToken) {\n return warnings;\n }\n const { loadConfig } = await import('../../../config/index.js');\n const { resolveConfigPath } = await import('../../../config/paths.js');\n const config = loadConfig(resolveConfigPath());\n const configToken = config?.gateway?.auth?.token;\n if (configToken && serviceToken !== configToken) {\n const warning =\n 'Token drift detected: service token differs from config. Run `xopc gateway service install --force` to sync.';\n warnings.push(warning);\n if (!options.json) {\n console.warn(`⚠️ ${warning}`);\n }\n }\n } catch {\n // Best-effort\n }\n return warnings;\n}\n\nexport async function runServiceStop(params: {\n service: GatewayService;\n opts?: DaemonLifecycleOptions;\n onNotLoaded?: (ctx: ServiceRecoveryContext) => Promise<ServiceRecoveryResult | null>;\n}): Promise<void> {\n const options = params.opts ?? {};\n const fail = createFail(options);\n const loaded = await resolveServiceLoadedOrFail(params.service, fail);\n if (loaded === null) {\n return;\n }\n\n if (!loaded) {\n try {\n const handled = await params.onNotLoaded?.({ json: Boolean(options.json), fail });\n if (handled) {\n emitResult(options, {\n ok: true,\n result: handled.result,\n message: handled.message,\n warnings: handled.warnings,\n });\n return;\n }\n } catch (err) {\n fail(`Gateway stop failed: ${String(err)}`);\n return;\n }\n await handleServiceNotLoaded({\n service: params.service,\n renderStartHints: () => ['xopc gateway service install', 'xopc gateway'],\n options,\n });\n return;\n }\n\n try {\n await params.service.stop({ env: process.env, disable: options.disable });\n emitResult(options, {\n ok: true,\n result: 'stopped',\n message: options.disable\n ? 'Gateway stopped and disabled (will not respawn).'\n : 'Gateway stopped.',\n });\n } catch (err) {\n log.error({ err }, 'Failed to stop gateway');\n fail(`Gateway stop failed: ${String(err)}`);\n }\n}\n\nexport async function runServiceRestart(params: {\n service: GatewayService;\n opts?: DaemonLifecycleOptions;\n renderStartHints: () => string[];\n checkTokenDrift?: boolean;\n onNotLoaded?: (ctx: ServiceRecoveryContext) => Promise<ServiceRecoveryResult | null>;\n postRestartCheck?: (ctx: RestartPostCheckContext) => Promise<void>;\n}): Promise<void> {\n const options = params.opts ?? {};\n const fail = createFail(options);\n const warnings: string[] = [];\n let handledRecovery: ServiceRecoveryResult | null = null;\n\n const loaded = await resolveServiceLoadedOrFail(params.service, fail);\n if (loaded === null) {\n return;\n }\n\n if (!loaded) {\n try {\n handledRecovery = (await params.onNotLoaded?.({ json: Boolean(options.json), fail })) ?? null;\n } catch (err) {\n fail(`Gateway restart failed: ${String(err)}`);\n return;\n }\n if (!handledRecovery) {\n await handleServiceNotLoaded({\n service: params.service,\n renderStartHints: params.renderStartHints,\n options,\n });\n return;\n }\n if (handledRecovery.warnings?.length) {\n warnings.push(...handledRecovery.warnings);\n }\n }\n\n if (loaded && params.checkTokenDrift) {\n warnings.push(...(await checkAndWarnTokenDrift(params.service, options)));\n }\n\n try {\n if (loaded) {\n let wroteRestartIntent = false;\n const runtime = await params.service.readRuntime(process.env).catch(() => null);\n wroteRestartIntent = writeGatewayRestartIntentSync({ targetPid: runtime?.pid });\n try {\n await params.service.restart({ env: process.env });\n } catch (err) {\n if (wroteRestartIntent) {\n clearGatewayRestartIntentSync();\n }\n throw err;\n }\n }\n\n if (params.postRestartCheck) {\n await params.postRestartCheck({ options, fail });\n }\n\n if (options.wait) {\n const timeoutMs = parseWaitTimeout(options.wait);\n const { loadConfig } = await import('../../../config/index.js');\n const { resolveConfigPath } = await import('../../../config/paths.js');\n const config = loadConfig(resolveConfigPath());\n const port = typeof config.gateway?.port === 'number' ? config.gateway.port : 18790;\n const { waitForRestartHealth } = await import('./restart-health.js');\n const snapshot = await waitForRestartHealth({\n service: params.service,\n port,\n timeoutMs,\n onProgress: () => {\n if (!options.json) {\n process.stdout.write('.');\n }\n },\n });\n if (!options.json) {\n process.stdout.write('\\n');\n }\n if (!snapshot.healthy) {\n fail(`Restart health check failed: ${snapshot.waitOutcome ?? 'timeout'}`, [\n 'xopc gateway logs',\n ]);\n return;\n }\n emitResult(options, {\n ok: true,\n result: 'healthy',\n message: `Gateway restarted and healthy (pid ${snapshot.runtime?.pid ?? 'unknown'}, ${snapshot.elapsedMs ?? 0}ms).`,\n warnings: warnings.length ? warnings : undefined,\n });\n return;\n }\n\n emitResult(options, {\n ok: true,\n result: 'restarted',\n message: handledRecovery?.message ?? 'Gateway restart completed.',\n warnings: warnings.length ? warnings : undefined,\n });\n } catch (err) {\n log.error({ err }, 'Failed to restart gateway');\n fail(`Gateway restart failed: ${String(err)}`, params.renderStartHints());\n } finally {\n clearGatewayRestartIntentSync();\n }\n}\n\nexport async function executeDaemonUninstall(options: DaemonLifecycleOptions = {}): Promise<void> {\n const { resolveGatewayService, isDaemonAvailableAsync } = await import('../../../daemon/service.js');\n const available = await isDaemonAvailableAsync();\n if (!available) {\n emitResult(options, { ok: false, error: 'Daemon service not available on this platform' });\n process.exit(1);\n }\n const service = await resolveGatewayService();\n const loaded = await service.isLoaded({ env: process.env }).catch(() => false);\n if (loaded) {\n try {\n await service.stop({ env: process.env });\n } catch {\n // Best-effort\n }\n }\n try {\n await service.uninstall({ env: process.env });\n emitResult(options, { ok: true, result: 'uninstalled', message: 'Gateway service uninstalled.' });\n } catch (err) {\n log.error({ err }, 'Failed to uninstall gateway service');\n emitResult(options, { ok: false, error: `Failed to uninstall: ${String(err)}` });\n process.exit(1);\n }\n}\n\nfunction parseWaitTimeout(wait: string): number {\n const match = wait.match(/^(\\d+)(s|m|ms)?$/);\n if (!match) return 60_000;\n const value = parseInt(match[1], 10);\n const unit = match[2] || 's';\n switch (unit) {\n case 'ms':\n return value;\n case 'm':\n return value * 60_000;\n case 's':\n default:\n return value * 1000;\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,14 @@
1
1
  import { Command } from 'commander';
2
+ declare function parseLineCount(value: string | number | undefined): number;
3
+ declare function resolveGatewayLogPath(configPath: string): string;
4
+ declare function readLastLines(filePath: string, lineCount: number): Promise<string>;
2
5
  /**
3
6
  * Create logs subcommand
4
7
  */
5
8
  export declare function createLogsCommand(): Command;
9
+ export declare const gatewayLogsTestInternals: {
10
+ parseLineCount: typeof parseLineCount;
11
+ readLastLines: typeof readLastLines;
12
+ resolveGatewayLogPath: typeof resolveGatewayLogPath;
13
+ };
14
+ export {};
@@ -1,39 +1,72 @@
1
1
  import { getContextWithOpts } from "../../context.js";
2
- import { execSync, spawn } from "child_process";
2
+ import { existsSync, statSync, watch } from "node:fs";
3
+ import { readFile } from "node:fs/promises";
4
+ import path from "node:path";
3
5
  import { Command } from "commander";
4
6
  //#region src/cli/commands/gateway/logs.ts
7
+ function parseLineCount(value) {
8
+ const parsed = parseInt(String(value ?? "50"), 10);
9
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 50;
10
+ }
11
+ function resolveGatewayLogPath(configPath) {
12
+ const logDir = process.env.XOPC_LOG_DIR || path.join(path.dirname(configPath), "logs");
13
+ return path.join(logDir, "app.log");
14
+ }
15
+ async function readLastLines(filePath, lineCount) {
16
+ if (!existsSync(filePath)) return "No logs found\n";
17
+ const lines = (await readFile(filePath, "utf8")).split(/\r?\n/);
18
+ const selectedLines = (lines.at(-1) === "" ? lines.slice(0, -1) : lines).slice(-lineCount);
19
+ return `${selectedLines.join("\n")}${selectedLines.length > 0 ? "\n" : ""}`;
20
+ }
21
+ async function followLogFile(filePath, lineCount) {
22
+ process.stdout.write(await readLastLines(filePath, lineCount));
23
+ let lastSize = existsSync(filePath) ? statSync(filePath).size : 0;
24
+ const directory = path.dirname(filePath);
25
+ const fileName = path.basename(filePath);
26
+ watch(directory, async (_eventType, changedFileName) => {
27
+ if (changedFileName && changedFileName.toString() !== fileName) return;
28
+ if (!existsSync(filePath)) {
29
+ lastSize = 0;
30
+ return;
31
+ }
32
+ const nextSize = statSync(filePath).size;
33
+ if (nextSize < lastSize) lastSize = 0;
34
+ if (nextSize === lastSize) return;
35
+ const content = await readFile(filePath, "utf8");
36
+ process.stdout.write(content.slice(lastSize));
37
+ lastSize = nextSize;
38
+ });
39
+ }
5
40
  /**
6
41
  * Create logs subcommand
7
42
  */
8
43
  function createLogsCommand() {
9
44
  return new Command("logs").description("View gateway logs").option("--lines <n>", "Number of lines to show", "50").option("--follow", "Follow log output (like tail -f)").action(async (options) => {
10
45
  const ctx = getContextWithOpts();
11
- const logDir = process.env.XOPC_LOG_DIR || `${ctx.configPath.replace("/config.json", "")}/logs`;
46
+ const lineCount = parseLineCount(options.lines);
47
+ const logPath = resolveGatewayLogPath(ctx.configPath);
12
48
  try {
13
49
  if (options.follow) {
14
50
  console.log(`📜 Following gateway logs (Ctrl+C to exit)...\n`);
15
- spawn("tail", [
16
- "-f",
17
- "-n",
18
- options.lines,
19
- `${logDir}/app.log`
20
- ], { stdio: "inherit" }).on("error", (err) => {
21
- console.error("❌ Failed to tail logs:", err.message);
22
- process.exit(1);
23
- });
24
- } else {
25
- const output = execSync(`tail -n ${options.lines} ${logDir}/app.log 2>/dev/null || echo "No logs found"`, { encoding: "utf-8" });
26
- console.log(`📜 Last ${options.lines} lines of gateway logs:\n`);
27
- console.log(output);
28
- process.exit(0);
51
+ await followLogFile(logPath, lineCount);
52
+ return;
29
53
  }
54
+ const output = await readLastLines(logPath, lineCount);
55
+ console.log(`📜 Last ${lineCount} lines of gateway logs:\n`);
56
+ console.log(output);
57
+ process.exit(0);
30
58
  } catch (err) {
31
59
  console.error("❌ Failed to read logs:", err);
32
60
  process.exit(1);
33
61
  }
34
62
  });
35
63
  }
64
+ const gatewayLogsTestInternals = {
65
+ parseLineCount,
66
+ readLastLines,
67
+ resolveGatewayLogPath
68
+ };
36
69
  //#endregion
37
- export { createLogsCommand };
70
+ export { createLogsCommand, gatewayLogsTestInternals };
38
71
 
39
72
  //# sourceMappingURL=logs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logs.js","names":[],"sources":["../../../../../src/cli/commands/gateway/logs.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { spawn, execSync } from 'child_process';\nimport { getContextWithOpts } from '../../context.js';\n\n/**\n * Create logs subcommand\n */\nexport function createLogsCommand(): Command {\n return new Command('logs')\n .description('View gateway logs')\n .option('--lines <n>', 'Number of lines to show', '50')\n .option('--follow', 'Follow log output (like tail -f)')\n .action(async (options) => {\n const ctx = getContextWithOpts();\n \n // Determine log directory from environment or default\n const logDir = process.env.XOPC_LOG_DIR || \n `${ctx.configPath.replace('/config.json', '')}/logs`;\n\n try {\n if (options.follow) {\n // Follow mode: use tail -f\n console.log(`📜 Following gateway logs (Ctrl+C to exit)...\\n`);\n const tail = spawn('tail', ['-f', '-n', options.lines, `${logDir}/app.log`], {\n stdio: 'inherit',\n });\n \n tail.on('error', (err) => {\n console.error('❌ Failed to tail logs:', err.message);\n process.exit(1);\n });\n } else {\n // Static mode: read last N lines\n const output = execSync(\n `tail -n ${options.lines} ${logDir}/app.log 2>/dev/null || echo \"No logs found\"`,\n { encoding: 'utf-8' }\n );\n \n console.log(`📜 Last ${options.lines} lines of gateway logs:\\n`);\n console.log(output);\n process.exit(0);\n }\n } catch (err) {\n console.error('❌ Failed to read logs:', err);\n process.exit(1);\n }\n });\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,oBAA6B;AAC3C,QAAO,IAAI,QAAQ,OAAO,CACvB,YAAY,oBAAoB,CAChC,OAAO,eAAe,2BAA2B,KAAK,CACtD,OAAO,YAAY,mCAAmC,CACtD,OAAO,OAAO,YAAY;EACzB,MAAM,MAAM,oBAAoB;EAGhC,MAAM,SAAS,QAAQ,IAAI,gBACzB,GAAG,IAAI,WAAW,QAAQ,gBAAgB,GAAG,CAAC;AAEhD,MAAI;AACF,OAAI,QAAQ,QAAQ;AAElB,YAAQ,IAAI,kDAAkD;AACjD,UAAM,QAAQ;KAAC;KAAM;KAAM,QAAQ;KAAO,GAAG,OAAO;KAAU,EAAE,EAC3E,OAAO,WACR,CAEG,CAAC,GAAG,UAAU,QAAQ;AACxB,aAAQ,MAAM,0BAA0B,IAAI,QAAQ;AACpD,aAAQ,KAAK,EAAE;MACf;UACG;IAEL,MAAM,SAAS,SACb,WAAW,QAAQ,MAAM,GAAG,OAAO,+CACnC,EAAE,UAAU,SAAS,CACtB;AAED,YAAQ,IAAI,WAAW,QAAQ,MAAM,2BAA2B;AAChE,YAAQ,IAAI,OAAO;AACnB,YAAQ,KAAK,EAAE;;WAEV,KAAK;AACZ,WAAQ,MAAM,0BAA0B,IAAI;AAC5C,WAAQ,KAAK,EAAE;;GAEjB"}
1
+ {"version":3,"file":"logs.js","names":[],"sources":["../../../../../src/cli/commands/gateway/logs.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { existsSync, statSync, watch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { getContextWithOpts } from '../../context.js';\n\nfunction parseLineCount(value: string | number | undefined): number {\n const parsed = parseInt(String(value ?? '50'), 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : 50;\n}\n\nfunction resolveGatewayLogPath(configPath: string): string {\n const logDir = process.env.XOPC_LOG_DIR || path.join(path.dirname(configPath), 'logs');\n return path.join(logDir, 'app.log');\n}\n\nasync function readLastLines(filePath: string, lineCount: number): Promise<string> {\n if (!existsSync(filePath)) {\n return 'No logs found\\n';\n }\n\n const content = await readFile(filePath, 'utf8');\n const lines = content.split(/\\r?\\n/);\n const trailingEmptyLine = lines.at(-1) === '';\n const logLines = trailingEmptyLine ? lines.slice(0, -1) : lines;\n const selectedLines = logLines.slice(-lineCount);\n return `${selectedLines.join('\\n')}${selectedLines.length > 0 ? '\\n' : ''}`;\n}\n\nasync function followLogFile(filePath: string, lineCount: number): Promise<void> {\n process.stdout.write(await readLastLines(filePath, lineCount));\n let lastSize = existsSync(filePath) ? statSync(filePath).size : 0;\n\n const directory = path.dirname(filePath);\n const fileName = path.basename(filePath);\n watch(directory, async (_eventType, changedFileName) => {\n if (changedFileName && changedFileName.toString() !== fileName) {\n return;\n }\n if (!existsSync(filePath)) {\n lastSize = 0;\n return;\n }\n\n const nextSize = statSync(filePath).size;\n if (nextSize < lastSize) {\n lastSize = 0;\n }\n if (nextSize === lastSize) {\n return;\n }\n\n const content = await readFile(filePath, 'utf8');\n process.stdout.write(content.slice(lastSize));\n lastSize = nextSize;\n });\n}\n\n/**\n * Create logs subcommand\n */\nexport function createLogsCommand(): Command {\n return new Command('logs')\n .description('View gateway logs')\n .option('--lines <n>', 'Number of lines to show', '50')\n .option('--follow', 'Follow log output (like tail -f)')\n .action(async (options) => {\n const ctx = getContextWithOpts();\n const lineCount = parseLineCount(options.lines);\n const logPath = resolveGatewayLogPath(ctx.configPath);\n\n try {\n if (options.follow) {\n console.log(`📜 Following gateway logs (Ctrl+C to exit)...\\n`);\n await followLogFile(logPath, lineCount);\n return;\n }\n\n const output = await readLastLines(logPath, lineCount);\n console.log(`📜 Last ${lineCount} lines of gateway logs:\\n`);\n console.log(output);\n process.exit(0);\n } catch (err) {\n console.error('❌ Failed to read logs:', err);\n process.exit(1);\n }\n });\n}\n\nexport const gatewayLogsTestInternals = {\n parseLineCount,\n readLastLines,\n resolveGatewayLogPath,\n};\n"],"mappings":";;;;;;AAOA,SAAS,eAAe,OAA4C;CAClE,MAAM,SAAS,SAAS,OAAO,SAAS,KAAK,EAAE,GAAG;AAClD,QAAO,OAAO,SAAS,OAAO,IAAI,SAAS,IAAI,SAAS;;AAG1D,SAAS,sBAAsB,YAA4B;CACzD,MAAM,SAAS,QAAQ,IAAI,gBAAgB,KAAK,KAAK,KAAK,QAAQ,WAAW,EAAE,OAAO;AACtF,QAAO,KAAK,KAAK,QAAQ,UAAU;;AAGrC,eAAe,cAAc,UAAkB,WAAoC;AACjF,KAAI,CAAC,WAAW,SAAS,CACvB,QAAO;CAIT,MAAM,SAAQ,MADQ,SAAS,UAAU,OAAO,EAC1B,MAAM,QAAQ;CAGpC,MAAM,iBAFoB,MAAM,GAAG,GAAG,KAAK,KACN,MAAM,MAAM,GAAG,GAAG,GAAG,OAC3B,MAAM,CAAC,UAAU;AAChD,QAAO,GAAG,cAAc,KAAK,KAAK,GAAG,cAAc,SAAS,IAAI,OAAO;;AAGzE,eAAe,cAAc,UAAkB,WAAkC;AAC/E,SAAQ,OAAO,MAAM,MAAM,cAAc,UAAU,UAAU,CAAC;CAC9D,IAAI,WAAW,WAAW,SAAS,GAAG,SAAS,SAAS,CAAC,OAAO;CAEhE,MAAM,YAAY,KAAK,QAAQ,SAAS;CACxC,MAAM,WAAW,KAAK,SAAS,SAAS;AACxC,OAAM,WAAW,OAAO,YAAY,oBAAoB;AACtD,MAAI,mBAAmB,gBAAgB,UAAU,KAAK,SACpD;AAEF,MAAI,CAAC,WAAW,SAAS,EAAE;AACzB,cAAW;AACX;;EAGF,MAAM,WAAW,SAAS,SAAS,CAAC;AACpC,MAAI,WAAW,SACb,YAAW;AAEb,MAAI,aAAa,SACf;EAGF,MAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,UAAQ,OAAO,MAAM,QAAQ,MAAM,SAAS,CAAC;AAC7C,aAAW;GACX;;;;;AAMJ,SAAgB,oBAA6B;AAC3C,QAAO,IAAI,QAAQ,OAAO,CACvB,YAAY,oBAAoB,CAChC,OAAO,eAAe,2BAA2B,KAAK,CACtD,OAAO,YAAY,mCAAmC,CACtD,OAAO,OAAO,YAAY;EACzB,MAAM,MAAM,oBAAoB;EAChC,MAAM,YAAY,eAAe,QAAQ,MAAM;EAC/C,MAAM,UAAU,sBAAsB,IAAI,WAAW;AAErD,MAAI;AACF,OAAI,QAAQ,QAAQ;AAClB,YAAQ,IAAI,kDAAkD;AAC9D,UAAM,cAAc,SAAS,UAAU;AACvC;;GAGF,MAAM,SAAS,MAAM,cAAc,SAAS,UAAU;AACtD,WAAQ,IAAI,WAAW,UAAU,2BAA2B;AAC5D,WAAQ,IAAI,OAAO;AACnB,WAAQ,KAAK,EAAE;WACR,KAAK;AACZ,WAAQ,MAAM,0BAA0B,IAAI;AAC5C,WAAQ,KAAK,EAAE;;GAEjB;;AAGN,MAAa,2BAA2B;CACtC;CACA;CACA;CACD"}
@@ -8,8 +8,8 @@ import { formatExamples, register } from "../registry.js";
8
8
  import { getContextWithOpts } from "../context.js";
9
9
  import "../../agent/image/index.js";
10
10
  import { colors } from "../utils/colors.js";
11
- import { join, resolve } from "node:path";
12
11
  import { mkdir, writeFile } from "node:fs/promises";
12
+ import { join, resolve } from "node:path";
13
13
  import { Command } from "commander";
14
14
  //#region src/cli/commands/image.ts
15
15
  init_loader();
@@ -102,11 +102,10 @@ function createImageCommand(_ctx) {
102
102
  if (!config.agents) config.agents = { defaults: {} };
103
103
  if (!config.agents.defaults) config.agents.defaults = {};
104
104
  const existingFallbacks = modelFallbacksToArray(config.agents.defaults.imageModel);
105
- if (existingFallbacks.length > 0) config.agents.defaults.imageModel = {
105
+ config.agents.defaults.imageModel = existingFallbacks.length > 0 ? {
106
106
  primary: modelRef,
107
107
  fallbacks: existingFallbacks
108
- };
109
- else config.agents.defaults.imageModel = modelRef;
108
+ } : { primary: modelRef };
110
109
  await saveConfig(config, configPath);
111
110
  console.log(colors.green(`Image understanding model set to: ${modelRef}`));
112
111
  });
@@ -122,11 +121,10 @@ function createImageCommand(_ctx) {
122
121
  if (!config.agents) config.agents = { defaults: {} };
123
122
  if (!config.agents.defaults) config.agents.defaults = {};
124
123
  const existingFallbacks = modelFallbacksToArray(config.agents.defaults.imageGenerationModel);
125
- if (existingFallbacks.length > 0) config.agents.defaults.imageGenerationModel = {
124
+ config.agents.defaults.imageGenerationModel = existingFallbacks.length > 0 ? {
126
125
  primary: modelRef,
127
126
  fallbacks: existingFallbacks
128
- };
129
- else config.agents.defaults.imageGenerationModel = modelRef;
127
+ } : { primary: modelRef };
130
128
  await saveConfig(config, configPath);
131
129
  console.log(colors.green(`Image generation model set to: ${modelRef}`));
132
130
  });
@@ -190,11 +188,10 @@ function createImageCommand(_ctx) {
190
188
  const removed = fallbacks.splice(index, 1)[0];
191
189
  if (!config.agents) config.agents = { defaults: {} };
192
190
  if (!config.agents.defaults) config.agents.defaults = {};
193
- if (fallbacks.length > 0 && primary) config.agents.defaults[configKey] = {
191
+ if (primary) config.agents.defaults[configKey] = fallbacks.length > 0 ? {
194
192
  primary,
195
193
  fallbacks
196
- };
197
- else if (primary) config.agents.defaults[configKey] = primary;
194
+ } : { primary };
198
195
  await saveConfig(config, configPath);
199
196
  console.log(colors.green(`Removed fallback: ${removed}`));
200
197
  });
@@ -272,22 +269,24 @@ function createImageCommand(_ctx) {
272
269
  if (!config.agents.defaults) config.agents.defaults = {};
273
270
  const current = config.agents.defaults.imageGenerationModel;
274
271
  const primary = resolveAgentModelPrimaryValue(current);
272
+ if (!primary) {
273
+ console.error(colors.red("No image generation model is configured. Run `xopc image set-generation <provider/model>` first."));
274
+ process.exit(1);
275
+ }
275
276
  const fallbacks = resolveAgentModelFallbackValues(current);
276
- const autoProviderFallback = typeof current === "object" && current !== null && !Array.isArray(current) ? current.autoProviderFallback === true : false;
277
+ const autoProviderFallback = current?.autoProviderFallback === true;
277
278
  if (ms === 0) {
278
- if (primary && fallbacks.length === 0 && !autoProviderFallback) config.agents.defaults.imageGenerationModel = primary;
279
- else if (primary || fallbacks.length > 0) config.agents.defaults.imageGenerationModel = {
280
- ...primary ? { primary } : {},
279
+ config.agents.defaults.imageGenerationModel = {
280
+ primary,
281
281
  ...fallbacks.length > 0 ? { fallbacks } : {},
282
282
  ...autoProviderFallback ? { autoProviderFallback: true } : {}
283
283
  };
284
- else delete config.agents.defaults.imageGenerationModel;
285
284
  await saveConfig(config, configPath);
286
285
  console.log(colors.green("Image generation timeout cleared."));
287
286
  return;
288
287
  }
289
288
  config.agents.defaults.imageGenerationModel = {
290
- ...primary ? { primary } : {},
289
+ primary,
291
290
  ...fallbacks.length > 0 ? { fallbacks } : {},
292
291
  ...autoProviderFallback ? { autoProviderFallback: true } : {},
293
292
  timeoutMs: ms
@@ -309,22 +308,24 @@ function createImageCommand(_ctx) {
309
308
  if (!config.agents.defaults) config.agents.defaults = {};
310
309
  const current = config.agents.defaults.imageGenerationModel;
311
310
  const primary = resolveAgentModelPrimaryValue(current);
311
+ if (!primary) {
312
+ console.error(colors.red("No image generation model is configured. Run `xopc image set-generation <provider/model>` first."));
313
+ process.exit(1);
314
+ }
312
315
  const fallbacks = resolveAgentModelFallbackValues(current);
313
- const timeoutMs = typeof current === "object" && current !== null && !Array.isArray(current) ? current.timeoutMs : void 0;
316
+ const timeoutMs = current?.timeoutMs;
314
317
  if (disable) {
315
- if (primary && fallbacks.length === 0 && !timeoutMs) config.agents.defaults.imageGenerationModel = primary;
316
- else if (primary || fallbacks.length > 0 || timeoutMs) config.agents.defaults.imageGenerationModel = {
317
- ...primary ? { primary } : {},
318
+ config.agents.defaults.imageGenerationModel = {
319
+ primary,
318
320
  ...fallbacks.length > 0 ? { fallbacks } : {},
319
321
  ...timeoutMs ? { timeoutMs } : {}
320
322
  };
321
- else delete config.agents.defaults.imageGenerationModel;
322
323
  await saveConfig(config, configPath);
323
324
  console.log(colors.green("Image generation auto-fallback disabled."));
324
325
  return;
325
326
  }
326
327
  config.agents.defaults.imageGenerationModel = {
327
- ...primary ? { primary } : {},
328
+ primary,
328
329
  ...fallbacks.length > 0 ? { fallbacks } : {},
329
330
  ...timeoutMs ? { timeoutMs } : {},
330
331
  autoProviderFallback: true