@xopcai/xopc 0.0.109 → 0.0.111

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 (346) hide show
  1. package/README.md +46 -4
  2. package/README.zh-CN.md +46 -4
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/pairing-config-resolver.d.ts +1 -0
  5. package/dist/extensions/feishu/src/pairing-config-resolver.js +30 -0
  6. package/dist/extensions/feishu/src/pairing-config-resolver.js.map +1 -0
  7. package/dist/extensions/feishu/src/plugin.d.ts +1 -0
  8. package/dist/extensions/feishu/src/plugin.js +1 -0
  9. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  10. package/dist/extensions/telegram/src/access-control.d.ts +2 -1
  11. package/dist/extensions/telegram/src/access-control.js.map +1 -1
  12. package/dist/extensions/telegram/src/account-manager.d.ts +2 -1
  13. package/dist/extensions/telegram/src/account-manager.js.map +1 -1
  14. package/dist/extensions/telegram/src/adapters/gateway-setup.js +26 -26
  15. package/dist/extensions/telegram/src/adapters/gateway-setup.js.map +1 -1
  16. package/dist/extensions/telegram/src/adapters/onboard-cli.js +8 -4
  17. package/dist/extensions/telegram/src/adapters/onboard-cli.js.map +1 -1
  18. package/dist/extensions/telegram/src/config-schema.d.ts +88 -50
  19. package/dist/extensions/telegram/src/config-schema.js +40 -32
  20. package/dist/extensions/telegram/src/config-schema.js.map +1 -1
  21. package/dist/extensions/telegram/src/config-types.d.ts +54 -0
  22. package/dist/extensions/telegram/src/config-types.js +1 -0
  23. package/dist/extensions/telegram/src/doctor.js +17 -16
  24. package/dist/extensions/telegram/src/doctor.js.map +1 -1
  25. package/dist/extensions/telegram/src/exec-approvals.js +2 -3
  26. package/dist/extensions/telegram/src/exec-approvals.js.map +1 -1
  27. package/dist/extensions/telegram/src/group-config-resolver.d.ts +1 -1
  28. package/dist/extensions/telegram/src/group-config-resolver.js.map +1 -1
  29. package/dist/extensions/telegram/src/pairing-config-resolver.d.ts +1 -0
  30. package/dist/extensions/telegram/src/pairing-config-resolver.js +56 -0
  31. package/dist/extensions/telegram/src/pairing-config-resolver.js.map +1 -0
  32. package/dist/extensions/telegram/src/plugin.d.ts +1 -0
  33. package/dist/extensions/telegram/src/plugin.js +8 -9
  34. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  35. package/dist/extensions/telegram/xopc.extension.json +156 -122
  36. package/dist/extensions/weixin/src/pairing-config-resolver.d.ts +1 -0
  37. package/dist/extensions/weixin/src/pairing-config-resolver.js +54 -0
  38. package/dist/extensions/weixin/src/pairing-config-resolver.js.map +1 -0
  39. package/dist/extensions/weixin/src/plugin.d.ts +1 -0
  40. package/dist/extensions/weixin/src/plugin.js +1 -0
  41. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  42. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
  43. package/dist/gateway/static/root/assets/agent-avatar-dicebear-zlx9l5Yp.js +1 -0
  44. package/dist/gateway/static/root/assets/agent-browser-settings-page-B-0zGjt8.js +6 -0
  45. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-Bz7JWjRM.js +1 -0
  46. package/dist/gateway/static/root/assets/agents-DwDnJlXT.js +71 -0
  47. package/dist/gateway/static/root/assets/app-management-settings-panel-DaQwdeCq.js +1 -0
  48. package/dist/gateway/static/root/assets/appearance-settings-D2zv6r3P.js +1 -0
  49. package/dist/gateway/static/root/assets/apps-page-BIppe_jj.js +1 -0
  50. package/dist/gateway/static/root/assets/archive-plugin-DEmu8eH7.js +1 -0
  51. package/dist/gateway/static/root/assets/attachment-load-B98lJoN5.js +2 -0
  52. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CybMSIoS.js → attachment-preview-renderer-DonnL2dL.js} +1 -1
  53. package/dist/gateway/static/root/assets/binary-plugins-CL9QKmyo.js +2 -0
  54. package/dist/gateway/static/root/assets/block-editor-BOAhMAhT.js +180 -0
  55. package/dist/gateway/static/root/assets/channels-settings-Br8iRnXp.js +1 -0
  56. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +1 -0
  57. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +1 -0
  58. package/dist/gateway/static/root/assets/config-api-0o1WYdz2.js +3 -0
  59. package/dist/gateway/static/root/assets/connectors-settings-DDvHo9in.js +2 -0
  60. package/dist/gateway/static/root/assets/cron-api-Dj_UZKST.js +1 -0
  61. package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +1 -0
  62. package/dist/gateway/static/root/assets/cron-page-Dv7GII9G.js +1 -0
  63. package/dist/gateway/static/root/assets/cron-schedule-picker-DH10KgD6.js +1 -0
  64. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  65. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  66. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  67. package/dist/gateway/static/root/assets/dreaming-scene-BHMRVEUS.js +4585 -0
  68. package/dist/gateway/static/root/assets/dreaming-settings-L2rgZDQl.js +1 -0
  69. package/dist/gateway/static/root/assets/extension-debug-page-Cjx6pZVz.js +1 -0
  70. package/dist/gateway/static/root/assets/{extension-page-DNcTendk.js → extension-page-BSPNL90V.js} +1 -1
  71. package/dist/gateway/static/root/assets/extension-settings-page-m_UQYkVc.js +1 -0
  72. package/dist/gateway/static/root/assets/fetch-Bs7in_4F.js +1 -0
  73. package/dist/gateway/static/root/assets/format-interval-label-CftJ5uXu.js +1 -0
  74. package/dist/gateway/static/root/assets/gateway-config-api-Clfck-hW.js +1 -0
  75. package/dist/gateway/static/root/assets/gateway-settings-CS177xni.js +1 -0
  76. package/dist/gateway/static/root/assets/gateway-startup-retry-BkjVJc38.js +1 -0
  77. package/dist/gateway/static/root/assets/goal-detail-page-kqJue0sE.js +1 -0
  78. package/dist/gateway/static/root/assets/goals-page-C0FujUB5.js +2 -0
  79. package/dist/gateway/static/root/assets/goals-settings-CJnzNSDo.js +1 -0
  80. package/dist/gateway/static/root/assets/heartbeat-config-api-Cp7CPuIn.js +1 -0
  81. package/dist/gateway/static/root/assets/heartbeat-settings-ifSI1Wbh.js +1 -0
  82. package/dist/gateway/static/root/assets/html-workspace-editor-CQLWDiwE.js +1 -0
  83. package/dist/gateway/static/root/assets/index-COkF54xv.js +121 -0
  84. package/dist/gateway/static/root/assets/index-DIaSNGEO.css +1 -0
  85. package/dist/gateway/static/root/assets/interval-presets-B29Ss_2y.js +2 -0
  86. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings--MI1rYl7.js +1 -0
  87. package/dist/gateway/static/root/assets/locale-store-DjbfSsfA.js +1 -0
  88. package/dist/gateway/static/root/assets/logs-page-BwrVNlyW.js +2 -0
  89. package/dist/gateway/static/root/assets/markdown-editor-AssmZFx4.js +2 -0
  90. package/dist/gateway/static/root/assets/markdown-split-B_oc9lJe.js +1 -0
  91. package/dist/gateway/static/root/assets/media-plugins-DLPvB5H3.js +1 -0
  92. package/dist/gateway/static/root/assets/mermaid-render-BbqDc_LQ.js +134 -0
  93. package/dist/gateway/static/root/assets/messages-Csef1aW7.js +3 -0
  94. package/dist/gateway/static/root/assets/middleware-Pd0e8Igk.js +1 -0
  95. package/dist/gateway/static/root/assets/models-hub-panel-DHGiTIvf.js +2 -0
  96. package/dist/gateway/static/root/assets/note-detail-page-BM7zlDiT.js +2 -0
  97. package/dist/gateway/static/root/assets/note-image-lightbox-rSqAgOi9.js +1 -0
  98. package/dist/gateway/static/root/assets/note-time-hm6JO_Wi.js +1 -0
  99. package/dist/gateway/static/root/assets/notes-page-C9ACGEty.js +1 -0
  100. package/dist/gateway/static/root/assets/preview-open-alternatives-Bw_N2oZi.js +1 -0
  101. package/dist/gateway/static/root/assets/remote-access-hub-BhcWIKuM.js +1 -0
  102. package/dist/gateway/static/root/assets/save-bar-controls-CNP2jmw0.js +1 -0
  103. package/dist/gateway/static/root/assets/schedule-field-BPAWui3P.js +1 -0
  104. package/dist/gateway/static/root/assets/schedule-summary-B-hdSRdR.js +1 -0
  105. package/dist/gateway/static/root/assets/schema-form-CDPzua9q.js +1 -0
  106. package/dist/gateway/static/root/assets/sessions-page-DzkpSDZr.js +1 -0
  107. package/dist/gateway/static/root/assets/settings-advanced-gate-BYS-rpzn.js +1 -0
  108. package/dist/gateway/static/root/assets/settings-collapsible-section-C9bff85B.js +1 -0
  109. package/dist/gateway/static/root/assets/settings-form-section-BsrK7TBF.js +1 -0
  110. package/dist/gateway/static/root/assets/settings-page-DWK4Zo7s.js +1 -0
  111. package/dist/gateway/static/root/assets/setup-status-panel-DJiksNu4.js +1 -0
  112. package/dist/gateway/static/root/assets/share-preview-page-DnutoY_S.js +2 -0
  113. package/dist/gateway/static/root/assets/shares-settings-6oRgJMpn.js +1 -0
  114. package/dist/gateway/static/root/assets/skill-reload-api-CU9i0nJV.js +1 -0
  115. package/dist/gateway/static/root/assets/skills-page-ERbdWENm.js +2 -0
  116. package/dist/gateway/static/root/assets/system-settings-panel-qP1JDtDd.js +1 -0
  117. package/dist/gateway/static/root/assets/theme-store-CD2wtgZV.js +1 -0
  118. package/dist/gateway/static/root/assets/use-agent-defaults-form-D3FGVLZb.js +1 -0
  119. package/dist/gateway/static/root/assets/use-blob-object-url-D4BFuzZB.js +1 -0
  120. package/dist/gateway/static/root/assets/use-channel-catalog-C4mg1hjD.js +1 -0
  121. package/dist/gateway/static/root/assets/use-settings-tab-guard-F6C0mpJt.js +1 -0
  122. package/dist/gateway/static/root/assets/vendor-codemirror-CNP1wPe7.js +45 -0
  123. package/dist/gateway/static/root/assets/voice-api-key-field-BnDDb6qO.js +1 -0
  124. package/dist/gateway/static/root/assets/voice-player-store-B2EwIhtY.js +1 -0
  125. package/dist/gateway/static/root/assets/{workflow-page.utils-BcZQmKBX.js → workflow-page.utils-CRB7WX9l.js} +1 -1
  126. package/dist/gateway/static/root/assets/workflows-page-2Fptr0je.js +18 -0
  127. package/dist/gateway/static/root/index.html +12 -10
  128. package/dist/package.js +1 -1
  129. package/dist/src/agent/goals/checklist-judge.d.ts +5 -0
  130. package/dist/src/agent/goals/checklist-judge.js +26 -2
  131. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  132. package/dist/src/agent/goals/evaluate-turn.d.ts +5 -1
  133. package/dist/src/agent/goals/evaluate-turn.js +29 -3
  134. package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
  135. package/dist/src/agent/goals/goal-locale.d.ts +0 -2
  136. package/dist/src/agent/goals/goal-locale.js +2 -15
  137. package/dist/src/agent/goals/goal-locale.js.map +1 -1
  138. package/dist/src/agent/goals/persistent-goal-service.d.ts +9 -0
  139. package/dist/src/agent/goals/persistent-goal-service.js +2 -1
  140. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  141. package/dist/src/agent/goals/post-turn.d.ts +7 -0
  142. package/dist/src/agent/goals/post-turn.js +68 -23
  143. package/dist/src/agent/goals/post-turn.js.map +1 -1
  144. package/dist/src/agent/goals/state.d.ts +0 -5
  145. package/dist/src/agent/goals/state.js +1 -96
  146. package/dist/src/agent/goals/state.js.map +1 -1
  147. package/dist/src/agent/messaging/command-handler.d.ts +4 -0
  148. package/dist/src/agent/messaging/command-handler.js +6 -2
  149. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  150. package/dist/src/agent/service/direct-turn-helpers.d.ts +2 -0
  151. package/dist/src/agent/service/direct-turn-helpers.js +3 -2
  152. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  153. package/dist/src/agent/service/process-direct-streaming.js +10 -1
  154. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  155. package/dist/src/agent/service.js +20 -1
  156. package/dist/src/agent/service.js.map +1 -1
  157. package/dist/src/agent/service.types.d.ts +8 -0
  158. package/dist/src/agent/tools/cronjob-tool.d.ts +2 -0
  159. package/dist/src/agent/tools/cronjob-tool.js +27 -4
  160. package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
  161. package/dist/src/agent/tools/edit.d.ts +2 -0
  162. package/dist/src/agent/tools/edit.js +10 -0
  163. package/dist/src/agent/tools/edit.js.map +1 -1
  164. package/dist/src/agent/tools/factory.js +16 -3
  165. package/dist/src/agent/tools/factory.js.map +1 -1
  166. package/dist/src/agent/tools/goal-evidence-recorder.d.ts +6 -0
  167. package/dist/src/agent/tools/goal-evidence-recorder.js +34 -0
  168. package/dist/src/agent/tools/goal-evidence-recorder.js.map +1 -0
  169. package/dist/src/agent/tools/goal-tool.d.ts +19 -0
  170. package/dist/src/agent/tools/goal-tool.js +101 -0
  171. package/dist/src/agent/tools/goal-tool.js.map +1 -0
  172. package/dist/src/agent/tools/index.d.ts +1 -0
  173. package/dist/src/agent/tools/index.js +2 -1
  174. package/dist/src/agent/tools/shell.d.ts +2 -0
  175. package/dist/src/agent/tools/shell.js +17 -2
  176. package/dist/src/agent/tools/shell.js.map +1 -1
  177. package/dist/src/agent/tools/workflow-tool.d.ts +1 -0
  178. package/dist/src/agent/tools/workflow-tool.js +10 -2
  179. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  180. package/dist/src/agent/tools/write.d.ts +2 -0
  181. package/dist/src/agent/tools/write.js +11 -0
  182. package/dist/src/agent/tools/write.js.map +1 -1
  183. package/dist/src/channels/attachments/inbound-persist.d.ts +7 -0
  184. package/dist/src/channels/attachments/inbound-persist.js +20 -2
  185. package/dist/src/channels/attachments/inbound-persist.js.map +1 -1
  186. package/dist/src/channels/channel-domain.d.ts +1 -81
  187. package/dist/src/channels/pairing/index.d.ts +2 -2
  188. package/dist/src/channels/pairing/index.js +2 -2
  189. package/dist/src/channels/pairing/pairing-service.d.ts +13 -0
  190. package/dist/src/channels/pairing/pairing-service.js +78 -63
  191. package/dist/src/channels/pairing/pairing-service.js.map +1 -1
  192. package/dist/src/chat-commands/builtins/config.js +4 -11
  193. package/dist/src/chat-commands/builtins/config.js.map +1 -1
  194. package/dist/src/chat-commands/builtins/goal.d.ts +1 -1
  195. package/dist/src/chat-commands/builtins/goal.js +55 -97
  196. package/dist/src/chat-commands/builtins/goal.js.map +1 -1
  197. package/dist/src/chat-commands/builtins/subgoal.d.ts +1 -1
  198. package/dist/src/chat-commands/builtins/subgoal.js +49 -108
  199. package/dist/src/chat-commands/builtins/subgoal.js.map +1 -1
  200. package/dist/src/chat-commands/builtins/workflow.js +132 -8
  201. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  202. package/dist/src/chat-commands/context.d.ts +3 -0
  203. package/dist/src/chat-commands/context.js +5 -0
  204. package/dist/src/chat-commands/context.js.map +1 -1
  205. package/dist/src/chat-commands/types.d.ts +5 -0
  206. package/dist/src/cli/command-catalog.js +43 -0
  207. package/dist/src/cli/command-catalog.js.map +1 -1
  208. package/dist/src/cli/command-loaders.js +1 -0
  209. package/dist/src/cli/command-loaders.js.map +1 -1
  210. package/dist/src/cli/command-manifest.js +4 -0
  211. package/dist/src/cli/command-manifest.js.map +1 -1
  212. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  213. package/dist/src/cli/commands/goal.d.ts +4 -0
  214. package/dist/src/cli/commands/goal.js +213 -0
  215. package/dist/src/cli/commands/goal.js.map +1 -0
  216. package/dist/src/cli/commands/onboard.js +11 -5
  217. package/dist/src/cli/commands/onboard.js.map +1 -1
  218. package/dist/src/config/index.js +2 -2
  219. package/dist/src/config/schema.d.ts +115 -0
  220. package/dist/src/config/schema.js +72 -18
  221. package/dist/src/config/schema.js.map +1 -1
  222. package/dist/src/config/web-patch.d.ts +14 -0
  223. package/dist/src/config/web-patch.js +45 -6
  224. package/dist/src/config/web-patch.js.map +1 -1
  225. package/dist/src/cron/executor.d.ts +2 -0
  226. package/dist/src/cron/executor.js +25 -0
  227. package/dist/src/cron/executor.js.map +1 -1
  228. package/dist/src/cron/job-content.js +1 -0
  229. package/dist/src/cron/job-content.js.map +1 -1
  230. package/dist/src/cron/types.d.ts +19 -1
  231. package/dist/src/cron/validation.d.ts +20 -0
  232. package/dist/src/cron/validation.js +7 -0
  233. package/dist/src/cron/validation.js.map +1 -1
  234. package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -0
  235. package/dist/src/gateway/hono/routes/goals.d.ts +1 -1
  236. package/dist/src/gateway/hono/routes/goals.js +670 -173
  237. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  238. package/dist/src/gateway/hono/routes/home.d.ts +5 -0
  239. package/dist/src/gateway/hono/routes/home.js +88 -3
  240. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  241. package/dist/src/gateway/hono/routes/notes.js +20 -14
  242. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  243. package/dist/src/gateway/hono/routes/workflows.js +6 -2
  244. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  245. package/dist/src/gateway/hono/sse.js.map +1 -1
  246. package/dist/src/gateway/service/agent-runner.d.ts +2 -0
  247. package/dist/src/gateway/service/agent-runner.js +6 -2
  248. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  249. package/dist/src/gateway/service/run-gateway-agent.d.ts +3 -0
  250. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  251. package/dist/src/gateway/service.d.ts +8 -0
  252. package/dist/src/gateway/service.js +70 -3
  253. package/dist/src/gateway/service.js.map +1 -1
  254. package/dist/src/goals/goal-notifications.d.ts +29 -0
  255. package/dist/src/goals/goal-notifications.js +154 -0
  256. package/dist/src/goals/goal-notifications.js.map +1 -0
  257. package/dist/src/goals/goal-queue-store.d.ts +16 -0
  258. package/dist/src/goals/goal-queue-store.js +131 -0
  259. package/dist/src/goals/goal-queue-store.js.map +1 -0
  260. package/dist/src/goals/goal-queue-types.d.ts +31 -0
  261. package/dist/src/goals/goal-queue-types.js +1 -0
  262. package/dist/src/goals/goal-runner.d.ts +17 -0
  263. package/dist/src/goals/goal-runner.js +127 -0
  264. package/dist/src/goals/goal-runner.js.map +1 -0
  265. package/dist/src/goals/goal-service.d.ts +77 -0
  266. package/dist/src/goals/goal-service.js +261 -0
  267. package/dist/src/goals/goal-service.js.map +1 -0
  268. package/dist/src/goals/goal-store.d.ts +38 -0
  269. package/dist/src/goals/goal-store.js +404 -0
  270. package/dist/src/goals/goal-store.js.map +1 -0
  271. package/dist/src/goals/goal-workflow-judge.d.ts +13 -0
  272. package/dist/src/goals/goal-workflow-judge.js +147 -0
  273. package/dist/src/goals/goal-workflow-judge.js.map +1 -0
  274. package/dist/src/goals/index.d.ts +10 -0
  275. package/dist/src/goals/index.js +7 -0
  276. package/dist/src/goals/types.d.ts +119 -0
  277. package/dist/src/goals/types.js +1 -0
  278. package/dist/src/storage/sqlite/migrations/006_add_goals.sql +108 -0
  279. package/dist/src/storage/sqlite/migrations/007_goal_run_judge_schema.sql +4 -0
  280. package/dist/src/storage/sqlite/migrations/008_goal_queue_workflow_runs.sql +53 -0
  281. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  282. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  283. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  284. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  285. package/dist/src/storage/sqlite/schema.js +1 -1
  286. package/dist/src/storage/sqlite/schema.sql +163 -0
  287. package/dist/src/utils/logger/stats.d.ts +1 -1
  288. package/dist/src/workflows/domain/run.d.ts +1 -0
  289. package/dist/src/workflows/domain/run.js.map +1 -1
  290. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  291. package/dist/src/workflows/service/workflow-run-service.js +5 -1
  292. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  293. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
  294. package/dist/src/workflows/service/workflow-session-bridge.js +7 -0
  295. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  296. package/dist/src/workflows/store/run-index-store.d.ts +8 -0
  297. package/dist/src/workflows/store/run-index-store.js +58 -0
  298. package/dist/src/workflows/store/run-index-store.js.map +1 -0
  299. package/dist/src/workflows/store/run-store.d.ts +2 -0
  300. package/dist/src/workflows/store/run-store.js +14 -21
  301. package/dist/src/workflows/store/run-store.js.map +1 -1
  302. package/package.json +9 -3
  303. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  304. package/dist/gateway/static/root/assets/agents-D2VtykeA.js +0 -78
  305. package/dist/gateway/static/root/assets/apps-page-BPQ6ueG-.js +0 -1
  306. package/dist/gateway/static/root/assets/channels-settings-DgZc25cS.js +0 -1
  307. package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +0 -1
  308. package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +0 -1
  309. package/dist/gateway/static/root/assets/cron-page-BQFw5O-8.js +0 -1
  310. package/dist/gateway/static/root/assets/dist-BLMShn4_.js +0 -1
  311. package/dist/gateway/static/root/assets/extension-debug-page-BbQ8uZY_.js +0 -1
  312. package/dist/gateway/static/root/assets/extension-settings-page-ClWJvwHK.js +0 -1
  313. package/dist/gateway/static/root/assets/fetch-CFdKBnE6.js +0 -1
  314. package/dist/gateway/static/root/assets/gateway-startup-retry-DdngdObI.js +0 -1
  315. package/dist/gateway/static/root/assets/heartbeat-config-api-4O1U_Oki.js +0 -1
  316. package/dist/gateway/static/root/assets/index-DI5_GsZt.css +0 -1
  317. package/dist/gateway/static/root/assets/index-S23p3aa0.js +0 -4845
  318. package/dist/gateway/static/root/assets/logs-page-BAIdbvSC.js +0 -2
  319. package/dist/gateway/static/root/assets/note-detail-page-BVDoLwec.js +0 -180
  320. package/dist/gateway/static/root/assets/note-time-COWUfBZO.js +0 -1
  321. package/dist/gateway/static/root/assets/notes-page-CI3aD7Tm.js +0 -1
  322. package/dist/gateway/static/root/assets/schema-form-CDpBshDP.js +0 -1
  323. package/dist/gateway/static/root/assets/sessions-page-DM1S4eso.js +0 -1
  324. package/dist/gateway/static/root/assets/settings-advanced-gate-Bz_nYzvB.js +0 -2
  325. package/dist/gateway/static/root/assets/settings-form-section-BxhPoWWH.js +0 -1
  326. package/dist/gateway/static/root/assets/settings-page-Ch_Sd28M.js +0 -3
  327. package/dist/gateway/static/root/assets/share-preview-page-D6u4llqD.js +0 -2
  328. package/dist/gateway/static/root/assets/skills-page-XMi76Nps.js +0 -2
  329. package/dist/gateway/static/root/assets/theme-store-BZozwAeK.js +0 -1
  330. package/dist/gateway/static/root/assets/url-DQRqHuL-.js +0 -3
  331. package/dist/gateway/static/root/assets/vendor-codemirror-DYoKfS8f.js +0 -45
  332. package/dist/gateway/static/root/assets/voice-api-key-field-CMt5Xc7_.js +0 -1
  333. package/dist/gateway/static/root/assets/workflows-page-CxFbPBed.js +0 -18
  334. package/dist/src/agent/goals/checklist-user.d.ts +0 -24
  335. package/dist/src/agent/goals/checklist-user.js +0 -92
  336. package/dist/src/agent/goals/checklist-user.js.map +0 -1
  337. package/dist/src/agent/goals/goal-run-store.d.ts +0 -19
  338. package/dist/src/agent/goals/goal-run-store.js +0 -138
  339. package/dist/src/agent/goals/goal-run-store.js.map +0 -1
  340. package/dist/src/agent/goals/goal-run-types.d.ts +0 -28
  341. package/dist/src/agent/goals/goal-run-types.js +0 -6
  342. package/dist/src/agent/goals/goal-run-types.js.map +0 -1
  343. package/dist/src/agent/goals/patch-from-user-action.d.ts +0 -20
  344. package/dist/src/agent/goals/patch-from-user-action.js +0 -103
  345. package/dist/src/agent/goals/patch-from-user-action.js.map +0 -1
  346. /package/dist/gateway/static/root/assets/{note-detail-page-D4ZIVQbk.css → block-editor-D4ZIVQbk.css} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../../src/chat-commands/builtins/config.ts"],"sourcesContent":["/**\n * /config — read and write persistent config (~/.xopc/xopc.json) from chat.\n */\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { parseConfigValue } from '../config-value.js';\nimport {\n parseConfigPath,\n getConfigValueAtPath,\n setConfigValueAtPath,\n unsetConfigValueAtPath,\n} from '../config-paths.js';\nimport { ConfigSchema, type TelegramConfig, type WeixinConfig } from '../../config/schema.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { parseSessionKey } from '../../routing/session-key.js';\nimport { resolveAllowlistMatchSimple } from '../../channels/security.js';\n\nconst log = createLogger('ConfigCommand');\n\nconst BLOCKED_WRITE_PATHS = new Set(['gateway.auth.token', 'providers']);\n\nfunction isBlockedPath(path: string[]): boolean {\n const joined = path.join('.');\n for (const blocked of BLOCKED_WRITE_PATHS) {\n if (joined === blocked || joined.startsWith(`${blocked}.`)) return true;\n }\n return false;\n}\n\nfunction redactConfigForDisplay(plain: Record<string, unknown>): void {\n if (plain.gateway && typeof plain.gateway === 'object') {\n const gw = plain.gateway as Record<string, unknown>;\n if (gw.auth && typeof gw.auth === 'object') {\n (gw.auth as Record<string, unknown>).token = '[redacted]';\n }\n }\n if (plain.providers !== undefined) plain.providers = '[redacted]';\n}\n\nfunction senderMayWritePersistentConfig(ctx: CommandContext): boolean {\n const { source, senderId, isGroup, sessionKey } = ctx;\n if (source !== 'telegram' && source !== 'weixin') {\n return true;\n }\n\n const cfg = ctx.getConfig?.() ?? ctx.config;\n\n if (source === 'weixin') {\n const wx = cfg.channels?.weixin as WeixinConfig | undefined;\n if (!wx?.enabled) return false;\n const parsed = parseSessionKey(sessionKey);\n const accountId = parsed?.accountId ?? 'default';\n let allowFrom: Array<string | number> = [];\n if (wx.accounts && Object.keys(wx.accounts).length > 0) {\n const acc = wx.accounts[accountId] ?? wx.accounts['default'];\n if (!acc || acc.enabled === false) return false;\n allowFrom = [...(acc.allowFrom ?? [])];\n } else {\n allowFrom = [...(wx.allowFrom ?? [])];\n }\n if (allowFrom.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom, senderId }).allowed;\n }\n\n const tg = cfg.channels?.telegram as TelegramConfig | undefined;\n if (!tg?.enabled) return false;\n const parsed = parseSessionKey(sessionKey);\n const accountId = parsed?.accountId ?? 'default';\n let allowFrom: Array<string | number> = [];\n let groupAllowFrom: Array<string | number> = [];\n if (tg.accounts && Object.keys(tg.accounts).length > 0) {\n const acc = tg.accounts[accountId] ?? tg.accounts['default'];\n if (!acc || acc.enabled === false) return false;\n allowFrom = [...(acc.allowFrom ?? [])];\n groupAllowFrom = [...(acc.groupAllowFrom ?? [])];\n } else {\n allowFrom = [...(tg.allowFrom ?? [])];\n groupAllowFrom = [...(tg.groupAllowFrom ?? [])];\n }\n const list = isGroup && groupAllowFrom.length > 0 ? groupAllowFrom : allowFrom;\n if (list.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom: list, senderId }).allowed;\n}\n\nconst configCommand: CommandDefinition = {\n id: 'system.config',\n name: 'config',\n aliases: ['cfg'],\n description:\n 'Show or update configuration. Usage: /config show [path] | /config set path=value | /config unset path',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: [\n '/config show',\n '/config show agents.defaults.models.chat',\n '/config set agents.defaults.models.chat.primary=anthropic/claude-opus-4-5',\n '/config set agents.defaults.temperature=0.5',\n '/config unset tts',\n ],\n handler: async (ctx: CommandContext, args: string) => {\n const parts = args.trim().split(/\\s+/);\n const action = parts[0]?.toLowerCase();\n const rest = parts.slice(1).join(' ').trim();\n\n if (!action || action === 'show' || action === 'get') {\n const config = ctx.getConfig?.() ?? loadConfig(resolveConfigPath());\n const plain = JSON.parse(JSON.stringify(config)) as Record<string, unknown>;\n redactConfigForDisplay(plain);\n\n if (rest) {\n const parsed = parseConfigPath(rest);\n if (!parsed.ok || !parsed.path) {\n return { content: `⚠️ ${parsed.error ?? 'Invalid path.'}`, success: false };\n }\n const value = getConfigValueAtPath(plain, parsed.path);\n const rendered = JSON.stringify(value ?? null, null, 2);\n return { content: `⚙️ \\`${rest}\\`:\\n\\`\\`\\`json\\n${rendered}\\n\\`\\`\\`` };\n }\n\n const json = JSON.stringify(plain, null, 2);\n return { content: `⚙️ Current config:\\n\\`\\`\\`json\\n${json}\\n\\`\\`\\`` };\n }\n\n if (action === 'set') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n const eqIndex = rest.indexOf('=');\n if (eqIndex <= 0) {\n return { content: '⚠️ Usage: /config set path=value', success: false };\n }\n const pathRaw = rest.slice(0, eqIndex).trim();\n const valueRaw = rest.slice(eqIndex + 1);\n\n const parsedPath = parseConfigPath(pathRaw);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${pathRaw}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const parsedValue = parseConfigValue(valueRaw);\n if (parsedValue.ok === false) {\n return { content: `⚠️ ${parsedValue.error}`, success: false };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n setConfigValueAtPath(currentConfig, parsedPath.path, parsedValue.value);\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after set (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: pathRaw, value: parsedValue.value }, 'Config updated via /config set');\n\n const valueLabel =\n typeof parsedValue.value === 'string'\n ? `\"${parsedValue.value}\"`\n : JSON.stringify(parsedValue.value);\n return { content: `⚙️ Config updated: \\`${pathRaw}\\` = ${valueLabel}` };\n }\n\n if (action === 'unset') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n if (!rest) {\n return { content: '⚠️ Usage: /config unset path', success: false };\n }\n const parsedPath = parseConfigPath(rest);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${rest}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n const removed = unsetConfigValueAtPath(currentConfig, parsedPath.path);\n if (!removed) {\n return { content: `⚙️ No config value found at \\`${rest}\\`.`, success: false };\n }\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after unset (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: rest }, 'Config key removed via /config unset');\n return { content: `⚙️ Config updated: \\`${rest}\\` removed.` };\n }\n\n return {\n content:\n '⚙️ *Config Command*\\n\\n' +\n '`/config show [path]` — view config (or a specific path)\\n' +\n '`/config set path=value` — update a config value\\n' +\n '`/config unset path` — remove a config key\\n\\n' +\n 'Examples:\\n' +\n '`/config show agents.defaults.models.chat`\\n' +\n '`/config set agents.defaults.temperature=0.5`\\n' +\n '`/config set agents.defaults.thinkingDefault=medium`\\n' +\n '`/config unset tts`',\n };\n },\n};\n\nexport function registerConfigCommand(): void {\n commandRegistry.register(configCommand);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../../../src/chat-commands/builtins/config.ts"],"sourcesContent":["/**\n * /config — read and write persistent config (~/.xopc/xopc.json) from chat.\n */\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { parseConfigValue } from '../config-value.js';\nimport {\n parseConfigPath,\n getConfigValueAtPath,\n setConfigValueAtPath,\n unsetConfigValueAtPath,\n} from '../config-paths.js';\nimport { ConfigSchema, type TelegramConfig, type WeixinConfig } from '../../config/schema.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport { resolveConfigPath } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { parseSessionKey } from '../../routing/session-key.js';\nimport { resolveAllowlistMatchSimple } from '../../channels/security.js';\n\nconst log = createLogger('ConfigCommand');\n\nconst BLOCKED_WRITE_PATHS = new Set(['gateway.auth.token', 'providers']);\n\nfunction isBlockedPath(path: string[]): boolean {\n const joined = path.join('.');\n for (const blocked of BLOCKED_WRITE_PATHS) {\n if (joined === blocked || joined.startsWith(`${blocked}.`)) return true;\n }\n return false;\n}\n\nfunction redactConfigForDisplay(plain: Record<string, unknown>): void {\n if (plain.gateway && typeof plain.gateway === 'object') {\n const gw = plain.gateway as Record<string, unknown>;\n if (gw.auth && typeof gw.auth === 'object') {\n (gw.auth as Record<string, unknown>).token = '[redacted]';\n }\n }\n if (plain.providers !== undefined) plain.providers = '[redacted]';\n}\n\nfunction senderMayWritePersistentConfig(ctx: CommandContext): boolean {\n const { source, senderId, isGroup, sessionKey } = ctx;\n if (source !== 'telegram' && source !== 'weixin') {\n return true;\n }\n\n const cfg = ctx.getConfig?.() ?? ctx.config;\n\n if (source === 'weixin') {\n const wx = cfg.channels?.weixin as WeixinConfig | undefined;\n if (!wx?.enabled) return false;\n const parsed = parseSessionKey(sessionKey);\n const accountId = parsed?.accountId ?? 'default';\n let allowFrom: Array<string | number> = [];\n if (wx.accounts && Object.keys(wx.accounts).length > 0) {\n const acc = wx.accounts[accountId] ?? wx.accounts['default'];\n if (!acc || acc.enabled === false) return false;\n allowFrom = [...(acc.allowFrom ?? [])];\n } else {\n allowFrom = [...(wx.allowFrom ?? [])];\n }\n if (allowFrom.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom, senderId }).allowed;\n }\n\n const tg = cfg.channels?.telegram as TelegramConfig | undefined;\n if (!tg?.enabled) return false;\n const parsed = parseSessionKey(sessionKey);\n const accountId = parsed?.accountId ?? 'default';\n const acc = tg.accounts?.[accountId] ?? tg.accounts?.['default'];\n if (!acc || acc.enabled === false) return false;\n const allowFrom = [...(acc.allowFrom ?? [])];\n const groupAllowFrom = [...(acc.groupAllowFrom ?? [])];\n const list = isGroup && groupAllowFrom.length > 0 ? groupAllowFrom : allowFrom;\n if (list.length === 0) return false;\n return resolveAllowlistMatchSimple({ allowFrom: list, senderId }).allowed;\n}\n\nconst configCommand: CommandDefinition = {\n id: 'system.config',\n name: 'config',\n aliases: ['cfg'],\n description:\n 'Show or update configuration. Usage: /config show [path] | /config set path=value | /config unset path',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: [\n '/config show',\n '/config show agents.defaults.models.chat',\n '/config set agents.defaults.models.chat.primary=anthropic/claude-opus-4-5',\n '/config set agents.defaults.temperature=0.5',\n '/config unset tts',\n ],\n handler: async (ctx: CommandContext, args: string) => {\n const parts = args.trim().split(/\\s+/);\n const action = parts[0]?.toLowerCase();\n const rest = parts.slice(1).join(' ').trim();\n\n if (!action || action === 'show' || action === 'get') {\n const config = ctx.getConfig?.() ?? loadConfig(resolveConfigPath());\n const plain = JSON.parse(JSON.stringify(config)) as Record<string, unknown>;\n redactConfigForDisplay(plain);\n\n if (rest) {\n const parsed = parseConfigPath(rest);\n if (!parsed.ok || !parsed.path) {\n return { content: `⚠️ ${parsed.error ?? 'Invalid path.'}`, success: false };\n }\n const value = getConfigValueAtPath(plain, parsed.path);\n const rendered = JSON.stringify(value ?? null, null, 2);\n return { content: `⚙️ \\`${rest}\\`:\\n\\`\\`\\`json\\n${rendered}\\n\\`\\`\\`` };\n }\n\n const json = JSON.stringify(plain, null, 2);\n return { content: `⚙️ Current config:\\n\\`\\`\\`json\\n${json}\\n\\`\\`\\`` };\n }\n\n if (action === 'set') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n const eqIndex = rest.indexOf('=');\n if (eqIndex <= 0) {\n return { content: '⚠️ Usage: /config set path=value', success: false };\n }\n const pathRaw = rest.slice(0, eqIndex).trim();\n const valueRaw = rest.slice(eqIndex + 1);\n\n const parsedPath = parseConfigPath(pathRaw);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${pathRaw}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const parsedValue = parseConfigValue(valueRaw);\n if (parsedValue.ok === false) {\n return { content: `⚠️ ${parsedValue.error}`, success: false };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n setConfigValueAtPath(currentConfig, parsedPath.path, parsedValue.value);\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after set (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: pathRaw, value: parsedValue.value }, 'Config updated via /config set');\n\n const valueLabel =\n typeof parsedValue.value === 'string'\n ? `\"${parsedValue.value}\"`\n : JSON.stringify(parsedValue.value);\n return { content: `⚙️ Config updated: \\`${pathRaw}\\` = ${valueLabel}` };\n }\n\n if (action === 'unset') {\n if (!senderMayWritePersistentConfig(ctx)) {\n return {\n content: '⚠️ You are not allowed to change config from this chat surface.',\n success: false,\n };\n }\n if (!rest) {\n return { content: '⚠️ Usage: /config unset path', success: false };\n }\n const parsedPath = parseConfigPath(rest);\n if (!parsedPath.ok || !parsedPath.path) {\n return { content: `⚠️ ${parsedPath.error}`, success: false };\n }\n if (isBlockedPath(parsedPath.path)) {\n return {\n content: `⚠️ Path \\`${rest}\\` cannot be modified via chat for security reasons.`,\n success: false,\n };\n }\n\n const configPath = resolveConfigPath();\n const currentConfig = loadConfig(configPath) as Record<string, unknown>;\n const removed = unsetConfigValueAtPath(currentConfig, parsedPath.path);\n if (!removed) {\n return { content: `⚙️ No config value found at \\`${rest}\\`.`, success: false };\n }\n\n const validated = ConfigSchema.safeParse(currentConfig);\n if (!validated.success) {\n const firstIssue = validated.error.issues[0];\n const fieldPath = firstIssue.path.join('.');\n return {\n content: `⚠️ Config invalid after unset (${fieldPath}: ${firstIssue.message}). Change not saved.`,\n success: false,\n };\n }\n\n await saveConfig(validated.data);\n log.info({ path: rest }, 'Config key removed via /config unset');\n return { content: `⚙️ Config updated: \\`${rest}\\` removed.` };\n }\n\n return {\n content:\n '⚙️ *Config Command*\\n\\n' +\n '`/config show [path]` — view config (or a specific path)\\n' +\n '`/config set path=value` — update a config value\\n' +\n '`/config unset path` — remove a config key\\n\\n' +\n 'Examples:\\n' +\n '`/config show agents.defaults.models.chat`\\n' +\n '`/config set agents.defaults.temperature=0.5`\\n' +\n '`/config set agents.defaults.thinkingDefault=medium`\\n' +\n '`/config unset tts`',\n };\n },\n};\n\nexport function registerConfigCommand(): void {\n commandRegistry.register(configCommand);\n}\n"],"mappings":";;;;;;;;;;;aAa8F;aAC9B;YACN;aACL;kBACU;AAG/D,MAAM,MAAM,aAAa,gBAAgB;AAEzC,MAAM,sBAAsB,IAAI,IAAI,CAAC,sBAAsB,YAAY,CAAC;AAExE,SAAS,cAAc,MAAyB;CAC9C,MAAM,SAAS,KAAK,KAAK,IAAI;AAC7B,MAAK,MAAM,WAAW,oBACpB,KAAI,WAAW,WAAW,OAAO,WAAW,GAAG,QAAQ,GAAG,CAAE,QAAO;AAErE,QAAO;;AAGT,SAAS,uBAAuB,OAAsC;AACpE,KAAI,MAAM,WAAW,OAAO,MAAM,YAAY,UAAU;EACtD,MAAM,KAAK,MAAM;AACjB,MAAI,GAAG,QAAQ,OAAO,GAAG,SAAS,SAC/B,IAAG,KAAiC,QAAQ;;AAGjD,KAAI,MAAM,cAAc,KAAA,EAAW,OAAM,YAAY;;AAGvD,SAAS,+BAA+B,KAA8B;CACpE,MAAM,EAAE,QAAQ,UAAU,SAAS,eAAe;AAClD,KAAI,WAAW,cAAc,WAAW,SACtC,QAAO;CAGT,MAAM,MAAM,IAAI,aAAa,IAAI,IAAI;AAErC,KAAI,WAAW,UAAU;EACvB,MAAM,KAAK,IAAI,UAAU;AACzB,MAAI,CAAC,IAAI,QAAS,QAAO;EAEzB,MAAM,YADS,gBAAgB,WACP,EAAE,aAAa;EACvC,IAAI,YAAoC,EAAE;AAC1C,MAAI,GAAG,YAAY,OAAO,KAAK,GAAG,SAAS,CAAC,SAAS,GAAG;GACtD,MAAM,MAAM,GAAG,SAAS,cAAc,GAAG,SAAS;AAClD,OAAI,CAAC,OAAO,IAAI,YAAY,MAAO,QAAO;AAC1C,eAAY,CAAC,GAAI,IAAI,aAAa,EAAE,CAAE;QAEtC,aAAY,CAAC,GAAI,GAAG,aAAa,EAAE,CAAE;AAEvC,MAAI,UAAU,WAAW,EAAG,QAAO;AACnC,SAAO,4BAA4B;GAAE;GAAW;GAAU,CAAC,CAAC;;CAG9D,MAAM,KAAK,IAAI,UAAU;AACzB,KAAI,CAAC,IAAI,QAAS,QAAO;CAEzB,MAAM,YADS,gBAAgB,WACP,EAAE,aAAa;CACvC,MAAM,MAAM,GAAG,WAAW,cAAc,GAAG,WAAW;AACtD,KAAI,CAAC,OAAO,IAAI,YAAY,MAAO,QAAO;CAC1C,MAAM,YAAY,CAAC,GAAI,IAAI,aAAa,EAAE,CAAE;CAC5C,MAAM,iBAAiB,CAAC,GAAI,IAAI,kBAAkB,EAAE,CAAE;CACtD,MAAM,OAAO,WAAW,eAAe,SAAS,IAAI,iBAAiB;AACrE,KAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,QAAO,4BAA4B;EAAE,WAAW;EAAM;EAAU,CAAC,CAAC;;AAGpE,MAAM,gBAAmC;CACvC,IAAI;CACJ,MAAM;CACN,SAAS,CAAC,MAAM;CAChB,aACE;CACF,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,aAAa;CACb,UAAU;EACR;EACA;EACA;EACA;EACA;EACD;CACD,SAAS,OAAO,KAAqB,SAAiB;EACpD,MAAM,QAAQ,KAAK,MAAM,CAAC,MAAM,MAAM;EACtC,MAAM,SAAS,MAAM,IAAI,aAAa;EACtC,MAAM,OAAO,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC,MAAM;AAE5C,MAAI,CAAC,UAAU,WAAW,UAAU,WAAW,OAAO;GACpD,MAAM,SAAS,IAAI,aAAa,IAAI,WAAW,mBAAmB,CAAC;GACnE,MAAM,QAAQ,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;AAChD,0BAAuB,MAAM;AAE7B,OAAI,MAAM;IACR,MAAM,SAAS,gBAAgB,KAAK;AACpC,QAAI,CAAC,OAAO,MAAM,CAAC,OAAO,KACxB,QAAO;KAAE,SAAS,MAAM,OAAO,SAAS;KAAmB,SAAS;KAAO;IAE7E,MAAM,QAAQ,qBAAqB,OAAO,OAAO,KAAK;AAEtD,WAAO,EAAE,SAAS,QAAQ,KAAK,mBADd,KAAK,UAAU,SAAS,MAAM,MAAM,EACK,CAAC,WAAW;;AAIxE,UAAO,EAAE,SAAS,mCADL,KAAK,UAAU,OAAO,MAAM,EACgB,CAAC,WAAW;;AAGvE,MAAI,WAAW,OAAO;AACpB,OAAI,CAAC,+BAA+B,IAAI,CACtC,QAAO;IACL,SAAS;IACT,SAAS;IACV;GAEH,MAAM,UAAU,KAAK,QAAQ,IAAI;AACjC,OAAI,WAAW,EACb,QAAO;IAAE,SAAS;IAAoC,SAAS;IAAO;GAExE,MAAM,UAAU,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM;GAC7C,MAAM,WAAW,KAAK,MAAM,UAAU,EAAE;GAExC,MAAM,aAAa,gBAAgB,QAAQ;AAC3C,OAAI,CAAC,WAAW,MAAM,CAAC,WAAW,KAChC,QAAO;IAAE,SAAS,MAAM,WAAW;IAAS,SAAS;IAAO;AAE9D,OAAI,cAAc,WAAW,KAAK,CAChC,QAAO;IACL,SAAS,aAAa,QAAQ;IAC9B,SAAS;IACV;GAGH,MAAM,cAAc,iBAAiB,SAAS;AAC9C,OAAI,YAAY,OAAO,MACrB,QAAO;IAAE,SAAS,MAAM,YAAY;IAAS,SAAS;IAAO;GAI/D,MAAM,gBAAgB,WADH,mBACwB,CAAC;AAC5C,wBAAqB,eAAe,WAAW,MAAM,YAAY,MAAM;GAEvE,MAAM,YAAY,aAAa,UAAU,cAAc;AACvD,OAAI,CAAC,UAAU,SAAS;IACtB,MAAM,aAAa,UAAU,MAAM,OAAO;AAE1C,WAAO;KACL,SAAS,gCAFO,WAAW,KAAK,KAAK,IAEa,CAAC,IAAI,WAAW,QAAQ;KAC1E,SAAS;KACV;;AAGH,SAAM,WAAW,UAAU,KAAK;AAChC,OAAI,KAAK;IAAE,MAAM;IAAS,OAAO,YAAY;IAAO,EAAE,iCAAiC;AAMvF,UAAO,EAAE,SAAS,wBAAwB,QAAQ,OAHhD,OAAO,YAAY,UAAU,WACzB,IAAI,YAAY,MAAM,KACtB,KAAK,UAAU,YAAY,MAAM,IACgC;;AAGzE,MAAI,WAAW,SAAS;AACtB,OAAI,CAAC,+BAA+B,IAAI,CACtC,QAAO;IACL,SAAS;IACT,SAAS;IACV;AAEH,OAAI,CAAC,KACH,QAAO;IAAE,SAAS;IAAgC,SAAS;IAAO;GAEpE,MAAM,aAAa,gBAAgB,KAAK;AACxC,OAAI,CAAC,WAAW,MAAM,CAAC,WAAW,KAChC,QAAO;IAAE,SAAS,MAAM,WAAW;IAAS,SAAS;IAAO;AAE9D,OAAI,cAAc,WAAW,KAAK,CAChC,QAAO;IACL,SAAS,aAAa,KAAK;IAC3B,SAAS;IACV;GAIH,MAAM,gBAAgB,WADH,mBACwB,CAAC;AAE5C,OAAI,CADY,uBAAuB,eAAe,WAAW,KACrD,CACV,QAAO;IAAE,SAAS,iCAAiC,KAAK;IAAM,SAAS;IAAO;GAGhF,MAAM,YAAY,aAAa,UAAU,cAAc;AACvD,OAAI,CAAC,UAAU,SAAS;IACtB,MAAM,aAAa,UAAU,MAAM,OAAO;AAE1C,WAAO;KACL,SAAS,kCAFO,WAAW,KAAK,KAAK,IAEe,CAAC,IAAI,WAAW,QAAQ;KAC5E,SAAS;KACV;;AAGH,SAAM,WAAW,UAAU,KAAK;AAChC,OAAI,KAAK,EAAE,MAAM,MAAM,EAAE,uCAAuC;AAChE,UAAO,EAAE,SAAS,wBAAwB,KAAK,cAAc;;AAG/D,SAAO,EACL,SACE,oWASH;;CAEJ;AAED,SAAgB,wBAA8B;AAC5C,iBAAgB,SAAS,cAAc"}
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Persistent `/goal` (Hermes-style Ralph loop) on any channel with session metadata.
2
+ * `/goal` — first-class goal control from any command surface.
3
3
  */
