@xopcai/xopc 0.0.114 → 0.0.115

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 (375) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  3. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  4. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  5. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  6. package/dist/extensions/telegram/src/plugin.js +1 -1
  7. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  8. package/dist/extensions/telegram/src/update-offset-store.js +1 -1
  9. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  10. package/dist/extensions/telegram/xopc.extension.json +1 -1
  11. package/dist/extensions/weixin/src/api/api.js +2 -2
  12. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  13. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  14. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  15. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  16. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  17. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  18. package/dist/extensions/weixin/src/plugin.js +1 -1
  19. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  20. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  21. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Fp-p7bP1.js → agent-avatar-dicebear-DVnBfANm.js} +1 -1
  22. package/dist/gateway/static/root/assets/agent-browser-settings-page-DPXc4hz8.js +6 -0
  23. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-CTJ0YnRQ.js +1 -0
  24. package/dist/gateway/static/root/assets/agents-zJXQfJ_W.js +71 -0
  25. package/dist/gateway/static/root/assets/{app-management-settings-panel-v24i25Oj.js → app-management-settings-panel-DzGbdr04.js} +1 -1
  26. package/dist/gateway/static/root/assets/{appearance-settings-ycbdJRuZ.js → appearance-settings-BQpPSTHD.js} +1 -1
  27. package/dist/gateway/static/root/assets/apps-page-CPjfyzSD.js +1 -0
  28. package/dist/gateway/static/root/assets/{archive-plugin-CJzSADJo.js → archive-plugin-CXu-Csep.js} +1 -1
  29. package/dist/gateway/static/root/assets/{attachment-load-BTAB4zGS.js → attachment-load-BAjgOoGY.js} +1 -1
  30. package/dist/gateway/static/root/assets/{binary-plugins-DXR1-mct.js → binary-plugins-BSBgB2hO.js} +1 -1
  31. package/dist/gateway/static/root/assets/{block-editor-CzQri9h2.js → block-editor-BpXw9TTR.js} +44 -44
  32. package/dist/gateway/static/root/assets/channels-settings-BbPUpzWB.js +1 -0
  33. package/dist/gateway/static/root/assets/{config-api-DRqjEvAx.js → config-api-NOoPiIYz.js} +1 -1
  34. package/dist/gateway/static/root/assets/connectors-settings-CAXYMOdp.js +2 -0
  35. package/dist/gateway/static/root/assets/{cron-api-BXaZXv1o.js → cron-api-C9BOqAXd.js} +1 -1
  36. package/dist/gateway/static/root/assets/cron-page-DuUbBeKI.js +3 -0
  37. package/dist/gateway/static/root/assets/dreaming-settings-DQ4DtiK1.js +1 -0
  38. package/dist/gateway/static/root/assets/{extension-debug-page-DSkqMYo7.js → extension-debug-page-D9kgUHCc.js} +1 -1
  39. package/dist/gateway/static/root/assets/{extension-page-h2dGDbMN.js → extension-page-CGyhXqzR.js} +1 -1
  40. package/dist/gateway/static/root/assets/{extension-settings-page-hN99RhOi.js → extension-settings-page-DL8Xquqd.js} +1 -1
  41. package/dist/gateway/static/root/assets/{fetch-D9QqUtzZ.js → fetch-D0VXA932.js} +1 -1
  42. package/dist/gateway/static/root/assets/{format-interval-label-D6E687rG.js → format-interval-label-Be8SmgUw.js} +1 -1
  43. package/dist/gateway/static/root/assets/{gateway-config-api-CLt_SKTC.js → gateway-config-api-C-xjn__h.js} +1 -1
  44. package/dist/gateway/static/root/assets/{gateway-settings-1PDi4lI0.js → gateway-settings-BMPwIjKI.js} +1 -1
  45. package/dist/gateway/static/root/assets/{gateway-startup-retry-N7Z_sz7p.js → gateway-startup-retry-DERUH61L.js} +1 -1
  46. package/dist/gateway/static/root/assets/goal-detail-page-BJsyjJnF.js +1 -0
  47. package/dist/gateway/static/root/assets/goals-config-api-BPmqWk90.js +1 -0
  48. package/dist/gateway/static/root/assets/goals-page-BerDgIhw.js +2 -0
  49. package/dist/gateway/static/root/assets/goals-settings-ByTjeAto.js +1 -0
  50. package/dist/gateway/static/root/assets/{heartbeat-config-api-DGPadTw-.js → heartbeat-config-api-Bfdzr8oV.js} +1 -1
  51. package/dist/gateway/static/root/assets/{heartbeat-settings-BHHAs8ZX.js → heartbeat-settings-TbHgcjTn.js} +1 -1
  52. package/dist/gateway/static/root/assets/{index-DefIdW9q.js → index-AkTrf6Pb.js} +56 -56
  53. package/dist/gateway/static/root/assets/index-fh5sXTj9.css +1 -0
  54. package/dist/gateway/static/root/assets/{interval-presets-CEklPQ_r.js → interval-presets-utKbuCRY.js} +1 -1
  55. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Ce_aQ8Iv.js → keyboard-shortcuts-settings-CjqS6c6V.js} +1 -1
  56. package/dist/gateway/static/root/assets/logs-page-DGXuPf5B.js +2 -0
  57. package/dist/gateway/static/root/assets/{markdown-split-BMz3xPXO.js → markdown-split-DW8C47iB.js} +1 -1
  58. package/dist/gateway/static/root/assets/{media-plugins-BalOSoz9.js → media-plugins-D6HwDhDT.js} +1 -1
  59. package/dist/gateway/static/root/assets/messages-upgxw6Ub.js +3 -0
  60. package/dist/gateway/static/root/assets/models-hub-panel-Bot16nn7.js +2 -0
  61. package/dist/gateway/static/root/assets/note-detail-page-Brlyou8M.js +2 -0
  62. package/dist/gateway/static/root/assets/{note-image-lightbox-C5D1Q5mY.js → note-image-lightbox-pJM35Pz5.js} +1 -1
  63. package/dist/gateway/static/root/assets/notes-page-DvZ4pwc-.js +1 -0
  64. package/dist/gateway/static/root/assets/{preview-open-alternatives-CYFR5U9l.js → preview-open-alternatives-CVwHuyN6.js} +1 -1
  65. package/dist/gateway/static/root/assets/remote-access-hub-BZEDmxbZ.js +1 -0
  66. package/dist/gateway/static/root/assets/{save-bar-controls-BQ79Z5IP.js → save-bar-controls-Ba-UEk7x.js} +1 -1
  67. package/dist/gateway/static/root/assets/{schedule-field-Bgk6Emue.js → schedule-field-CNN9595U.js} +1 -1
  68. package/dist/gateway/static/root/assets/{schema-form-DzS36TMa.js → schema-form-DnNMmtD5.js} +1 -1
  69. package/dist/gateway/static/root/assets/sessions-page-DdGGlsfn.js +1 -0
  70. package/dist/gateway/static/root/assets/settings-advanced-gate-DlkEkPf9.js +1 -0
  71. package/dist/gateway/static/root/assets/{settings-collapsible-section-CdjFnSAy.js → settings-collapsible-section-CmOz80i5.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-form-section-DZLy_exu.js → settings-form-section-BmK7JJOV.js} +1 -1
  73. package/dist/gateway/static/root/assets/settings-page-DFPTrsPF.js +1 -0
  74. package/dist/gateway/static/root/assets/setup-status-panel-CYCCfgh4.js +1 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-_qRDr4g_.js → share-preview-page-Dp2qGrHC.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-Bff1pGd0.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-CJGKpBur.js +1 -0
  78. package/dist/gateway/static/root/assets/skills-page-C6ocduTD.js +2 -0
  79. package/dist/gateway/static/root/assets/{system-settings-panel-hqaBF5aG.js → system-settings-panel-5jrIEr5b.js} +1 -1
  80. package/dist/gateway/static/root/assets/{use-agent-defaults-form-zbVIQLOA.js → use-agent-defaults-form-BuiXLIs5.js} +1 -1
  81. package/dist/gateway/static/root/assets/{use-channel-catalog-CbXq97rT.js → use-channel-catalog-CHlO8J9G.js} +1 -1
  82. package/dist/gateway/static/root/assets/{use-settings-tab-guard-DwS3drWK.js → use-settings-tab-guard-CW5JORnl.js} +1 -1
  83. package/dist/gateway/static/root/assets/voice-api-key-field-DDoQyghO.js +1 -0
  84. package/dist/gateway/static/root/assets/{voice-player-store-DSuOd9zy.js → voice-player-store-DDDWYHvg.js} +1 -1
  85. package/dist/gateway/static/root/assets/{workflow-page.utils-C0Uq3xyq.js → workflow-page.utils-CKjeEGqx.js} +1 -1
  86. package/dist/gateway/static/root/assets/workflows-page-B604ehHG.js +18 -0
  87. package/dist/gateway/static/root/index.html +5 -5
  88. package/dist/gateway/static/root/logo.svg +4 -3
  89. package/dist/package.js +1 -1
  90. package/dist/src/agent/agent-manager.js +6 -6
  91. package/dist/src/agent/agent-scope.js +1 -1
  92. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  93. package/dist/src/agent/bootstrap/project-agents-context.js +1 -1
  94. package/dist/src/agent/context/workspace-seed.js +2 -2
  95. package/dist/src/agent/context/workspace-state.js +1 -1
  96. package/dist/src/agent/context/workspace.js +1 -1
  97. package/dist/src/agent/embedded/session-tool-result-guard.js +8 -1
  98. package/dist/src/agent/embedded/session-tool-result-guard.js.map +1 -1
  99. package/dist/src/agent/goals/checklist-judge.d.ts +1 -0
  100. package/dist/src/agent/goals/checklist-judge.js +3 -2
  101. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  102. package/dist/src/agent/goals/evaluate-turn.d.ts +1 -1
  103. package/dist/src/agent/goals/evaluate-turn.js +1 -0
  104. package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
  105. package/dist/src/agent/goals/goal-locale.js +2 -2
  106. package/dist/src/agent/goals/post-turn.d.ts +6 -1
  107. package/dist/src/agent/goals/post-turn.js +15 -6
  108. package/dist/src/agent/goals/post-turn.js.map +1 -1
  109. package/dist/src/agent/image/load-image-media.js +2 -2
  110. package/dist/src/agent/ipc/inbox.js +3 -3
  111. package/dist/src/agent/ipc/socket.js +1 -1
  112. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  113. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  114. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  115. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  116. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  117. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  118. package/dist/src/agent/memory/dreaming/events.js +1 -1
  119. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  120. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  121. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  122. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  123. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  124. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  125. package/dist/src/agent/memory/memory-flush.js +1 -1
  126. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  127. package/dist/src/agent/models/manager.js +1 -1
  128. package/dist/src/agent/prompt/memory/index.js +1 -1
  129. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  130. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  131. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  132. package/dist/src/agent/sandbox/path-policy.js +2 -2
  133. package/dist/src/agent/service.js +4 -4
  134. package/dist/src/agent/session/session-inspector.js +1 -1
  135. package/dist/src/agent/skills/config.js +2 -2
  136. package/dist/src/agent/skills/filesystem-watcher.js +1 -1
  137. package/dist/src/agent/skills/hub-hash.js +2 -2
  138. package/dist/src/agent/skills/hub-lock.js +1 -1
  139. package/dist/src/agent/skills/hub-pull.js +2 -2
  140. package/dist/src/agent/skills/index.js +2 -2
  141. package/dist/src/agent/skills/installer.js +2 -2
  142. package/dist/src/agent/skills/managed-store.js +1 -1
  143. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  144. package/dist/src/agent/skills/skill-manager.js +1 -1
  145. package/dist/src/agent/skills/skill-view-path.js +1 -1
  146. package/dist/src/agent/skills/test-framework.js +1 -1
  147. package/dist/src/agent/starter-agents.js +1 -1
  148. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  149. package/dist/src/agent/tools/find.js +1 -1
  150. package/dist/src/agent/tools/grep.js +1 -1
  151. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  152. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  153. package/dist/src/agent/tools/workflow-tool.js +1 -1
  154. package/dist/src/agent/workflow/catalog.js +1 -1
  155. package/dist/src/agent/workflow/snapshot.d.ts +10 -0
  156. package/dist/src/agent/workflow/snapshot.js +136 -1
  157. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  158. package/dist/src/ai-assist/text-assist.js +1 -1
  159. package/dist/src/auth/credentials.js +2 -2
  160. package/dist/src/auth/profiles/store.js +2 -2
  161. package/dist/src/auth/sync-provider-auth.js +1 -1
  162. package/dist/src/browser/cache-dir-policy.js +1 -1
  163. package/dist/src/browser/cdp-local-launcher.js +2 -2
  164. package/dist/src/browser/pipeline/source.js +1 -1
  165. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  166. package/dist/src/browser/providers/cloakbrowser.js +5 -5
  167. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  168. package/dist/src/browser/stealth.js +1 -1
  169. package/dist/src/channels/catalog/channel-catalog-service.d.ts +2 -1
  170. package/dist/src/channels/catalog/channel-catalog-service.js +133 -16
  171. package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -1
  172. package/dist/src/channels/catalog/channel-catalog-types.d.ts +13 -0
  173. package/dist/src/channels/outbound/persist-store.js +1 -1
  174. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  175. package/dist/src/channels/pairing/pairing-store.js +2 -2
  176. package/dist/src/chat-commands/agent-edit.js +2 -2
  177. package/dist/src/chat-commands/builtins/config.js +2 -2
  178. package/dist/src/cli/commands/config.js +1 -1
  179. package/dist/src/cli/commands/doctor/checks/channel-config.js +14 -1
  180. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -1
  181. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  182. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  183. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  184. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  185. package/dist/src/cli/commands/extension-create.js +1 -1
  186. package/dist/src/cli/commands/extension-dev.js +2 -2
  187. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  188. package/dist/src/cli/commands/extension-pack.js +2 -2
  189. package/dist/src/cli/commands/extension.js +3 -3
  190. package/dist/src/cli/commands/gateway/logs.js +1 -1
  191. package/dist/src/cli/commands/image.js +1 -1
  192. package/dist/src/cli/commands/init.js +2 -2
  193. package/dist/src/cli/commands/models.js +1 -1
  194. package/dist/src/cli/commands/skills-test.js +1 -1
  195. package/dist/src/cli/templates.js +1 -1
  196. package/dist/src/cli/utils/gateway-client.js +1 -1
  197. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  198. package/dist/src/config/agent-profile.js +1 -1
  199. package/dist/src/config/agent-typed-models.js +1 -1
  200. package/dist/src/config/gateway-bind.js +1 -1
  201. package/dist/src/config/index.js +7 -7
  202. package/dist/src/config/loader.js +4 -4
  203. package/dist/src/config/models-json.js +2 -2
  204. package/dist/src/config/paths-state.js +1 -1
  205. package/dist/src/config/paths.js +1 -1
  206. package/dist/src/config/profile.js +1 -1
  207. package/dist/src/config/reload.js +1 -1
  208. package/dist/src/config/schema.d.ts +8 -0
  209. package/dist/src/config/schema.js +7 -0
  210. package/dist/src/config/schema.js.map +1 -1
  211. package/dist/src/config/web-patch.d.ts +1 -0
  212. package/dist/src/config/web-patch.js +1 -0
  213. package/dist/src/config/web-patch.js.map +1 -1
  214. package/dist/src/config/workspace-path.js +1 -1
  215. package/dist/src/cron/executor.js +1 -1
  216. package/dist/src/cron/service.js +1 -1
  217. package/dist/src/daemon/constants.js +1 -1
  218. package/dist/src/daemon/install-plan.js +2 -2
  219. package/dist/src/daemon/launchd.js +2 -2
  220. package/dist/src/daemon/schtasks.js +2 -2
  221. package/dist/src/daemon/systemd.js +2 -2
  222. package/dist/src/extensions/bundle-mcp.js +1 -1
  223. package/dist/src/extensions/discover-extensions.js +2 -2
  224. package/dist/src/extensions/health.js +1 -1
  225. package/dist/src/extensions/install.js +2 -2
  226. package/dist/src/extensions/loader.js +2 -2
  227. package/dist/src/extensions/lockfile.js +3 -3
  228. package/dist/src/extensions/security.js +1 -1
  229. package/dist/src/extensions/update.js +2 -2
  230. package/dist/src/gateway/agents-admin.js +2 -2
  231. package/dist/src/gateway/file-path-classifier.js +2 -2
  232. package/dist/src/gateway/hono/app.js +5 -1
  233. package/dist/src/gateway/hono/app.js.map +1 -1
  234. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -1
  235. package/dist/src/gateway/hono/lib/config-payload.js +7 -4
  236. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  237. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  238. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  239. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
  240. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +19 -5
  241. package/dist/src/gateway/hono/middleware/strict-rate-limit.js.map +1 -1
  242. package/dist/src/gateway/hono/routes/agents.js +1 -1
  243. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  244. package/dist/src/gateway/hono/routes/channels.js +18 -14
  245. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  246. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  247. package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
  248. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  249. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  250. package/dist/src/gateway/hono/routes/models.js +1 -1
  251. package/dist/src/gateway/hono/routes/shares.js +1 -1
  252. package/dist/src/gateway/hono/routes/workflows.js +1 -1
  253. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  254. package/dist/src/gateway/lock.js +3 -3
  255. package/dist/src/gateway/ports.js +1 -1
  256. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  257. package/dist/src/gateway/rate-limit/buckets.js +12 -0
  258. package/dist/src/gateway/rate-limit/buckets.js.map +1 -1
  259. package/dist/src/gateway/service/config-coordinator.js +1 -1
  260. package/dist/src/gateway/service/marketplace-service.js +2 -2
  261. package/dist/src/gateway/service.js +4 -4
  262. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  263. package/dist/src/goals/goal-workflow-judge.js +2 -2
  264. package/dist/src/i18n/goals-bundle.js +1 -1
  265. package/dist/src/i18n/index.js +1 -1
  266. package/dist/src/i18n/share-tool-bundle.js +2 -2
  267. package/dist/src/infra/brew.js +1 -1
  268. package/dist/src/infra/package-json.js +1 -1
  269. package/dist/src/infra/package-update-steps.js +1 -1
  270. package/dist/src/infra/path-env.js +2 -2
  271. package/dist/src/infra/restart.js +1 -1
  272. package/dist/src/infra/stable-node-path.js +1 -1
  273. package/dist/src/infra/update-check.js +1 -1
  274. package/dist/src/infra/update-global.js +1 -1
  275. package/dist/src/infra/update-lock.js +2 -2
  276. package/dist/src/infra/update-restart.js +1 -1
  277. package/dist/src/infra/update-runner.js +1 -1
  278. package/dist/src/infra/update-startup.js +1 -1
  279. package/dist/src/infra/write-file-atomic.js +2 -2
  280. package/dist/src/media/store.js +1 -1
  281. package/dist/src/notes/agent-context.js +1 -1
  282. package/dist/src/notes/service.js +1 -1
  283. package/dist/src/notes/store.js +2 -2
  284. package/dist/src/project-trust/trust-store.js +2 -2
  285. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  286. package/dist/src/providers/index.js +1 -1
  287. package/dist/src/providers/model-registry.js +4 -4
  288. package/dist/src/session/init-session-turn.js +1 -1
  289. package/dist/src/session/resolve-session.js +1 -1
  290. package/dist/src/session/session-title.js +2 -2
  291. package/dist/src/session/store.js +1 -1
  292. package/dist/src/share/share-auto.js +2 -2
  293. package/dist/src/share/share-store.js +3 -3
  294. package/dist/src/share/share-thumbnail.js +2 -2
  295. package/dist/src/share/share-zip.js +1 -1
  296. package/dist/src/share/site-share-store.js +3 -3
  297. package/dist/src/share/site-static-serve.js +1 -1
  298. package/dist/src/storage/sqlite/connection.js +1 -1
  299. package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
  300. package/dist/src/storage/sqlite/migrations/discover.js +1 -1
  301. package/dist/src/storage/sqlite/migrations/runner.js +1 -1
  302. package/dist/src/storage/sqlite/schema.js +1 -1
  303. package/dist/src/tui/backends/embedded-backend.d.ts +8 -1
  304. package/dist/src/tui/backends/embedded-backend.js +73 -0
  305. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  306. package/dist/src/tui/backends/gateway-sse-backend.d.ts +2 -1
  307. package/dist/src/tui/backends/gateway-sse-backend.js +24 -0
  308. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  309. package/dist/src/tui/clipboard-image.js +3 -3
  310. package/dist/src/tui/components/chat-log.d.ts +2 -0
  311. package/dist/src/tui/components/chat-log.js +19 -0
  312. package/dist/src/tui/components/chat-log.js.map +1 -1
  313. package/dist/src/tui/extension-host/autocomplete.d.ts +3 -2
  314. package/dist/src/tui/extension-host/autocomplete.js +17 -3
  315. package/dist/src/tui/extension-host/autocomplete.js.map +1 -1
  316. package/dist/src/tui/extension-host/load-extensions.js +1 -1
  317. package/dist/src/tui/extension-host/runtime.d.ts +5 -0
  318. package/dist/src/tui/extension-host/runtime.js +1 -1
  319. package/dist/src/tui/extension-host/runtime.js.map +1 -1
  320. package/dist/src/tui/theme-manager.js +1 -1
  321. package/dist/src/tui/tui-backend.d.ts +14 -0
  322. package/dist/src/tui/tui-command-formatters.js +4 -4
  323. package/dist/src/tui/tui-commands.d.ts +16 -3
  324. package/dist/src/tui/tui-commands.js +49 -21
  325. package/dist/src/tui/tui-commands.js.map +1 -1
  326. package/dist/src/tui/tui-keybindings-file.js +1 -1
  327. package/dist/src/tui/tui-scoped-models.js +2 -2
  328. package/dist/src/tui/tui-settings.js +1 -1
  329. package/dist/src/tui/tui-startup-resources.js +1 -1
  330. package/dist/src/tui/tui-startup-text.js +1 -1
  331. package/dist/src/tui/tui-startup-text.js.map +1 -1
  332. package/dist/src/tui/tui.js +78 -7
  333. package/dist/src/tui/tui.js.map +1 -1
  334. package/dist/src/tunnel/frpc-binary.js +4 -4
  335. package/dist/src/tunnel/frpc-config.js +1 -1
  336. package/dist/src/tunnel/frpc-extract.js +1 -1
  337. package/dist/src/tunnel/tunnel-state.js +1 -1
  338. package/dist/src/utils/logger/audit.js +1 -1
  339. package/dist/src/utils/logger/log-store.js +1 -1
  340. package/dist/src/utils/logger/rotation.js +1 -1
  341. package/dist/src/utils/logger/streams.js +1 -1
  342. package/dist/src/voice/tts/audio.js +1 -1
  343. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  344. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  345. package/dist/src/workflows/service/workflow-run-service.js +1 -1
  346. package/dist/src/workflows/store/event-store.js +1 -1
  347. package/dist/src/workflows/store/run-store.js +1 -1
  348. package/package.json +1 -1
  349. package/dist/gateway/static/root/assets/agent-browser-settings-page-CWh7trjd.js +0 -6
  350. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-kC8OuLoj.js +0 -1
  351. package/dist/gateway/static/root/assets/agents-DJWG26Si.js +0 -71
  352. package/dist/gateway/static/root/assets/apps-page-0V3DXZ7J.js +0 -1
  353. package/dist/gateway/static/root/assets/channels-settings-CIKOkYdO.js +0 -1
  354. package/dist/gateway/static/root/assets/connectors-settings-ClrDS5jH.js +0 -2
  355. package/dist/gateway/static/root/assets/cron-page-Chi_4u4P.js +0 -3
  356. package/dist/gateway/static/root/assets/dreaming-settings-B0_rs2tj.js +0 -1
  357. package/dist/gateway/static/root/assets/goal-detail-page-D_wwXL-t.js +0 -1
  358. package/dist/gateway/static/root/assets/goals-page-DZ2toZ8y.js +0 -2
  359. package/dist/gateway/static/root/assets/goals-settings-LFlwtIKE.js +0 -1
  360. package/dist/gateway/static/root/assets/index-DzmWBkq-.css +0 -1
  361. package/dist/gateway/static/root/assets/logs-page-j_D2QTuQ.js +0 -2
  362. package/dist/gateway/static/root/assets/messages-BN_WiUg0.js +0 -3
  363. package/dist/gateway/static/root/assets/models-hub-panel-CMH_TmZz.js +0 -2
  364. package/dist/gateway/static/root/assets/note-detail-page-O18BrQPq.js +0 -2
  365. package/dist/gateway/static/root/assets/notes-page-B_ZYCmY9.js +0 -1
  366. package/dist/gateway/static/root/assets/remote-access-hub-CwKgWixY.js +0 -1
  367. package/dist/gateway/static/root/assets/sessions-page-C4fcD-7B.js +0 -1
  368. package/dist/gateway/static/root/assets/settings-advanced-gate-Ad2OJ86w.js +0 -1
  369. package/dist/gateway/static/root/assets/settings-page-D2BMY5wo.js +0 -1
  370. package/dist/gateway/static/root/assets/setup-status-panel-aWwxl_E1.js +0 -1
  371. package/dist/gateway/static/root/assets/shares-settings-DUE83uIf.js +0 -1
  372. package/dist/gateway/static/root/assets/skill-reload-api-mWKJcrog.js +0 -1
  373. package/dist/gateway/static/root/assets/skills-page-0Sx1Q58n.js +0 -2
  374. package/dist/gateway/static/root/assets/voice-api-key-field-D6HR0hR2.js +0 -1
  375. package/dist/gateway/static/root/assets/workflows-page-DW0fmWhQ.js +0 -18
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","names":[],"sources":["../../../../src/agent/workflow/snapshot.ts"],"sourcesContent":["/**\n * Workflow progress snapshot model + text renderers.\n *\n * The runtime emits per-event callbacks (`onPhase`, `onAgentStart`, `onAgentEnd`,\n * `onLog`). The workflow tool wraps those callbacks to mutate a snapshot and push\n * a text rendering through `onUpdate` — keeping TUI / Gateway / IM consumers in\n * lock-step from a single source of truth.\n */\n\nimport type {\n WorkflowAgentSnapshot,\n WorkflowAgentStatus,\n WorkflowMeta,\n WorkflowSnapshot,\n} from './types.js';\nimport { emptySnapshotFor } from './snapshot-empty.js';\n\nexport function createWorkflowSnapshot(meta: WorkflowMeta): WorkflowSnapshot {\n return emptySnapshotFor(\n meta.name,\n meta.description,\n meta.phases?.map((p) => p.title),\n );\n}\n\nexport function recomputeCounts(snapshot: WorkflowSnapshot): void {\n let running = 0;\n let done = 0;\n let error = 0;\n let skipped = 0;\n for (const agent of snapshot.agents) {\n switch (agent.status) {\n case 'running':\n running++;\n break;\n case 'done':\n done++;\n break;\n case 'error':\n error++;\n break;\n case 'skipped':\n skipped++;\n break;\n }\n }\n snapshot.agentCount = snapshot.agents.length;\n snapshot.runningCount = running;\n snapshot.doneCount = done;\n snapshot.errorCount = error;\n snapshot.skippedCount = skipped;\n}\n\nexport interface RenderOptions {\n maxAgentsPerPhase?: number;\n maxLogs?: number;\n showResultPreviews?: boolean;\n}\n\nexport function renderWorkflowText(\n snapshot: WorkflowSnapshot,\n completed = false,\n options: RenderOptions = {},\n): string {\n const maxAgentsPerPhase = options.maxAgentsPerPhase ?? 6;\n const maxLogs = options.maxLogs ?? 2;\n const showPreviews = options.showResultPreviews ?? false;\n\n const state = stateSuffix(snapshot);\n const header = completed\n ? `◆ workflow ✓ ${snapshot.name} (${snapshot.doneCount}/${snapshot.agentCount} done${state})`\n : `◆ workflow: ${snapshot.name} (${snapshot.doneCount}/${snapshot.agentCount} done${state})`;\n const lines = [header];\n\n const phaseNames = uniqueOrdered([\n ...snapshot.phases,\n ...(snapshot.currentPhase ? [snapshot.currentPhase] : []),\n ...snapshot.agents.map((a) => a.phase).filter((p): p is string => Boolean(p)),\n ]);\n const rendered = new Set<WorkflowAgentSnapshot>();\n\n for (const phase of phaseNames) {\n const agents = snapshot.agents.filter((a) => a.phase === phase);\n if (agents.length === 0 && snapshot.currentPhase !== phase) continue;\n for (const a of agents) rendered.add(a);\n\n const counts = countAgents(agents);\n const completeHere = agents.length > 0 && counts.done + counts.error + counts.skipped === agents.length;\n const marker =\n counts.running > 0 || (!completeHere && snapshot.currentPhase === phase)\n ? '▶'\n : completeHere\n ? '✓'\n : ' ';\n\n const tail =\n (counts.running ? ` · ${counts.running} running` : '') +\n (counts.error ? ` · ${counts.error} errors` : '') +\n (counts.skipped ? ` · ${counts.skipped} skipped` : '');\n lines.push(` ${marker} ${phase} ${counts.done}/${agents.length}${tail}`);\n\n const visible = agents.slice(-maxAgentsPerPhase);\n for (const agent of visible) {\n const previewText = showPreviews && agent.resultPreview ? ` — ${agent.resultPreview}` : '';\n lines.push(\n ` #${agent.id} ${statusIcon(agent.status)} ${shorten(agent.label, 56)}${previewText}`,\n );\n }\n if (agents.length > visible.length) {\n lines.push(` … ${agents.length - visible.length} earlier agents`);\n }\n }\n\n const unphased = snapshot.agents.filter((a) => !rendered.has(a));\n if (unphased.length > 0) {\n lines.push(' unphased');\n for (const agent of unphased.slice(-maxAgentsPerPhase)) {\n const previewText = showPreviews && agent.resultPreview ? ` — ${agent.resultPreview}` : '';\n lines.push(\n ` #${agent.id} ${statusIcon(agent.status)} ${shorten(agent.label, 56)}${previewText}`,\n );\n }\n }\n\n const visibleLogs = snapshot.logs.slice(-maxLogs);\n if (visibleLogs.length > 0) {\n lines.push('');\n for (const log of visibleLogs) {\n lines.push(` log: ${shorten(log, 80)}`);\n }\n }\n return lines.join('\\n');\n}\n\nexport function previewValue(value: unknown, max = 80): string {\n if (value === null || value === undefined) return '';\n const text = typeof value === 'string' ? value : safeStringify(value);\n if (!text) return '';\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\n// ---------------------------------------------------------------------------\n\nfunction countAgents(agents: WorkflowAgentSnapshot[]) {\n let done = 0;\n let running = 0;\n let error = 0;\n let skipped = 0;\n for (const a of agents) {\n if (a.status === 'done') done++;\n else if (a.status === 'running') running++;\n else if (a.status === 'error') error++;\n else if (a.status === 'skipped') skipped++;\n }\n return { done, running, error, skipped };\n}\n\nfunction statusIcon(status: WorkflowAgentStatus): string {\n switch (status) {\n case 'queued':\n return '○';\n case 'running':\n return '●';\n case 'done':\n return '✓';\n case 'error':\n return '✗';\n case 'skipped':\n return '-';\n }\n}\n\nfunction stateSuffix(snapshot: WorkflowSnapshot): string {\n if (snapshot.errorCount > 0) return `, ${snapshot.errorCount} errors`;\n if (snapshot.skippedCount > 0) return `, ${snapshot.skippedCount} skipped`;\n if (snapshot.runningCount > 0) return `, ${snapshot.runningCount} running`;\n return '';\n}\n\nfunction uniqueOrdered(values: string[]): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const v of values) {\n if (!seen.has(v)) {\n seen.add(v);\n out.push(v);\n }\n }\n return out;\n}\n\nfunction shorten(value: string, max: number): string {\n const text = value.replace(/\\s+/g, ' ').trim();\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"snapshot.js","names":[],"sources":["../../../../src/agent/workflow/snapshot.ts"],"sourcesContent":["/**\n * Workflow progress snapshot model + text renderers.\n *\n * The runtime emits per-event callbacks (`onPhase`, `onAgentStart`, `onAgentEnd`,\n * `onLog`). The workflow tool wraps those callbacks to mutate a snapshot and push\n * a text rendering through `onUpdate` — keeping TUI / Gateway / IM consumers in\n * lock-step from a single source of truth.\n */\n\nimport type {\n WorkflowAgentSnapshot,\n WorkflowAgentStatus,\n WorkflowMeta,\n WorkflowSnapshot,\n} from './types.js';\nimport { emptySnapshotFor } from './snapshot-empty.js';\n\nexport function createWorkflowSnapshot(meta: WorkflowMeta): WorkflowSnapshot {\n return emptySnapshotFor(\n meta.name,\n meta.description,\n meta.phases?.map((p) => p.title),\n );\n}\n\nexport function recomputeCounts(snapshot: WorkflowSnapshot): void {\n let running = 0;\n let done = 0;\n let error = 0;\n let skipped = 0;\n for (const agent of snapshot.agents) {\n switch (agent.status) {\n case 'running':\n running++;\n break;\n case 'done':\n done++;\n break;\n case 'error':\n error++;\n break;\n case 'skipped':\n skipped++;\n break;\n }\n }\n snapshot.agentCount = snapshot.agents.length;\n snapshot.runningCount = running;\n snapshot.doneCount = done;\n snapshot.errorCount = error;\n snapshot.skippedCount = skipped;\n}\n\nexport interface RenderOptions {\n maxAgentsPerPhase?: number;\n maxLogs?: number;\n showResultPreviews?: boolean;\n}\n\nexport type WorkflowPanelStatus =\n | 'queued'\n | 'running'\n | 'succeeded'\n | 'failed'\n | 'cancelled'\n | 'timeout'\n | string;\n\nexport interface WorkflowPanelOptions {\n status?: WorkflowPanelStatus;\n maxActiveAgents?: number;\n maxRecentAgents?: number;\n maxErrors?: number;\n nowMs?: number;\n}\n\nexport function renderWorkflowText(\n snapshot: WorkflowSnapshot,\n completed = false,\n options: RenderOptions = {},\n): string {\n const maxAgentsPerPhase = options.maxAgentsPerPhase ?? 6;\n const maxLogs = options.maxLogs ?? 2;\n const showPreviews = options.showResultPreviews ?? false;\n\n const state = stateSuffix(snapshot);\n const header = completed\n ? `◆ workflow ✓ ${snapshot.name} (${snapshot.doneCount}/${snapshot.agentCount} done${state})`\n : `◆ workflow: ${snapshot.name} (${snapshot.doneCount}/${snapshot.agentCount} done${state})`;\n const lines = [header];\n\n const phaseNames = uniqueOrdered([\n ...snapshot.phases,\n ...(snapshot.currentPhase ? [snapshot.currentPhase] : []),\n ...snapshot.agents.map((a) => a.phase).filter((p): p is string => Boolean(p)),\n ]);\n const rendered = new Set<WorkflowAgentSnapshot>();\n\n for (const phase of phaseNames) {\n const agents = snapshot.agents.filter((a) => a.phase === phase);\n if (agents.length === 0 && snapshot.currentPhase !== phase) continue;\n for (const a of agents) rendered.add(a);\n\n const counts = countAgents(agents);\n const completeHere = agents.length > 0 && counts.done + counts.error + counts.skipped === agents.length;\n const marker =\n counts.running > 0 || (!completeHere && snapshot.currentPhase === phase)\n ? '▶'\n : completeHere\n ? '✓'\n : ' ';\n\n const tail =\n (counts.running ? ` · ${counts.running} running` : '') +\n (counts.error ? ` · ${counts.error} errors` : '') +\n (counts.skipped ? ` · ${counts.skipped} skipped` : '');\n lines.push(` ${marker} ${phase} ${counts.done}/${agents.length}${tail}`);\n\n const visible = agents.slice(-maxAgentsPerPhase);\n for (const agent of visible) {\n const previewText = showPreviews && agent.resultPreview ? ` — ${agent.resultPreview}` : '';\n lines.push(\n ` #${agent.id} ${statusIcon(agent.status)} ${shorten(agent.label, 56)}${previewText}`,\n );\n }\n if (agents.length > visible.length) {\n lines.push(` … ${agents.length - visible.length} earlier agents`);\n }\n }\n\n const unphased = snapshot.agents.filter((a) => !rendered.has(a));\n if (unphased.length > 0) {\n lines.push(' unphased');\n for (const agent of unphased.slice(-maxAgentsPerPhase)) {\n const previewText = showPreviews && agent.resultPreview ? ` — ${agent.resultPreview}` : '';\n lines.push(\n ` #${agent.id} ${statusIcon(agent.status)} ${shorten(agent.label, 56)}${previewText}`,\n );\n }\n }\n\n const visibleLogs = snapshot.logs.slice(-maxLogs);\n if (visibleLogs.length > 0) {\n lines.push('');\n for (const log of visibleLogs) {\n lines.push(` log: ${shorten(log, 80)}`);\n }\n }\n return lines.join('\\n');\n}\n\nexport function previewValue(value: unknown, max = 80): string {\n if (value === null || value === undefined) return '';\n const text = typeof value === 'string' ? value : safeStringify(value);\n if (!text) return '';\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\nexport function renderWorkflowPanel(\n snapshot: WorkflowSnapshot,\n options: WorkflowPanelOptions = {},\n): string {\n const status = options.status ?? inferPanelStatus(snapshot);\n const activeAgents = snapshot.agents.filter((agent) => agent.status === 'running');\n const queuedAgents = snapshot.agents.filter((agent) => agent.status === 'queued');\n const activeLimit = options.maxActiveAgents ?? 4;\n const recentLimit = options.maxRecentAgents ?? 4;\n const durationText = formatDuration(resolveElapsedMs(snapshot, options.nowMs));\n const counts = formatRunCounts(snapshot);\n\n const lines = [\n `◆ ${snapshot.name} ${statusText(status)} ${counts}${durationText ? ` ${durationText}` : ''}`,\n ];\n\n const phaseLines = renderPanelPhaseLines(snapshot);\n if (phaseLines.length > 0) {\n lines.push('', 'Phase', ...phaseLines);\n }\n\n const visibleActive = activeAgents.length > 0 ? activeAgents : queuedAgents;\n if (visibleActive.length > 0) {\n lines.push('', activeAgents.length > 0 ? 'Active' : 'Queued');\n for (const agent of visibleActive.slice(0, activeLimit)) {\n lines.push(...renderActiveAgentLines(agent));\n }\n if (visibleActive.length > activeLimit) {\n lines.push(` … ${visibleActive.length - activeLimit} more`);\n }\n }\n\n const recent = recentCompletedAgents(snapshot).slice(0, recentLimit);\n if (recent.length > 0) {\n lines.push('', 'Recent');\n for (const agent of recent) {\n lines.push(renderRecentAgentLine(agent));\n }\n }\n\n const errors = snapshot.agents.filter((agent) => agent.status === 'error' || agent.error);\n if (errors.length > 0) {\n lines.push('', 'Errors');\n for (const agent of errors.slice(0, options.maxErrors ?? 3)) {\n lines.push(\n ` ✗ #${agent.id} ${shorten(agent.label, 28)}${\n agent.error ? `: ${shorten(agent.error, 96)}` : ''\n }`,\n );\n }\n if (errors.length > (options.maxErrors ?? 3)) {\n lines.push(` … ${errors.length - (options.maxErrors ?? 3)} more`);\n }\n }\n\n return lines.join('\\n');\n}\n\nexport function renderWorkflowFinalSummary(\n snapshot: WorkflowSnapshot,\n options: WorkflowPanelOptions = {},\n): string {\n const status = options.status ?? inferPanelStatus(snapshot);\n const durationText = formatDuration(resolveElapsedMs(snapshot, options.nowMs));\n const lines = [\n `◆ ${snapshot.name} ${statusText(status)} ${formatRunCounts(snapshot)}${durationText ? ` ${durationText}` : ''}`,\n ];\n\n const result = previewValue(snapshot.result, 280);\n if (result) {\n lines.push('', 'Result', ` ${result}`);\n } else {\n const fallback = recentCompletedAgents(snapshot)\n .map((agent) => agent.resultPreview)\n .find((value): value is string => Boolean(value));\n if (fallback) {\n lines.push('', 'Result', ` ${shorten(fallback, 280)}`);\n }\n }\n\n const errors = snapshot.agents.filter((agent) => agent.status === 'error' || agent.error);\n if (errors.length > 0) {\n lines.push('', 'Errors');\n for (const agent of errors.slice(0, options.maxErrors ?? 5)) {\n lines.push(\n ` ✗ #${agent.id} ${shorten(agent.label, 32)}${\n agent.error ? `: ${shorten(agent.error, 120)}` : ''\n }`,\n );\n }\n }\n\n const recent = recentCompletedAgents(snapshot).slice(0, options.maxRecentAgents ?? 5);\n if (recent.length > 0) {\n lines.push('', 'Completed');\n for (const agent of recent) {\n lines.push(renderRecentAgentLine(agent));\n }\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n\nfunction countAgents(agents: WorkflowAgentSnapshot[]) {\n let done = 0;\n let running = 0;\n let error = 0;\n let skipped = 0;\n for (const a of agents) {\n if (a.status === 'done') done++;\n else if (a.status === 'running') running++;\n else if (a.status === 'error') error++;\n else if (a.status === 'skipped') skipped++;\n }\n return { done, running, error, skipped };\n}\n\nfunction statusIcon(status: WorkflowAgentStatus): string {\n switch (status) {\n case 'queued':\n return '○';\n case 'running':\n return '●';\n case 'done':\n return '✓';\n case 'error':\n return '✗';\n case 'skipped':\n return '-';\n }\n}\n\nfunction statusText(status: WorkflowPanelStatus): string {\n switch (status) {\n case 'queued':\n return 'queued';\n case 'running':\n return 'running';\n case 'succeeded':\n return '✓ completed';\n case 'failed':\n return '✗ failed';\n case 'cancelled':\n return 'cancelled';\n case 'timeout':\n return 'timeout';\n default:\n return String(status || 'running');\n }\n}\n\nfunction inferPanelStatus(snapshot: WorkflowSnapshot): WorkflowPanelStatus {\n if (snapshot.errorCount > 0) return 'failed';\n if (snapshot.runningCount > 0) return 'running';\n if (snapshot.doneCount + snapshot.skippedCount >= snapshot.agentCount && snapshot.agentCount > 0) {\n return 'succeeded';\n }\n return 'queued';\n}\n\nfunction formatRunCounts(snapshot: WorkflowSnapshot): string {\n const parts = [`${snapshot.doneCount}/${snapshot.agentCount} done`];\n if (snapshot.runningCount > 0) parts.push(`${snapshot.runningCount} running`);\n if (snapshot.errorCount > 0) parts.push(`${snapshot.errorCount} errors`);\n if (snapshot.skippedCount > 0) parts.push(`${snapshot.skippedCount} skipped`);\n return parts.join(' · ');\n}\n\nfunction resolveElapsedMs(snapshot: WorkflowSnapshot, nowMs = Date.now()): number | undefined {\n if (snapshot.durationMs != null) return snapshot.durationMs;\n const starts = snapshot.agents\n .map((agent) => agent.startedAtMs)\n .filter((value): value is number => typeof value === 'number' && Number.isFinite(value));\n if (starts.length === 0) return undefined;\n return Math.max(0, nowMs - Math.min(...starts));\n}\n\nfunction formatDuration(ms: number | undefined): string {\n if (ms == null || !Number.isFinite(ms)) return '';\n const totalSeconds = Math.max(0, Math.floor(ms / 1000));\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n if (minutes < 60) return `${minutes}:${String(seconds).padStart(2, '0')}`;\n const hours = Math.floor(minutes / 60);\n const restMinutes = minutes % 60;\n return `${hours}:${String(restMinutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n}\n\nfunction renderPanelPhaseLines(snapshot: WorkflowSnapshot): string[] {\n const phaseNames = uniqueOrdered([\n ...snapshot.phases,\n ...(snapshot.currentPhase ? [snapshot.currentPhase] : []),\n ...snapshot.agents.map((a) => a.phase).filter((p): p is string => Boolean(p)),\n ]);\n const out: string[] = [];\n for (const phase of phaseNames) {\n const agents = snapshot.agents.filter((agent) => agent.phase === phase);\n const counts = countAgents(agents);\n const complete = agents.length > 0 && counts.done + counts.error + counts.skipped === agents.length;\n const marker =\n counts.running > 0 || (!complete && snapshot.currentPhase === phase)\n ? '▶'\n : complete\n ? '✓'\n : '○';\n const tail = [\n counts.running > 0 ? `${counts.running} running` : '',\n counts.error > 0 ? `${counts.error} errors` : '',\n counts.skipped > 0 ? `${counts.skipped} skipped` : '',\n ].filter(Boolean).join(' · ');\n out.push(` ${marker} ${phase} ${counts.done}/${agents.length}${tail ? ` · ${tail}` : ''}`);\n }\n return out;\n}\n\nfunction renderActiveAgentLines(agent: WorkflowAgentSnapshot): string[] {\n const step = agent.currentStep || latestStepSummary(agent);\n const iteration =\n agent.iteration != null && agent.maxIterations != null\n ? ` [${agent.iteration}/${agent.maxIterations}]`\n : '';\n const head = ` ${agent.status === 'running' ? '●' : '○'} #${agent.id} ${shorten(agent.label, 32)}${iteration}`;\n return step ? [head, ` ${shorten(step, 96)}`] : [head];\n}\n\nfunction renderRecentAgentLine(agent: WorkflowAgentSnapshot): string {\n const preview = agent.error || agent.resultPreview || latestStepResult(agent);\n return ` ${statusIcon(agent.status)} #${agent.id} ${shorten(agent.label, 32)}${\n preview ? ` — ${shorten(preview, 96)}` : ''\n }`;\n}\n\nfunction recentCompletedAgents(snapshot: WorkflowSnapshot): WorkflowAgentSnapshot[] {\n return [...snapshot.agents]\n .filter((agent) => agent.status === 'done' || agent.status === 'error' || agent.status === 'skipped')\n .reverse();\n}\n\nfunction latestStepSummary(agent: WorkflowAgentSnapshot): string {\n const step =\n [...(agent.steps ?? [])].reverse().find((entry) => entry.status === 'running') ??\n agent.steps?.[agent.steps.length - 1];\n if (!step) return '';\n return step.detail ? `${step.label}: ${step.detail}` : step.label;\n}\n\nfunction latestStepResult(agent: WorkflowAgentSnapshot): string {\n const step = [...(agent.steps ?? [])].reverse().find((entry) => entry.resultPreview || entry.error);\n return step?.error || step?.resultPreview || '';\n}\n\nfunction stateSuffix(snapshot: WorkflowSnapshot): string {\n if (snapshot.errorCount > 0) return `, ${snapshot.errorCount} errors`;\n if (snapshot.skippedCount > 0) return `, ${snapshot.skippedCount} skipped`;\n if (snapshot.runningCount > 0) return `, ${snapshot.runningCount} running`;\n return '';\n}\n\nfunction uniqueOrdered(values: string[]): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const v of values) {\n if (!seen.has(v)) {\n seen.add(v);\n out.push(v);\n }\n }\n return out;\n}\n\nfunction shorten(value: string, max: number): string {\n const text = value.replace(/\\s+/g, ' ').trim();\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { getApiKey, getDefaultModelSync, init_providers, resolveModel } from "../providers/index.js";
4
- import { getAssistantMessageErrorReason, stripCodeFences } from "../agent/goals/judge.js";
5
4
  import { createExtensionAwareStreamFn } from "../providers/extension-stream-bridge.js";
5
+ import { getAssistantMessageErrorReason, stripCodeFences } from "../agent/goals/judge.js";
6
6
  //#region src/ai-assist/text-assist.ts
7
7
  init_providers();
8
8
  init_logger();
@@ -1,8 +1,8 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
- import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
3
- import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveCredentialsDir, resolveOAuthPath } from "../config/paths.js";
4
2
  import { createLogger } from "../utils/logger/index.js";
