@xopcai/xopc 0.0.84 → 0.0.85

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 (410) 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/plugin.d.ts +2 -0
  4. package/dist/extensions/feishu/src/plugin.js +10 -0
  5. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  6. package/dist/extensions/feishu/src/workflow-progress.d.ts +27 -0
  7. package/dist/extensions/feishu/src/workflow-progress.js +99 -0
  8. package/dist/extensions/feishu/src/workflow-progress.js.map +1 -0
  9. package/dist/extensions/telegram/src/plugin.d.ts +2 -0
  10. package/dist/extensions/telegram/src/plugin.js +11 -1
  11. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  12. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  13. package/dist/extensions/telegram/src/workflow-progress.d.ts +24 -0
  14. package/dist/extensions/telegram/src/workflow-progress.js +73 -0
  15. package/dist/extensions/telegram/src/workflow-progress.js.map +1 -0
  16. package/dist/extensions/telegram/xopc.extension.json +1 -1
  17. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js +158 -0
  18. package/dist/extensions/weixin/src/__tests__/workflow-progress.test.js.map +1 -0
  19. package/dist/extensions/weixin/src/api/api.js +2 -2
  20. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  21. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  22. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  23. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  24. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  25. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  26. package/dist/extensions/weixin/src/plugin.d.ts +2 -0
  27. package/dist/extensions/weixin/src/plugin.js +11 -1
  28. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  29. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  30. package/dist/extensions/weixin/src/workflow-progress.d.ts +26 -0
  31. package/dist/extensions/weixin/src/workflow-progress.js +99 -0
  32. package/dist/extensions/weixin/src/workflow-progress.js.map +1 -0
  33. package/dist/gateway/static/root/assets/agents-D3_-kNlZ.js +222 -0
  34. package/dist/gateway/static/root/assets/apps-page-D7v7649T.js +1 -0
  35. package/dist/gateway/static/root/assets/channels-settings-nCaMb0a7.js +1 -0
  36. package/dist/gateway/static/root/assets/channels-status-swr-C1gZBcJV.js +8 -0
  37. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
  38. package/dist/gateway/static/root/assets/cron-api-CoYK0hlm.js +1 -0
  39. package/dist/gateway/static/root/assets/cron-page-DeGo-Vjc.js +1 -0
  40. package/dist/gateway/static/root/assets/dist-BTWC-BTN.js +45 -0
  41. package/dist/gateway/static/root/assets/{dist-CqNMNhJM.js → dist-DaK4dsss.js} +1 -1
  42. package/dist/gateway/static/root/assets/{extension-debug-page-gf2L0kY_.js → extension-debug-page-BZngZWbO.js} +1 -1
  43. package/dist/gateway/static/root/assets/extension-page-D6JSyV27.js +1 -0
  44. package/dist/gateway/static/root/assets/extension-settings-page-8PZcmWI7.js +1 -0
  45. package/dist/gateway/static/root/assets/fetch-B2MYHbWg.js +1 -0
  46. package/dist/gateway/static/root/assets/{field-primitives-DTtlp-l8.js → field-primitives-Zzl22MvN.js} +1 -1
  47. package/dist/gateway/static/root/assets/heartbeat-config-api-BtIcpG0O.js +1 -0
  48. package/dist/gateway/static/root/assets/index-D4vM3-P7.js +4700 -0
  49. package/dist/gateway/static/root/assets/index-ew_2L2We.css +1 -0
  50. package/dist/gateway/static/root/assets/logs-page-_d4UJ-qQ.js +1 -0
  51. package/dist/gateway/static/root/assets/sessions-page-5N4aF2Wk.js +1 -0
  52. package/dist/gateway/static/root/assets/settings-form-section-D_tgb8r2.js +1 -0
  53. package/dist/gateway/static/root/assets/settings-page-C18xBt4X.js +3 -0
  54. package/dist/gateway/static/root/assets/share-preview-page-D4EG_vM1.js +2 -0
  55. package/dist/gateway/static/root/assets/skills-page-sPAXhh8w.js +2 -0
  56. package/dist/gateway/static/root/assets/theme-store-DryYl3qD.js +1 -0
  57. package/dist/gateway/static/root/assets/url-BwNL6Rgk.js +3 -0
  58. package/dist/gateway/static/root/assets/utils-CYO9eTCM.js +1 -0
  59. package/dist/gateway/static/root/assets/voice-api-key-field-Ds51havm.js +1 -0
  60. package/dist/gateway/static/root/index.html +7 -6
  61. package/dist/package.js +1 -1
  62. package/dist/src/agent/agent-manager.js +7 -7
  63. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  64. package/dist/src/agent/context/workspace-seed.js +3 -3
  65. package/dist/src/agent/embedded/map-stream-events.js +6 -0
  66. package/dist/src/agent/embedded/map-stream-events.js.map +1 -1
  67. package/dist/src/agent/embedded/subscribe-session.js +24 -0
  68. package/dist/src/agent/embedded/subscribe-session.js.map +1 -1
  69. package/dist/src/agent/embedded/types.d.ts +19 -0
  70. package/dist/src/agent/goals/goal-locale.js +2 -2
  71. package/dist/src/agent/goals/goal-run-store.js +4 -4
  72. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  73. package/dist/src/agent/goals/post-turn.js +2 -2
  74. package/dist/src/agent/image/load-image-media.js +2 -2
  75. package/dist/src/agent/ipc/bus.js +1 -1
  76. package/dist/src/agent/ipc/inbox.js +2 -2
  77. package/dist/src/agent/ipc/socket.js +1 -1
  78. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  79. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  80. package/dist/src/agent/memory/dreaming/events.js +1 -1
  81. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  82. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  83. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  84. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  85. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  86. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  87. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  88. package/dist/src/agent/models/manager.js +1 -1
  89. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  90. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  91. package/dist/src/agent/reply/startup-context.d.ts +3 -0
  92. package/dist/src/agent/reply/startup-context.js +25 -2
  93. package/dist/src/agent/reply/startup-context.js.map +1 -1
  94. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  95. package/dist/src/agent/sandbox/path-policy.js +2 -2
  96. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  97. package/dist/src/agent/service.d.ts +1 -0
  98. package/dist/src/agent/service.js +10 -4
  99. package/dist/src/agent/service.js.map +1 -1
  100. package/dist/src/agent/session/session-inspector.js +1 -1
  101. package/dist/src/agent/skills/config.js +1 -1
  102. package/dist/src/agent/skills/hub-hash.js +2 -2
  103. package/dist/src/agent/skills/hub-lock.js +1 -1
  104. package/dist/src/agent/skills/hub-pull.js +3 -3
  105. package/dist/src/agent/skills/index.js +1 -1
  106. package/dist/src/agent/skills/managed-store.js +1 -1
  107. package/dist/src/agent/skills/scanner.js +1 -1
  108. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  109. package/dist/src/agent/skills/skill-manager.js +1 -1
  110. package/dist/src/agent/tools/create-share-tool.d.ts +27 -0
  111. package/dist/src/agent/tools/create-share-tool.js +237 -0
  112. package/dist/src/agent/tools/create-share-tool.js.map +1 -0
  113. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  114. package/dist/src/agent/tools/factory.js +35 -1
  115. package/dist/src/agent/tools/factory.js.map +1 -1
  116. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  117. package/dist/src/agent/tools/index.d.ts +2 -0
  118. package/dist/src/agent/tools/index.js +3 -1
  119. package/dist/src/agent/tools/send-media.js +1 -1
  120. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  121. package/dist/src/agent/tools/workflow-tool.d.ts +41 -0
  122. package/dist/src/agent/tools/workflow-tool.js +271 -0
  123. package/dist/src/agent/tools/workflow-tool.js.map +1 -0
  124. package/dist/src/agent/tools/write.js +1 -1
  125. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +9 -0
  126. package/dist/src/agent/workflow/builtins/audit-repo.js +115 -0
  127. package/dist/src/agent/workflow/builtins/audit-repo.js.map +1 -0
  128. package/dist/src/agent/workflow/builtins/index.d.ts +15 -0
  129. package/dist/src/agent/workflow/builtins/index.js +28 -0
  130. package/dist/src/agent/workflow/builtins/index.js.map +1 -0
  131. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +9 -0
  132. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +113 -0
  133. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +1 -0
  134. package/dist/src/agent/workflow/builtins/research.d.ts +9 -0
  135. package/dist/src/agent/workflow/builtins/research.js +129 -0
  136. package/dist/src/agent/workflow/builtins/research.js.map +1 -0
  137. package/dist/src/agent/workflow/catalog.d.ts +51 -0
  138. package/dist/src/agent/workflow/catalog.js +155 -0
  139. package/dist/src/agent/workflow/catalog.js.map +1 -0
  140. package/dist/src/agent/workflow/channel-capability.d.ts +76 -0
  141. package/dist/src/agent/workflow/channel-capability.js +1 -0
  142. package/dist/src/agent/workflow/index.d.ts +11 -0
  143. package/dist/src/agent/workflow/index.js +10 -0
  144. package/dist/src/agent/workflow/last-run-memory.d.ts +42 -0
  145. package/dist/src/agent/workflow/last-run-memory.js +60 -0
  146. package/dist/src/agent/workflow/last-run-memory.js.map +1 -0
  147. package/dist/src/agent/workflow/parser.d.ts +20 -0
  148. package/dist/src/agent/workflow/parser.js +137 -0
  149. package/dist/src/agent/workflow/parser.js.map +1 -0
  150. package/dist/src/agent/workflow/progress-broker.d.ts +80 -0
  151. package/dist/src/agent/workflow/progress-broker.js +263 -0
  152. package/dist/src/agent/workflow/progress-broker.js.map +1 -0
  153. package/dist/src/agent/workflow/runtime.d.ts +31 -0
  154. package/dist/src/agent/workflow/runtime.js +301 -0
  155. package/dist/src/agent/workflow/runtime.js.map +1 -0
  156. package/dist/src/agent/workflow/snapshot.d.ts +18 -0
  157. package/dist/src/agent/workflow/snapshot.js +144 -0
  158. package/dist/src/agent/workflow/snapshot.js.map +1 -0
  159. package/dist/src/agent/workflow/structured-output-tool.d.ts +33 -0
  160. package/dist/src/agent/workflow/structured-output-tool.js +58 -0
  161. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -0
  162. package/dist/src/agent/workflow/subagent-runner.d.ts +42 -0
  163. package/dist/src/agent/workflow/subagent-runner.js +104 -0
  164. package/dist/src/agent/workflow/subagent-runner.js.map +1 -0
  165. package/dist/src/agent/workflow/types.d.ts +137 -0
  166. package/dist/src/agent/workflow/types.js +1 -0
  167. package/dist/src/auth/credentials.js +3 -3
  168. package/dist/src/auth/profiles/store.js +1 -1
  169. package/dist/src/auth/sync-provider-auth.js +1 -1
  170. package/dist/src/browser/cache-dir-policy.js +1 -1
  171. package/dist/src/browser/cdp-local-launcher.js +2 -2
  172. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  173. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  174. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  175. package/dist/src/browser/stealth.js +1 -1
  176. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  177. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  178. package/dist/src/channels/outbound/persist-store.js +1 -1
  179. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  180. package/dist/src/channels/pairing/pairing-store.js +2 -2
  181. package/dist/src/chat-commands/builtins/config.js +2 -2
  182. package/dist/src/chat-commands/builtins/model.js +40 -23
  183. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  184. package/dist/src/chat-commands/builtins/system.js +30 -15
  185. package/dist/src/chat-commands/builtins/system.js.map +1 -1
  186. package/dist/src/chat-commands/builtins/workflow.d.ts +18 -0
  187. package/dist/src/chat-commands/builtins/workflow.js +167 -0
  188. package/dist/src/chat-commands/builtins/workflow.js.map +1 -0
  189. package/dist/src/chat-commands/context.js +1 -1
  190. package/dist/src/chat-commands/format-output.d.ts +28 -0
  191. package/dist/src/chat-commands/format-output.js +45 -0
  192. package/dist/src/chat-commands/format-output.js.map +1 -0
  193. package/dist/src/chat-commands/index.d.ts +1 -0
  194. package/dist/src/chat-commands/index.js +3 -1
  195. package/dist/src/chat-commands/index.js.map +1 -1
  196. package/dist/src/cli/commands/config.js +2 -2
  197. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  198. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  199. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  200. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  201. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  202. package/dist/src/cli/commands/extension-dev.js +1 -1
  203. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  204. package/dist/src/cli/commands/extension-pack.js +1 -1
  205. package/dist/src/cli/commands/gateway/lifecycle.js +10 -4
  206. package/dist/src/cli/commands/gateway/lifecycle.js.map +1 -1
  207. package/dist/src/cli/commands/gateway/shared.js +1 -1
  208. package/dist/src/cli/commands/image.js +1 -1
  209. package/dist/src/cli/commands/init.js +4 -4
  210. package/dist/src/cli/commands/onboard.js +2 -2
  211. package/dist/src/cli/commands/tunnel.js +2 -2
  212. package/dist/src/cli/utils/gateway-client.js +1 -1
  213. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  214. package/dist/src/config/agent-profile.js +1 -1
  215. package/dist/src/config/gateway-bind.js +1 -1
  216. package/dist/src/config/index.js +5 -5
  217. package/dist/src/config/loader.js +2 -2
  218. package/dist/src/config/models-json.js +2 -2
  219. package/dist/src/config/paths-state.js +1 -1
  220. package/dist/src/config/profile.js +2 -2
  221. package/dist/src/config/public-url.d.ts +28 -0
  222. package/dist/src/config/public-url.js +103 -0
  223. package/dist/src/config/public-url.js.map +1 -0
  224. package/dist/src/config/schema.d.ts +82 -0
  225. package/dist/src/config/schema.js +130 -1
  226. package/dist/src/config/schema.js.map +1 -1
  227. package/dist/src/config/workspace-path.js +1 -1
  228. package/dist/src/cron/executor.js +2 -2
  229. package/dist/src/cron/persistence.js +1 -1
  230. package/dist/src/cron/run-log-store.js +1 -1
  231. package/dist/src/daemon/constants.js +1 -1
  232. package/dist/src/daemon/install-plan.js +3 -3
  233. package/dist/src/daemon/install-plan.js.map +1 -1
  234. package/dist/src/daemon/launchd.js +2 -2
  235. package/dist/src/daemon/schtasks.js +38 -1
  236. package/dist/src/daemon/schtasks.js.map +1 -1
  237. package/dist/src/daemon/systemd.js +2 -2
  238. package/dist/src/extensions/bundle-mcp.js +1 -1
  239. package/dist/src/extensions/discover-extensions.js +1 -1
  240. package/dist/src/extensions/health.js +1 -1
  241. package/dist/src/extensions/loader.js +1 -1
  242. package/dist/src/extensions/lockfile.js +2 -2
  243. package/dist/src/gateway/agents-admin.js +2 -2
  244. package/dist/src/gateway/file-path-classifier.js +2 -2
  245. package/dist/src/gateway/hono/app.js +33 -2
  246. package/dist/src/gateway/hono/app.js.map +1 -1
  247. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  248. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  249. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  250. package/dist/src/gateway/hono/oauth.js +1 -1
  251. package/dist/src/gateway/hono/routes/agents.js +1 -1
  252. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  253. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  254. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  255. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  256. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  257. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  258. package/dist/src/gateway/hono/routes/models.js +1 -1
  259. package/dist/src/gateway/hono/routes/shares.js +631 -34
  260. package/dist/src/gateway/hono/routes/shares.js.map +1 -1
  261. package/dist/src/gateway/hono/routes/site-shares.d.ts +3 -0
  262. package/dist/src/gateway/hono/routes/site-shares.js +228 -0
  263. package/dist/src/gateway/hono/routes/site-shares.js.map +1 -0
  264. package/dist/src/gateway/hono/routes/tunnel.js +97 -8
  265. package/dist/src/gateway/hono/routes/tunnel.js.map +1 -1
  266. package/dist/src/gateway/hono/routes/workspace.js +5 -5
  267. package/dist/src/gateway/hono/sse.js +2 -2
  268. package/dist/src/gateway/host.d.ts +3 -1
  269. package/dist/src/gateway/host.js +3 -1
  270. package/dist/src/gateway/host.js.map +1 -1
  271. package/dist/src/gateway/lock.js +3 -3
  272. package/dist/src/gateway/ports.d.ts +6 -0
  273. package/dist/src/gateway/ports.js +38 -2
  274. package/dist/src/gateway/ports.js.map +1 -1
  275. package/dist/src/gateway/public-url.d.ts +8 -0
  276. package/dist/src/gateway/public-url.js +10 -0
  277. package/dist/src/gateway/public-url.js.map +1 -0
  278. package/dist/src/gateway/security/origin-check.d.ts +9 -1
  279. package/dist/src/gateway/security/origin-check.js +4 -0
  280. package/dist/src/gateway/security/origin-check.js.map +1 -1
  281. package/dist/src/gateway/server.js +15 -0
  282. package/dist/src/gateway/server.js.map +1 -1
  283. package/dist/src/gateway/service/agent-runner.js +2 -2
  284. package/dist/src/gateway/service/marketplace-service.js +2 -2
  285. package/dist/src/gateway/service/run-gateway-agent.js +2 -2
  286. package/dist/src/gateway/service.js +3 -2
  287. package/dist/src/gateway/service.js.map +1 -1
  288. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  289. package/dist/src/i18n/goals-bundle.js +1 -1
  290. package/dist/src/i18n/index.d.ts +1 -0
  291. package/dist/src/i18n/index.js +2 -1
  292. package/dist/src/i18n/locales/share-tool.en.js +15 -0
  293. package/dist/src/i18n/locales/share-tool.en.js.map +1 -0
  294. package/dist/src/i18n/locales/share-tool.zh.js +15 -0
  295. package/dist/src/i18n/locales/share-tool.zh.js.map +1 -0
  296. package/dist/src/i18n/share-tool-bundle.d.ts +20 -0
  297. package/dist/src/i18n/share-tool-bundle.js +56 -0
  298. package/dist/src/i18n/share-tool-bundle.js.map +1 -0
  299. package/dist/src/infra/gateway-processes.js +1 -0
  300. package/dist/src/infra/gateway-processes.js.map +1 -1
  301. package/dist/src/infra/restart.js +2 -2
  302. package/dist/src/infra/update-check.js +1 -1
  303. package/dist/src/infra/update-lock.js +3 -3
  304. package/dist/src/infra/update-runner.js +1 -1
  305. package/dist/src/infra/update-startup.js +2 -2
  306. package/dist/src/infra/write-file-atomic.js +2 -2
  307. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  308. package/dist/src/providers/index.js +2 -2
  309. package/dist/src/providers/model-registry.js +1 -1
  310. package/dist/src/session/config-store.js +2 -2
  311. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  312. package/dist/src/session/parity/sessions-json-file.js +1 -1
  313. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  314. package/dist/src/session/parity/transcript-paths.js +1 -1
  315. package/dist/src/session/search-index-cache.js +1 -1
  316. package/dist/src/session/search-index.js +1 -1
  317. package/dist/src/session/session-title.js +3 -2
  318. package/dist/src/session/session-title.js.map +1 -1
  319. package/dist/src/session/store.js +5 -5
  320. package/dist/src/share/share-auto.d.ts +74 -0
  321. package/dist/src/share/share-auto.js +247 -0
  322. package/dist/src/share/share-auto.js.map +1 -0
  323. package/dist/src/share/share-config.js +63 -4
  324. package/dist/src/share/share-config.js.map +1 -1
  325. package/dist/src/share/share-landing.d.ts +28 -2
  326. package/dist/src/share/share-landing.js +155 -34
  327. package/dist/src/share/share-landing.js.map +1 -1
  328. package/dist/src/share/share-store.d.ts +48 -4
  329. package/dist/src/share/share-store.js +322 -51
  330. package/dist/src/share/share-store.js.map +1 -1
  331. package/dist/src/share/share-thumbnail.d.ts +35 -0
  332. package/dist/src/share/share-thumbnail.js +277 -0
  333. package/dist/src/share/share-thumbnail.js.map +1 -0
  334. package/dist/src/share/share-types.d.ts +68 -10
  335. package/dist/src/share/share-types.js +18 -1
  336. package/dist/src/share/share-types.js.map +1 -1
  337. package/dist/src/share/share-url.js +1 -1
  338. package/dist/src/share/share-zip.d.ts +35 -0
  339. package/dist/src/share/share-zip.js +303 -0
  340. package/dist/src/share/share-zip.js.map +1 -0
  341. package/dist/src/share/site-proxy.d.ts +35 -0
  342. package/dist/src/share/site-proxy.js +234 -0
  343. package/dist/src/share/site-proxy.js.map +1 -0
  344. package/dist/src/share/site-share-config.d.ts +11 -0
  345. package/dist/src/share/site-share-config.js +103 -0
  346. package/dist/src/share/site-share-config.js.map +1 -0
  347. package/dist/src/share/site-share-router.d.ts +23 -0
  348. package/dist/src/share/site-share-router.js +147 -0
  349. package/dist/src/share/site-share-router.js.map +1 -0
  350. package/dist/src/share/site-share-store.d.ts +53 -0
  351. package/dist/src/share/site-share-store.js +400 -0
  352. package/dist/src/share/site-share-store.js.map +1 -0
  353. package/dist/src/share/site-share-types.d.ts +103 -0
  354. package/dist/src/share/site-share-types.js +41 -0
  355. package/dist/src/share/site-share-types.js.map +1 -0
  356. package/dist/src/share/site-static-serve.d.ts +10 -0
  357. package/dist/src/share/site-static-serve.js +145 -0
  358. package/dist/src/share/site-static-serve.js.map +1 -0
  359. package/dist/src/tui/clipboard-image.js +3 -3
  360. package/dist/src/tui/theme-manager.js +1 -1
  361. package/dist/src/tui/tui-commands.js +18 -0
  362. package/dist/src/tui/tui-commands.js.map +1 -1
  363. package/dist/src/tui/tui-keybindings-file.js +1 -1
  364. package/dist/src/tui/tui-scoped-models.js +2 -2
  365. package/dist/src/tui/tui-settings.js +1 -1
  366. package/dist/src/tui/tui-workflow-slash.d.ts +32 -0
  367. package/dist/src/tui/tui-workflow-slash.js +63 -0
  368. package/dist/src/tui/tui-workflow-slash.js.map +1 -0
  369. package/dist/src/tui/tui.js +2 -2
  370. package/dist/src/tunnel/enable-lan-pairing.js +1 -1
  371. package/dist/src/tunnel/frpc-binary.js +3 -3
  372. package/dist/src/tunnel/frpc-config.js +1 -1
  373. package/dist/src/tunnel/frpc-extract.js +1 -1
  374. package/dist/src/tunnel/index.js +2 -2
  375. package/dist/src/tunnel/pair-context.d.ts +7 -1
  376. package/dist/src/tunnel/pair-context.js +25 -9
  377. package/dist/src/tunnel/pair-context.js.map +1 -1
  378. package/dist/src/tunnel/pair-url.d.ts +14 -1
  379. package/dist/src/tunnel/pair-url.js +14 -1
  380. package/dist/src/tunnel/pair-url.js.map +1 -1
  381. package/dist/src/tunnel/tunnel-service.js +2 -2
  382. package/dist/src/tunnel/tunnel-state.js +1 -1
  383. package/dist/src/utils/logger/audit.js +1 -1
  384. package/dist/src/utils/logger/log-store.js +1 -1
  385. package/dist/src/utils/logger/rotation.js +1 -1
  386. package/dist/src/voice/tts/audio.js +1 -1
  387. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  388. package/package.json +3 -2
  389. package/dist/gateway/static/root/assets/agents-tR-nNP04.js +0 -222
  390. package/dist/gateway/static/root/assets/apps-page-BDw6SP-d.js +0 -1
  391. package/dist/gateway/static/root/assets/button-KafIU8dx.js +0 -1
  392. package/dist/gateway/static/root/assets/channels-settings-DEFd-jj1.js +0 -1
  393. package/dist/gateway/static/root/assets/channels-status-swr-DI5FHdGe.js +0 -8
  394. package/dist/gateway/static/root/assets/cron-api-BSqY8LwW.js +0 -1
  395. package/dist/gateway/static/root/assets/cron-page-D7lVDjcR.js +0 -1
  396. package/dist/gateway/static/root/assets/dist-C57OMHW8.js +0 -48
  397. package/dist/gateway/static/root/assets/extension-page-CQo2Xsmg.js +0 -1
  398. package/dist/gateway/static/root/assets/extension-settings-page-CZf0WoZg.js +0 -1
  399. package/dist/gateway/static/root/assets/fetch-2iRFmd3n.js +0 -3
  400. package/dist/gateway/static/root/assets/heartbeat-config-api-B0drdQEJ.js +0 -1
  401. package/dist/gateway/static/root/assets/index-0Gt3TG4j.js +0 -4693
  402. package/dist/gateway/static/root/assets/index-BuFldCsB.css +0 -1
  403. package/dist/gateway/static/root/assets/logs-page-DMuORLfC.js +0 -1
  404. package/dist/gateway/static/root/assets/sessions-page-_UO8g6NN.js +0 -1
  405. package/dist/gateway/static/root/assets/settings-form-section-DkmHkknc.js +0 -1
  406. package/dist/gateway/static/root/assets/settings-page-Cz8FoW_A.js +0 -3
  407. package/dist/gateway/static/root/assets/skills-page-HrUOxF7H.js +0 -2
  408. package/dist/gateway/static/root/assets/theme-store-D01dJt95.js +0 -1
  409. package/dist/gateway/static/root/assets/utils-BFwcR6pL.js +0 -1
  410. package/dist/gateway/static/root/assets/voice-api-key-field-JF8-aqc5.js +0 -1