4
4
  export declare function registerGoalCommand(): void;
@@ -1,33 +1,29 @@
1
+ import { getDefaultAgentId, init_resolve_route } from "../../routing/resolve-route.js";
2
+ import { GoalService } from "../../goals/goal-service.js";
3
+ import "../../goals/index.js";
1
4
  import { commandRegistry } from "../registry.js";
2
- import { PERSISTENT_GOAL_CUSTOM_KEY, defaultMaxTurns, mergeCustomDataPatch, readPersistentGoal, serializePersistentGoal } from "../../agent/goals/state.js";
3
- import { applyPersistentGoalUserAction } from "../../agent/goals/patch-from-user-action.js";
4
5
  //#region src/chat-commands/builtins/goal.ts
5
- function statusLine(state) {
6
- const turns = `${state.turnsUsed}/${state.maxTurns} turns`;
7
- if (state.status === "active") return `⊙ Goal (active, ${turns}): ${state.goal}`;
8
- if (state.status === "paused") return `⏸ Goal (paused, ${turns}${state.pausedReason ? ` — ${state.pausedReason}` : ""}): ${state.goal}`;
9
- if (state.status === "done") return `✓ Goal done (${turns}): ${state.goal}`;
10
- return `Goal (${state.status}, ${turns}): ${state.goal}`;
6
+ init_resolve_route();
7
+ const goals = new GoalService();
8
+ function statusLine(goal) {
9
+ const turns = `${goal.turnsUsed}/${goal.maxTurns} turns`;
10
+ const progress = goal.checklist.length ? ` · ${goal.checklist.filter((it) => it.status === "completed" || it.status === "impossible").length}/${goal.checklist.length} criteria` : "";
11
+ if (goal.status === "active") return `⊙ Goal (active, ${turns}${progress}): ${goal.title}`;
12
+ if (goal.status === "paused") return `⏸ Goal (paused, ${turns}${progress}): ${goal.title}`;
13
+ if (goal.status === "blocked" || goal.status === "needs_input") {
14
+ const reason = goal.blockedReason ? ` — ${goal.blockedReason}` : "";
15
+ return `⏸ Goal (${goal.status}, ${turns}${progress}${reason}): ${goal.title}`;
16
+ }
17
+ if (goal.status === "done") return `✓ Goal done (${turns}${progress}): ${goal.title}`;
18
+ return `Goal (${goal.status}, ${turns}${progress}): ${goal.title}`;
11
19
  }
12
- async function patchGoalMetadata(ctx, patchCustom) {
13
- const apis = ctx.persistentGoalApis;
14
- if (!apis) return {
15
- ok: false,
16
- error: "Goals unavailable on this surface."
17
- };
18
- const meta = await apis.getSessionMetadata(ctx.sessionKey);
19
- if (!meta) return {
20
- ok: false,
21
- error: "Session not found"
22
- };
23
- const customData = patchCustom({ ...meta.customData });
24
- await apis.updateSessionMetadata(ctx.sessionKey, { customData });
25
- return { ok: true };
20
+ function activeGoal(ctx) {
21
+ return goals.getActiveForSession(ctx.sessionKey);
26
22
  }
27
23
  const goalCommand = {
28
24
  id: "system.goal",
29
25
  name: "goal",
30
- description: "Set or manage a standing goal (Hermes-style): checklist + judge loop; /subgoal edits criteria; pause, resume, clear",
26
+ description: "Create and manage a durable goal: checklist + judge loop; /subgoal edits criteria",
31
27
  category: "system",
32
28
  scope: [
33
29
  "global",
@@ -43,111 +39,73 @@ const goalCommand = {
43
39
  "/goal clear"
44
40
  ],
45
41
  handler: async (ctx, args) => {
46
- const apis = ctx.persistentGoalApis;
47
- if (!apis) return {
48
- content: "Goals unavailable on this surface.",
49
- success: false
50
- };
51
42
  const t = args.trim();
52
43
  const lower = t.toLowerCase();
53
44
  if (!t || lower === "status") {
54
- const s = readPersistentGoal((await apis.getSessionMetadata(ctx.sessionKey))?.customData);
55
- if (!s || s.status === "cleared") return {
56
- content: "No active goal. Set one with /goal <text>.",
57
- success: true
58
- };
45
+ const goal = activeGoal(ctx);
59
46
  return {
60
- content: statusLine(s),
47
+ content: goal ? statusLine(goal) : "No active goal. Set one with /goal <text>.",
61
48
  success: true
62
49
  };
63
50
  }
64
51
  if (lower === "pause") {
65
- const applied = applyPersistentGoalUserAction((await apis.getSessionMetadata(ctx.sessionKey))?.customData, "pause");
66
- if (applied.kind === "error") return {
67
- content: applied.error,
68
- success: false
69
- };
70
- if (applied.kind === "noop") return {
71
- content: applied.message,
52
+ const goal = activeGoal(ctx);
53
+ if (!goal) return {
54
+ content: "No active goal.",
72
55
  success: true
73
56
  };
74
- const r = await patchGoalMetadata(ctx, () => applied.customData);
75
- if (!r.ok) return {
76
- content: "error" in r ? r.error : "Failed",
77
- success: false
78
- };
79
57
  return {
80
- content: `⏸ Goal paused: ${readPersistentGoal(applied.customData)?.goal ?? ""}`,
58
+ content: `⏸ Goal paused: ${goals.pause(goal.id)?.title ?? goal.title}`,
81
59
  success: true
82
60
  };
83
61
  }
84
62
  if (lower === "resume") {
85
- const applied = applyPersistentGoalUserAction((await apis.getSessionMetadata(ctx.sessionKey))?.customData, "resume");
86
- if (applied.kind === "error") return {
87
- content: applied.error,
88
- success: false
89
- };
90
- if (applied.kind === "noop") return {
91
- content: applied.message,
63
+ const goal = activeGoal(ctx);
64
+ if (!goal) return {
65
+ content: "No goal to resume.",
92
66
  success: true
93
67
  };
94
- const r = await patchGoalMetadata(ctx, () => applied.customData);
95
- if (!r.ok) return {
96
- content: "error" in r ? r.error : "Failed",
97
- success: false
98
- };
68
+ const next = goals.resume(goal.id);
69
+ ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, next?.nextAction || next?.title || goal.title);
99
70
  return {
100
- content: `▶ Goal resumed: ${readPersistentGoal(applied.customData)?.goal ?? ""}\nSend any message to continue, or wait — the next assistant turn will pick up from here.`,
71
+ content: `▶ Goal resumed: ${next?.title ?? goal.title}`,
101
72
  success: true
102
73
  };
103
74
  }
104
- if (lower === "clear" || lower === "stop" || lower === "done") {
105
- const meta = await apis.getSessionMetadata(ctx.sessionKey);
106
- const had = !!readPersistentGoal(meta?.customData);
107
- const applied = applyPersistentGoalUserAction(meta?.customData, "clear");
108
- if (applied.kind === "error") return {
109
- content: applied.error,
110
- success: false
111
- };
112
- if (applied.kind === "noop") return {
113
- content: applied.message,
75
+ if (lower === "clear" || lower === "stop" || lower === "archive") {
76
+ const goal = activeGoal(ctx);
77
+ if (!goal) return {
78
+ content: "No active goal.",
114
79
  success: true
115
80
  };
116
- const r = await patchGoalMetadata(ctx, () => applied.customData);
117
- if (!r.ok) return {
118
- content: "error" in r ? r.error : "Failed",
119
- success: false
120
- };
81
+ goals.archive(goal.id);
82
+ try {
83
+ await ctx.abortCurrentTurn?.();
84
+ } catch {
85
+ return {
86
+ content: "✓ Goal archived. Current turn could not be stopped automatically.",
87
+ success: true
88
+ };
89
+ }
121
90
  return {
122
- content: had ? "✓ Goal cleared." : "No active goal.",
91
+ content: "✓ Goal archived.",
123
92
  success: true
124
93
  };
125
94
  }
126
- if (apis.inboundConcurrentDepth(ctx.sessionKey) > 1) return {
95
+ if ((ctx.persistentGoalApis?.inboundConcurrentDepth(ctx.sessionKey) ?? 0) > 1) return {
127
96
  content: "Agent is running — use /goal status / pause / clear mid-run, or wait for the current turn to finish before setting a new goal.",
128
97
  success: false
129
98
  };
130
- const maxTurns = defaultMaxTurns(ctx.config.goals);
131
- const judgeModelRef = typeof ctx.config.goals?.judgeModelRef === "string" ? ctx.config.goals.judgeModelRef.trim() : void 0;
132
- const next = {
133
- goal: t,
134
- status: "active",
135
- turnsUsed: 0,
136
- maxTurns,
137
- createdAt: Date.now(),
138
- lastTurnAt: 0,
139
- decomposed: false,
140
- consecutiveParseFailures: 0,
141
- ...judgeModelRef ? { judgeModelRef } : {}
142
- };
143
- const r = await patchGoalMetadata(ctx, (base) => mergeCustomDataPatch(base, { [PERSISTENT_GOAL_CUSTOM_KEY]: serializePersistentGoal(next) }));
144
- if (!r.ok) return {
145
- content: "error" in r ? r.error : "Failed",
146
- success: false
147
- };
148
- apis.scheduleContinuation(ctx.sessionKey, next.goal);
99
+ const goal = goals.create({
100
+ title: t,
101
+ sessionKey: ctx.sessionKey,
102
+ agentId: getDefaultAgentId(ctx.config),
103
+ config: ctx.config,
104
+ source: ctx.source === "cli" ? "cli" : ctx.source === "api" ? "api" : "channel"
105
+ });
106
+ ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, goal.title);
149
107
  return {
150
- content: `⊙ Goal set (${next.maxTurns}-turn budget): ${next.goal}\nI'll keep working until the goal is done, you pause/clear it, or the budget is exhausted.
108
+ content: `⊙ Goal set (${goal.maxTurns}-turn budget): ${goal.title}\nI'll keep working until the goal is done, you pause/archive it, or the budget is exhausted.
151
109
  Controls: /goal status · /goal pause · /goal resume · /goal clear · /subgoal`,
152
110
  success: true
153
111
  };
@@ -1 +1 @@
1
- {"version":3,"file":"goal.js","names":[],"sources":["../../../../src/chat-commands/builtins/goal.ts"],"sourcesContent":["/**\n * Persistent `/goal` (Hermes-style Ralph loop) on any channel with session metadata.\n */\n\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { commandRegistry } from '../registry.js';\n\nimport {\n defaultMaxTurns,\n mergeCustomDataPatch,\n readPersistentGoal,\n serializePersistentGoal,\n PERSISTENT_GOAL_CUSTOM_KEY,\n type PersistentGoalState,\n} from '../../agent/goals/state.js';\nimport { applyPersistentGoalUserAction } from '../../agent/goals/patch-from-user-action.js';\n\nfunction statusLine(state: NonNullable<ReturnType<typeof readPersistentGoal>>): string {\n const turns = `${state.turnsUsed}/${state.maxTurns} turns`;\n if (state.status === 'active') {\n return `⊙ Goal (active, ${turns}): ${state.goal}`;\n }\n if (state.status === 'paused') {\n const extra = state.pausedReason ? ` — ${state.pausedReason}` : '';\n return `⏸ Goal (paused, ${turns}${extra}): ${state.goal}`;\n }\n if (state.status === 'done') {\n return `✓ Goal done (${turns}): ${state.goal}`;\n }\n return `Goal (${state.status}, ${turns}): ${state.goal}`;\n}\n\nasync function patchGoalMetadata(\n ctx: CommandContext,\n patchCustom: (base: Record<string, unknown>) => Record<string, unknown>,\n): Promise<{ ok: true } | { ok: false; error: string }> {\n const apis = ctx.persistentGoalApis;\n if (!apis) return { ok: false, error: 'Goals unavailable on this surface.' };\n const meta = await apis.getSessionMetadata(ctx.sessionKey);\n if (!meta) return { ok: false, error: 'Session not found' };\n const base = { ...(meta.customData as Record<string, unknown> | undefined) };\n const customData = patchCustom(base);\n await apis.updateSessionMetadata(ctx.sessionKey, { customData });\n return { ok: true };\n}\n\nconst goalCommand: CommandDefinition = {\n id: 'system.goal',\n name: 'goal',\n description:\n 'Set or manage a standing goal (Hermes-style): checklist + judge loop; /subgoal edits criteria; pause, resume, clear',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/goal Ship the fix', '/goal status', '/goal pause', '/goal resume', '/goal clear'],\n handler: async (ctx: CommandContext, args: string) => {\n const apis = ctx.persistentGoalApis;\n if (!apis) {\n return {\n content: 'Goals unavailable on this surface.',\n success: false,\n };\n }\n\n const t = args.trim();\n const lower = t.toLowerCase();\n\n if (!t || lower === 'status') {\n const meta = await apis.getSessionMetadata(ctx.sessionKey);\n const s = readPersistentGoal(meta?.customData as Record<string, unknown> | undefined);\n if (!s || s.status === 'cleared') {\n return {\n content: 'No active goal. Set one with /goal <text>.',\n success: true,\n };\n }\n return { content: statusLine(s), success: true };\n }\n\n if (lower === 'pause') {\n const meta = await apis.getSessionMetadata(ctx.sessionKey);\n const applied = applyPersistentGoalUserAction(\n meta?.customData as Record<string, unknown> | undefined,\n 'pause',\n );\n if (applied.kind === 'error') {\n return { content: applied.error, success: false };\n }\n if (applied.kind === 'noop') {\n return { content: applied.message, success: true };\n }\n const r = await patchGoalMetadata(ctx, () => applied.customData);\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n const s = readPersistentGoal(applied.customData);\n return { content: `⏸ Goal paused: ${s?.goal ?? ''}`, success: true };\n }\n\n if (lower === 'resume') {\n const meta = await apis.getSessionMetadata(ctx.sessionKey);\n const applied = applyPersistentGoalUserAction(\n meta?.customData as Record<string, unknown> | undefined,\n 'resume',\n );\n if (applied.kind === 'error') {\n return { content: applied.error, success: false };\n }\n if (applied.kind === 'noop') {\n return { content: applied.message, success: true };\n }\n const r = await patchGoalMetadata(ctx, () => applied.customData);\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n const s = readPersistentGoal(applied.customData);\n return {\n content:\n `▶ Goal resumed: ${s?.goal ?? ''}\\n` +\n 'Send any message to continue, or wait — the next assistant turn will pick up from here.',\n success: true,\n };\n }\n\n if (lower === 'clear' || lower === 'stop' || lower === 'done') {\n const meta = await apis.getSessionMetadata(ctx.sessionKey);\n const had = !!readPersistentGoal(meta?.customData as Record<string, unknown> | undefined);\n const applied = applyPersistentGoalUserAction(\n meta?.customData as Record<string, unknown> | undefined,\n 'clear',\n );\n if (applied.kind === 'error') {\n return { content: applied.error, success: false };\n }\n if (applied.kind === 'noop') {\n return { content: applied.message, success: true };\n }\n const r = await patchGoalMetadata(ctx, () => applied.customData);\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n return { content: had ? '✓ Goal cleared.' : 'No active goal.', success: true };\n }\n\n // New goal text — Hermes rejects when another inbound turn is in flight for this session.\n const depth = apis.inboundConcurrentDepth(ctx.sessionKey);\n if (depth > 1) {\n return {\n content:\n 'Agent is running — use /goal status / pause / clear mid-run, or wait for the current turn to finish before setting a new goal.',\n success: false,\n };\n }\n\n const maxTurns = defaultMaxTurns(ctx.config.goals);\n const judgeModelRef =\n typeof ctx.config.goals?.judgeModelRef === 'string' ? ctx.config.goals.judgeModelRef.trim() : undefined;\n\n const next: PersistentGoalState = {\n goal: t,\n status: 'active',\n turnsUsed: 0,\n maxTurns,\n createdAt: Date.now(),\n lastTurnAt: 0,\n decomposed: false,\n consecutiveParseFailures: 0,\n ...(judgeModelRef ? { judgeModelRef } : {}),\n };\n\n const r = await patchGoalMetadata(ctx, (base) =>\n mergeCustomDataPatch(base, { [PERSISTENT_GOAL_CUSTOM_KEY]: serializePersistentGoal(next) }),\n );\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n\n apis.scheduleContinuation(ctx.sessionKey, next.goal);\n\n return {\n content:\n `⊙ Goal set (${next.maxTurns}-turn budget): ${next.goal}\\n` +\n \"I'll keep working until the goal is done, you pause/clear it, or the budget is exhausted.\\n\" +\n 'Controls: /goal status · /goal pause · /goal resume · /goal clear · /subgoal',\n success: true,\n };\n },\n};\n\nexport function registerGoalCommand(): void {\n commandRegistry.register(goalCommand);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"goal.js","names":[],"sources":["../../../../src/chat-commands/builtins/goal.ts"],"sourcesContent":["/**\n * `/goal` — first-class goal control from any command surface.\n */\n\nimport { getDefaultAgentId } from '../../routing/resolve-route.js';\nimport { GoalService, type GoalWithDetails } from '../../goals/index.js';\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { commandRegistry } from '../registry.js';\n\nconst goals = new GoalService();\n\nfunction statusLine(goal: GoalWithDetails): string {\n const turns = `${goal.turnsUsed}/${goal.maxTurns} turns`;\n const progress = goal.checklist.length\n ? ` · ${goal.checklist.filter((it) => it.status === 'completed' || it.status === 'impossible').length}/${goal.checklist.length} criteria`\n : '';\n if (goal.status === 'active') return `⊙ Goal (active, ${turns}${progress}): ${goal.title}`;\n if (goal.status === 'paused') return `⏸ Goal (paused, ${turns}${progress}): ${goal.title}`;\n if (goal.status === 'blocked' || goal.status === 'needs_input') {\n const reason = goal.blockedReason ? ` — ${goal.blockedReason}` : '';\n return `⏸ Goal (${goal.status}, ${turns}${progress}${reason}): ${goal.title}`;\n }\n if (goal.status === 'done') return `✓ Goal done (${turns}${progress}): ${goal.title}`;\n return `Goal (${goal.status}, ${turns}${progress}): ${goal.title}`;\n}\n\nfunction activeGoal(ctx: CommandContext): GoalWithDetails | null {\n return goals.getActiveForSession(ctx.sessionKey);\n}\n\nconst goalCommand: CommandDefinition = {\n id: 'system.goal',\n name: 'goal',\n description: 'Create and manage a durable goal: checklist + judge loop; /subgoal edits criteria',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/goal Ship the fix', '/goal status', '/goal pause', '/goal resume', '/goal clear'],\n handler: async (ctx: CommandContext, args: string) => {\n const t = args.trim();\n const lower = t.toLowerCase();\n\n if (!t || lower === 'status') {\n const goal = activeGoal(ctx);\n return {\n content: goal ? statusLine(goal) : 'No active goal. Set one with /goal <text>.',\n success: true,\n };\n }\n\n if (lower === 'pause') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No active goal.', success: true };\n const next = goals.pause(goal.id);\n return { content: `⏸ Goal paused: ${next?.title ?? goal.title}`, success: true };\n }\n\n if (lower === 'resume') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No goal to resume.', success: true };\n const next = goals.resume(goal.id);\n ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, next?.nextAction || next?.title || goal.title);\n return { content: `▶ Goal resumed: ${next?.title ?? goal.title}`, success: true };\n }\n\n if (lower === 'clear' || lower === 'stop' || lower === 'archive') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No active goal.', success: true };\n goals.archive(goal.id);\n try {\n await ctx.abortCurrentTurn?.();\n } catch {\n return { content: '✓ Goal archived. Current turn could not be stopped automatically.', success: true };\n }\n return { content: '✓ Goal archived.', success: true };\n }\n\n const depth = ctx.persistentGoalApis?.inboundConcurrentDepth(ctx.sessionKey) ?? 0;\n if (depth > 1) {\n return {\n content:\n 'Agent is running — use /goal status / pause / clear mid-run, or wait for the current turn to finish before setting a new goal.',\n success: false,\n };\n }\n\n const goal = goals.create({\n title: t,\n sessionKey: ctx.sessionKey,\n agentId: getDefaultAgentId(ctx.config),\n config: ctx.config,\n source: ctx.source === 'cli' ? 'cli' : ctx.source === 'api' ? 'api' : 'channel',\n });\n\n ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, goal.title);\n\n return {\n content:\n `⊙ Goal set (${goal.maxTurns}-turn budget): ${goal.title}\\n` +\n \"I'll keep working until the goal is done, you pause/archive it, or the budget is exhausted.\\n\" +\n 'Controls: /goal status · /goal pause · /goal resume · /goal clear · /subgoal',\n success: true,\n };\n },\n};\n\nexport function registerGoalCommand(): void {\n commandRegistry.register(goalCommand);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  /**
2
- * `/subgoal` — view or edit the standing goal checklist (Hermes parity).
2
+ * `/subgoal` — view or edit checklist criteria for the active first-class goal.
3
3
  */
4
4
  export declare function registerSubgoalCommand(): void;
@@ -1,27 +1,28 @@
1
+ import { GoalService } from "../../goals/goal-service.js";
2
+ import "../../goals/index.js";
1
3
  import { commandRegistry } from "../registry.js";
2
- import { checklistCounts } from "../../agent/goals/checklist-types.js";
3
- import { readPersistentGoal, renderChecklistNumbered } from "../../agent/goals/state.js";
4
- import { applyChecklistUserMutation } from "../../agent/goals/checklist-user.js";
5
4
  //#region src/chat-commands/builtins/subgoal.ts
6
- async function patchMetadata(ctx, patchCustom) {
7
- const apis = ctx.persistentGoalApis;
8
- if (!apis) return {
9
- ok: false,
10
- error: "Goals unavailable on this surface."
11
- };
12
- const meta = await apis.getSessionMetadata(ctx.sessionKey);
13
- if (!meta) return {
14
- ok: false,
15
- error: "Session not found"
16
- };
17
- const customData = patchCustom({ ...meta.customData });
18
- await apis.updateSessionMetadata(ctx.sessionKey, { customData });
19
- return { ok: true };
5
+ /**
6
+ * `/subgoal` view or edit checklist criteria for the active first-class goal.
7
+ */
8
+ const goals = new GoalService();
9
+ function activeGoal(ctx) {
10
+ return goals.getActiveForSession(ctx.sessionKey);
11
+ }
12
+ function renderChecklist(goal) {
13
+ if (!goal.checklist.length) return "Checklist is empty. Add criteria with /subgoal add <text>.";
14
+ const done = goal.checklist.filter((it) => it.status === "completed" || it.status === "impossible").length;
15
+ const lines = goal.checklist.map((it, index) => {
16
+ const marker = it.status === "completed" ? "[x]" : it.status === "impossible" ? "[!]" : "[ ]";
17
+ const evidence = it.evidenceSummary ? ` (${it.evidenceSummary})` : "";
18
+ return `${index + 1}. ${marker} ${it.text}${evidence}`;
19
+ });
20
+ return `Checklist (${done}/${goal.checklist.length} terminal):\n${lines.join("\n")}`;
20
21
  }
21
22
  const subgoalCommand = {
22
23
  id: "system.subgoal",
23
24
  name: "subgoal",
24
- description: "View or edit checklist criteria for the active /goal (add, mark, remove, reset)",
25
+ description: "View or edit checklist criteria for the active goal (add, mark, remove, reset)",
25
26
  category: "system",
26
27
  scope: [
27
28
  "global",
@@ -37,73 +38,31 @@ const subgoalCommand = {
37
38
  "/subgoal reset"
38
39
  ],
39
40
  handler: async (ctx, args) => {
40
- const apis = ctx.persistentGoalApis;
41
- if (!apis) return {
42
- content: "Goals unavailable on this surface.",
43
- success: false
41
+ const goal = activeGoal(ctx);
42
+ if (!goal) return {
43
+ content: "No active goal. Set one with /goal <text> first.",
44
+ success: true
44
45
  };
45
46
  const t = args.trim();
46
47
  const lower = t.toLowerCase();
47
- const custom = (await apis.getSessionMetadata(ctx.sessionKey))?.customData;
48
- const s = readPersistentGoal(custom);
49
- if (!t || lower === "list" || lower === "status") {
50
- if (!s || s.status === "cleared") return {
51
- content: "No active goal. Set one with /goal <text> first.",
52
- success: true
53
- };
54
- const items = s.checklist ?? [];
55
- if (!items.length) return {
56
- content: s.decomposed === true ? "Checklist is empty (decomposition produced no items). The judge will use freeform mode." : "Checklist not built yet — it appears after the first assistant turn once decomposition runs.",
57
- success: true
58
- };
59
- const { total, completed, impossible } = checklistCounts(items);
60
- return {
61
- content: `Checklist (${completed + impossible}/${total} terminal):\n` + renderChecklistNumbered(items),
62
- success: true
63
- };
64
- }
48
+ if (!t || lower === "list" || lower === "status") return {
49
+ content: renderChecklist(goal),
50
+ success: true
51
+ };
65
52
  if (lower === "reset" || lower === "clear") {
66
- const applied = applyChecklistUserMutation(custom, { type: "reset" });
67
- if (applied.kind === "error") return {
68
- content: applied.error,
69
- success: false
70
- };
71
- if (applied.kind === "noop") return {
72
- content: applied.message,
73
- success: true
74
- };
75
- const cd = applied.customData;
76
- const r = await patchMetadata(ctx, () => cd);
77
- if (!r.ok) return {
78
- content: "error" in r ? r.error : "Failed",
79
- success: false
80
- };
53
+ goals.updateChecklist(goal.id, { type: "reset" });
81
54
  return {
82
- content: "✓ Checklist cleared. Decomposition will run again on the next goal evaluation turn (or set /goal anew).",
55
+ content: "✓ Checklist cleared.",
83
56
  success: true
84
57
  };
85
58
  }
86
59
  const addM = t.match(/^add\s+([\s\S]+)$/i);
87
60
  if (addM) {
88
61
  const text = addM[1].trim();
89
- const applied = applyChecklistUserMutation(custom, {
62
+ goals.updateChecklist(goal.id, {
90
63
  type: "add",
91
64
  text
92
65
  });
93
- if (applied.kind === "error") return {
94
- content: applied.error,
95
- success: false
96
- };
97
- if (applied.kind === "noop") return {
98
- content: applied.message,
99
- success: true
100
- };
101
- const cd = applied.customData;
102
- const r = await patchMetadata(ctx, () => cd);
103
- if (!r.ok) return {
104
- content: "error" in r ? r.error : "Failed",
105
- success: false
106
- };
107
66
  return {
108
67
  content: `⊙ Added checklist item: ${text}`,
109
68
  success: true
@@ -111,60 +70,42 @@ const subgoalCommand = {
111
70
  }
112
71
  const removeM = t.match(/^remove\s+(\d+)\s*$/i);
113
72
  if (removeM) {
114
- const idx = Number(removeM[1]);
115
- const applied = applyChecklistUserMutation(custom, {
116
- type: "remove",
117
- index1Based: idx
118
- });
119
- if (applied.kind === "error") return {
120
- content: applied.error,
121
- success: false
122
- };
123
- if (applied.kind === "noop") return {
124
- content: applied.message,
125
- success: true
126
- };
127
- const cd = applied.customData;
128
- const r = await patchMetadata(ctx, () => cd);
129
- if (!r.ok) return {
130
- content: "error" in r ? r.error : "Failed",
73
+ const index = Number(removeM[1]);
74
+ const item = goal.checklist[index - 1];
75
+ if (!item) return {
76
+ content: `No checklist item #${index}.`,
131
77
  success: false
132
78
  };
79
+ goals.updateChecklist(goal.id, {
80
+ type: "remove",
81
+ itemId: item.id
82
+ });
133
83
  return {
134
- content: `✓ Removed item #${idx}.`,
84
+ content: `✓ Removed item #${index}.`,
135
85
  success: true
136
86
  };
137
87
  }
138
88
  const markM = t.match(/^mark\s+(\d+)\s+(pending|completed|impossible)\s*$/i);
139
89
  if (markM) {
140
- const idx = Number(markM[1]);
90
+ const index = Number(markM[1]);
141
91
  const status = markM[2].toLowerCase();
142
- const applied = applyChecklistUserMutation(custom, {
92
+ const item = goal.checklist[index - 1];
93
+ if (!item) return {
94
+ content: `No checklist item #${index}.`,
95
+ success: false
96
+ };
97
+ goals.updateChecklist(goal.id, {
143
98
  type: "mark",
144
- index1Based: idx,
99
+ itemId: item.id,
145
100
  status
146
101
  });
147
- if (applied.kind === "error") return {
148
- content: applied.error,
149
- success: false
150
- };
151
- if (applied.kind === "noop") return {
152
- content: applied.message,
153
- success: true
154
- };
155
- const cd = applied.customData;
156
- const r = await patchMetadata(ctx, () => cd);
157
- if (!r.ok) return {
158
- content: "error" in r ? r.error : "Failed",
159
- success: false
160
- };
161
102
  return {
162
- content: `⊙ Item #${idx} ${status}.`,
103
+ content: `⊙ Item #${index} -> ${status}.`,
163
104
  success: true
164
105
  };
165
106
  }
166
107
  return {
167
- content: "Usage:\n• /subgoal — show checklist\n• /subgoal add <text>\n• /subgoal mark <n> pending|completed|impossible\n• /subgoal remove <n>\n• /subgoal reset — wipe checklist (re-decompose on next turn)",
108
+ content: "Usage:\n• /subgoal — show checklist\n• /subgoal add <text>\n• /subgoal mark <n> pending|completed|impossible\n• /subgoal remove <n>\n• /subgoal reset",
168
109
  success: true
169
110
  };
170
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"subgoal.js","names":[],"sources":["../../../../src/chat-commands/builtins/subgoal.ts"],"sourcesContent":["/**\n * `/subgoal` — view or edit the standing goal checklist (Hermes parity).\n */\n\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { commandRegistry } from '../registry.js';\n\nimport { applyChecklistUserMutation } from '../../agent/goals/checklist-user.js';\nimport { checklistCounts } from '../../agent/goals/checklist-types.js';\nimport { readPersistentGoal, renderChecklistNumbered } from '../../agent/goals/state.js';\n\nasync function patchMetadata(\n ctx: CommandContext,\n patchCustom: (base: Record<string, unknown>) => Record<string, unknown>,\n): Promise<{ ok: true } | { ok: false; error: string }> {\n const apis = ctx.persistentGoalApis;\n if (!apis) return { ok: false, error: 'Goals unavailable on this surface.' };\n const meta = await apis.getSessionMetadata(ctx.sessionKey);\n if (!meta) return { ok: false, error: 'Session not found' };\n const base = { ...(meta.customData as Record<string, unknown> | undefined) };\n const customData = patchCustom(base);\n await apis.updateSessionMetadata(ctx.sessionKey, { customData });\n return { ok: true };\n}\n\nconst subgoalCommand: CommandDefinition = {\n id: 'system.subgoal',\n name: 'subgoal',\n description: 'View or edit checklist criteria for the active /goal (add, mark, remove, reset)',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: [\n '/subgoal',\n '/subgoal add Run tests in CI',\n '/subgoal mark 2 completed',\n '/subgoal remove 3',\n '/subgoal reset',\n ],\n handler: async (ctx: CommandContext, args: string) => {\n const apis = ctx.persistentGoalApis;\n if (!apis) {\n return { content: 'Goals unavailable on this surface.', success: false };\n }\n\n const t = args.trim();\n const lower = t.toLowerCase();\n const meta = await apis.getSessionMetadata(ctx.sessionKey);\n const custom = meta?.customData as Record<string, unknown> | undefined;\n const s = readPersistentGoal(custom);\n\n if (!t || lower === 'list' || lower === 'status') {\n if (!s || s.status === 'cleared') {\n return { content: 'No active goal. Set one with /goal <text> first.', success: true };\n }\n const items = s.checklist ?? [];\n if (!items.length) {\n return {\n content:\n s.decomposed === true\n ? 'Checklist is empty (decomposition produced no items). The judge will use freeform mode.'\n : 'Checklist not built yet — it appears after the first assistant turn once decomposition runs.',\n success: true,\n };\n }\n const { total, completed, impossible } = checklistCounts(items);\n const header = `Checklist (${completed + impossible}/${total} terminal):\\n`;\n return { content: header + renderChecklistNumbered(items), success: true };\n }\n\n if (lower === 'reset' || lower === 'clear') {\n const applied = applyChecklistUserMutation(custom, { type: 'reset' });\n if (applied.kind === 'error') return { content: applied.error, success: false };\n if (applied.kind === 'noop') return { content: applied.message, success: true };\n const cd = applied.customData;\n const r = await patchMetadata(ctx, () => cd);\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n return {\n content:\n '✓ Checklist cleared. Decomposition will run again on the next goal evaluation turn (or set /goal anew).',\n success: true,\n };\n }\n\n const addM = t.match(/^add\\s+([\\s\\S]+)$/i);\n if (addM) {\n const text = addM[1]!.trim();\n const applied = applyChecklistUserMutation(custom, { type: 'add', text });\n if (applied.kind === 'error') return { content: applied.error, success: false };\n if (applied.kind === 'noop') return { content: applied.message, success: true };\n const cd = applied.customData;\n const r = await patchMetadata(ctx, () => cd);\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n return { content: `⊙ Added checklist item: ${text}`, success: true };\n }\n\n const removeM = t.match(/^remove\\s+(\\d+)\\s*$/i);\n if (removeM) {\n const idx = Number(removeM[1]);\n const applied = applyChecklistUserMutation(custom, { type: 'remove', index1Based: idx });\n if (applied.kind === 'error') return { content: applied.error, success: false };\n if (applied.kind === 'noop') return { content: applied.message, success: true };\n const cd = applied.customData;\n const r = await patchMetadata(ctx, () => cd);\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n return { content: `✓ Removed item #${idx}.`, success: true };\n }\n\n const markM = t.match(/^mark\\s+(\\d+)\\s+(pending|completed|impossible)\\s*$/i);\n if (markM) {\n const idx = Number(markM[1]);\n const status = markM[2]!.toLowerCase() as 'pending' | 'completed' | 'impossible';\n const applied = applyChecklistUserMutation(custom, { type: 'mark', index1Based: idx, status });\n if (applied.kind === 'error') return { content: applied.error, success: false };\n if (applied.kind === 'noop') return { content: applied.message, success: true };\n const cd = applied.customData;\n const r = await patchMetadata(ctx, () => cd);\n if (!r.ok) return { content: 'error' in r ? r.error : 'Failed', success: false };\n return { content: `⊙ Item #${idx} ${status}.`, success: true };\n }\n\n return {\n content:\n 'Usage:\\n' +\n '• /subgoal — show checklist\\n' +\n '• /subgoal add <text>\\n' +\n '• /subgoal mark <n> pending|completed|impossible\\n' +\n '• /subgoal remove <n>\\n' +\n '• /subgoal reset — wipe checklist (re-decompose on next turn)',\n success: true,\n };\n },\n};\n\nexport function registerSubgoalCommand(): void {\n commandRegistry.register(subgoalCommand);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"subgoal.js","names":[],"sources":["../../../../src/chat-commands/builtins/subgoal.ts"],"sourcesContent":["/**\n * `/subgoal` — view or edit checklist criteria for the active first-class goal.\n */\n\nimport { GoalService } from '../../goals/index.js';\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { commandRegistry } from '../registry.js';\n\nconst goals = new GoalService();\n\nfunction activeGoal(ctx: CommandContext) {\n return goals.getActiveForSession(ctx.sessionKey);\n}\n\nfunction renderChecklist(goal: NonNullable<ReturnType<typeof activeGoal>>): string {\n if (!goal.checklist.length) return 'Checklist is empty. Add criteria with /subgoal add <text>.';\n const done = goal.checklist.filter((it) => it.status === 'completed' || it.status === 'impossible').length;\n const lines = goal.checklist.map((it, index) => {\n const marker = it.status === 'completed' ? '[x]' : it.status === 'impossible' ? '[!]' : '[ ]';\n const evidence = it.evidenceSummary ? ` (${it.evidenceSummary})` : '';\n return `${index + 1}. ${marker} ${it.text}${evidence}`;\n });\n return `Checklist (${done}/${goal.checklist.length} terminal):\\n${lines.join('\\n')}`;\n}\n\nconst subgoalCommand: CommandDefinition = {\n id: 'system.subgoal',\n name: 'subgoal',\n description: 'View or edit checklist criteria for the active goal (add, mark, remove, reset)',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: [\n '/subgoal',\n '/subgoal add Run tests in CI',\n '/subgoal mark 2 completed',\n '/subgoal remove 3',\n '/subgoal reset',\n ],\n handler: async (ctx: CommandContext, args: string) => {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No active goal. Set one with /goal <text> first.', success: true };\n\n const t = args.trim();\n const lower = t.toLowerCase();\n\n if (!t || lower === 'list' || lower === 'status') {\n return { content: renderChecklist(goal), success: true };\n }\n\n if (lower === 'reset' || lower === 'clear') {\n goals.updateChecklist(goal.id, { type: 'reset' });\n return { content: '✓ Checklist cleared.', success: true };\n }\n\n const addM = t.match(/^add\\s+([\\s\\S]+)$/i);\n if (addM) {\n const text = addM[1]!.trim();\n goals.updateChecklist(goal.id, { type: 'add', text });\n return { content: `⊙ Added checklist item: ${text}`, success: true };\n }\n\n const removeM = t.match(/^remove\\s+(\\d+)\\s*$/i);\n if (removeM) {\n const index = Number(removeM[1]);\n const item = goal.checklist[index - 1];\n if (!item) return { content: `No checklist item #${index}.`, success: false };\n goals.updateChecklist(goal.id, { type: 'remove', itemId: item.id });\n return { content: `✓ Removed item #${index}.`, success: true };\n }\n\n const markM = t.match(/^mark\\s+(\\d+)\\s+(pending|completed|impossible)\\s*$/i);\n if (markM) {\n const index = Number(markM[1]);\n const status = markM[2]!.toLowerCase() as 'pending' | 'completed' | 'impossible';\n const item = goal.checklist[index - 1];\n if (!item) return { content: `No checklist item #${index}.`, success: false };\n goals.updateChecklist(goal.id, { type: 'mark', itemId: item.id, status });\n return { content: `⊙ Item #${index} -> ${status}.`, success: true };\n }\n\n return {\n content:\n 'Usage:\\n' +\n '• /subgoal — show checklist\\n' +\n '• /subgoal add <text>\\n' +\n '• /subgoal mark <n> pending|completed|impossible\\n' +\n '• /subgoal remove <n>\\n' +\n '• /subgoal reset',\n success: true,\n };\n },\n};\n\nexport function registerSubgoalCommand(): void {\n commandRegistry.register(subgoalCommand);\n}\n"],"mappings":";;;;;;;AAQA,MAAM,QAAQ,IAAI,aAAa;AAE/B,SAAS,WAAW,KAAqB;AACvC,QAAO,MAAM,oBAAoB,IAAI,WAAW;;AAGlD,SAAS,gBAAgB,MAA0D;AACjF,KAAI,CAAC,KAAK,UAAU,OAAQ,QAAO;CACnC,MAAM,OAAO,KAAK,UAAU,QAAQ,OAAO,GAAG,WAAW,eAAe,GAAG,WAAW,aAAa,CAAC;CACpG,MAAM,QAAQ,KAAK,UAAU,KAAK,IAAI,UAAU;EAC9C,MAAM,SAAS,GAAG,WAAW,cAAc,QAAQ,GAAG,WAAW,eAAe,QAAQ;EACxF,MAAM,WAAW,GAAG,kBAAkB,KAAK,GAAG,gBAAgB,KAAK;AACnE,SAAO,GAAG,QAAQ,EAAE,IAAI,OAAO,GAAG,GAAG,OAAO;GAC5C;AACF,QAAO,cAAc,KAAK,GAAG,KAAK,UAAU,OAAO,eAAe,MAAM,KAAK,KAAK;;AAGpF,MAAM,iBAAoC;CACxC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,aAAa;CACb,UAAU;EACR;EACA;EACA;EACA;EACA;EACD;CACD,SAAS,OAAO,KAAqB,SAAiB;EACpD,MAAM,OAAO,WAAW,IAAI;AAC5B,MAAI,CAAC,KAAM,QAAO;GAAE,SAAS;GAAoD,SAAS;GAAM;EAEhG,MAAM,IAAI,KAAK,MAAM;EACrB,MAAM,QAAQ,EAAE,aAAa;AAE7B,MAAI,CAAC,KAAK,UAAU,UAAU,UAAU,SACtC,QAAO;GAAE,SAAS,gBAAgB,KAAK;GAAE,SAAS;GAAM;AAG1D,MAAI,UAAU,WAAW,UAAU,SAAS;AAC1C,SAAM,gBAAgB,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AACjD,UAAO;IAAE,SAAS;IAAwB,SAAS;IAAM;;EAG3D,MAAM,OAAO,EAAE,MAAM,qBAAqB;AAC1C,MAAI,MAAM;GACR,MAAM,OAAO,KAAK,GAAI,MAAM;AAC5B,SAAM,gBAAgB,KAAK,IAAI;IAAE,MAAM;IAAO;IAAM,CAAC;AACrD,UAAO;IAAE,SAAS,2BAA2B;IAAQ,SAAS;IAAM;;EAGtE,MAAM,UAAU,EAAE,MAAM,uBAAuB;AAC/C,MAAI,SAAS;GACX,MAAM,QAAQ,OAAO,QAAQ,GAAG;GAChC,MAAM,OAAO,KAAK,UAAU,QAAQ;AACpC,OAAI,CAAC,KAAM,QAAO;IAAE,SAAS,sBAAsB,MAAM;IAAI,SAAS;IAAO;AAC7E,SAAM,gBAAgB,KAAK,IAAI;IAAE,MAAM;IAAU,QAAQ,KAAK;IAAI,CAAC;AACnE,UAAO;IAAE,SAAS,mBAAmB,MAAM;IAAI,SAAS;IAAM;;EAGhE,MAAM,QAAQ,EAAE,MAAM,sDAAsD;AAC5E,MAAI,OAAO;GACT,MAAM,QAAQ,OAAO,MAAM,GAAG;GAC9B,MAAM,SAAS,MAAM,GAAI,aAAa;GACtC,MAAM,OAAO,KAAK,UAAU,QAAQ;AACpC,OAAI,CAAC,KAAM,QAAO;IAAE,SAAS,sBAAsB,MAAM;IAAI,SAAS;IAAO;AAC7E,SAAM,gBAAgB,KAAK,IAAI;IAAE,MAAM;IAAQ,QAAQ,KAAK;IAAI;IAAQ,CAAC;AACzE,UAAO;IAAE,SAAS,WAAW,MAAM,MAAM,OAAO;IAAI,SAAS;IAAM;;AAGrE,SAAO;GACL,SACE;GAMF,SAAS;GACV;;CAEJ;AAED,SAAgB,yBAA+B;AAC7C,iBAAgB,SAAS,eAAe"}