5
3
  import { init_logger } from "../utils/logger.js";
4
+ import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveCredentialsDir, resolveOAuthPath } from "../config/paths.js";
5
+ import { init_write_file_atomic, writeTextAtomic } from "../infra/write-file-atomic.js";
6
6
  import { getApiKeyFromEnv, init_env_keys } from "../providers/env-keys.js";
7
7
  import { dirname, join } from "path";
8
8
  import { mkdir, readFile, readdir, rm } from "fs/promises";
@@ -1,7 +1,7 @@
1
- import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
2
1
  import { init_paths, resolveCredentialsDir } from "../../config/paths.js";
3
- import { chmodSync, existsSync, mkdirSync, readFileSync } from "node:fs";
2
+ import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
4
3
  import path from "node:path";
4
+ import { chmodSync, existsSync, mkdirSync, readFileSync } from "node:fs";
5
5
  //#region src/auth/profiles/store.ts
6
6
  /**
7
7
  * Auth Profile Store
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
+ import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
2
3
  import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveOAuthPath } from "../config/paths.js";
3
4
  import { init_loader, loadConfig } from "../config/loader.js";
4
- import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
5
5
  import { existsSync, readFileSync } from "node:fs";
6
6
  //#region src/auth/sync-provider-auth.ts
7
7
  /**
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
- import { isAbsolute, relative, resolve, sep } from "node:path";
3
2
  import { homedir } from "node:os";
3
+ import { isAbsolute, relative, resolve, sep } from "node:path";
4
4
  //#region src/browser/cache-dir-policy.ts
5
5
  function expandHome(input) {
6
6
  if (input === "~") return homedir();
@@ -2,10 +2,10 @@ import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { loadPlaywrightCoreModule } from "./providers/playwright-doctor.js";
4
4
  import { pickFreePort } from "./free-port.js";
5
+ import { homedir, platform } from "node:os";
6
+ import { join } from "node:path";
5
7
  import { existsSync } from "node:fs";
6
8
  import { mkdir, rm } from "node:fs/promises";
7
- import { join } from "node:path";
8
- import { homedir, platform } from "node:os";
9
9
  import { spawn } from "node:child_process";
10
10
  //#region src/browser/cdp-local-launcher.ts
11
11
  /**
@@ -1,5 +1,5 @@
1
- import { readFile } from "node:fs/promises";
2
1
  import { dirname, resolve } from "node:path";
2
+ import { readFile } from "node:fs/promises";
3
3
  //#region src/browser/pipeline/source.ts
4
4
  const DEFAULT_PIPELINE_SOURCE_TIMEOUT_MS = 3e4;
5
5
  const MAX_PIPELINE_SOURCE_BYTES = 1024 * 1024;
@@ -1,13 +1,13 @@
1
1
  import { PACKAGE_VERSION, init_package_version } from "../../package-version.js";
2
- import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
3
- import { init_paths, resolveBinDir } from "../../config/paths.js";
2
+ import { assertCacheDir, init_cache_dir_policy } from "../cache-dir-policy.js";
4
3
  import { createLogger } from "../../utils/logger/index.js";
5
4
  import { init_logger } from "../../utils/logger.js";
6
- import { assertCacheDir, init_cache_dir_policy } from "../cache-dir-policy.js";
5
+ import { init_paths, resolveBinDir } from "../../config/paths.js";
6
+ import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
7
7
  import { resolvePackageRoot } from "../../infra/update-check.js";
8
+ import { dirname, join } from "node:path";
8
9
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
9
10
  import { readFile, readdir, rm } from "node:fs/promises";
10
- import { dirname, join } from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { spawn } from "node:child_process";
13
13
  //#region src/browser/providers/browser-ext-install.ts
@@ -1,15 +1,15 @@
1
- import { init_paths, resolveBinDir } from "../../config/paths.js";
1
+ import { assertCacheDir, expandHome, init_cache_dir_policy } from "../cache-dir-policy.js";
2
2
  import { createLogger } from "../../utils/logger/index.js";
3
3
  import { init_logger } from "../../utils/logger.js";
4
- import { assertCacheDir, expandHome, init_cache_dir_policy } from "../cache-dir-policy.js";
4
+ import { init_paths, resolveBinDir } from "../../config/paths.js";
5
5
  import { loadPlaywrightCoreModule } from "./playwright-doctor.js";
6
6
  import { WEBDRIVER_OVERRIDE_SCRIPT, buildStealthArgs, filterCloakBrowserExtraArgs, generateFingerprintSeed, makeExecutable, removeQuarantineAttr } from "../stealth.js";
7
7
  import { pickFreePort } from "../free-port.js";
8
- import { createHash } from "node:crypto";
8
+ import { arch, platform, tmpdir } from "node:os";
9
+ import { join, resolve } from "node:path";
9
10
  import { createReadStream, createWriteStream } from "node:fs";
11
+ import { createHash } from "node:crypto";
10
12
  import { mkdir, mkdtemp, rm, stat } from "node:fs/promises";
11
- import { join, resolve } from "node:path";
12
- import { arch, platform, tmpdir } from "node:os";
13
13
  import { spawn } from "node:child_process";
14
14
  import { Readable, Transform } from "node:stream";
15
15
  import AdmZip from "adm-zip";
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
+ import { dirname, join } from "node:path";
2
3
  import { existsSync } from "node:fs";
3
4
  import { stat } from "node:fs/promises";
4
- import { dirname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  //#region src/browser/providers/playwright-doctor.ts
7
7
  /** Root directory of the `playwright-core` package (Electron extraResources or node_modules). */
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { chmod, stat } from "node:fs/promises";
4
3
  import { platform } from "node:os";