@@ -1,4 +1,5 @@
1
1
  import { commandRegistry } from "../registry.js";
2
+ import { bulletList, commandBullet, joinBlocks, kvList, section } from "../format-output.js";
2
3
  //#region src/chat-commands/builtins/system.ts
3
4
  const helpCommand = {
4
5
  id: "system.help",
@@ -18,17 +19,10 @@ const helpCommand = {
18
19
  if (!byCategory.has(cmd.category)) byCategory.set(cmd.category, []);
19
20
  byCategory.get(cmd.category).push(cmd);
20
21
  }
21
- const lines = ["📖 *Available Commands*\n"];
22
- for (const [category, commands] of byCategory) {
23
- lines.push(`*${category.toUpperCase()}*`);
24
- for (const cmd of commands) {
25
- const aliases = cmd.aliases?.length ? ` (${cmd.aliases.join(", ")})` : "";
26
- lines.push(`/${cmd.name}${aliases} - ${cmd.description}`);
27
- }
28
- lines.push("");
29
- }
22
+ const categoryBlocks = [];
23
+ for (const [category, commands] of byCategory) categoryBlocks.push(joinBlocks(section(category.toUpperCase()), commands.map((cmd) => commandBullet(cmd.name, cmd.description, cmd.aliases)).join("\n")));
30
24
  return {
31
- content: lines.join("\n"),
25
+ content: joinBlocks(section("📖 Available Commands"), ...categoryBlocks),
32
26
  success: true
33
27
  };
34
28
  }
