@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-perspective-review.js","names":[],"sources":["../../../../../src/agent/workflow/builtins/multi-perspective-review.ts"],"sourcesContent":["/**\n * Built-in workflow: `multi_perspective_review`\n *\n * Reviews a target (file, PR, design doc, plan — passed via args.target) from\n * several independent perspectives, then asks an adversarial judge to decide\n * what would actually break in practice. Useful for sanity-checking decisions\n * before they ship.\n */\n\nexport const MULTI_PERSPECTIVE_REVIEW_SCRIPT = `export const meta = {\n name: 'multi_perspective_review',\n description: 'Review a target from N independent perspectives, then adversarially judge what would actually break.',\n whenToUse: 'User wants a stress-test of a design, plan, PR, or proposal before committing to it.',\n phases: [\n { title: 'Lenses' },\n { title: 'Adversarial' },\n { title: 'Synthesize' },\n ],\n}\n\nconst target = args && typeof args === 'object' && args.target\n ? String(args.target)\n : 'No explicit target was provided. Treat the currently focused file or recent context as the target.'\n\nconst LENSES = [\n { name: 'User', angle: 'How a real user experiences this. Friction, confusion, surprise paths, accessibility.' },\n { name: 'Operator', angle: 'How an on-call engineer experiences this in production. Failure modes, observability, rollback.' },\n { name: 'Skeptic', angle: 'Hidden assumptions. What is being implied but not stated. What would break under load or weird input.' },\n { name: 'Maintainer', angle: 'Six-month-later view. Clarity, naming, layering, ease of changing nearby code.' },\n]\n\nphase('Lenses')\nconst lensViews = await parallel(\n LENSES.map((l) => () =>\n agent(\n 'Review the following target through the ' + l.name + ' lens.\\\\n' +\n 'Lens focus: ' + l.angle + '\\\\n\\\\n' +\n 'TARGET:\\\\n' + target + '\\\\n\\\\n' +\n 'Return 3–7 concrete observations. Each entry: title (5–10 words), why-it-matters (1 sentence), risk (low/med/high).',\n {\n label: l.name + ' lens',\n schema: {\n type: 'object',\n properties: {\n observations: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n why: { type: 'string' },\n risk: { type: 'string', enum: ['low', 'med', 'high'] },\n },\n required: ['title', 'why', 'risk'],\n },\n },\n },\n required: ['observations'],\n },\n },\n ),\n ),\n)\n\nphase('Adversarial')\nconst valid = lensViews.filter(Boolean)\nconst allObs = valid.flatMap((v, i) =>\n (v?.observations ?? []).map((o) => ({ lens: LENSES[i].name, ...o })),\n)\n\nconst verdict = await agent(\n 'You are an adversarial judge. Given these multi-lens observations of a target, decide which would actually cause real harm if shipped as-is. ' +\n 'Default to refuted=true unless an observation has clear, mechanism-level evidence.\\\\n\\\\n' +\n JSON.stringify(allObs, null, 2),\n {\n label: 'adversarial verdict',\n schema: {\n type: 'object',\n properties: {\n verdicts: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n lens: { type: 'string' },\n realRisk: { type: 'boolean' },\n reason: { type: 'string' },\n },\n required: ['title', 'lens', 'realRisk', 'reason'],\n },\n },\n },\n required: ['verdicts'],\n },\n },\n)\n\nphase('Synthesize')\nconst confirmed = (verdict?.verdicts ?? []).filter((v) => v.realRisk)\nreturn {\n ok: true,\n target,\n observationCount: allObs.length,\n confirmedRiskCount: confirmed.length,\n topRisks: confirmed.slice(0, 10),\n allVerdicts: verdict?.verdicts ?? [],\n}\n`\n"],"mappings":";;;;;;;;;AASA,MAAa,kCAAkC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Built-in workflow: `research`
3
+ *
4
+ * Multi-modal research sweep on a question (args.question). Fans out search /
5
+ * exploration / source-reading angles in parallel, then synthesises a cited
6
+ * report. Each angle is its own subagent so source reading does not pollute the
7
+ * parent context.
8
+ */
9
+ export declare const RESEARCH_SCRIPT = "export const meta = {\n name: 'research',\n description: 'Multi-angle research on a question with parallel exploration and a cited synthesis.',\n whenToUse: 'User asks a non-trivial research question that benefits from multiple search angles or source reads.',\n phases: [\n { title: 'Frame' },\n { title: 'Sweep' },\n { title: 'Synthesize' },\n ],\n}\n\nconst question = args && typeof args === 'object' && args.question\n ? String(args.question)\n : 'No explicit question supplied; infer from the most recent user turn.'\n\nphase('Frame')\nconst frame = await agent(\n 'Frame this research question. Return 3\u20135 distinct angles worth investigating, plus the single most decisive sub-question for each. Be concrete.\\n\\nQUESTION:\\n' +\n question,\n {\n label: 'framing',\n schema: {\n type: 'object',\n properties: {\n angles: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n key_question: { type: 'string' },\n },\n required: ['title', 'key_question'],\n },\n },\n },\n required: ['angles'],\n },\n },\n)\n\nif (!frame || !frame.angles?.length) {\n return { ok: false, reason: 'framing failed', question }\n}\n\nphase('Sweep')\nconst angleReports = await parallel(\n frame.angles.map((a) => () =>\n agent(\n 'Investigate this angle. Use search and source-read tools liberally. Distinguish what you can confirm from what is conjecture.\\n\\n' +\n 'ANGLE: ' + a.title + '\\n' +\n 'KEY QUESTION: ' + a.key_question + '\\n\\n' +\n 'Return: 3\u20136 grounded findings (each with a 1-line claim and a source URL or file path), plus the strongest counter-evidence.',\n {\n label: a.title,\n schema: {\n type: 'object',\n properties: {\n findings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n claim: { type: 'string' },\n source: { type: 'string' },\n confidence: { type: 'string', enum: ['low', 'med', 'high'] },\n },\n required: ['claim', 'source', 'confidence'],\n },\n },\n counterEvidence: { type: 'string' },\n },\n required: ['findings'],\n },\n },\n ),\n ),\n)\n\nphase('Synthesize')\nconst live = angleReports.filter(Boolean)\nconst synthesis = await agent(\n 'Synthesize a cited research report from these angle-level findings. Drop unsupported or duplicate claims. Use the highest-confidence source per claim. ' +\n 'Return: an executive summary (max 5 sentences), a bullet list of top findings with inline source URLs, and one section listing open questions.\\n\\n' +\n 'QUESTION:\\n' + question + '\\n\\n' +\n JSON.stringify({ angles: frame.angles, reports: live }, null, 2),\n {\n label: 'synthesis',\n schema: {\n type: 'object',\n properties: {\n executiveSummary: { type: 'string' },\n topFindings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n claim: { type: 'string' },\n source: { type: 'string' },\n },\n required: ['claim', 'source'],\n },\n },\n openQuestions: { type: 'array', items: { type: 'string' } },\n },\n required: ['executiveSummary', 'topFindings'],\n },\n },\n)\n\nreturn {\n ok: true,\n question,\n ...(synthesis ?? { executiveSummary: 'synthesis failed', topFindings: [] }),\n}\n";
@@ -0,0 +1,129 @@
1
+ //#region src/agent/workflow/builtins/research.ts
2
+ /**
3
+ * Built-in workflow: `research`
4
+ *
5
+ * Multi-modal research sweep on a question (args.question). Fans out search /
6
+ * exploration / source-reading angles in parallel, then synthesises a cited
7
+ * report. Each angle is its own subagent so source reading does not pollute the
8
+ * parent context.
9
+ */
10
+ const RESEARCH_SCRIPT = `export const meta = {
11
+ name: 'research',
12
+ description: 'Multi-angle research on a question with parallel exploration and a cited synthesis.',
13
+ whenToUse: 'User asks a non-trivial research question that benefits from multiple search angles or source reads.',
14
+ phases: [
15
+ { title: 'Frame' },
16
+ { title: 'Sweep' },
17
+ { title: 'Synthesize' },
18
+ ],
19
+ }
20
+
21
+ const question = args && typeof args === 'object' && args.question
22
+ ? String(args.question)
23
+ : 'No explicit question supplied; infer from the most recent user turn.'
24
+
25
+ phase('Frame')
26
+ const frame = await agent(
27
+ 'Frame this research question. Return 3–5 distinct angles worth investigating, plus the single most decisive sub-question for each. Be concrete.\\n\\nQUESTION:\\n' +
28
+ question,
29
+ {
30
+ label: 'framing',
31
+ schema: {
32
+ type: 'object',
33
+ properties: {
34
+ angles: {
35
+ type: 'array',
36
+ items: {
37
+ type: 'object',
38
+ properties: {
39
+ title: { type: 'string' },
40
+ key_question: { type: 'string' },
41
+ },
42
+ required: ['title', 'key_question'],
43
+ },
44
+ },
45
+ },
46
+ required: ['angles'],
47
+ },
48
+ },
49
+ )
50
+
51
+ if (!frame || !frame.angles?.length) {
52
+ return { ok: false, reason: 'framing failed', question }
53
+ }
54
+
55
+ phase('Sweep')
56
+ const angleReports = await parallel(
57
+ frame.angles.map((a) => () =>
58
+ agent(
59
+ 'Investigate this angle. Use search and source-read tools liberally. Distinguish what you can confirm from what is conjecture.\\n\\n' +
60
+ 'ANGLE: ' + a.title + '\\n' +
61
+ 'KEY QUESTION: ' + a.key_question + '\\n\\n' +
62
+ 'Return: 3–6 grounded findings (each with a 1-line claim and a source URL or file path), plus the strongest counter-evidence.',
63
+ {
64
+ label: a.title,
65
+ schema: {
66
+ type: 'object',
67
+ properties: {
68
+ findings: {
69
+ type: 'array',
70
+ items: {
71
+ type: 'object',
72
+ properties: {
73
+ claim: { type: 'string' },
74
+ source: { type: 'string' },
75
+ confidence: { type: 'string', enum: ['low', 'med', 'high'] },
76
+ },
77
+ required: ['claim', 'source', 'confidence'],
78
+ },
79
+ },
80
+ counterEvidence: { type: 'string' },
81
+ },
82
+ required: ['findings'],
83
+ },
84
+ },
85
+ ),
86
+ ),
87
+ )
88
+
89
+ phase('Synthesize')
90
+ const live = angleReports.filter(Boolean)
91
+ const synthesis = await agent(
92
+ 'Synthesize a cited research report from these angle-level findings. Drop unsupported or duplicate claims. Use the highest-confidence source per claim. ' +
93
+ 'Return: an executive summary (max 5 sentences), a bullet list of top findings with inline source URLs, and one section listing open questions.\\n\\n' +
94
+ 'QUESTION:\\n' + question + '\\n\\n' +
95
+ JSON.stringify({ angles: frame.angles, reports: live }, null, 2),
96
+ {
97
+ label: 'synthesis',
98
+ schema: {
99
+ type: 'object',
100
+ properties: {
101
+ executiveSummary: { type: 'string' },
102
+ topFindings: {
103
+ type: 'array',
104
+ items: {
105
+ type: 'object',
106
+ properties: {
107
+ claim: { type: 'string' },
108
+ source: { type: 'string' },
109
+ },
110
+ required: ['claim', 'source'],
111
+ },
112
+ },
113
+ openQuestions: { type: 'array', items: { type: 'string' } },
114
+ },
115
+ required: ['executiveSummary', 'topFindings'],
116
+ },
117
+ },
118
+ )
119
+
120
+ return {
121
+ ok: true,
122
+ question,
123
+ ...(synthesis ?? { executiveSummary: 'synthesis failed', topFindings: [] }),
124
+ }
125
+ `;
126
+ //#endregion
127
+ export { RESEARCH_SCRIPT };
128
+
129
+ //# sourceMappingURL=research.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research.js","names":[],"sources":["../../../../../src/agent/workflow/builtins/research.ts"],"sourcesContent":["/**\n * Built-in workflow: `research`\n *\n * Multi-modal research sweep on a question (args.question). Fans out search /\n * exploration / source-reading angles in parallel, then synthesises a cited\n * report. Each angle is its own subagent so source reading does not pollute the\n * parent context.\n */\n\nexport const RESEARCH_SCRIPT = `export const meta = {\n name: 'research',\n description: 'Multi-angle research on a question with parallel exploration and a cited synthesis.',\n whenToUse: 'User asks a non-trivial research question that benefits from multiple search angles or source reads.',\n phases: [\n { title: 'Frame' },\n { title: 'Sweep' },\n { title: 'Synthesize' },\n ],\n}\n\nconst question = args && typeof args === 'object' && args.question\n ? String(args.question)\n : 'No explicit question supplied; infer from the most recent user turn.'\n\nphase('Frame')\nconst frame = await agent(\n 'Frame this research question. Return 3–5 distinct angles worth investigating, plus the single most decisive sub-question for each. Be concrete.\\\\n\\\\nQUESTION:\\\\n' +\n question,\n {\n label: 'framing',\n schema: {\n type: 'object',\n properties: {\n angles: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n title: { type: 'string' },\n key_question: { type: 'string' },\n },\n required: ['title', 'key_question'],\n },\n },\n },\n required: ['angles'],\n },\n },\n)\n\nif (!frame || !frame.angles?.length) {\n return { ok: false, reason: 'framing failed', question }\n}\n\nphase('Sweep')\nconst angleReports = await parallel(\n frame.angles.map((a) => () =>\n agent(\n 'Investigate this angle. Use search and source-read tools liberally. Distinguish what you can confirm from what is conjecture.\\\\n\\\\n' +\n 'ANGLE: ' + a.title + '\\\\n' +\n 'KEY QUESTION: ' + a.key_question + '\\\\n\\\\n' +\n 'Return: 3–6 grounded findings (each with a 1-line claim and a source URL or file path), plus the strongest counter-evidence.',\n {\n label: a.title,\n schema: {\n type: 'object',\n properties: {\n findings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n claim: { type: 'string' },\n source: { type: 'string' },\n confidence: { type: 'string', enum: ['low', 'med', 'high'] },\n },\n required: ['claim', 'source', 'confidence'],\n },\n },\n counterEvidence: { type: 'string' },\n },\n required: ['findings'],\n },\n },\n ),\n ),\n)\n\nphase('Synthesize')\nconst live = angleReports.filter(Boolean)\nconst synthesis = await agent(\n 'Synthesize a cited research report from these angle-level findings. Drop unsupported or duplicate claims. Use the highest-confidence source per claim. ' +\n 'Return: an executive summary (max 5 sentences), a bullet list of top findings with inline source URLs, and one section listing open questions.\\\\n\\\\n' +\n 'QUESTION:\\\\n' + question + '\\\\n\\\\n' +\n JSON.stringify({ angles: frame.angles, reports: live }, null, 2),\n {\n label: 'synthesis',\n schema: {\n type: 'object',\n properties: {\n executiveSummary: { type: 'string' },\n topFindings: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n claim: { type: 'string' },\n source: { type: 'string' },\n },\n required: ['claim', 'source'],\n },\n },\n openQuestions: { type: 'array', items: { type: 'string' } },\n },\n required: ['executiveSummary', 'topFindings'],\n },\n },\n)\n\nreturn {\n ok: true,\n question,\n ...(synthesis ?? { executiveSummary: 'synthesis failed', topFindings: [] }),\n}\n`\n"],"mappings":";;;;;;;;;AASA,MAAa,kBAAkB"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Catalog for named workflows.
3
+ *
4
+ * Resolution order (built-ins are starting points, user workflows win):
5
+ * 1. `~/.xopc/workflows/<name>.js` (or `<name>.workflow.js`)
6
+ * 2. {@link BUILTIN_WORKFLOWS}
7
+ *
8
+ * The user dir is discovered via {@link resolveStateDir}, so `XOPC_STATE_DIR`
9
+ * overrides apply automatically (matches how skills / extensions are wired).
10
+ *
11
+ * Listing is filesystem-cheap (single `readdir`) and runs synchronously — the
12
+ * `/workflows` slash command is interactive and should return immediately.
13
+ *
14
+ * Validation: on load we re-parse the script to make sure `meta.name` matches
15
+ * the filename. This prevents copy-pasted scripts from being silently
16
+ * mis-addressed when invoked by name.
17
+ */
18
+ import type { WorkflowMeta } from './types.js';
19
+ export type WorkflowSource = 'user' | 'builtin';
20
+ export interface CatalogEntry {
21
+ name: string;
22
+ source: WorkflowSource;
23
+ /** Absolute path for user entries; null for built-ins (in-memory). */
24
+ path: string | null;
25
+ description: string;
26
+ whenToUse?: string;
27
+ }
28
+ export interface LoadedWorkflow {
29
+ name: string;
30
+ source: WorkflowSource;
31
+ script: string;
32
+ meta: WorkflowMeta;
33
+ path: string | null;
34
+ }
35
+ export interface WorkflowCatalog {
36
+ list(): CatalogEntry[];
37
+ /** Load a named workflow. Throws if missing or meta.name disagrees with filename. */
38
+ load(name: string): LoadedWorkflow;
39
+ /** Save a script as a user workflow. Throws if the script fails to parse. */
40
+ save(name: string, script: string): {
41
+ path: string;
42
+ };
43
+ /** Remove a user workflow. No-op if absent. Built-ins are never removed. */
44
+ remove(name: string): boolean;
45
+ /** Absolute path to the user workflows directory (created lazily on save). */
46
+ userDir: string;
47
+ }
48
+ export declare function createWorkflowCatalog(opts?: {
49
+ userDir?: string;
50
+ }): WorkflowCatalog;
51
+ export declare function defaultUserDir(): string;
@@ -0,0 +1,155 @@
1
+ import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
2
+ import { BUILTIN_WORKFLOWS } from "./builtins/index.js";
3
+ import { parseWorkflowScript } from "./parser.js";
4
+ import { join } from "node:path";
5
+ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
6
+ //#region src/agent/workflow/catalog.ts
7
+ /**
8
+ * Catalog for named workflows.
9
+ *
10
+ * Resolution order (built-ins are starting points, user workflows win):
11
+ * 1. `~/.xopc/workflows/<name>.js` (or `<name>.workflow.js`)
12
+ * 2. {@link BUILTIN_WORKFLOWS}
13
+ *
14
+ * The user dir is discovered via {@link resolveStateDir}, so `XOPC_STATE_DIR`
15
+ * overrides apply automatically (matches how skills / extensions are wired).
16
+ *
17
+ * Listing is filesystem-cheap (single `readdir`) and runs synchronously — the
18
+ * `/workflows` slash command is interactive and should return immediately.
19
+ *
20
+ * Validation: on load we re-parse the script to make sure `meta.name` matches
21
+ * the filename. This prevents copy-pasted scripts from being silently
22
+ * mis-addressed when invoked by name.
23
+ */
24
+ init_paths_state();
25
+ const NAME_RE = /^[a-z][a-z0-9_-]*$/;
26
+ function createWorkflowCatalog(opts = {}) {
27
+ const userDir = opts.userDir ?? defaultUserDir();
28
+ const list = () => {
29
+ const entries = /* @__PURE__ */ new Map();
30
+ for (const b of BUILTIN_WORKFLOWS) {
31
+ const meta = safeMeta(b.script);
32
+ entries.set(b.name, {
33
+ name: b.name,
34
+ source: "builtin",
35
+ path: null,
36
+ description: meta?.description ?? "(unparseable)",
37
+ whenToUse: meta?.whenToUse
38
+ });
39
+ }
40
+ for (const file of safeListUserFiles(userDir)) {
41
+ const name = stripExt(file);
42
+ if (!isValidName(name)) continue;
43
+ const full = join(userDir, file);
44
+ const meta = safeMeta(readScript(full));
45
+ entries.set(name, {
46
+ name,
47
+ source: "user",
48
+ path: full,
49
+ description: meta?.description ?? "(unparseable)",
50
+ whenToUse: meta?.whenToUse
51
+ });
52
+ }
53
+ return [...entries.values()].sort((a, b) => a.name.localeCompare(b.name));
54
+ };
55
+ const load = (name) => {
56
+ requireValidName(name);
57
+ const userPath = findUserPath(userDir, name);
58
+ if (userPath) {
59
+ const script = readScript(userPath);
60
+ const { meta } = parseWorkflowScript(script);
61
+ ensureMetaNameMatches(meta, name, userPath);
62
+ return {
63
+ name,
64
+ source: "user",
65
+ script,
66
+ meta,
67
+ path: userPath
68
+ };
69
+ }
70
+ const builtin = BUILTIN_WORKFLOWS.find((b) => b.name === name);
71
+ if (builtin) {
72
+ const { meta } = parseWorkflowScript(builtin.script);
73
+ ensureMetaNameMatches(meta, name, "<builtin>");
74
+ return {
75
+ name,
76
+ source: "builtin",
77
+ script: builtin.script,
78
+ meta,
79
+ path: null
80
+ };
81
+ }
82
+ throw new Error(`workflow not found: ${name}. Drop a script at ${join(userDir, `${name}.js`)} or pick one of: ${list().map((e) => e.name).join(", ")}`);
83
+ };
84
+ const save = (name, script) => {
85
+ requireValidName(name);
86
+ const { meta } = parseWorkflowScript(script);
87
+ if (meta.name !== name) throw new Error(`meta.name "${meta.name}" does not match save name "${name}". Adjust one to match the other.`);
88
+ if (!existsSync(userDir)) mkdirSync(userDir, { recursive: true });
89
+ const path = join(userDir, `${name}.js`);
90
+ writeFileSync(path, normalizeNewlines(script), "utf-8");
91
+ return { path };
92
+ };
93
+ const remove = (name) => {
94
+ requireValidName(name);
95
+ const userPath = findUserPath(userDir, name);
96
+ if (!userPath) return false;
97
+ unlinkSync(userPath);
98
+ return true;
99
+ };
100
+ return {
101
+ list,
102
+ load,
103
+ save,
104
+ remove,
105
+ userDir
106
+ };
107
+ }
108
+ function defaultUserDir() {
109
+ return join(resolveStateDir(), "workflows");
110
+ }
111
+ function safeListUserFiles(dir) {
112
+ try {
113
+ if (!existsSync(dir)) return [];
114
+ if (!statSync(dir).isDirectory()) return [];
115
+ return readdirSync(dir).filter((f) => /\.(js|workflow\.js)$/i.test(f));
116
+ } catch {
117
+ return [];
118
+ }
119
+ }
120
+ function findUserPath(dir, name) {
121
+ for (const candidate of [`${name}.js`, `${name}.workflow.js`]) {
122
+ const full = join(dir, candidate);
123
+ if (existsSync(full)) return full;
124
+ }
125
+ return null;
126
+ }
127
+ function readScript(path) {
128
+ return readFileSync(path, "utf-8");
129
+ }
130
+ function safeMeta(script) {
131
+ try {
132
+ return parseWorkflowScript(script).meta;
133
+ } catch {
134
+ return null;
135
+ }
136
+ }
137
+ function stripExt(filename) {
138
+ return filename.replace(/\.workflow\.js$/i, "").replace(/\.js$/i, "");
139
+ }
140
+ function isValidName(name) {
141
+ return NAME_RE.test(name);
142
+ }
143
+ function requireValidName(name) {
144
+ if (!isValidName(name)) throw new Error(`invalid workflow name "${name}". Use lowercase snake_case, e.g. "audit_repo".`);
145
+ }
146
+ function ensureMetaNameMatches(meta, name, locator) {
147
+ if (meta.name !== name) throw new Error(`workflow ${locator}: meta.name "${meta.name}" disagrees with addressable name "${name}". Rename the file or the meta.name to match.`);
148
+ }
149
+ function normalizeNewlines(s) {
150
+ return s.endsWith("\n") ? s : `${s}\n`;
151
+ }
152
+ //#endregion
153
+ export { createWorkflowCatalog, defaultUserDir };
154
+
155
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","names":[],"sources":["../../../../src/agent/workflow/catalog.ts"],"sourcesContent":["/**\n * Catalog for named workflows.\n *\n * Resolution order (built-ins are starting points, user workflows win):\n * 1. `~/.xopc/workflows/<name>.js` (or `<name>.workflow.js`)\n * 2. {@link BUILTIN_WORKFLOWS}\n *\n * The user dir is discovered via {@link resolveStateDir}, so `XOPC_STATE_DIR`\n * overrides apply automatically (matches how skills / extensions are wired).\n *\n * Listing is filesystem-cheap (single `readdir`) and runs synchronously — the\n * `/workflows` slash command is interactive and should return immediately.\n *\n * Validation: on load we re-parse the script to make sure `meta.name` matches\n * the filename. This prevents copy-pasted scripts from being silently\n * mis-addressed when invoked by name.\n */\n\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { join } from 'node:path';\n\nimport { resolveStateDir } from '../../config/paths-state.js';\n\nimport { BUILTIN_WORKFLOWS } from './builtins/index.js';\nimport { parseWorkflowScript } from './parser.js';\nimport type { WorkflowMeta } from './types.js';\n\nexport type WorkflowSource = 'user' | 'builtin';\n\nexport interface CatalogEntry {\n name: string;\n source: WorkflowSource;\n /** Absolute path for user entries; null for built-ins (in-memory). */\n path: string | null;\n description: string;\n whenToUse?: string;\n}\n\nexport interface LoadedWorkflow {\n name: string;\n source: WorkflowSource;\n script: string;\n meta: WorkflowMeta;\n path: string | null;\n}\n\nexport interface WorkflowCatalog {\n list(): CatalogEntry[];\n /** Load a named workflow. Throws if missing or meta.name disagrees with filename. */\n load(name: string): LoadedWorkflow;\n /** Save a script as a user workflow. Throws if the script fails to parse. */\n save(name: string, script: string): { path: string };\n /** Remove a user workflow. No-op if absent. Built-ins are never removed. */\n remove(name: string): boolean;\n /** Absolute path to the user workflows directory (created lazily on save). */\n userDir: string;\n}\n\nconst NAME_RE = /^[a-z][a-z0-9_-]*$/;\n\nexport function createWorkflowCatalog(opts: { userDir?: string } = {}): WorkflowCatalog {\n const userDir = opts.userDir ?? defaultUserDir();\n\n const list = (): CatalogEntry[] => {\n const entries = new Map<string, CatalogEntry>();\n for (const b of BUILTIN_WORKFLOWS) {\n const meta = safeMeta(b.script);\n entries.set(b.name, {\n name: b.name,\n source: 'builtin',\n path: null,\n description: meta?.description ?? '(unparseable)',\n whenToUse: meta?.whenToUse,\n });\n }\n for (const file of safeListUserFiles(userDir)) {\n const name = stripExt(file);\n if (!isValidName(name)) continue;\n const full = join(userDir, file);\n const meta = safeMeta(readScript(full));\n // User wins on collision.\n entries.set(name, {\n name,\n source: 'user',\n path: full,\n description: meta?.description ?? '(unparseable)',\n whenToUse: meta?.whenToUse,\n });\n }\n return [...entries.values()].sort((a, b) => a.name.localeCompare(b.name));\n };\n\n const load = (name: string): LoadedWorkflow => {\n requireValidName(name);\n const userPath = findUserPath(userDir, name);\n if (userPath) {\n const script = readScript(userPath);\n const { meta } = parseWorkflowScript(script);\n ensureMetaNameMatches(meta, name, userPath);\n return { name, source: 'user', script, meta, path: userPath };\n }\n const builtin = BUILTIN_WORKFLOWS.find((b) => b.name === name);\n if (builtin) {\n const { meta } = parseWorkflowScript(builtin.script);\n ensureMetaNameMatches(meta, name, '<builtin>');\n return { name, source: 'builtin', script: builtin.script, meta, path: null };\n }\n throw new Error(\n `workflow not found: ${name}. Drop a script at ${join(userDir, `${name}.js`)} or pick one of: ${list()\n .map((e) => e.name)\n .join(', ')}`,\n );\n };\n\n const save = (name: string, script: string): { path: string } => {\n requireValidName(name);\n const { meta } = parseWorkflowScript(script);\n if (meta.name !== name) {\n throw new Error(\n `meta.name \"${meta.name}\" does not match save name \"${name}\". Adjust one to match the other.`,\n );\n }\n if (!existsSync(userDir)) {\n mkdirSync(userDir, { recursive: true });\n }\n const path = join(userDir, `${name}.js`);\n writeFileSync(path, normalizeNewlines(script), 'utf-8');\n return { path };\n };\n\n const remove = (name: string): boolean => {\n requireValidName(name);\n const userPath = findUserPath(userDir, name);\n if (!userPath) return false;\n unlinkSync(userPath);\n return true;\n };\n\n return { list, load, save, remove, userDir };\n}\n\n// ---------------------------------------------------------------------------\n\nexport function defaultUserDir(): string {\n return join(resolveStateDir(), 'workflows');\n}\n\nfunction safeListUserFiles(dir: string): string[] {\n try {\n if (!existsSync(dir)) return [];\n const st = statSync(dir);\n if (!st.isDirectory()) return [];\n return readdirSync(dir).filter((f) => /\\.(js|workflow\\.js)$/i.test(f));\n } catch {\n return [];\n }\n}\n\nfunction findUserPath(dir: string, name: string): string | null {\n for (const candidate of [`${name}.js`, `${name}.workflow.js`]) {\n const full = join(dir, candidate);\n if (existsSync(full)) return full;\n }\n return null;\n}\n\nfunction readScript(path: string): string {\n return readFileSync(path, 'utf-8');\n}\n\nfunction safeMeta(script: string): WorkflowMeta | null {\n try {\n return parseWorkflowScript(script).meta;\n } catch {\n return null;\n }\n}\n\nfunction stripExt(filename: string): string {\n return filename.replace(/\\.workflow\\.js$/i, '').replace(/\\.js$/i, '');\n}\n\nfunction isValidName(name: string): boolean {\n return NAME_RE.test(name);\n}\n\nfunction requireValidName(name: string): void {\n if (!isValidName(name)) {\n throw new Error(`invalid workflow name \"${name}\". Use lowercase snake_case, e.g. \"audit_repo\".`);\n }\n}\n\nfunction ensureMetaNameMatches(meta: WorkflowMeta, name: string, locator: string): void {\n if (meta.name !== name) {\n throw new Error(\n `workflow ${locator}: meta.name \"${meta.name}\" disagrees with addressable name \"${name}\". ` +\n 'Rename the file or the meta.name to match.',\n );\n }\n}\n\nfunction normalizeNewlines(s: string): string {\n return s.endsWith('\\n') ? s : `${s}\\n`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;kBA6B8D;AAqC9D,MAAM,UAAU;AAEhB,SAAgB,sBAAsB,OAA6B,EAAE,EAAmB;CACtF,MAAM,UAAU,KAAK,WAAW,gBAAgB;CAEhD,MAAM,aAA6B;EACjC,MAAM,0BAAU,IAAI,KAA2B;AAC/C,OAAK,MAAM,KAAK,mBAAmB;GACjC,MAAM,OAAO,SAAS,EAAE,OAAO;AAC/B,WAAQ,IAAI,EAAE,MAAM;IAClB,MAAM,EAAE;IACR,QAAQ;IACR,MAAM;IACN,aAAa,MAAM,eAAe;IAClC,WAAW,MAAM;IAClB,CAAC;;AAEJ,OAAK,MAAM,QAAQ,kBAAkB,QAAQ,EAAE;GAC7C,MAAM,OAAO,SAAS,KAAK;AAC3B,OAAI,CAAC,YAAY,KAAK,CAAE;GACxB,MAAM,OAAO,KAAK,SAAS,KAAK;GAChC,MAAM,OAAO,SAAS,WAAW,KAAK,CAAC;AAEvC,WAAQ,IAAI,MAAM;IAChB;IACA,QAAQ;IACR,MAAM;IACN,aAAa,MAAM,eAAe;IAClC,WAAW,MAAM;IAClB,CAAC;;AAEJ,SAAO,CAAC,GAAG,QAAQ,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;;CAG3E,MAAM,QAAQ,SAAiC;AAC7C,mBAAiB,KAAK;EACtB,MAAM,WAAW,aAAa,SAAS,KAAK;AAC5C,MAAI,UAAU;GACZ,MAAM,SAAS,WAAW,SAAS;GACnC,MAAM,EAAE,SAAS,oBAAoB,OAAO;AAC5C,yBAAsB,MAAM,MAAM,SAAS;AAC3C,UAAO;IAAE;IAAM,QAAQ;IAAQ;IAAQ;IAAM,MAAM;IAAU;;EAE/D,MAAM,UAAU,kBAAkB,MAAM,MAAM,EAAE,SAAS,KAAK;AAC9D,MAAI,SAAS;GACX,MAAM,EAAE,SAAS,oBAAoB,QAAQ,OAAO;AACpD,yBAAsB,MAAM,MAAM,YAAY;AAC9C,UAAO;IAAE;IAAM,QAAQ;IAAW,QAAQ,QAAQ;IAAQ;IAAM,MAAM;IAAM;;AAE9E,QAAM,IAAI,MACR,uBAAuB,KAAK,qBAAqB,KAAK,SAAS,GAAG,KAAK,KAAK,CAAC,mBAAmB,MAAM,CACnG,KAAK,MAAM,EAAE,KAAK,CAClB,KAAK,KAAK,GACd;;CAGH,MAAM,QAAQ,MAAc,WAAqC;AAC/D,mBAAiB,KAAK;EACtB,MAAM,EAAE,SAAS,oBAAoB,OAAO;AAC5C,MAAI,KAAK,SAAS,KAChB,OAAM,IAAI,MACR,cAAc,KAAK,KAAK,8BAA8B,KAAK,mCAC5D;AAEH,MAAI,CAAC,WAAW,QAAQ,CACtB,WAAU,SAAS,EAAE,WAAW,MAAM,CAAC;EAEzC,MAAM,OAAO,KAAK,SAAS,GAAG,KAAK,KAAK;AACxC,gBAAc,MAAM,kBAAkB,OAAO,EAAE,QAAQ;AACvD,SAAO,EAAE,MAAM;;CAGjB,MAAM,UAAU,SAA0B;AACxC,mBAAiB,KAAK;EACtB,MAAM,WAAW,aAAa,SAAS,KAAK;AAC5C,MAAI,CAAC,SAAU,QAAO;AACtB,aAAW,SAAS;AACpB,SAAO;;AAGT,QAAO;EAAE;EAAM;EAAM;EAAM;EAAQ;EAAS;;AAK9C,SAAgB,iBAAyB;AACvC,QAAO,KAAK,iBAAiB,EAAE,YAAY;;AAG7C,SAAS,kBAAkB,KAAuB;AAChD,KAAI;AACF,MAAI,CAAC,WAAW,IAAI,CAAE,QAAO,EAAE;AAE/B,MAAI,CADO,SAAS,IACb,CAAC,aAAa,CAAE,QAAO,EAAE;AAChC,SAAO,YAAY,IAAI,CAAC,QAAQ,MAAM,wBAAwB,KAAK,EAAE,CAAC;SAChE;AACN,SAAO,EAAE;;;AAIb,SAAS,aAAa,KAAa,MAA6B;AAC9D,MAAK,MAAM,aAAa,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,cAAc,EAAE;EAC7D,MAAM,OAAO,KAAK,KAAK,UAAU;AACjC,MAAI,WAAW,KAAK,CAAE,QAAO;;AAE/B,QAAO;;AAGT,SAAS,WAAW,MAAsB;AACxC,QAAO,aAAa,MAAM,QAAQ;;AAGpC,SAAS,SAAS,QAAqC;AACrD,KAAI;AACF,SAAO,oBAAoB,OAAO,CAAC;SAC7B;AACN,SAAO;;;AAIX,SAAS,SAAS,UAA0B;AAC1C,QAAO,SAAS,QAAQ,oBAAoB,GAAG,CAAC,QAAQ,UAAU,GAAG;;AAGvE,SAAS,YAAY,MAAuB;AAC1C,QAAO,QAAQ,KAAK,KAAK;;AAG3B,SAAS,iBAAiB,MAAoB;AAC5C,KAAI,CAAC,YAAY,KAAK,CACpB,OAAM,IAAI,MAAM,0BAA0B,KAAK,iDAAiD;;AAIpG,SAAS,sBAAsB,MAAoB,MAAc,SAAuB;AACtF,KAAI,KAAK,SAAS,KAChB,OAAM,IAAI,MACR,YAAY,QAAQ,eAAe,KAAK,KAAK,qCAAqC,KAAK,+CAExF;;AAIL,SAAS,kBAAkB,GAAmB;AAC5C,QAAO,EAAE,SAAS,KAAK,GAAG,IAAI,GAAG,EAAE"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Channel-side contract used by {@link WorkflowProgressBroker} to deliver
3
+ * workflow progress to a specific messaging surface (Telegram, Feishu, …).
4
+ *
5
+ * Why a capability instead of a hook on `ChannelPlugin`?
6
+ * - Optional opt-in: channels register themselves at boot; no plugin
7
+ * changes for surfaces that don't ship progress (e.g. SMS).
8
+ * - Per-channel sane defaults baked in (throttle, mode) — the broker
9
+ * reads these and lets `channels.<id>.workflowProgress` in config
10
+ * override per deployment.
11
+ * - Decouples the broker from the {@link ChannelPlugin} interface so
12
+ * adding new channels never grows broker imports.
13
+ */
14
+ export type WorkflowProgressMode =
15
+ /** Edit a single message in place (Telegram, Feishu). */
16
+ 'edit'
17
+ /** Append a new message on each key event (WeChat — can't edit). */
18
+ | 'append'
19
+ /** No mid-run updates; final-only message at completion. */
20
+ | 'final-only';
21
+ export interface WorkflowProgressPostInput {
22
+ /** Routing key for the run — channel uses it to resolve the destination chat. */
23
+ sessionKey: string;
24
+ /** Pre-rendered progress text (already includes header / phases / logs). */
25
+ text: string;
26
+ /**
27
+ * Message id returned by the previous `postProgress` for the same run, when
28
+ * editing in place. `undefined` for the first message of a run, or always
29
+ * for `append` / `final-only` modes.
30
+ */
31
+ previousMessageId?: string;
32
+ /**
33
+ * `true` for the final completion message (sent right after `tool_end`).
34
+ * Useful for channels that want to bypass their own rate limiting for the
35
+ * last update (so users always see the conclusion).
36
+ */
37
+ isFinal: boolean;
38
+ /**
39
+ * The effective rendering mode for this dispatch — broker resolves it from
40
+ * the capability's `defaultMode` plus any `channels.<id>.workflowProgress.mode`
41
+ * override. Capabilities can use this to adjust message shape (e.g. WeChat
42
+ * prefixes mid-run `append` messages with "▾ progress" so the user can tell
43
+ * them apart from the final summary).
44
+ *
45
+ * Optional for backwards compatibility with hand-rolled callers and unit
46
+ * tests; the broker always provides it. Capabilities that consume the field
47
+ * should default to `'edit'` when missing.
48
+ */
49
+ mode?: WorkflowProgressMode;
50
+ }
51
+ export interface WorkflowProgressPostResult {
52
+ /** New / unchanged message id to use as `previousMessageId` next time. */
53
+ messageId: string;
54
+ }
55
+ export interface ChannelProgressCapability {
56
+ /** Stable channel id matching `channels.<id>` in config (e.g. `telegram`). */
57
+ readonly channelId: string;
58
+ /** True when the underlying platform exposes editMessage semantics. */
59
+ readonly supportsEdit: boolean;
60
+ /** Sane default throttle (ms) for this surface; respects platform limits. */
61
+ readonly defaultThrottleMs: number;
62
+ /** Sane default mode for this surface. */
63
+ readonly defaultMode: WorkflowProgressMode;
64
+ /**
65
+ * Deliver one progress update.
66
+ *
67
+ * Capability is responsible for:
68
+ * - Resolving `sessionKey` → platform chat/thread id (channel-specific).
69
+ * - Encoding the text payload (markdown / plain / HTML, line breaks).
70
+ * - Calling editMessageText vs sendMessage based on `previousMessageId`.
71
+ * - Honouring platform rate limits (429 retry-after, etc.).
72
+ *
73
+ * Throw on hard failure; the broker logs and drops the update.
74
+ */
75
+ postProgress(input: WorkflowProgressPostInput): Promise<WorkflowProgressPostResult>;
76
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ export { BUILTIN_WORKFLOWS, type BuiltinWorkflow } from './builtins/index.js';
2
+ export { createWorkflowCatalog, defaultUserDir, type CatalogEntry, type LoadedWorkflow, type WorkflowCatalog, type WorkflowSource, } from './catalog.js';
3
+ export { getLastWorkflowMemory, _resetLastWorkflowMemoryForTests, type LastWorkflowEntry, type LastWorkflowMemory, } from './last-run-memory.js';
4
+ export type { ChannelProgressCapability, WorkflowProgressMode, WorkflowProgressPostInput, WorkflowProgressPostResult, } from './channel-capability.js';
5
+ export { parseWorkflowScript, type ParsedWorkflow } from './parser.js';
6
+ export { WorkflowProgressBroker, getWorkflowProgressBroker, _resetWorkflowProgressBrokerForTests, type BrokerListenerHandle, type SessionBusLike, } from './progress-broker.js';
7
+ export { emptySnapshotFor, runWorkflow, type RunWorkflowDeps, } from './runtime.js';
8
+ export { createWorkflowSnapshot, previewValue, recomputeCounts, renderWorkflowText, type RenderOptions, } from './snapshot.js';
9
+ export { createStructuredOutputTool, STRUCTURED_OUTPUT_TOOL_NAME, type CreateStructuredOutputToolOptions, type StructuredOutputCapture, } from './structured-output-tool.js';
10
+ export { DelegateSubagentRunner, type DelegateSubagentRunnerDeps, } from './subagent-runner.js';
11
+ export type { AgentScriptOptions, JsonSchema, SubagentRunner, SubagentRunOptions, WorkflowAgentSnapshot, WorkflowAgentStatus, WorkflowMeta, WorkflowMetaPhase, WorkflowRunOptions, WorkflowRunResult, WorkflowSnapshot, } from './types.js';
@@ -0,0 +1,10 @@
1
+ import { BUILTIN_WORKFLOWS } from "./builtins/index.js";
2
+ import { parseWorkflowScript } from "./parser.js";
3
+ import { createWorkflowCatalog, defaultUserDir } from "./catalog.js";
4
+ import { _resetLastWorkflowMemoryForTests, getLastWorkflowMemory } from "./last-run-memory.js";
5
+ import { createWorkflowSnapshot, previewValue, recomputeCounts, renderWorkflowText } from "./snapshot.js";
6
+ import { WorkflowProgressBroker, _resetWorkflowProgressBrokerForTests, getWorkflowProgressBroker } from "./progress-broker.js";
7
+ import { emptySnapshotFor, runWorkflow } from "./runtime.js";
8
+ import { STRUCTURED_OUTPUT_TOOL_NAME, createStructuredOutputTool } from "./structured-output-tool.js";
9
+ import { DelegateSubagentRunner } from "./subagent-runner.js";
10
+ export { BUILTIN_WORKFLOWS, DelegateSubagentRunner, STRUCTURED_OUTPUT_TOOL_NAME, WorkflowProgressBroker, _resetLastWorkflowMemoryForTests, _resetWorkflowProgressBrokerForTests, createStructuredOutputTool, createWorkflowCatalog, createWorkflowSnapshot, defaultUserDir, emptySnapshotFor, getLastWorkflowMemory, getWorkflowProgressBroker, parseWorkflowScript, previewValue, recomputeCounts, renderWorkflowText, runWorkflow };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Per-session memory of the most recent workflow script that ran successfully.
3
+ *
4
+ * Purpose: enable `/workflow save <name>` — the user sees a workflow run,
5
+ * likes it, types `/workflow save audit_repo_strict`, and the model-generated
6
+ * script lands in `~/.xopc/workflows/`.
7
+ *
8
+ * Scope decision (KISS):
9
+ * - In-memory only, keyed by sessionKey. Cleared on process restart. OPC is
10
+ * long-lived per session, so the practical window is "from when the user
11
+ * ran the workflow until they save it" — minutes, not days. Persisting
12
+ * across restarts would require either session-store coupling or a separate
13
+ * sidecar file, both bigger than the value.
14
+ * - Records on EVERY successful workflow tool execution, including runs by
15
+ * name (so users can re-save a slightly modified built-in too).
16
+ * - Bounded by a small LRU so a runaway never grows the heap.
17
+ */
18
+ export interface LastWorkflowEntry {
19
+ /** Raw workflow script as the runtime saw it (post-fence-strip, pre-parse). */
20
+ script: string;
21
+ /** meta.name from the script (used to default a save target). */
22
+ metaName: string;
23
+ /** Where the script came from on this run — for save-time UX hints. */
24
+ source: 'name' | 'script';
25
+ /** ms since epoch when recorded — UI uses this for "ran 2 min ago". */
26
+ recordedAt: number;
27
+ }
28
+ declare class LastWorkflowMemoryImpl {
29
+ private readonly maxEntries;
30
+ private readonly entries;
31
+ constructor(maxEntries?: number);
32
+ record(sessionKey: string | undefined, entry: LastWorkflowEntry): void;
33
+ get(sessionKey: string | undefined): LastWorkflowEntry | undefined;
34
+ clear(sessionKey?: string): void;
35
+ /** Visible for tests; do not consume from production code. */
36
+ _size(): number;
37
+ }
38
+ export type LastWorkflowMemory = LastWorkflowMemoryImpl;
39
+ export declare function getLastWorkflowMemory(): LastWorkflowMemoryImpl;
40
+ /** Reset the singleton (tests only). */
41
+ export declare function _resetLastWorkflowMemoryForTests(): void;
42
+ export {};
@@ -0,0 +1,60 @@
1
+ //#region src/agent/workflow/last-run-memory.ts
2
+ /**
3
+ * Per-session memory of the most recent workflow script that ran successfully.
4
+ *
5
+ * Purpose: enable `/workflow save <name>` — the user sees a workflow run,
6
+ * likes it, types `/workflow save audit_repo_strict`, and the model-generated
7
+ * script lands in `~/.xopc/workflows/`.
8
+ *
9
+ * Scope decision (KISS):
10
+ * - In-memory only, keyed by sessionKey. Cleared on process restart. OPC is
11
+ * long-lived per session, so the practical window is "from when the user
12
+ * ran the workflow until they save it" — minutes, not days. Persisting
13
+ * across restarts would require either session-store coupling or a separate
14
+ * sidecar file, both bigger than the value.
15
+ * - Records on EVERY successful workflow tool execution, including runs by
16
+ * name (so users can re-save a slightly modified built-in too).
17
+ * - Bounded by a small LRU so a runaway never grows the heap.
18
+ */
19
+ const DEFAULT_MAX_ENTRIES = 64;
20
+ var LastWorkflowMemoryImpl = class {
21
+ entries = /* @__PURE__ */ new Map();
22
+ constructor(maxEntries = DEFAULT_MAX_ENTRIES) {
23
+ this.maxEntries = maxEntries;
24
+ }
25
+ record(sessionKey, entry) {
26
+ if (!sessionKey) return;
27
+ if (this.entries.has(sessionKey)) this.entries.delete(sessionKey);
28
+ this.entries.set(sessionKey, entry);
29
+ while (this.entries.size > this.maxEntries) {
30
+ const oldestKey = this.entries.keys().next().value;
31
+ if (oldestKey === void 0) break;
32
+ this.entries.delete(oldestKey);
33
+ }
34
+ }
35
+ get(sessionKey) {
36
+ if (!sessionKey) return void 0;
37
+ return this.entries.get(sessionKey);
38
+ }
39
+ clear(sessionKey) {
40
+ if (sessionKey === void 0) this.entries.clear();
41
+ else this.entries.delete(sessionKey);
42
+ }
43
+ /** Visible for tests; do not consume from production code. */
44
+ _size() {
45
+ return this.entries.size;
46
+ }
47
+ };
48
+ let singleton = null;
49
+ function getLastWorkflowMemory() {
50
+ if (!singleton) singleton = new LastWorkflowMemoryImpl();
51
+ return singleton;
52
+ }
53
+ /** Reset the singleton (tests only). */
54
+ function _resetLastWorkflowMemoryForTests() {
55
+ singleton = null;
56
+ }
57
+ //#endregion
58
+ export { _resetLastWorkflowMemoryForTests, getLastWorkflowMemory };
59
+
60
+ //# sourceMappingURL=last-run-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"last-run-memory.js","names":[],"sources":["../../../../src/agent/workflow/last-run-memory.ts"],"sourcesContent":["/**\n * Per-session memory of the most recent workflow script that ran successfully.\n *\n * Purpose: enable `/workflow save <name>` — the user sees a workflow run,\n * likes it, types `/workflow save audit_repo_strict`, and the model-generated\n * script lands in `~/.xopc/workflows/`.\n *\n * Scope decision (KISS):\n * - In-memory only, keyed by sessionKey. Cleared on process restart. OPC is\n * long-lived per session, so the practical window is \"from when the user\n * ran the workflow until they save it\" — minutes, not days. Persisting\n * across restarts would require either session-store coupling or a separate\n * sidecar file, both bigger than the value.\n * - Records on EVERY successful workflow tool execution, including runs by\n * name (so users can re-save a slightly modified built-in too).\n * - Bounded by a small LRU so a runaway never grows the heap.\n */\n\nconst DEFAULT_MAX_ENTRIES = 64;\n\nexport interface LastWorkflowEntry {\n /** Raw workflow script as the runtime saw it (post-fence-strip, pre-parse). */\n script: string;\n /** meta.name from the script (used to default a save target). */\n metaName: string;\n /** Where the script came from on this run — for save-time UX hints. */\n source: 'name' | 'script';\n /** ms since epoch when recorded — UI uses this for \"ran 2 min ago\". */\n recordedAt: number;\n}\n\nclass LastWorkflowMemoryImpl {\n private readonly entries = new Map<string, LastWorkflowEntry>();\n\n constructor(private readonly maxEntries: number = DEFAULT_MAX_ENTRIES) {}\n\n record(sessionKey: string | undefined, entry: LastWorkflowEntry): void {\n if (!sessionKey) return;\n // Move-to-end semantics: delete then set so iteration order = LRU.\n if (this.entries.has(sessionKey)) this.entries.delete(sessionKey);\n this.entries.set(sessionKey, entry);\n while (this.entries.size > this.maxEntries) {\n const oldestKey = this.entries.keys().next().value;\n if (oldestKey === undefined) break;\n this.entries.delete(oldestKey);\n }\n }\n\n get(sessionKey: string | undefined): LastWorkflowEntry | undefined {\n if (!sessionKey) return undefined;\n return this.entries.get(sessionKey);\n }\n\n clear(sessionKey?: string): void {\n if (sessionKey === undefined) this.entries.clear();\n else this.entries.delete(sessionKey);\n }\n\n /** Visible for tests; do not consume from production code. */\n _size(): number {\n return this.entries.size;\n }\n}\n\nexport type LastWorkflowMemory = LastWorkflowMemoryImpl;\n\nlet singleton: LastWorkflowMemoryImpl | null = null;\n\nexport function getLastWorkflowMemory(): LastWorkflowMemoryImpl {\n if (!singleton) singleton = new LastWorkflowMemoryImpl();\n return singleton;\n}\n\n/** Reset the singleton (tests only). */\nexport function _resetLastWorkflowMemoryForTests(): void {\n singleton = null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,MAAM,sBAAsB;AAa5B,IAAM,yBAAN,MAA6B;CAC3B,0BAA2B,IAAI,KAAgC;CAE/D,YAAY,aAAsC,qBAAqB;AAA1C,OAAA,aAAA;;CAE7B,OAAO,YAAgC,OAAgC;AACrE,MAAI,CAAC,WAAY;AAEjB,MAAI,KAAK,QAAQ,IAAI,WAAW,CAAE,MAAK,QAAQ,OAAO,WAAW;AACjE,OAAK,QAAQ,IAAI,YAAY,MAAM;AACnC,SAAO,KAAK,QAAQ,OAAO,KAAK,YAAY;GAC1C,MAAM,YAAY,KAAK,QAAQ,MAAM,CAAC,MAAM,CAAC;AAC7C,OAAI,cAAc,KAAA,EAAW;AAC7B,QAAK,QAAQ,OAAO,UAAU;;;CAIlC,IAAI,YAA+D;AACjE,MAAI,CAAC,WAAY,QAAO,KAAA;AACxB,SAAO,KAAK,QAAQ,IAAI,WAAW;;CAGrC,MAAM,YAA2B;AAC/B,MAAI,eAAe,KAAA,EAAW,MAAK,QAAQ,OAAO;MAC7C,MAAK,QAAQ,OAAO,WAAW;;;CAItC,QAAgB;AACd,SAAO,KAAK,QAAQ;;;AAMxB,IAAI,YAA2C;AAE/C,SAAgB,wBAAgD;AAC9D,KAAI,CAAC,UAAW,aAAY,IAAI,wBAAwB;AACxD,QAAO;;;AAIT,SAAgB,mCAAyC;AACvD,aAAY"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Workflow script parser.
3
+ *
4
+ * Responsibilities:
5
+ * 1. Parse the script with acorn (latest ECMA, top-level await + return allowed).
6
+ * 2. Enforce determinism — reject `Date.now()`, `Math.random()`, `new Date()`,
7
+ * `require`, `import`, dynamic eval. This keeps future resume/replay possible
8
+ * and surfaces non-deterministic mistakes early.
9
+ * 3. Require the first statement to be `export const meta = <literal>`, validate
10
+ * the literal shape, and strip that line from the body returned to the runtime.
11
+ *
12
+ * Returning a `{ meta, body }` pair means the runtime can `vm.Script(body)` without
13
+ * any further AST work.
14
+ */
15
+ import type { WorkflowMeta } from './types.js';
16
+ export interface ParsedWorkflow {
17
+ meta: WorkflowMeta;
18
+ body: string;
19
+ }
20
+ export declare function parseWorkflowScript(script: string): ParsedWorkflow;