4
+ import { chmod, stat } from "node:fs/promises";
5
5
  import { exec } from "node:child_process";
6
6
  import { promisify } from "node:util";
7
7
  //#region src/browser/stealth.ts
@@ -1,11 +1,12 @@
1
1
  import type { Config } from '../../config/schema.js';
2
2
  import type { ExtensionMetadataSnapshot } from '../../extensions/extension-metadata-snapshot.js';
3
- import type { ChannelCatalog } from './channel-catalog-types.js';
3
+ import type { ChannelCatalog, ChannelCatalogEntry, ChannelSetupStatus } from './channel-catalog-types.js';
4
4
  type BuildChannelCatalogOptions = {
5
5
  locale?: string;
6
6
  };
7
7
  export declare function buildChannelCatalogFromSnapshot(snapshot: ExtensionMetadataSnapshot, options?: BuildChannelCatalogOptions): ChannelCatalog;
8
8
  export declare function buildChannelCatalogForConfig(config: Config, options?: BuildChannelCatalogOptions): ChannelCatalog;
9
+ export declare function getChannelSetupStatus(config: Config, channelId: string, entry?: ChannelCatalogEntry): ChannelSetupStatus;
9
10
  export declare function isChannelConfigured(config: Config, channelId: string): boolean;
10
11
  export declare function getConfiguredChannelIds(config: Config): string[];