@@ -45,7 +39,11 @@ const startCommand = {
45
39
  ],
46
40
  handler: async (_ctx) => {
47
41
  return {
48
- content: "👋 *Welcome to xopc!*\n\nI am your AI assistant. Here's what I can do:\n\n🤖 *AI Chat* - Just send a message to start chatting\n📊 *Session Management* - Use /new, /list, /usage\n🔧 *Model Selection* - `/models` shows names and `provider/model` refs; `/switch` uses that ref\n\nType /help to see all available commands.",
42
+ content: joinBlocks(section("👋 Welcome to xopc!"), "I am your AI assistant. Here's what I can do:", bulletList([
43
+ "**AI Chat** — Just send a message to start chatting",
44
+ "**Session Management** — Use `/new`, `/list`, `/usage`",
45
+ "**Model Selection** — `/models` shows names and `provider/model` refs; `/switch` uses that ref"
46
+ ]), "Type `/help` to see all available commands."),
49
47
  success: true
50
48
  };
51
49
  }
@@ -61,10 +59,27 @@ const settingsCommand = {
61
59
  "group"
62
60
  ],
63
61
  handler: async (ctx) => {
62
+ const model = ctx.getCurrentModel();
63
+ const sessionKey = ctx.sessionKey;
64
64
  return {
65
- content: `⚙️ *Current Settings*
66
-
67
- 🤖 Model: ${ctx.getCurrentModel()}\n💬 Session: ${ctx.sessionKey}\n📱 Platform: ${ctx.source}\n👥 Group: ${ctx.isGroup ? "Yes" : "No"}`,
65
+ content: joinBlocks(section("⚙️ Current Settings"), kvList([
66
+ {
67
+ key: "Model",
68
+ value: model
69
+ },
70
+ {
71
+ key: "Session",
72
+ value: sessionKey
73
+ },
74
+ {
75
+ key: "Platform",
76
+ value: ctx.source
77
+ },
78
+ {
79
+ key: "Group",
80
+ value: ctx.isGroup ? "Yes" : "No"
81
+ }
82
+ ])),
68
83
  success: true
69
84
  };
70
85
  }
@@ -87,7 +102,7 @@ const skillsCommand = {
87
102
  success: true
88
103
  };
89
104
  return {
90
- content: "🛠️ *Skills Management*\n\nAvailable commands:\n/skills reload - Reload all skills from disk",
105
+ content: joinBlocks(section("🛠️ Skills Management"), bulletList(["`/skills reload` Reload all skills from disk"])),
91
106
  success: true
92
107
  };