11
12
  export {};
@@ -1,5 +1,8 @@
1
1
  import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
2
+ import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
2
3
  import { buildExtensionMetadataSnapshot, init_extension_metadata_snapshot, resolveExtensionLoaderOptionsFromConfig } from "../../extensions/extension-metadata-snapshot.js";
4
+ import { join } from "node:path";
5
+ import { existsSync, readFileSync } from "node:fs";
3
6
  //#region src/channels/catalog/channel-catalog-service.ts
4
7
  function normalizeChannelId(raw) {
5
8
  return raw.trim().toLowerCase();
@@ -20,28 +23,63 @@ function normalizeConfigPath(channelId, raw) {
20
23
  if (!trimmed.startsWith("channels.")) return expected;
21
24
  return trimmed;
22
25
  }
26
+ function configChannelKey(entry, channelId) {
27
+ const path = entry?.configPath;
28
+ if (path?.startsWith("channels.")) return path.slice(9).split(".")[0] || channelId;
29
+ return channelId;
30
+ }
23
31
  function isRecord(value) {
24
32
  return typeof value === "object" && value !== null && !Array.isArray(value);
25
33
  }
26
34
  function hasNonEmptyString(value) {
27
35
  return typeof value === "string" && value.trim().length > 0;
28
36
  }
37
+ function readTextFileIfPresent(filePath) {
38
+ if (!filePath?.trim()) return "";
39
+ try {
40
+ return readFileSync(filePath.trim(), "utf8").trim();
41
+ } catch {
42
+ return "";
43
+ }
44
+ }
45
+ function readJsonFileIfPresent(filePath) {
46
+ try {
47
+ if (!existsSync(filePath)) return void 0;
48
+ return JSON.parse(readFileSync(filePath, "utf8"));
49
+ } catch {
50
+ return;
51
+ }
52
+ }
53
+ function resolveTelegramToken(account) {
54
+ const inline = typeof account.botToken === "string" ? account.botToken.trim() : "";
55
+ if (inline) return inline;
56
+ return readTextFileIfPresent(typeof account.tokenFile === "string" ? account.tokenFile : void 0);
57
+ }
58
+ function resolveWeixinAccountIds(raw) {
59
+ const accounts = isRecord(raw) && isRecord(raw.accounts) ? Object.keys(raw.accounts) : [];
60
+ const indexed = readJsonFileIfPresent(join(resolveStateDir(), "weixin", "accounts.json"));
61
+ if (!Array.isArray(indexed)) return accounts;
62
+ return [...new Set([...indexed.filter((id) => typeof id === "string" && id.trim() !== ""), ...accounts])];
63
+ }
64
+ function hasConfiguredWeixinAccount(raw) {
65
+ const accounts = isRecord(raw) && isRecord(raw.accounts) ? raw.accounts : {};
66
+ for (const accountId of resolveWeixinAccountIds(raw)) {
67
+ const accountCfg = accounts[accountId];
68
+ if (isRecord(accountCfg) && accountCfg.enabled === false) continue;
69
+ const accountData = readJsonFileIfPresent(join(resolveStateDir(), "weixin", "accounts", `${accountId}.json`));
70
+ if (isRecord(accountData) && hasNonEmptyString(accountData.token)) return true;
71
+ }
72
+ return false;
73
+ }
29
74
  function hasConfiguredTelegramCredential(raw) {
30
75
  if (!isRecord(raw)) return false;
31
76
  const accounts = raw.accounts;
32
77
  if (!isRecord(accounts)) return false;
33
78
  return Object.values(accounts).some((account) => {
34
79
  if (!isRecord(account) || account.enabled === false) return false;
35
- return hasNonEmptyString(account.botToken) || hasNonEmptyString(account.tokenFile);
80
+ return hasNonEmptyString(resolveTelegramToken(account));
36
81
  });
37
82
  }
38
- function hasConfiguredWeixinAccount(raw) {
39
- if (!isRecord(raw)) return false;
40
- if (raw.enabled === true) return true;
41
- const accounts = raw.accounts;
42
- if (!isRecord(accounts)) return false;
43
- return Object.values(accounts).some((account) => isRecord(account) && account.enabled !== false);
44
- }
45
83
  function hasConfiguredFeishuCredential(raw) {
46
84
  if (!isRecord(raw)) return false;
47
85
  if (hasNonEmptyString(raw.appId) && hasNonEmptyString(raw.appSecret)) return true;
@@ -54,6 +92,75 @@ function hasConfiguredFeishuCredential(raw) {
54
92
  return hasNonEmptyString(appId) && hasNonEmptyString(appSecret);
55
93
  });
56
94
  }
95
+ function issue(params) {
96
+ return {
97
+ code: params.code,
98
+ severity: "required",
99
+ fieldPath: params.fieldPath,
100
+ message: params.message,
101
+ action: params.action ?? "open_config"
102
+ };
103
+ }
104
+ function readConfigPath(value, path) {
105
+ let current = value;
106
+ for (const part of path.split(".")) {
107
+ if (!isRecord(current)) return void 0;
108
+ current = current[part];
109
+ }
110
+ return current;
111
+ }
112
+ function isEmptyConfigValue(value) {
113
+ if (value === void 0 || value === null) return true;
114
+ if (typeof value === "string") return value.trim().length === 0;
115
+ if (Array.isArray(value)) return value.length === 0;
116
+ return false;
117
+ }
118
+ function schemaFieldTitle(schema, path) {
119
+ let current = schema;
120
+ for (const part of path.split(".")) {
121
+ if (!isRecord(current)) break;
122
+ const props = current.properties;
123
+ if (!isRecord(props)) break;
124
+ current = props[part];
125
+ }
126
+ if (isRecord(current) && typeof current.title === "string" && current.title.trim()) return current.title.trim();
127
+ return path;
128
+ }
129
+ function collectRequiredSchemaIssues(entry, raw) {
130
+ const schema = entry?.configSchema;
131
+ if (!isRecord(schema)) return [];
132
+ const required = schema.required;
133
+ if (!Array.isArray(required)) return [];
134
+ return required.map(String).filter((fieldPath) => fieldPath !== "enabled").filter((fieldPath) => isEmptyConfigValue(readConfigPath(raw, fieldPath))).map((fieldPath) => issue({
135
+ code: "config.missing_required",
136
+ fieldPath,
137
+ message: `Missing required field: ${schemaFieldTitle(schema, fieldPath)}.`
138
+ }));
139
+ }
140
+ function collectChannelSetupIssues(id, raw, entry) {
141
+ if (id === "telegram" && !hasConfiguredTelegramCredential(raw)) return [issue({
142
+ code: "telegram.missing_credential",
143
+ fieldPath: "accounts.default.botToken",
144
+ message: "Telegram requires at least one enabled account with a Bot Token or token file.",
145
+ action: "open_config"
146
+ })];
147
+ if (id === "weixin" && !hasConfiguredWeixinAccount(raw)) return [issue({
148
+ code: "weixin.missing_account",
149
+ fieldPath: "accounts",
150
+ message: "Weixin requires at least one logged-in account before it can run.",
151
+ action: "run_setup"
152
+ })];
153
+ if ((id === "feishu" || id === "lark") && !hasConfiguredFeishuCredential(raw)) return [issue({
154
+ code: "feishu.missing_credentials",
155
+ fieldPath: "appId",
156
+ message: "Feishu/Lark requires App ID and App Secret credentials.",
157
+ action: "open_config"
158
+ })];
159
+ return collectRequiredSchemaIssues(entry, raw);
160
+ }
161
+ function hasChannelSetupOutsideConfig(id, raw) {
162
+ return id === "weixin" && hasConfiguredWeixinAccount(raw);
163
+ }
57
164
  function withoutUndefined(value) {
58
165
  return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0));