93
108
  }
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","names":[],"sources":["../../../../src/chat-commands/builtins/system.ts"],"sourcesContent":["/**\n * System Commands\n *\n * Built-in system commands:\n * - /help - Show help message\n * - /start - Welcome message\n * - /settings - Show settings\n */\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\n\nconst helpCommand: CommandDefinition = {\n id: 'system.help',\n name: 'help',\n aliases: ['h', 'commands'],\n description: 'Show available commands',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (_ctx: CommandContext) => {\n const allCommands = commandRegistry.list();\n\n // Group by category\n const byCategory = new Map<string, typeof allCommands>();\n for (const cmd of allCommands) {\n if (!byCategory.has(cmd.category)) {\n byCategory.set(cmd.category, []);\n }\n byCategory.get(cmd.category)!.push(cmd);\n }\n\n const lines: string[] = ['📖 *Available Commands*\\n'];\n\n for (const [category, commands] of byCategory) {\n lines.push(`*${category.toUpperCase()}*`);\n for (const cmd of commands) {\n const aliases = cmd.aliases?.length ? ` (${cmd.aliases.join(', ')})` : '';\n lines.push(`/${cmd.name}${aliases} - ${cmd.description}`);\n }\n lines.push('');\n }\n\n return {\n content: lines.join('\\n'),\n success: true,\n };\n },\n};\n\nconst startCommand: CommandDefinition = {\n id: 'system.start',\n name: 'start',\n description: 'Show welcome message',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (_ctx: CommandContext) => {\n const content =\n '👋 *Welcome to xopc!*\\n\\n' +\n 'I am your AI assistant. Here\\'s what I can do:\\n\\n' +\n '🤖 *AI Chat* - Just send a message to start chatting\\n' +\n '📊 *Session Management* - Use /new, /list, /usage\\n' +\n '🔧 *Model Selection* - `/models` shows names and `provider/model` refs; `/switch` uses that ref\\n\\n' +\n 'Type /help to see all available commands.';\n\n return {\n content,\n success: true,\n };\n },\n};\n\nconst settingsCommand: CommandDefinition = {\n id: 'system.settings',\n name: 'settings',\n description: 'Show current settings',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (ctx: CommandContext) => {\n const model = ctx.getCurrentModel();\n const sessionKey = ctx.sessionKey;\n\n const content =\n '⚙️ *Current Settings*\\n\\n' +\n `🤖 Model: ${model}\\n` +\n `💬 Session: ${sessionKey}\\n` +\n `📱 Platform: ${ctx.source}\\n` +\n `👥 Group: ${ctx.isGroup ? 'Yes' : 'No'}`;\n\n return {\n content,\n success: true,\n };\n },\n};\n\nconst skillsCommand: CommandDefinition = {\n id: 'system.skills',\n name: 'skills',\n description: 'Manage skills (e.g., /skills reload)',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/skills reload'],\n handler: async (ctx: CommandContext, args: string) => {\n if (args === 'reload') {\n // Publish system event to reload skills\n // This will be handled by AgentService skill reload logic\n return {\n content: '✅ Skills reloaded successfully',\n success: true,\n };\n }\n \n return {\n content: \n '🛠️ *Skills Management*\\n\\n' +\n 'Available commands:\\n' +\n '/skills reload - Reload all skills from disk',\n success: true,\n };\n },\n};\n\n// Register all system commands\nexport function registerSystemCommands(): void {\n commandRegistry.register(helpCommand);\n commandRegistry.register(startCommand);\n commandRegistry.register(settingsCommand);\n commandRegistry.register(skillsCommand);\n}\n"],"mappings":";;AAYA,MAAM,cAAiC;CACrC,IAAI;CACJ,MAAM;CACN,SAAS,CAAC,KAAK,WAAW;CAC1B,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,SAAS,OAAO,SAAyB;EACvC,MAAM,cAAc,gBAAgB,MAAM;EAG1C,MAAM,6BAAa,IAAI,KAAiC;AACxD,OAAK,MAAM,OAAO,aAAa;AAC7B,OAAI,CAAC,WAAW,IAAI,IAAI,SAAS,CAC/B,YAAW,IAAI,IAAI,UAAU,EAAE,CAAC;AAElC,cAAW,IAAI,IAAI,SAAS,CAAE,KAAK,IAAI;;EAGzC,MAAM,QAAkB,CAAC,4BAA4B;AAErD,OAAK,MAAM,CAAC,UAAU,aAAa,YAAY;AAC7C,SAAM,KAAK,IAAI,SAAS,aAAa,CAAC,GAAG;AACzC,QAAK,MAAM,OAAO,UAAU;IAC1B,MAAM,UAAU,IAAI,SAAS,SAAS,KAAK,IAAI,QAAQ,KAAK,KAAK,CAAC,KAAK;AACvE,UAAM,KAAK,IAAI,IAAI,OAAO,QAAQ,KAAK,IAAI,cAAc;;AAE3D,SAAM,KAAK,GAAG;;AAGhB,SAAO;GACL,SAAS,MAAM,KAAK,KAAK;GACzB,SAAS;GACV;;CAEJ;AAED,MAAM,eAAkC;CACtC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,SAAS,OAAO,SAAyB;AASvC,SAAO;GACL,SAAA;GACA,SAAS;GACV;;CAEJ;AAED,MAAM,kBAAqC;CACzC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,SAAS,OAAO,QAAwB;AAWtC,SAAO;GACL,SAAA;;YAXY,IAAI,iBAKE,CAAC,gBAJF,IAAI,WAKK,iBACV,IAAI,OAAO,cACd,IAAI,UAAU,QAAQ;GAInC,SAAS;GACV;;CAEJ;AAED,MAAM,gBAAmC;CACvC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,aAAa;CACb,UAAU,CAAC,iBAAiB;CAC5B,SAAS,OAAO,KAAqB,SAAiB;AACpD,MAAI,SAAS,SAGX,QAAO;GACL,SAAS;GACT,SAAS;GACV;AAGH,SAAO;GACL,SACE;GAGF,SAAS;GACV;;CAEJ;AAGD,SAAgB,yBAA+B;AAC7C,iBAAgB,SAAS,YAAY;AACrC,iBAAgB,SAAS,aAAa;AACtC,iBAAgB,SAAS,gBAAgB;AACzC,iBAAgB,SAAS,cAAc"}
1
+ {"version":3,"file":"system.js","names":[],"sources":["../../../../src/chat-commands/builtins/system.ts"],"sourcesContent":["/**\n * System Commands\n *\n * Built-in system commands:\n * - /help - Show help message\n * - /start - Welcome message\n * - /settings - Show settings\n */\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { bulletList, commandBullet, joinBlocks, kvList, section } from '../format-output.js';\n\nconst helpCommand: CommandDefinition = {\n id: 'system.help',\n name: 'help',\n aliases: ['h', 'commands'],\n description: 'Show available commands',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (_ctx: CommandContext) => {\n const allCommands = commandRegistry.list();\n\n // Group by category\n const byCategory = new Map<string, typeof allCommands>();\n for (const cmd of allCommands) {\n if (!byCategory.has(cmd.category)) {\n byCategory.set(cmd.category, []);\n }\n byCategory.get(cmd.category)!.push(cmd);\n }\n\n const categoryBlocks: string[] = [];\n for (const [category, commands] of byCategory) {\n categoryBlocks.push(\n joinBlocks(\n section(category.toUpperCase()),\n commands\n .map((cmd) => commandBullet(cmd.name, cmd.description, cmd.aliases))\n .join('\\n'),\n ),\n );\n }\n\n return {\n content: joinBlocks(section('📖 Available Commands'), ...categoryBlocks),\n success: true,\n };\n },\n};\n\nconst startCommand: CommandDefinition = {\n id: 'system.start',\n name: 'start',\n description: 'Show welcome message',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (_ctx: CommandContext) => {\n const content = joinBlocks(\n section('👋 Welcome to xopc!'),\n \"I am your AI assistant. Here's what I can do:\",\n bulletList([\n '**AI Chat** Just send a message to start chatting',\n '**Session Management** Use `/new`, `/list`, `/usage`',\n '**Model Selection** `/models` shows names and `provider/model` refs; `/switch` uses that ref',\n ]),\n 'Type `/help` to see all available commands.',\n );\n\n return {\n content,\n success: true,\n };\n },\n};\n\nconst settingsCommand: CommandDefinition = {\n id: 'system.settings',\n name: 'settings',\n description: 'Show current settings',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (ctx: CommandContext) => {\n const model = ctx.getCurrentModel();\n const sessionKey = ctx.sessionKey;\n\n const content = joinBlocks(\n section('⚙️ Current Settings'),\n kvList([\n { key: 'Model', value: model },\n { key: 'Session', value: sessionKey },\n { key: 'Platform', value: ctx.source },\n { key: 'Group', value: ctx.isGroup ? 'Yes' : 'No' },\n ]),\n );\n\n return {\n content,\n success: true,\n };\n },\n};\n\nconst skillsCommand: CommandDefinition = {\n id: 'system.skills',\n name: 'skills',\n description: 'Manage skills (e.g., /skills reload)',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/skills reload'],\n handler: async (ctx: CommandContext, args: string) => {\n if (args === 'reload') {\n // Publish system event to reload skills\n // This will be handled by AgentService skill reload logic\n return {\n content: '✅ Skills reloaded successfully',\n success: true,\n };\n }\n\n const content = joinBlocks(\n section('🛠️ Skills Management'),\n bulletList(['`/skills reload` Reload all skills from disk']),\n );\n\n return {\n content,\n success: true,\n };\n },\n};\n\n// Register all system commands\nexport function registerSystemCommands(): void {\n commandRegistry.register(helpCommand);\n commandRegistry.register(startCommand);\n commandRegistry.register(settingsCommand);\n commandRegistry.register(skillsCommand);\n}\n"],"mappings":";;;AAaA,MAAM,cAAiC;CACrC,IAAI;CACJ,MAAM;CACN,SAAS,CAAC,KAAK,WAAW;CAC1B,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,SAAS,OAAO,SAAyB;EACvC,MAAM,cAAc,gBAAgB,MAAM;EAG1C,MAAM,6BAAa,IAAI,KAAiC;AACxD,OAAK,MAAM,OAAO,aAAa;AAC7B,OAAI,CAAC,WAAW,IAAI,IAAI,SAAS,CAC/B,YAAW,IAAI,IAAI,UAAU,EAAE,CAAC;AAElC,cAAW,IAAI,IAAI,SAAS,CAAE,KAAK,IAAI;;EAGzC,MAAM,iBAA2B,EAAE;AACnC,OAAK,MAAM,CAAC,UAAU,aAAa,WACjC,gBAAe,KACb,WACE,QAAQ,SAAS,aAAa,CAAC,EAC/B,SACG,KAAK,QAAQ,cAAc,IAAI,MAAM,IAAI,aAAa,IAAI,QAAQ,CAAC,CACnE,KAAK,KAAK,CACd,CACF;AAGH,SAAO;GACL,SAAS,WAAW,QAAQ,wBAAwB,EAAE,GAAG,eAAe;GACxE,SAAS;GACV;;CAEJ;AAED,MAAM,eAAkC;CACtC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,SAAS,OAAO,SAAyB;AAYvC,SAAO;GACL,SAZc,WACd,QAAQ,sBAAsB,EAC9B,iDACA,WAAW;IACT;IACA;IACA;IACD,CAAC,EACF,8CAIO;GACP,SAAS;GACV;;CAEJ;AAED,MAAM,kBAAqC;CACzC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,SAAS,OAAO,QAAwB;EACtC,MAAM,QAAQ,IAAI,iBAAiB;EACnC,MAAM,aAAa,IAAI;AAYvB,SAAO;GACL,SAXc,WACd,QAAQ,sBAAsB,EAC9B,OAAO;IACL;KAAE,KAAK;KAAS,OAAO;KAAO;IAC9B;KAAE,KAAK;KAAW,OAAO;KAAY;IACrC;KAAE,KAAK;KAAY,OAAO,IAAI;KAAQ;IACtC;KAAE,KAAK;KAAS,OAAO,IAAI,UAAU,QAAQ;KAAM;IACpD,CAAC,CAIK;GACP,SAAS;GACV;;CAEJ;AAED,MAAM,gBAAmC;CACvC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,aAAa;CACb,UAAU,CAAC,iBAAiB;CAC5B,SAAS,OAAO,KAAqB,SAAiB;AACpD,MAAI,SAAS,SAGX,QAAO;GACL,SAAS;GACT,SAAS;GACV;AAQH,SAAO;GACL,SANc,WACd,QAAQ,wBAAwB,EAChC,WAAW,CAAC,iDAAiD,CAAC,CAIvD;GACP,SAAS;GACV;;CAEJ;AAGD,SAAgB,yBAA+B;AAC7C,iBAAgB,SAAS,YAAY;AACrC,iBAAgB,SAAS,aAAa;AACtC,iBAAgB,SAAS,gBAAgB;AACzC,iBAAgB,SAAS,cAAc"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `/workflows` and `/workflow <subcommand>` — read-only commands for browsing
3
+ * saved workflows.
4
+ *
5
+ * Why only read commands here? Slash command results are sent to the user; they
6
+ * are NOT injected back into the agent's turn. Triggering a workflow run from
7
+ * the slash layer would require a non-trivial cross-cutting "inject this as the
8
+ * next user message" hook that doesn't exist yet. Instead, the workflow tool
9
+ * understands `name`, and its description tells the model to prefer that route
10
+ * whenever a user mentions a saved workflow by name. Plain text — "run the
11
+ * audit_repo workflow" — works end-to-end.
12
+ *
13
+ * `/workflows` and `/workflow view` make discovery cheap, which is the missing
14
+ * piece.
15
+ */
16
+ import type { CommandDefinition } from '../types.js';
17
+ export declare const workflowCommand: CommandDefinition;
18
+ export declare function registerWorkflowCommands(): void;
@@ -0,0 +1,167 @@
1
+ import { createWorkflowCatalog } from "../../agent/workflow/catalog.js";
2
+ import { getLastWorkflowMemory } from "../../agent/workflow/last-run-memory.js";
3
+ import { commandRegistry } from "../registry.js";
4
+ import { bulletList, code, joinBlocks, section } from "../format-output.js";
5
+ //#region src/chat-commands/builtins/workflow.ts
6
+ /**
7
+ * `/workflows` and `/workflow <subcommand>` — read-only commands for browsing
8
+ * saved workflows.
9
+ *
10
+ * Why only read commands here? Slash command results are sent to the user; they
11
+ * are NOT injected back into the agent's turn. Triggering a workflow run from
12
+ * the slash layer would require a non-trivial cross-cutting "inject this as the
13
+ * next user message" hook that doesn't exist yet. Instead, the workflow tool
14
+ * understands `name`, and its description tells the model to prefer that route
15
+ * whenever a user mentions a saved workflow by name. Plain text — "run the
16
+ * audit_repo workflow" — works end-to-end.
17
+ *
18
+ * `/workflows` and `/workflow view` make discovery cheap, which is the missing
19
+ * piece.
20
+ */
21
+ const VIEW_MAX_LINES = 200;
22
+ function formatWorkflowListContent(entries, userDir) {
23
+ const grouped = {
24
+ builtin: entries.filter((e) => e.source === "builtin"),
25
+ user: entries.filter((e) => e.source === "user")
26
+ };
27
+ const exampleName = entries[0]?.name ?? "audit_repo";
28
+ const blocks = [];
29
+ if (grouped.user.length > 0) blocks.push(joinBlocks(section("User workflows"), bulletList(grouped.user.map((e) => ({
30
+ label: e.name,
31
+ detail: e.description
32
+ })))));
33
+ if (grouped.builtin.length > 0) blocks.push(joinBlocks(section("Built-in workflows"), bulletList(grouped.builtin.map((e) => ({
34
+ label: e.name,
35
+ detail: e.description
36
+ })))));
37
+ blocks.push(joinBlocks(section("How to run"), bulletList([
38
+ `Plain language: "run the ${exampleName} workflow"`,
39
+ `Inspect source: ${code(`/workflow view ${exampleName}`)}`,
40
+ `Add your own: drop a ${code(".js")} at ${code(userDir)}`
41
+ ])));
42
+ return joinBlocks(...blocks);
43
+ }
44
+ const workflowsCommand = {
45
+ id: "system.workflows",
46
+ name: "workflows",
47
+ description: "List saved workflows (built-in + ~/.xopc/workflows/)",
48
+ category: "system",
49
+ scope: [
50
+ "global",
51
+ "private",
52
+ "group"
53
+ ],
54
+ handler: async (_ctx) => {
55
+ const catalog = createWorkflowCatalog();
56
+ const entries = catalog.list();
57
+ if (entries.length === 0) return {
58
+ content: `No workflows found. Drop a script at ${code(`${catalog.userDir}/<name>.js`)} to add one.`,
59
+ success: true
60
+ };
61
+ return {
62
+ content: formatWorkflowListContent(entries, catalog.userDir),
63
+ success: true
64
+ };
65
+ }
66
+ };
67
+ const workflowCommand = {
68
+ id: "system.workflow",
69
+ name: "workflow",
70
+ description: "Inspect or manage saved workflows. Subcommands: list, view <name>",
71
+ category: "system",
72
+ scope: [
73
+ "global",
74
+ "private",
75
+ "group"
76
+ ],
77
+ acceptsArgs: true,
78
+ examples: ["/workflow list", "/workflow view audit_repo"],
79
+ handler: async (ctx, args) => {
80
+ const trimmed = args.trim();
81
+ if (!trimmed || trimmed.toLowerCase() === "list") return workflowsCommand.handler(ctx, "");
82
+ const [sub, ...rest] = trimmed.split(/\s+/);
83
+ const subLower = sub.toLowerCase();
84
+ const target = rest.join(" ").trim();
85
+ if (subLower === "view" || subLower === "show" || subLower === "cat") {
86
+ if (!target) return {
87
+ content: `usage: ${code("/workflow view <name>")}`,
88
+ success: false
89
+ };
90
+ const catalog = createWorkflowCatalog();
91
+ try {
92
+ const loaded = catalog.load(target);
93
+ const lines = loaded.script.split("\n");
94
+ const visible = lines.length > VIEW_MAX_LINES ? [...lines.slice(0, VIEW_MAX_LINES), `… (truncated; ${lines.length - VIEW_MAX_LINES} more lines)`] : lines;
95
+ const source = loaded.source === "user" ? loaded.path ?? "user" : "built-in";
96
+ return {
97
+ content: joinBlocks(`**${loaded.name}** (${source}) — ${loaded.meta.description}`, "```js\n" + visible.join("\n") + "\n```"),
98
+ success: true
99
+ };
100
+ } catch (e) {
101
+ return {
102
+ content: `error: ${e instanceof Error ? e.message : String(e)}`,
103
+ success: false
104
+ };
105
+ }
106
+ }
107
+ if (subLower === "run" || subLower === "start") {
108
+ const name = target || "<name>";
109
+ return {
110
+ content: joinBlocks(`To run a workflow, ask in plain language: "run the ${name} workflow".`, `The assistant will call the workflow tool with ${code(`name="${name}"`)} and stream progress inline.`),
111
+ success: true
112
+ };
113
+ }
114
+ if (subLower === "save") {
115
+ if (!target) return {
116
+ content: `usage: ${code("/workflow save <name>")}`,
117
+ success: false
118
+ };
119
+ const last = getLastWorkflowMemory().get(ctx.sessionKey);
120
+ if (!last) return {
121
+ content: "No workflow has run successfully in this session yet. Run one first (e.g. ask \"run the audit_repo workflow\"), then `/workflow save <name>`.",
122
+ success: false
123
+ };
124
+ const catalog = createWorkflowCatalog();
125
+ try {
126
+ const script = last.metaName === target ? last.script : rewriteMetaName(last.script, target);
127
+ const { path } = catalog.save(target, script);
128
+ return {
129
+ content: joinBlocks(`✓ Saved workflow **${target}** → ${code(path)}`, bulletList([`Trigger with ${code(`/${target}`)} or "run the ${target} workflow"`, `Inspect with ${code(`/workflow view ${target}`)}`])),
130
+ success: true
131
+ };
132
+ } catch (e) {
133
+ return {
134
+ content: `error: ${e instanceof Error ? e.message : String(e)}`,
135
+ success: false
136
+ };
137
+ }
138
+ }
139
+ return {
140
+ content: joinBlocks(`Unknown subcommand "${sub}". Available: list, view ${code("<name>")}, save ${code("<name>")}.`, "To run a workflow, ask in plain language (\"run the audit_repo workflow\") — the assistant uses the workflow tool with `name=\"...\"`."),
141
+ success: false
142
+ };
143
+ }
144
+ };
145
+ /**
146
+ * Replace the `name` field inside the FIRST `export const meta = { ... }` literal.
147
+ *
148
+ * Why text-level (not AST re-emit)? The parser already accepted the script
149
+ * once (the runtime ran it), so the surrounding code is unchanged. A targeted
150
+ * regex on the `name: '...'` slot inside the first object literal keeps the
151
+ * user's formatting / comments / quote style intact, which an AST round-trip
152
+ * would smash. The match anchors to the first `name:` after `export const meta`
153
+ * and only touches that single value.
154
+ */
155
+ function rewriteMetaName(script, newName) {
156
+ const re = /(export\s+const\s+meta\s*=\s*\{[^}]*?\bname\s*:\s*)(['"`])([^'"`]*)\2/;
157
+ if (!re.test(script)) throw new Error("could not locate meta.name in the recorded script to rewrite");
158
+ return script.replace(re, (_m, prefix, quote) => `${prefix}${quote}${newName}${quote}`);
159
+ }
160
+ function registerWorkflowCommands() {
161
+ commandRegistry.register(workflowsCommand);
162
+ commandRegistry.register(workflowCommand);
163
+ }
164
+ //#endregion
165
+ export { registerWorkflowCommands, workflowCommand };
166
+
167
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.js","names":[],"sources":["../../../../src/chat-commands/builtins/workflow.ts"],"sourcesContent":["/**\n * `/workflows` and `/workflow <subcommand>` — read-only commands for browsing\n * saved workflows.\n *\n * Why only read commands here? Slash command results are sent to the user; they\n * are NOT injected back into the agent's turn. Triggering a workflow run from\n * the slash layer would require a non-trivial cross-cutting \"inject this as the\n * next user message\" hook that doesn't exist yet. Instead, the workflow tool\n * understands `name`, and its description tells the model to prefer that route\n * whenever a user mentions a saved workflow by name. Plain text — \"run the\n * audit_repo workflow\" — works end-to-end.\n *\n * `/workflows` and `/workflow view` make discovery cheap, which is the missing\n * piece.\n */\n\nimport { commandRegistry } from '../registry.js';\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { bulletList, code, joinBlocks, section } from '../format-output.js';\n\nimport { createWorkflowCatalog } from '../../agent/workflow/catalog.js';\nimport { getLastWorkflowMemory } from '../../agent/workflow/last-run-memory.js';\nimport type { CatalogEntry } from '../../agent/workflow/catalog.js';\n\nconst VIEW_MAX_LINES = 200;\n\nfunction formatWorkflowListContent(entries: CatalogEntry[], userDir: string): string {\n const grouped = {\n builtin: entries.filter((e) => e.source === 'builtin'),\n user: entries.filter((e) => e.source === 'user'),\n };\n const exampleName = entries[0]?.name ?? 'audit_repo';\n const blocks: string[] = [];\n\n if (grouped.user.length > 0) {\n blocks.push(\n joinBlocks(\n section('User workflows'),\n bulletList(grouped.user.map((e) => ({ label: e.name, detail: e.description }))),\n ),\n );\n }\n if (grouped.builtin.length > 0) {\n blocks.push(\n joinBlocks(\n section('Built-in workflows'),\n bulletList(grouped.builtin.map((e) => ({ label: e.name, detail: e.description }))),\n ),\n );\n }\n\n blocks.push(\n joinBlocks(\n section('How to run'),\n bulletList([\n `Plain language: \"run the ${exampleName} workflow\"`,\n `Inspect source: ${code(`/workflow view ${exampleName}`)}`,\n `Add your own: drop a ${code('.js')} at ${code(userDir)}`,\n ]),\n ),\n );\n\n return joinBlocks(...blocks);\n}\n\nconst workflowsCommand: CommandDefinition = {\n id: 'system.workflows',\n name: 'workflows',\n description: 'List saved workflows (built-in + ~/.xopc/workflows/)',\n category: 'system',\n scope: ['global', 'private', 'group'],\n handler: async (_ctx: CommandContext) => {\n const catalog = createWorkflowCatalog();\n const entries = catalog.list();\n if (entries.length === 0) {\n return {\n content: `No workflows found. Drop a script at ${code(`${catalog.userDir}/<name>.js`)} to add one.`,\n success: true,\n };\n }\n return { content: formatWorkflowListContent(entries, catalog.userDir), success: true };\n },\n};\n\nexport const workflowCommand: CommandDefinition = {\n id: 'system.workflow',\n name: 'workflow',\n description: 'Inspect or manage saved workflows. Subcommands: list, view <name>',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/workflow list', '/workflow view audit_repo'],\n handler: async (ctx: CommandContext, args: string) => {\n const trimmed = args.trim();\n if (!trimmed || trimmed.toLowerCase() === 'list') {\n return workflowsCommand.handler(ctx, '');\n }\n const [sub, ...rest] = trimmed.split(/\\s+/);\n const subLower = sub.toLowerCase();\n const target = rest.join(' ').trim();\n\n if (subLower === 'view' || subLower === 'show' || subLower === 'cat') {\n if (!target) {\n return { content: `usage: ${code('/workflow view <name>')}`, success: false };\n }\n const catalog = createWorkflowCatalog();\n try {\n const loaded = catalog.load(target);\n const lines = loaded.script.split('\\n');\n const visible =\n lines.length > VIEW_MAX_LINES\n ? [...lines.slice(0, VIEW_MAX_LINES), `… (truncated; ${lines.length - VIEW_MAX_LINES} more lines)`]\n : lines;\n const source = loaded.source === 'user' ? loaded.path ?? 'user' : 'built-in';\n return {\n content: joinBlocks(\n `**${loaded.name}** (${source}) — ${loaded.meta.description}`,\n '```js\\n' + visible.join('\\n') + '\\n```',\n ),\n success: true,\n };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { content: `error: ${message}`, success: false };\n }\n }\n\n if (subLower === 'run' || subLower === 'start') {\n const name = target || '<name>';\n return {\n content: joinBlocks(\n `To run a workflow, ask in plain language: \"run the ${name} workflow\".`,\n `The assistant will call the workflow tool with ${code(`name=\"${name}\"`)} and stream progress inline.`,\n ),\n success: true,\n };\n }\n\n if (subLower === 'save') {\n if (!target) {\n return { content: `usage: ${code('/workflow save <name>')}`, success: false };\n }\n const last = getLastWorkflowMemory().get(ctx.sessionKey);\n if (!last) {\n return {\n content:\n 'No workflow has run successfully in this session yet. Run one first (e.g. ask \"run the audit_repo workflow\"), then `/workflow save <name>`.',\n success: false,\n };\n }\n const catalog = createWorkflowCatalog();\n try {\n // Allow the user to rename: if target differs from meta.name, rewrite it\n // before saving so the file is addressable as `target`.\n const script =\n last.metaName === target ? last.script : rewriteMetaName(last.script, target);\n const { path } = catalog.save(target, script);\n return {\n content: joinBlocks(\n `✓ Saved workflow **${target}** → ${code(path)}`,\n bulletList([\n `Trigger with ${code(`/${target}`)} or \"run the ${target} workflow\"`,\n `Inspect with ${code(`/workflow view ${target}`)}`,\n ]),\n ),\n success: true,\n };\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return { content: `error: ${message}`, success: false };\n }\n }\n\n return {\n content: joinBlocks(\n `Unknown subcommand \"${sub}\". Available: list, view ${code('<name>')}, save ${code('<name>')}.`,\n 'To run a workflow, ask in plain language (\"run the audit_repo workflow\") — the assistant uses the workflow tool with `name=\"...\"`.',\n ),\n success: false,\n };\n },\n};\n\n/**\n * Replace the `name` field inside the FIRST `export const meta = { ... }` literal.\n *\n * Why text-level (not AST re-emit)? The parser already accepted the script\n * once (the runtime ran it), so the surrounding code is unchanged. A targeted\n * regex on the `name: '...'` slot inside the first object literal keeps the\n * user's formatting / comments / quote style intact, which an AST round-trip\n * would smash. The match anchors to the first `name:` after `export const meta`\n * and only touches that single value.\n */\nfunction rewriteMetaName(script: string, newName: string): string {\n const re = /(export\\s+const\\s+meta\\s*=\\s*\\{[^}]*?\\bname\\s*:\\s*)(['\"`])([^'\"`]*)\\2/;\n if (!re.test(script)) {\n throw new Error('could not locate meta.name in the recorded script to rewrite');\n }\n return script.replace(re, (_m, prefix, quote) => `${prefix}${quote}${newName}${quote}`);\n}\n\nexport function registerWorkflowCommands(): void {\n commandRegistry.register(workflowsCommand);\n commandRegistry.register(workflowCommand);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,iBAAiB;AAEvB,SAAS,0BAA0B,SAAyB,SAAyB;CACnF,MAAM,UAAU;EACd,SAAS,QAAQ,QAAQ,MAAM,EAAE,WAAW,UAAU;EACtD,MAAM,QAAQ,QAAQ,MAAM,EAAE,WAAW,OAAO;EACjD;CACD,MAAM,cAAc,QAAQ,IAAI,QAAQ;CACxC,MAAM,SAAmB,EAAE;AAE3B,KAAI,QAAQ,KAAK,SAAS,EACxB,QAAO,KACL,WACE,QAAQ,iBAAiB,EACzB,WAAW,QAAQ,KAAK,KAAK,OAAO;EAAE,OAAO,EAAE;EAAM,QAAQ,EAAE;EAAa,EAAE,CAAC,CAChF,CACF;AAEH,KAAI,QAAQ,QAAQ,SAAS,EAC3B,QAAO,KACL,WACE,QAAQ,qBAAqB,EAC7B,WAAW,QAAQ,QAAQ,KAAK,OAAO;EAAE,OAAO,EAAE;EAAM,QAAQ,EAAE;EAAa,EAAE,CAAC,CACnF,CACF;AAGH,QAAO,KACL,WACE,QAAQ,aAAa,EACrB,WAAW;EACT,4BAA4B,YAAY;EACxC,mBAAmB,KAAK,kBAAkB,cAAc;EACxD,wBAAwB,KAAK,MAAM,CAAC,MAAM,KAAK,QAAQ;EACxD,CAAC,CACH,CACF;AAED,QAAO,WAAW,GAAG,OAAO;;AAG9B,MAAM,mBAAsC;CAC1C,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,SAAS,OAAO,SAAyB;EACvC,MAAM,UAAU,uBAAuB;EACvC,MAAM,UAAU,QAAQ,MAAM;AAC9B,MAAI,QAAQ,WAAW,EACrB,QAAO;GACL,SAAS,wCAAwC,KAAK,GAAG,QAAQ,QAAQ,YAAY,CAAC;GACtF,SAAS;GACV;AAEH,SAAO;GAAE,SAAS,0BAA0B,SAAS,QAAQ,QAAQ;GAAE,SAAS;GAAM;;CAEzF;AAED,MAAa,kBAAqC;CAChD,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,aAAa;CACb,UAAU,CAAC,kBAAkB,4BAA4B;CACzD,SAAS,OAAO,KAAqB,SAAiB;EACpD,MAAM,UAAU,KAAK,MAAM;AAC3B,MAAI,CAAC,WAAW,QAAQ,aAAa,KAAK,OACxC,QAAO,iBAAiB,QAAQ,KAAK,GAAG;EAE1C,MAAM,CAAC,KAAK,GAAG,QAAQ,QAAQ,MAAM,MAAM;EAC3C,MAAM,WAAW,IAAI,aAAa;EAClC,MAAM,SAAS,KAAK,KAAK,IAAI,CAAC,MAAM;AAEpC,MAAI,aAAa,UAAU,aAAa,UAAU,aAAa,OAAO;AACpE,OAAI,CAAC,OACH,QAAO;IAAE,SAAS,UAAU,KAAK,wBAAwB;IAAI,SAAS;IAAO;GAE/E,MAAM,UAAU,uBAAuB;AACvC,OAAI;IACF,MAAM,SAAS,QAAQ,KAAK,OAAO;IACnC,MAAM,QAAQ,OAAO,OAAO,MAAM,KAAK;IACvC,MAAM,UACJ,MAAM,SAAS,iBACX,CAAC,GAAG,MAAM,MAAM,GAAG,eAAe,EAAE,iBAAiB,MAAM,SAAS,eAAe,cAAc,GACjG;IACN,MAAM,SAAS,OAAO,WAAW,SAAS,OAAO,QAAQ,SAAS;AAClE,WAAO;KACL,SAAS,WACP,KAAK,OAAO,KAAK,MAAM,OAAO,MAAM,OAAO,KAAK,eAChD,YAAY,QAAQ,KAAK,KAAK,GAAG,QAClC;KACD,SAAS;KACV;YACM,GAAG;AAEV,WAAO;KAAE,SAAS,UADF,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;KACnB,SAAS;KAAO;;;AAI3D,MAAI,aAAa,SAAS,aAAa,SAAS;GAC9C,MAAM,OAAO,UAAU;AACvB,UAAO;IACL,SAAS,WACP,sDAAsD,KAAK,cAC3D,kDAAkD,KAAK,SAAS,KAAK,GAAG,CAAC,8BAC1E;IACD,SAAS;IACV;;AAGH,MAAI,aAAa,QAAQ;AACvB,OAAI,CAAC,OACH,QAAO;IAAE,SAAS,UAAU,KAAK,wBAAwB;IAAI,SAAS;IAAO;GAE/E,MAAM,OAAO,uBAAuB,CAAC,IAAI,IAAI,WAAW;AACxD,OAAI,CAAC,KACH,QAAO;IACL,SACE;IACF,SAAS;IACV;GAEH,MAAM,UAAU,uBAAuB;AACvC,OAAI;IAGF,MAAM,SACJ,KAAK,aAAa,SAAS,KAAK,SAAS,gBAAgB,KAAK,QAAQ,OAAO;IAC/E,MAAM,EAAE,SAAS,QAAQ,KAAK,QAAQ,OAAO;AAC7C,WAAO;KACL,SAAS,WACP,sBAAsB,OAAO,OAAO,KAAK,KAAK,IAC9C,WAAW,CACT,gBAAgB,KAAK,IAAI,SAAS,CAAC,eAAe,OAAO,aACzD,gBAAgB,KAAK,kBAAkB,SAAS,GACjD,CAAC,CACH;KACD,SAAS;KACV;YACM,GAAG;AAEV,WAAO;KAAE,SAAS,UADF,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;KACnB,SAAS;KAAO;;;AAI3D,SAAO;GACL,SAAS,WACP,uBAAuB,IAAI,2BAA2B,KAAK,SAAS,CAAC,SAAS,KAAK,SAAS,CAAC,IAC7F,yIACD;GACD,SAAS;GACV;;CAEJ;;;;;;;;;;;AAYD,SAAS,gBAAgB,QAAgB,SAAyB;CAChE,MAAM,KAAK;AACX,KAAI,CAAC,GAAG,KAAK,OAAO,CAClB,OAAM,IAAI,MAAM,+DAA+D;AAEjF,QAAO,OAAO,QAAQ,KAAK,IAAI,QAAQ,UAAU,GAAG,SAAS,QAAQ,UAAU,QAAQ;;AAGzF,SAAgB,2BAAiC;AAC/C,iBAAgB,SAAS,iBAAiB;AAC1C,iBAAgB,SAAS,gBAAgB"}
@@ -4,8 +4,8 @@ import { init_loader, saveConfig } from "../config/loader.js";
4
4
  import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
5
5
  import { getRoutingInfo, getSessionDisplayName } from "./session-key.js";
6
6
  import { wrapMarkdownExportAsHtml } from "../session/chat-export.js";
7
- import { mkdir, writeFile } from "fs/promises";
8
7
  import { join } from "path";
8
+ import { mkdir, writeFile } from "fs/promises";
9
9
  //#region src/chat-commands/context.ts
10
10
  init_logger();
11
11
  init_loader();
@@ -0,0 +1,28 @@
1
+ /**
2
+ * GFM formatters for slash-command replies.
3
+ *
4
+ * Command output is rendered as Markdown on Web UI, TUI (gateway), and channels
5
+ * (Telegram IR). Use blank-line-separated blocks and `-` lists — not single
6
+ * newlines or unicode `•` bullets — so lists and headings parse correctly.
7
+ */
8
+ /** Join non-empty blocks with a blank line (GFM paragraph separation). */
9
+ export declare function joinBlocks(...blocks: Array<string | undefined | null | false>): string;
10
+ /** Section heading (bold). */
11
+ export declare function section(title: string): string;
12
+ /** Inline code span. */
13
+ export declare function code(text: string): string;
14
+ /** Italic hint / footnote. */
15
+ export declare function hint(text: string): string;
16
+ export type BulletItem = string | {
17
+ label: string;
18
+ detail: string;
19
+ };
20
+ /** GFM bullet list (`-` prefix). */
21
+ export declare function bulletList(items: BulletItem[]): string;
22
+ /** Settings-style key/value bullets. */
23
+ export declare function kvList(entries: Array<{
24
+ key: string;
25
+ value: string;
26
+ }>): string;
27
+ /** Slash command reference line in a bullet list. */
28
+ export declare function commandBullet(name: string, description: string, aliases?: string[]): string;
@@ -0,0 +1,45 @@
1
+ //#region src/chat-commands/format-output.ts
2
+ /**
3
+ * GFM formatters for slash-command replies.
4
+ *
5
+ * Command output is rendered as Markdown on Web UI, TUI (gateway), and channels
6
+ * (Telegram IR). Use blank-line-separated blocks and `-` lists — not single
7
+ * newlines or unicode `•` bullets — so lists and headings parse correctly.
8
+ */
9
+ /** Join non-empty blocks with a blank line (GFM paragraph separation). */
10
+ function joinBlocks(...blocks) {
11
+ return blocks.filter((b) => typeof b === "string" && b.trim().length > 0).join("\n\n").trimEnd();
12
+ }
13
+ /** Section heading (bold). */
14
+ function section(title) {
15
+ return `**${title}**`;
16
+ }
17
+ /** Inline code span. */
18
+ function code(text) {
19
+ return `\`${text}\``;
20
+ }
21
+ /** Italic hint / footnote. */
22
+ function hint(text) {
23
+ return `_${text}_`;
24
+ }
25
+ /** GFM bullet list (`-` prefix). */
26
+ function bulletList(items) {
27
+ if (items.length === 0) return "";
28
+ return items.map((item) => {
29
+ if (typeof item === "string") return `- ${item}`;
30
+ return `- **${item.label}** — ${item.detail}`;
31
+ }).join("\n");
32
+ }
33
+ /** Settings-style key/value bullets. */
34
+ function kvList(entries) {
35
+ if (entries.length === 0) return "";
36
+ return entries.map(({ key, value }) => `- **${key}**: ${value}`).join("\n");
37
+ }
38
+ /** Slash command reference line in a bullet list. */
39
+ function commandBullet(name, description, aliases) {
40
+ return `- ${code(`/${name}${aliases?.length ? ` (${aliases.join(", ")})` : ""}`)} — ${description}`;
41
+ }
42
+ //#endregion
43
+ export { bulletList, code, commandBullet, hint, joinBlocks, kvList, section };
44
+
45
+ //# sourceMappingURL=format-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-output.js","names":[],"sources":["../../../src/chat-commands/format-output.ts"],"sourcesContent":["/**\n * GFM formatters for slash-command replies.\n *\n * Command output is rendered as Markdown on Web UI, TUI (gateway), and channels\n * (Telegram IR). Use blank-line-separated blocks and `-` lists — not single\n * newlines or unicode `•` bullets — so lists and headings parse correctly.\n */\n\n/** Join non-empty blocks with a blank line (GFM paragraph separation). */\nexport function joinBlocks(...blocks: Array<string | undefined | null | false>): string {\n return blocks\n .filter((b): b is string => typeof b === 'string' && b.trim().length > 0)\n .join('\\n\\n')\n .trimEnd();\n}\n\n/** Section heading (bold). */\nexport function section(title: string): string {\n return `**${title}**`;\n}\n\n/** Inline code span. */\nexport function code(text: string): string {\n return `\\`${text}\\``;\n}\n\n/** Italic hint / footnote. */\nexport function hint(text: string): string {\n return `_${text}_`;\n}\n\nexport type BulletItem = string | { label: string; detail: string };\n\n/** GFM bullet list (`-` prefix). */\nexport function bulletList(items: BulletItem[]): string {\n if (items.length === 0) return '';\n return items\n .map((item) => {\n if (typeof item === 'string') return `- ${item}`;\n return `- **${item.label}** — ${item.detail}`;\n })\n .join('\\n');\n}\n\n/** Settings-style key/value bullets. */\nexport function kvList(entries: Array<{ key: string; value: string }>): string {\n if (entries.length === 0) return '';\n return entries.map(({ key, value }) => `- **${key}**: ${value}`).join('\\n');\n}\n\n/** Slash command reference line in a bullet list. */\nexport function commandBullet(name: string, description: string, aliases?: string[]): string {\n const aliasSuffix = aliases?.length ? ` (${aliases.join(', ')})` : '';\n return `- ${code(`/${name}${aliasSuffix}`)} — ${description}`;\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,WAAW,GAAG,QAA0D;AACtF,QAAO,OACJ,QAAQ,MAAmB,OAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,CACxE,KAAK,OAAO,CACZ,SAAS;;;AAId,SAAgB,QAAQ,OAAuB;AAC7C,QAAO,KAAK,MAAM;;;AAIpB,SAAgB,KAAK,MAAsB;AACzC,QAAO,KAAK,KAAK;;;AAInB,SAAgB,KAAK,MAAsB;AACzC,QAAO,IAAI,KAAK;;;AAMlB,SAAgB,WAAW,OAA6B;AACtD,KAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAO,MACJ,KAAK,SAAS;AACb,MAAI,OAAO,SAAS,SAAU,QAAO,KAAK;AAC1C,SAAO,OAAO,KAAK,MAAM,OAAO,KAAK;GACrC,CACD,KAAK,KAAK;;;AAIf,SAAgB,OAAO,SAAwD;AAC7E,KAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAO,QAAQ,KAAK,EAAE,KAAK,YAAY,OAAO,IAAI,MAAM,QAAQ,CAAC,KAAK,KAAK;;;AAI7E,SAAgB,cAAc,MAAc,aAAqB,SAA4B;AAE3F,QAAO,KAAK,KAAK,IAAI,OADD,SAAS,SAAS,KAAK,QAAQ,KAAK,KAAK,CAAC,KAAK,KACzB,CAAC,KAAK"}
@@ -19,6 +19,7 @@ export { registerConfigCommand } from './builtins/config.js';
19
19
  export { registerContextCommands } from './builtins/context.js';
20
20
  export { registerGoalCommand } from './builtins/goal.js';
21
21
  export { registerSubgoalCommand } from './builtins/subgoal.js';
22
+ export { registerWorkflowCommands } from './builtins/workflow.js';
22
23
  /**
23
24
  * Initialize the command system with all built-in commands
24
25
  */
@@ -10,6 +10,7 @@ import { registerConfigCommand } from "./builtins/config.js";
10
10
  import { registerContextCommands } from "./builtins/context.js";
11
11
  import { registerGoalCommand } from "./builtins/goal.js";
12
12
  import { registerSubgoalCommand } from "./builtins/subgoal.js";
13
+ import { registerWorkflowCommands } from "./builtins/workflow.js";
13
14
  import { CommandContextImpl, createCommandContext } from "./context.js";
14
15
  //#region src/chat-commands/index.ts
15
16
  /**
@@ -31,8 +32,9 @@ function initializeCommands() {
31
32
  registerThinkingCommands();
32
33
  registerGoalCommand();
33
34
  registerSubgoalCommand();
35
+ registerWorkflowCommands();
34
36
  }
35
37
  //#endregion
36
- export { CommandContextImpl, CommandRegistry, commandRegistry, createCommandContext, generateSessionKey, getRoutingInfo, getSessionDisplayName, initializeCommands, isValidSessionKey, normalizeTelegramCommandName, parseSessionKey, parseSlashCommand, registerConfigCommand, registerContextCommands, registerGoalCommand, registerModelCommands, registerSessionCommands, registerSubgoalCommand, registerSystemCommands, registerTTSCommands, registerThinkingCommands };
38
+ export { CommandContextImpl, CommandRegistry, commandRegistry, createCommandContext, generateSessionKey, getRoutingInfo, getSessionDisplayName, initializeCommands, isValidSessionKey, normalizeTelegramCommandName, parseSessionKey, parseSlashCommand, registerConfigCommand, registerContextCommands, registerGoalCommand, registerModelCommands, registerSessionCommands, registerSubgoalCommand, registerSystemCommands, registerTTSCommands, registerThinkingCommands, registerWorkflowCommands };
37
39
 
38
40
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/chat-commands/index.ts"],"sourcesContent":["/**\n * Unified Command System\n *\n * Provides a platform-agnostic command system that works across\n * Telegram, Feishu, Web UI, CLI, and other channel surfaces.\n */\n\n// Built-in Commands (import first to avoid circular deps)\nimport { registerSessionCommands } from './builtins/session.js';\nimport { registerModelCommands } from './builtins/model.js';\nimport { registerSystemCommands } from './builtins/system.js';\nimport { registerTTSCommands } from './builtins/tts.js';\nimport { registerThinkingCommands } from './builtins/thinking.js';\nimport { registerConfigCommand } from './builtins/config.js';\nimport { registerContextCommands } from './builtins/context.js';\nimport { registerGoalCommand } from './builtins/goal.js';\nimport { registerSubgoalCommand } from './builtins/subgoal.js';\n\n// Types\nexport type {\n MessageSource,\n UnifiedMessage,\n PlatformMetadata,\n MessageAttachment,\n CommandDefinition,\n CommandCategory,\n CommandScope,\n CommandHandler,\n CommandResult,\n CommandContext,\n ReplyOptions,\n UIComponent,\n ButtonGroup,\n SelectMenu,\n ModelPicker,\n UsageDisplay,\n SessionList,\n TextInput,\n ProviderInfo,\n ModelInfo,\n UsageStats,\n SessionInfo,\n PlatformFeature,\n ChannelAdapter,\n ReplyPayload,\n} from './types.js';\n\n// Session Key\nexport {\n generateSessionKey,\n parseSessionKey,\n isValidSessionKey,\n getSessionDisplayName,\n getRoutingInfo,\n type SessionKeyContext,\n} from './session-key.js';\n\n// Command parsing helpers\nexport { normalizeTelegramCommandName, parseSlashCommand } from './command-parse.js';\n\n// Registry\nexport { CommandRegistry, commandRegistry } from './registry.js';\nexport type { CommandRegistry as CommandRegistryType } from './types.js';\n\n// Context\nexport { CommandContextImpl, createCommandContext } from './context.js';\n\n// Built-in Commands\nexport { registerSessionCommands } from './builtins/session.js';\nexport { registerModelCommands } from './builtins/model.js';\nexport { registerSystemCommands } from './builtins/system.js';\nexport { registerTTSCommands } from './builtins/tts.js';\nexport { registerThinkingCommands } from './builtins/thinking.js';\nexport { registerConfigCommand } from './builtins/config.js';\nexport { registerContextCommands } from './builtins/context.js';\nexport { registerGoalCommand } from './builtins/goal.js';\nexport { registerSubgoalCommand } from './builtins/subgoal.js';\n\n/**\n * Initialize the command system with all built-in commands\n */\nexport function initializeCommands(): void {\n registerSessionCommands();\n registerModelCommands();\n registerSystemCommands();\n registerConfigCommand();\n registerContextCommands();\n registerTTSCommands();\n registerThinkingCommands();\n registerGoalCommand();\n registerSubgoalCommand();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAiFA,SAAgB,qBAA2B;AACzC,0BAAyB;AACzB,wBAAuB;AACvB,yBAAwB;AACxB,wBAAuB;AACvB,0BAAyB;AACzB,sBAAqB;AACrB,2BAA0B;AAC1B,sBAAqB;AACrB,yBAAwB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/chat-commands/index.ts"],"sourcesContent":["/**\n * Unified Command System\n *\n * Provides a platform-agnostic command system that works across\n * Telegram, Feishu, Web UI, CLI, and other channel surfaces.\n */\n\n// Built-in Commands (import first to avoid circular deps)\nimport { registerSessionCommands } from './builtins/session.js';\nimport { registerModelCommands } from './builtins/model.js';\nimport { registerSystemCommands } from './builtins/system.js';\nimport { registerTTSCommands } from './builtins/tts.js';\nimport { registerThinkingCommands } from './builtins/thinking.js';\nimport { registerConfigCommand } from './builtins/config.js';\nimport { registerContextCommands } from './builtins/context.js';\nimport { registerGoalCommand } from './builtins/goal.js';\nimport { registerSubgoalCommand } from './builtins/subgoal.js';\nimport { registerWorkflowCommands } from './builtins/workflow.js';\n\n// Types\nexport type {\n MessageSource,\n UnifiedMessage,\n PlatformMetadata,\n MessageAttachment,\n CommandDefinition,\n CommandCategory,\n CommandScope,\n CommandHandler,\n CommandResult,\n CommandContext,\n ReplyOptions,\n UIComponent,\n ButtonGroup,\n SelectMenu,\n ModelPicker,\n UsageDisplay,\n SessionList,\n TextInput,\n ProviderInfo,\n ModelInfo,\n UsageStats,\n SessionInfo,\n PlatformFeature,\n ChannelAdapter,\n ReplyPayload,\n} from './types.js';\n\n// Session Key\nexport {\n generateSessionKey,\n parseSessionKey,\n isValidSessionKey,\n getSessionDisplayName,\n getRoutingInfo,\n type SessionKeyContext,\n} from './session-key.js';\n\n// Command parsing helpers\nexport { normalizeTelegramCommandName, parseSlashCommand } from './command-parse.js';\n\n// Registry\nexport { CommandRegistry, commandRegistry } from './registry.js';\nexport type { CommandRegistry as CommandRegistryType } from './types.js';\n\n// Context\nexport { CommandContextImpl, createCommandContext } from './context.js';\n\n// Built-in Commands\nexport { registerSessionCommands } from './builtins/session.js';\nexport { registerModelCommands } from './builtins/model.js';\nexport { registerSystemCommands } from './builtins/system.js';\nexport { registerTTSCommands } from './builtins/tts.js';\nexport { registerThinkingCommands } from './builtins/thinking.js';\nexport { registerConfigCommand } from './builtins/config.js';\nexport { registerContextCommands } from './builtins/context.js';\nexport { registerGoalCommand } from './builtins/goal.js';\nexport { registerSubgoalCommand } from './builtins/subgoal.js';\nexport { registerWorkflowCommands } from './builtins/workflow.js';\n\n/**\n * Initialize the command system with all built-in commands\n */\nexport function initializeCommands(): void {\n registerSessionCommands();\n registerModelCommands();\n registerSystemCommands();\n registerConfigCommand();\n registerContextCommands();\n registerTTSCommands();\n registerThinkingCommands();\n registerGoalCommand();\n registerSubgoalCommand();\n registerWorkflowCommands();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmFA,SAAgB,qBAA2B;AACzC,0BAAyB;AACzB,wBAAuB;AACvB,yBAAwB;AACxB,wBAAuB;AACvB,0BAAyB;AACzB,sBAAqB;AACrB,2BAA0B;AAC1B,sBAAqB;AACrB,yBAAwB;AACxB,2BAA0B"}
@@ -1,7 +1,7 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
1
  import { ConfigSchema, init_schema } from "../../config/schema.js";
3
- import { formatExamples, register } from "../registry.js";
2
+ import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
4
3
  import { resolveGatewayLocalClientHost } from "../../config/gateway-bind.js";
4
+ import { formatExamples, register } from "../registry.js";
5
5
  import { existsSync, readFileSync } from "fs";
6
6
  import { Command } from "commander";
7
7
  //#region src/cli/commands/config.ts
@@ -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 { existsSync, mkdirSync, readFileSync } from "node:fs";
4
3
  import { dirname } from "node:path";
4
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
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";
2
1
  import { getAgentDefaultModelRef, init_schema, parseModelRef } from "../../../../config/schema.js";
3
2
  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 { existsSync, readFileSync } from "node:fs";
6
5
  import { join } from "node:path";
6
+ import { existsSync, readFileSync } from "node:fs";
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 { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
2
1
  import { join } from "node:path";
2
+ import { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
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 { existsSync } from "node:fs";
5
4
  import { join } from "node:path";
5
+ import { existsSync } from "node:fs";
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 { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, watch } from "node:fs";
16
15
  import { join, resolve } from "node:path";
16
+ import { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, watch } from "node:fs";
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 { existsSync, readFileSync, rmSync, statSync } from "node:fs";
11
10
  import { join, resolve } from "node:path";
11
+ import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
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 { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
8
7
  import { isAbsolute, join, resolve } from "node:path";
8
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
9
9
  import { execSync } from "node:child_process";
10
10
  import { Command } from "commander";
11
11
  //#region src/cli/commands/extension-pack.ts
@@ -3,7 +3,7 @@ import { loadConfig } from "../../../config/loader.js";
3
3
  import "../../../config/index.js";
4
4
  import { isRestartEnabled } from "../../../config/commands.flags.js";
5
5
  import { resolveGatewayService } from "../../../daemon/service.js";
6
- import { authorizeGatewaySigusr1Restart } from "../../../infra/restart.js";
6
+ import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
7
7
  import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
8
8
  import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
9
9
  import { DEFAULT_RESTART_HEALTH_ATTEMPTS, renderGatewayPortHealthDiagnostics, waitForGatewayHealthyListener } from "./restart-health.js";
@@ -48,11 +48,17 @@ async function restartGatewayWithoutServiceManager(port) {
48
48
  const pids = resolveVerifiedGatewayListenerPids(port);
49
49
  if (pids.length === 0) return null;
50
50
  if (pids.length > 1) throw new Error(`multiple gateway processes are listening on port ${port}: ${formatGatewayPidList(pids)}; use "xopc gateway status" before retrying restart`);
51
- authorizeGatewaySigusr1Restart();
52
- signalVerifiedGatewayPidSync(pids[0], "SIGUSR1");
51
+ const targetPid = pids[0];
52
+ if (process.platform === "win32") {
53
+ writeGatewayRestartIntentSync({ targetPid });
54
+ signalVerifiedGatewayPidSync(targetPid, "SIGTERM");
55
+ } else {
56
+ authorizeGatewaySigusr1Restart();
57
+ signalVerifiedGatewayPidSync(targetPid, "SIGUSR1");
58
+ }
53
59
  return {
54
60
  result: "restarted",
55
- message: `Gateway restart signal sent to unmanaged process on port ${port}: ${pids[0]}.`
61
+ message: `Gateway restart signal sent to unmanaged process on port ${port}: ${targetPid}.`
56
62
  };
57
63
  }
58
64
  async function runDaemonStop(options = {}) {