59
166
  }
@@ -154,20 +261,30 @@ function buildChannelCatalogFromSnapshot(snapshot, options = {}) {
154
261
  function buildChannelCatalogForConfig(config, options = {}) {
155
262
  return buildChannelCatalogFromSnapshot(buildExtensionMetadataSnapshot(resolveExtensionLoaderOptionsFromConfig(config), config), options);
156
263
  }
157
- function isChannelConfigured(config, channelId) {
264
+ function getChannelSetupStatus(config, channelId, entry) {
158
265
  const id = normalizeChannelId(channelId);
159
- const raw = config.channels?.[id];
160
- if (!raw) return false;
161
- if (id === "telegram") return hasConfiguredTelegramCredential(raw);
162
- if (id === "weixin") return hasConfiguredWeixinAccount(raw);
163
- if (id === "feishu" || id === "lark") return hasConfiguredFeishuCredential(raw);
164
- return isRecord(raw) ? raw.enabled === true || Object.keys(raw).length > 0 : true;
266
+ const configKey = normalizeChannelId(configChannelKey(entry, id));
267
+ const raw = config.channels?.[configKey];
268
+ const enabled = isRecord(raw) && raw.enabled === true;
269
+ const issues = collectChannelSetupIssues(id, raw, entry);
270
+ const hasAnyConfig = isRecord(raw) ? Object.keys(raw).some((key) => key !== "enabled") : Boolean(raw);
271
+ const ready = issues.length === 0 && (enabled || hasAnyConfig || hasChannelSetupOutsideConfig(id, raw));
272
+ return {
273
+ enabled,
274
+ ready,
275
+ state: enabled ? ready ? "ready" : "needs_setup" : "disabled",
276
+ issues
277
+ };
278
+ }
279
+ function isChannelConfigured(config, channelId) {
280
+ return getChannelSetupStatus(config, channelId).ready;
165
281
  }
166
282
  function getConfiguredChannelIds(config) {
167
283
  return Object.keys(config.channels ?? {}).map(normalizeChannelId).filter((id) => id && isChannelConfigured(config, id));
168
284
  }
169
285
  var DEFAULT_CONFIG_SCHEMA;
170
286
  var init_channel_catalog_service = __esmMin((() => {
287
+ init_paths_state();
171
288
  init_extension_metadata_snapshot();
172
289
  DEFAULT_CONFIG_SCHEMA = {
173
290
  type: "object",
@@ -176,6 +293,6 @@ var init_channel_catalog_service = __esmMin((() => {
176
293
  }));
177
294
  //#endregion
178
295
  init_channel_catalog_service();
179
- export { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getConfiguredChannelIds, init_channel_catalog_service, isChannelConfigured };
296
+ export { buildChannelCatalogForConfig, buildChannelCatalogFromSnapshot, getChannelSetupStatus, getConfiguredChannelIds, init_channel_catalog_service, isChannelConfigured };
180
297
 
181
298
  //# sourceMappingURL=channel-catalog-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"channel-catalog-service.js","names":[],"sources":["../../../../src/channels/catalog/channel-catalog-service.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport {\n buildExtensionMetadataSnapshot,\n resolveExtensionLoaderOptionsFromConfig,\n} from '../../extensions/extension-metadata-snapshot.js';\nimport type { ExtensionMetadataSnapshot } from '../../extensions/extension-metadata-snapshot.js';\nimport type { ManifestRegistryEntry } from '../../extensions/manifest-registry.js';\nimport type { ChannelContributionDeclaration } from '../../extensions/types/manifest.js';\n\nimport type { ChannelCatalog, ChannelCatalogEntry } from './channel-catalog-types.js';\n\ntype BuildChannelCatalogOptions = {\n locale?: string;\n};\n\nconst DEFAULT_CONFIG_SCHEMA: Record<string, unknown> = {\n type: 'object',\n additionalProperties: true,\n};\n\nfunction normalizeChannelId(raw: string): string {\n return raw.trim().toLowerCase();\n}\n\nfunction normalizeLocale(raw: string | undefined): string | undefined {\n const value = raw?.trim().toLowerCase().replace('_', '-');\n return value || undefined;\n}\n\nfunction localeCandidates(raw: string | undefined): string[] {\n const locale = normalizeLocale(raw);\n if (!locale) return [];\n const base = locale.split('-')[0];\n return base && base !== locale ? [locale, base] : [locale];\n}\n\nfunction normalizeConfigPath(channelId: string, raw: string | undefined): `channels.${string}` {\n const expected = `channels.${channelId}` as const;\n if (!raw) return expected;\n const trimmed = raw.trim();\n if (!trimmed.startsWith('channels.')) return expected;\n return trimmed as `channels.${string}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasNonEmptyString(value: unknown): boolean {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nfunction hasConfiguredTelegramCredential(raw: unknown): boolean {\n if (!isRecord(raw)) return false;\n const accounts = raw.accounts;\n if (!isRecord(accounts)) return false;\n return Object.values(accounts).some((account) => {\n if (!isRecord(account) || account.enabled === false) return false;\n return hasNonEmptyString(account.botToken) || hasNonEmptyString(account.tokenFile);\n });\n}\n\nfunction hasConfiguredWeixinAccount(raw: unknown): boolean {\n if (!isRecord(raw)) return false;\n if (raw.enabled === true) return true;\n const accounts = raw.accounts;\n if (!isRecord(accounts)) return false;\n return Object.values(accounts).some((account) => isRecord(account) && account.enabled !== false);\n}\n\nfunction hasConfiguredFeishuCredential(raw: unknown): boolean {\n if (!isRecord(raw)) return false;\n const hasRootCredentials = hasNonEmptyString(raw.appId) && hasNonEmptyString(raw.appSecret);\n if (hasRootCredentials) return true;\n const accounts = raw.accounts;\n if (!isRecord(accounts)) return false;\n return Object.values(accounts).some((account) => {\n if (!isRecord(account) || account.enabled === false) return false;\n const appId = hasNonEmptyString(account.appId) ? account.appId : raw.appId;\n const appSecret = hasNonEmptyString(account.appSecret) ? account.appSecret : raw.appSecret;\n return hasNonEmptyString(appId) && hasNonEmptyString(appSecret);\n });\n}\n\nfunction withoutUndefined(value: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));\n}\n\nfunction mergeObjectMap<T extends Record<string, unknown>>(base: T | undefined, override: T | undefined): T | undefined {\n if (!base && !override) return undefined;\n if (!base) return override ? withoutUndefined(override) as T : undefined;\n if (!override) return base;\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n out[key] = isRecord(out[key]) && isRecord(value)\n ? { ...out[key], ...withoutUndefined(value) }\n : value;\n }\n return out as T;\n}\n\nfunction mergeRecordDeep(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n out[key] = isRecord(out[key]) && isRecord(value)\n ? mergeRecordDeep(out[key], value)\n : value;\n }\n return out;\n}\n\nfunction mergeJsonSchema(base: Record<string, unknown> | undefined, override: Record<string, unknown> | undefined) {\n if (!base && !override) return undefined;\n if (!base) return override ? withoutUndefined(override) : undefined;\n if (!override) return base;\n return mergeRecordDeep(base, override);\n}\n\nfunction mergeChannelUi(\n base: ChannelContributionDeclaration['ui'],\n override: ChannelContributionDeclaration['ui'],\n): ChannelContributionDeclaration['ui'] {\n if (!base && !override) return undefined;\n return {\n ...(base ?? {}),\n ...(override ?? {}),\n card: mergeObjectMap(base?.card, override?.card),\n modal: mergeObjectMap(base?.modal, override?.modal),\n };\n}\n\nfunction localizeContribution(\n contribution: ChannelContributionDeclaration,\n locale: string | undefined,\n): ChannelContributionDeclaration {\n const i18n = contribution.i18n;\n if (!i18n) return contribution;\n const override = localeCandidates(locale).map((key) => i18n[key]).find(Boolean);\n if (!override) return contribution;\n return {\n ...contribution,\n label: override.label ?? contribution.label,\n description: override.description ?? contribution.description,\n configSchema: mergeJsonSchema(contribution.configSchema, override.configSchema),\n uiHints: mergeObjectMap(contribution.uiHints, override.uiHints),\n actions: mergeObjectMap(contribution.actions, override.actions),\n ui: mergeChannelUi(contribution.ui, override.ui),\n };\n}\n\nfunction toCatalogEntry(params: {\n extension: ManifestRegistryEntry;\n channelId: string;\n contribution: ChannelContributionDeclaration;\n locale?: string;\n}): ChannelCatalogEntry {\n const contribution = localizeContribution(params.contribution, params.locale);\n const id = normalizeChannelId(params.channelId);\n return {\n id,\n extensionId: params.extension.id,\n source: params.extension.source,\n path: params.extension.path,\n label: contribution.label,\n description: contribution.description,\n docsPath: contribution.docsPath,\n order: contribution.order ?? 999,\n configPath: normalizeConfigPath(id, contribution.configPath),\n capabilities: contribution.capabilities ?? {},\n configSchema: contribution.configSchema ?? DEFAULT_CONFIG_SCHEMA,\n uiHints: contribution.uiHints ?? {},\n actions: contribution.actions ?? {},\n ui: contribution.ui,\n };\n}\n\nexport function buildChannelCatalogFromSnapshot(\n snapshot: ExtensionMetadataSnapshot,\n options: BuildChannelCatalogOptions = {},\n): ChannelCatalog {\n const byId = new Map<string, ChannelCatalogEntry>();\n for (const extension of snapshot.manifestRegistry.getAllEntries()) {\n const contributions = extension.manifest.channelContributions ?? {};\n for (const [channelId, contribution] of Object.entries(contributions)) {\n const entry = toCatalogEntry({ extension, channelId, contribution, locale: options.locale });\n byId.set(entry.id, entry);\n }\n }\n const entries = Array.from(byId.values()).toSorted((a, b) => {\n if (a.order !== b.order) return a.order - b.order;\n return a.id.localeCompare(b.id);\n });\n return { entries, byId };\n}\n\nexport function buildChannelCatalogForConfig(config: Config, options: BuildChannelCatalogOptions = {}): ChannelCatalog {\n const snapshot = buildExtensionMetadataSnapshot(resolveExtensionLoaderOptionsFromConfig(config), config);\n return buildChannelCatalogFromSnapshot(snapshot, options);\n}\n\nexport function isChannelConfigured(config: Config, channelId: string): boolean {\n const id = normalizeChannelId(channelId);\n const raw = (config.channels as Record<string, unknown> | undefined)?.[id];\n if (!raw) return false;\n if (id === 'telegram') return hasConfiguredTelegramCredential(raw);\n if (id === 'weixin') return hasConfiguredWeixinAccount(raw);\n if (id === 'feishu' || id === 'lark') return hasConfiguredFeishuCredential(raw);\n return isRecord(raw) ? raw.enabled === true || Object.keys(raw).length > 0 : true;\n}\n\nexport function getConfiguredChannelIds(config: Config): string[] {\n return Object.keys(config.channels ?? {})\n .map(normalizeChannelId)\n .filter((id) => id && isChannelConfigured(config, id));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"channel-catalog-service.js","names":[],"sources":["../../../../src/channels/catalog/channel-catalog-service.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { Config } from '../../config/schema.js';\nimport { resolveStateDir } from '../../config/paths-state.js';\nimport {\n buildExtensionMetadataSnapshot,\n resolveExtensionLoaderOptionsFromConfig,\n} from '../../extensions/extension-metadata-snapshot.js';\nimport type { ExtensionMetadataSnapshot } from '../../extensions/extension-metadata-snapshot.js';\nimport type { ManifestRegistryEntry } from '../../extensions/manifest-registry.js';\nimport type { ChannelContributionDeclaration } from '../../extensions/types/manifest.js';\n\nimport type { ChannelCatalog, ChannelCatalogEntry, ChannelSetupIssue, ChannelSetupStatus } from './channel-catalog-types.js';\n\ntype BuildChannelCatalogOptions = {\n locale?: string;\n};\n\nconst DEFAULT_CONFIG_SCHEMA: Record<string, unknown> = {\n type: 'object',\n additionalProperties: true,\n};\n\nfunction normalizeChannelId(raw: string): string {\n return raw.trim().toLowerCase();\n}\n\nfunction normalizeLocale(raw: string | undefined): string | undefined {\n const value = raw?.trim().toLowerCase().replace('_', '-');\n return value || undefined;\n}\n\nfunction localeCandidates(raw: string | undefined): string[] {\n const locale = normalizeLocale(raw);\n if (!locale) return [];\n const base = locale.split('-')[0];\n return base && base !== locale ? [locale, base] : [locale];\n}\n\nfunction normalizeConfigPath(channelId: string, raw: string | undefined): `channels.${string}` {\n const expected = `channels.${channelId}` as const;\n if (!raw) return expected;\n const trimmed = raw.trim();\n if (!trimmed.startsWith('channels.')) return expected;\n return trimmed as `channels.${string}`;\n}\n\nfunction configChannelKey(entry: ChannelCatalogEntry | undefined, channelId: string): string {\n const path = entry?.configPath;\n if (path?.startsWith('channels.')) {\n return path.slice('channels.'.length).split('.')[0] || channelId;\n }\n return channelId;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction hasNonEmptyString(value: unknown): boolean {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nfunction readTextFileIfPresent(filePath: string | undefined): string {\n if (!filePath?.trim()) return '';\n try {\n return readFileSync(filePath.trim(), 'utf8').trim();\n } catch {\n return '';\n }\n}\n\nfunction readJsonFileIfPresent(filePath: string): unknown {\n try {\n if (!existsSync(filePath)) return undefined;\n return JSON.parse(readFileSync(filePath, 'utf8')) as unknown;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveTelegramToken(account: Record<string, unknown>): string {\n const inline = typeof account.botToken === 'string' ? account.botToken.trim() : '';\n if (inline) return inline;\n return readTextFileIfPresent(typeof account.tokenFile === 'string' ? account.tokenFile : undefined);\n}\n\nfunction resolveWeixinAccountIds(raw: unknown): string[] {\n const accounts = isRecord(raw) && isRecord(raw.accounts) ? Object.keys(raw.accounts) : [];\n const indexed = readJsonFileIfPresent(join(resolveStateDir(), 'weixin', 'accounts.json'));\n if (!Array.isArray(indexed)) return accounts;\n return [...new Set([\n ...indexed.filter((id): id is string => typeof id === 'string' && id.trim() !== ''),\n ...accounts,\n ])];\n}\n\nfunction hasConfiguredWeixinAccount(raw: unknown): boolean {\n const accounts = isRecord(raw) && isRecord(raw.accounts) ? raw.accounts : {};\n for (const accountId of resolveWeixinAccountIds(raw)) {\n const accountCfg = accounts[accountId];\n if (isRecord(accountCfg) && accountCfg.enabled === false) continue;\n const accountData = readJsonFileIfPresent(join(resolveStateDir(), 'weixin', 'accounts', `${accountId}.json`));\n if (isRecord(accountData) && hasNonEmptyString(accountData.token)) return true;\n }\n return false;\n}\n\nfunction hasConfiguredTelegramCredential(raw: unknown): boolean {\n if (!isRecord(raw)) return false;\n const accounts = raw.accounts;\n if (!isRecord(accounts)) return false;\n return Object.values(accounts).some((account) => {\n if (!isRecord(account) || account.enabled === false) return false;\n return hasNonEmptyString(resolveTelegramToken(account));\n });\n}\n\nfunction hasConfiguredFeishuCredential(raw: unknown): boolean {\n if (!isRecord(raw)) return false;\n const hasRootCredentials = hasNonEmptyString(raw.appId) && hasNonEmptyString(raw.appSecret);\n if (hasRootCredentials) return true;\n const accounts = raw.accounts;\n if (!isRecord(accounts)) return false;\n return Object.values(accounts).some((account) => {\n if (!isRecord(account) || account.enabled === false) return false;\n const appId = hasNonEmptyString(account.appId) ? account.appId : raw.appId;\n const appSecret = hasNonEmptyString(account.appSecret) ? account.appSecret : raw.appSecret;\n return hasNonEmptyString(appId) && hasNonEmptyString(appSecret);\n });\n}\n\nfunction issue(params: {\n code: string;\n fieldPath?: string;\n message: string;\n action?: ChannelSetupIssue['action'];\n}): ChannelSetupIssue {\n return {\n code: params.code,\n severity: 'required',\n fieldPath: params.fieldPath,\n message: params.message,\n action: params.action ?? 'open_config',\n };\n}\n\nfunction readConfigPath(value: unknown, path: string): unknown {\n let current = value;\n for (const part of path.split('.')) {\n if (!isRecord(current)) return undefined;\n current = current[part];\n }\n return current;\n}\n\nfunction isEmptyConfigValue(value: unknown): boolean {\n if (value === undefined || value === null) return true;\n if (typeof value === 'string') return value.trim().length === 0;\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\nfunction schemaFieldTitle(schema: Record<string, unknown>, path: string): string {\n let current: unknown = schema;\n for (const part of path.split('.')) {\n if (!isRecord(current)) break;\n const props = current.properties;\n if (!isRecord(props)) break;\n current = props[part];\n }\n if (isRecord(current) && typeof current.title === 'string' && current.title.trim()) {\n return current.title.trim();\n }\n return path;\n}\n\nfunction collectRequiredSchemaIssues(\n entry: ChannelCatalogEntry | undefined,\n raw: unknown,\n): ChannelSetupIssue[] {\n const schema = entry?.configSchema;\n if (!isRecord(schema)) return [];\n const required = schema.required;\n if (!Array.isArray(required)) return [];\n return required\n .map(String)\n .filter((fieldPath) => fieldPath !== 'enabled')\n .filter((fieldPath) => isEmptyConfigValue(readConfigPath(raw, fieldPath)))\n .map((fieldPath) => issue({\n code: 'config.missing_required',\n fieldPath,\n message: `Missing required field: ${schemaFieldTitle(schema, fieldPath)}.`,\n }));\n}\n\nfunction collectChannelSetupIssues(\n id: string,\n raw: unknown,\n entry: ChannelCatalogEntry | undefined,\n): ChannelSetupIssue[] {\n if (id === 'telegram' && !hasConfiguredTelegramCredential(raw)) {\n return [issue({\n code: 'telegram.missing_credential',\n fieldPath: 'accounts.default.botToken',\n message: 'Telegram requires at least one enabled account with a Bot Token or token file.',\n action: 'open_config',\n })];\n }\n if (id === 'weixin' && !hasConfiguredWeixinAccount(raw)) {\n return [issue({\n code: 'weixin.missing_account',\n fieldPath: 'accounts',\n message: 'Weixin requires at least one logged-in account before it can run.',\n action: 'run_setup',\n })];\n }\n if ((id === 'feishu' || id === 'lark') && !hasConfiguredFeishuCredential(raw)) {\n return [issue({\n code: 'feishu.missing_credentials',\n fieldPath: 'appId',\n message: 'Feishu/Lark requires App ID and App Secret credentials.',\n action: 'open_config',\n })];\n }\n return collectRequiredSchemaIssues(entry, raw);\n}\n\nfunction hasChannelSetupOutsideConfig(id: string, raw: unknown): boolean {\n return id === 'weixin' && hasConfiguredWeixinAccount(raw);\n}\n\nfunction withoutUndefined(value: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));\n}\n\nfunction mergeObjectMap<T extends Record<string, unknown>>(base: T | undefined, override: T | undefined): T | undefined {\n if (!base && !override) return undefined;\n if (!base) return override ? withoutUndefined(override) as T : undefined;\n if (!override) return base;\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n out[key] = isRecord(out[key]) && isRecord(value)\n ? { ...out[key], ...withoutUndefined(value) }\n : value;\n }\n return out as T;\n}\n\nfunction mergeRecordDeep(base: Record<string, unknown>, override: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n if (value === undefined) continue;\n out[key] = isRecord(out[key]) && isRecord(value)\n ? mergeRecordDeep(out[key], value)\n : value;\n }\n return out;\n}\n\nfunction mergeJsonSchema(base: Record<string, unknown> | undefined, override: Record<string, unknown> | undefined) {\n if (!base && !override) return undefined;\n if (!base) return override ? withoutUndefined(override) : undefined;\n if (!override) return base;\n return mergeRecordDeep(base, override);\n}\n\nfunction mergeChannelUi(\n base: ChannelContributionDeclaration['ui'],\n override: ChannelContributionDeclaration['ui'],\n): ChannelContributionDeclaration['ui'] {\n if (!base && !override) return undefined;\n return {\n ...(base ?? {}),\n ...(override ?? {}),\n card: mergeObjectMap(base?.card, override?.card),\n modal: mergeObjectMap(base?.modal, override?.modal),\n };\n}\n\nfunction localizeContribution(\n contribution: ChannelContributionDeclaration,\n locale: string | undefined,\n): ChannelContributionDeclaration {\n const i18n = contribution.i18n;\n if (!i18n) return contribution;\n const override = localeCandidates(locale).map((key) => i18n[key]).find(Boolean);\n if (!override) return contribution;\n return {\n ...contribution,\n label: override.label ?? contribution.label,\n description: override.description ?? contribution.description,\n configSchema: mergeJsonSchema(contribution.configSchema, override.configSchema),\n uiHints: mergeObjectMap(contribution.uiHints, override.uiHints),\n actions: mergeObjectMap(contribution.actions, override.actions),\n ui: mergeChannelUi(contribution.ui, override.ui),\n };\n}\n\nfunction toCatalogEntry(params: {\n extension: ManifestRegistryEntry;\n channelId: string;\n contribution: ChannelContributionDeclaration;\n locale?: string;\n}): ChannelCatalogEntry {\n const contribution = localizeContribution(params.contribution, params.locale);\n const id = normalizeChannelId(params.channelId);\n return {\n id,\n extensionId: params.extension.id,\n source: params.extension.source,\n path: params.extension.path,\n label: contribution.label,\n description: contribution.description,\n docsPath: contribution.docsPath,\n order: contribution.order ?? 999,\n configPath: normalizeConfigPath(id, contribution.configPath),\n capabilities: contribution.capabilities ?? {},\n configSchema: contribution.configSchema ?? DEFAULT_CONFIG_SCHEMA,\n uiHints: contribution.uiHints ?? {},\n actions: contribution.actions ?? {},\n ui: contribution.ui,\n };\n}\n\nexport function buildChannelCatalogFromSnapshot(\n snapshot: ExtensionMetadataSnapshot,\n options: BuildChannelCatalogOptions = {},\n): ChannelCatalog {\n const byId = new Map<string, ChannelCatalogEntry>();\n for (const extension of snapshot.manifestRegistry.getAllEntries()) {\n const contributions = extension.manifest.channelContributions ?? {};\n for (const [channelId, contribution] of Object.entries(contributions)) {\n const entry = toCatalogEntry({ extension, channelId, contribution, locale: options.locale });\n byId.set(entry.id, entry);\n }\n }\n const entries = Array.from(byId.values()).toSorted((a, b) => {\n if (a.order !== b.order) return a.order - b.order;\n return a.id.localeCompare(b.id);\n });\n return { entries, byId };\n}\n\nexport function buildChannelCatalogForConfig(config: Config, options: BuildChannelCatalogOptions = {}): ChannelCatalog {\n const snapshot = buildExtensionMetadataSnapshot(resolveExtensionLoaderOptionsFromConfig(config), config);\n return buildChannelCatalogFromSnapshot(snapshot, options);\n}\n\nexport function getChannelSetupStatus(\n config: Config,\n channelId: string,\n entry?: ChannelCatalogEntry,\n): ChannelSetupStatus {\n const id = normalizeChannelId(channelId);\n const configKey = normalizeChannelId(configChannelKey(entry, id));\n const raw = (config.channels as Record<string, unknown> | undefined)?.[configKey];\n const enabled = isRecord(raw) && raw.enabled === true;\n const issues = collectChannelSetupIssues(id, raw, entry);\n const hasAnyConfig = isRecord(raw) ? Object.keys(raw).some((key) => key !== 'enabled') : Boolean(raw);\n const ready = issues.length === 0 && (enabled || hasAnyConfig || hasChannelSetupOutsideConfig(id, raw));\n return {\n enabled,\n ready,\n state: enabled ? (ready ? 'ready' : 'needs_setup') : 'disabled',\n issues,\n };\n}\n\nexport function isChannelConfigured(config: Config, channelId: string): boolean {\n return getChannelSetupStatus(config, channelId).ready;\n}\n\nexport function getConfiguredChannelIds(config: Config): string[] {\n return Object.keys(config.channels ?? {})\n .map(normalizeChannelId)\n .filter((id) => id && isChannelConfigured(config, id));\n}\n"],"mappings":"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"}
@@ -1,5 +1,18 @@
1
1
  import type { ChannelActionDescriptor, ChannelConfigUiHint, ChannelContributionCapabilities, ChannelContributionUiDeclaration } from '../../extensions/types/manifest.js';
2
2
  export type ChannelCatalogSource = 'workspace' | 'global' | 'bundled' | 'config';
3
+ export interface ChannelSetupIssue {
4
+ code: string;
5
+ severity: 'required' | 'warning';
6
+ fieldPath?: string;
7
+ message: string;
8
+ action?: 'open_config' | 'run_setup' | 'run_doctor';
9
+ }
10
+ export interface ChannelSetupStatus {
11
+ enabled: boolean;
12
+ ready: boolean;
13
+ state: 'disabled' | 'needs_setup' | 'ready' | 'error';
14
+ issues: ChannelSetupIssue[];
15
+ }
3
16
  export interface ChannelCatalogEntry {
4
17
  id: string;
5
18
  extensionId: string;
@@ -1,7 +1,7 @@
1
1
  import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
2
+ import { join } from "path";
2
3
  import { existsSync, mkdirSync, readFileSync } from "fs";
3
4
  import { randomUUID } from "node:crypto";
4
- import { join } from "path";
5
5
  //#region src/channels/outbound/persist-store.ts
6
6
  /**
7
7
  * Durable outbound queue (crash recovery): JSON file under agent internal dir.
@@ -1,5 +1,5 @@
1
- import fs from "node:fs";
2
1
  import path from "node:path";
2
+ import fs from "node:fs";
3
3
  //#region src/channels/pairing/allow-from-file.ts
4
4
  function readAllowFromFile(filePath) {
5
5
  try {
@@ -1,8 +1,8 @@
1
1
  import { appendAllowFromIdSync } from "./allow-from-file.js";
2
2
  import "./pairing-constants.js";
3
- import crypto from "node:crypto";
4
- import fs from "node:fs";
5
3
  import path from "node:path";
4
+ import fs from "node:fs";
5
+ import crypto from "node:crypto";
6
6
  //#region src/channels/pairing/pairing-store.ts
7
7
  const PAIRING_CODE_LENGTH = 8;
8
8
  const PAIRING_CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
@@ -1,9 +1,9 @@
1
1
  import { init_agent_scope, normalizeAgentId, resolveAgentProfileDir } from "../agent/agent-scope.js";
2
- import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
3
2
  import { init_agent_session_key, resolveAgentIdFromSessionKey } from "../routing/agent-session-key.js";
3
+ import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
4
4
  import { commandRegistry } from "./registry.js";
5
- import { readFile } from "node:fs/promises";
6
5
  import { join } from "node:path";
6
+ import { readFile } from "node:fs/promises";
7
7
  //#region src/chat-commands/agent-edit.ts
8
8
  /**
9
9
  * /agent-edit — open the current chat as an agent profile editing session.
@@ -1,7 +1,7 @@
1
- import { init_paths, resolveConfigPath } from "../../config/paths.js";
1
+ import { ConfigSchema, init_schema } from "../../config/schema.js";
2
2
  import { createLogger } from "../../utils/logger/index.js";
3
3
  import { init_logger } from "../../utils/logger.js";
4
- import { ConfigSchema, init_schema } from "../../config/schema.js";
4
+ import { init_paths, resolveConfigPath } from "../../config/paths.js";
5
5
  import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
6
6
  import { commandRegistry } from "../registry.js";
7
7
  import { parseConfigValue } from "../config-value.js";
@@ -1,5 +1,5 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
1
  import { ConfigSchema, init_schema } from "../../config/schema.js";
2
+ import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.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";