@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
@@ -0,0 +1,154 @@
1
+ import { init_session_key, parseSessionKey } from "../routing/session-key.js";
2
+ import { createLogger } from "../utils/logger/index.js";
3
+ import { init_logger } from "../utils/logger.js";
4
+ import { GoalService } from "./goal-service.js";
5
+ //#region src/goals/goal-notifications.ts
6
+ init_session_key();
7
+ init_logger();
8
+ const log = createLogger("GoalNotifications");
9
+ function eventForQueueStatus(status) {
10
+ if (status === "failed") return "queue_failed";
11
+ if (status === "retry_waiting") return "queue_retry";
12
+ if (status === "succeeded") return "queue_succeeded";
13
+ if (status === "skipped") return "queue_skipped";
14
+ return null;
15
+ }
16
+ function eventForGoalStatus(status) {
17
+ if (status === "done" || status === "blocked" || status === "needs_input") return status;
18
+ return null;
19
+ }
20
+ function targetKey(target) {
21
+ return [
22
+ target.channel,
23
+ target.chatId,
24
+ target.accountId ?? "",
25
+ target.threadId ?? ""
26
+ ].join("\0");
27
+ }
28
+ function formatGoalNotification(event, goal, opts) {
29
+ const lines = [`${{
30
+ done: "Goal completed",
31
+ blocked: "Goal blocked",
32
+ needs_input: "Goal needs input",
33
+ queue_failed: "Goal run failed",
34
+ queue_retry: "Goal run retry scheduled",
35
+ queue_succeeded: "Goal run finished",
36
+ queue_skipped: "Goal run skipped"
37
+ }[event]}: ${goal.title}`];
38
+ if (goal.blockedReason) lines.push(`Reason: ${goal.blockedReason}`);
39
+ if (goal.nextAction) lines.push(`Next: ${goal.nextAction}`);
40
+ if (goal.latestRun?.reason && goal.latestRun.reason !== goal.blockedReason) lines.push(`Run: ${goal.latestRun.reason}`);
41
+ if (opts?.queueItem?.lastError) lines.push(`Queue: ${opts.queueItem.lastError}`);
42
+ const progress = goal.checklist.length ? goal.checklist.filter((it) => it.status === "completed" || it.status === "impossible").length : 0;
43
+ if (goal.checklist.length) lines.push(`Checklist: ${progress}/${goal.checklist.length}`);
44
+ lines.push(`Turns: ${goal.turnsUsed}/${goal.maxTurns}`);
45
+ return lines.join("\n");
46
+ }
47
+ var GoalNotificationService = class {
48
+ goals = new GoalService();
49
+ sentKeys = /* @__PURE__ */ new Set();
50
+ constructor(opts) {
51
+ this.opts = opts;
52
+ }
53
+ handleGatewayEvent(type, payload) {
54
+ if (type === "goal.queue.updated") {
55
+ this.handleQueueUpdated(payload).catch((err) => {
56
+ log.warn({ err }, "Goal queue notification failed");
57
+ });
58
+ return;
59
+ }
60
+ if (type === "goal.status.updated") this.handleStatusUpdated(payload).catch((err) => {
61
+ log.warn({ err }, "Goal status notification failed");
62
+ });
63
+ }
64
+ async handleQueueUpdated(payload) {
65
+ const item = this.parseQueueItem(payload);
66
+ if (!item) return;
67
+ const event = eventForQueueStatus(item.status);
68
+ if (!event) return;
69
+ const goal = this.goals.get(item.goalId);
70
+ if (!goal) return;
71
+ await this.notify(event, goal, {
72
+ queueItem: item,
73
+ eventKey: `${item.id}:${item.status}:${item.attempts}`
74
+ });
75
+ }
76
+ async handleStatusUpdated(payload) {
77
+ if (!payload || typeof payload !== "object") return;
78
+ const rec = payload;
79
+ const goal = this.isGoal(rec.goal) ? rec.goal : typeof rec.goalId === "string" ? this.goals.get(rec.goalId) : null;
80
+ if (!goal) return;
81
+ const status = typeof rec.status === "string" ? rec.status : goal.status;
82
+ const event = eventForGoalStatus(status);
83
+ if (!event) return;
84
+ if (rec.previousStatus === status) return;
85
+ await this.notify(event, goal, { eventKey: `${goal.id}:${event}:${goal.updatedAt}` });
86
+ }
87
+ async notify(event, goal, opts) {
88
+ const policy = this.opts.getConfig().goals?.notifications;
89
+ if (!policy?.enabled) return;
90
+ if (!policy.events.includes(event)) return;
91
+ const targets = this.resolveTargets(event, goal);
92
+ if (targets.length === 0) return;
93
+ const text = formatGoalNotification(event, goal, { queueItem: opts?.queueItem });
94
+ for (const target of targets) {
95
+ const dedupeKey = `${opts?.eventKey ?? `${goal.id}:${event}`}:${targetKey(target)}`;
96
+ if (this.sentKeys.has(dedupeKey)) continue;
97
+ this.sentKeys.add(dedupeKey);
98
+ await this.opts.send({
99
+ ...target,
100
+ text
101
+ }).catch((err) => {
102
+ this.sentKeys.delete(dedupeKey);
103
+ throw err;
104
+ });
105
+ }
106
+ }
107
+ resolveTargets(event, goal) {
108
+ const policy = this.opts.getConfig().goals?.notifications;
109
+ if (!policy?.enabled) return [];
110
+ const byKey = /* @__PURE__ */ new Map();
111
+ if (policy.includeLinkedSessions !== false && goal.activeSessionKey) {
112
+ const parsed = parseSessionKey(goal.activeSessionKey);
113
+ if (parsed && policy.channels.includes(parsed.source)) {
114
+ const target = {
115
+ channel: parsed.source,
116
+ chatId: parsed.peerId,
117
+ accountId: parsed.accountId,
118
+ ...parsed.threadId ? { threadId: parsed.threadId } : {}
119
+ };
120
+ byKey.set(targetKey(target), target);
121
+ }
122
+ }
123
+ for (const target of policy.targets ?? []) {
124
+ const events = target.events;
125
+ if (events && !events.includes(event)) continue;
126
+ const normalized = {
127
+ channel: target.channel,
128
+ chatId: target.chatId,
129
+ ...target.accountId ? { accountId: target.accountId } : {},
130
+ ...target.threadId != null ? { threadId: target.threadId } : {},
131
+ ...target.silent != null ? { silent: target.silent } : {}
132
+ };
133
+ byKey.set(targetKey(normalized), normalized);
134
+ }
135
+ return [...byKey.values()];
136
+ }
137
+ parseQueueItem(payload) {
138
+ if (!payload || typeof payload !== "object") return null;
139
+ const item = payload.item;
140
+ if (!item || typeof item !== "object") return null;
141
+ const rec = item;
142
+ if (typeof rec.id !== "string" || typeof rec.goalId !== "string" || typeof rec.status !== "string") return null;
143
+ return rec;
144
+ }
145
+ isGoal(value) {
146
+ if (!value || typeof value !== "object") return false;
147
+ const rec = value;
148
+ return typeof rec.id === "string" && typeof rec.title === "string" && Array.isArray(rec.checklist);
149
+ }
150
+ };
151
+ //#endregion
152
+ export { GoalNotificationService };
153
+
154
+ //# sourceMappingURL=goal-notifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-notifications.js","names":[],"sources":["../../../src/goals/goal-notifications.ts"],"sourcesContent":["import type { Config } from '../config/schema.js';\nimport { parseSessionKey } from '../routing/session-key.js';\nimport { createLogger } from '../utils/logger.js';\n\nimport { GoalService } from './goal-service.js';\nimport type { GoalWithDetails } from './types.js';\nimport type { GoalQueueItemSnapshot } from './goal-queue-types.js';\n\nconst log = createLogger('GoalNotifications');\n\nexport type GoalNotificationEvent =\n | 'done'\n | 'blocked'\n | 'needs_input'\n | 'queue_failed'\n | 'queue_retry'\n | 'queue_succeeded'\n | 'queue_skipped';\n\nexport interface GoalNotificationTarget {\n channel: string;\n chatId: string;\n accountId?: string;\n threadId?: string | number;\n silent?: boolean;\n}\n\nexport interface GoalNotificationSendInput extends GoalNotificationTarget {\n text: string;\n}\n\nexport interface GoalNotificationServiceOptions {\n getConfig: () => Config;\n send: (input: GoalNotificationSendInput) => Promise<void>;\n}\n\nfunction eventForQueueStatus(status: GoalQueueItemSnapshot['status']): GoalNotificationEvent | null {\n if (status === 'failed') return 'queue_failed';\n if (status === 'retry_waiting') return 'queue_retry';\n if (status === 'succeeded') return 'queue_succeeded';\n if (status === 'skipped') return 'queue_skipped';\n return null;\n}\n\nfunction eventForGoalStatus(status: GoalWithDetails['status']): GoalNotificationEvent | null {\n if (status === 'done' || status === 'blocked' || status === 'needs_input') return status;\n return null;\n}\n\nfunction targetKey(target: GoalNotificationTarget): string {\n return [\n target.channel,\n target.chatId,\n target.accountId ?? '',\n target.threadId ?? '',\n ].join('\\u0000');\n}\n\nfunction formatGoalNotification(event: GoalNotificationEvent, goal: GoalWithDetails, opts?: {\n queueItem?: GoalQueueItemSnapshot;\n}): string {\n const labels: Record<GoalNotificationEvent, string> = {\n done: 'Goal completed',\n blocked: 'Goal blocked',\n needs_input: 'Goal needs input',\n queue_failed: 'Goal run failed',\n queue_retry: 'Goal run retry scheduled',\n queue_succeeded: 'Goal run finished',\n queue_skipped: 'Goal run skipped',\n };\n const lines = [`${labels[event]}: ${goal.title}`];\n if (goal.blockedReason) lines.push(`Reason: ${goal.blockedReason}`);\n if (goal.nextAction) lines.push(`Next: ${goal.nextAction}`);\n if (goal.latestRun?.reason && goal.latestRun.reason !== goal.blockedReason) {\n lines.push(`Run: ${goal.latestRun.reason}`);\n }\n if (opts?.queueItem?.lastError) lines.push(`Queue: ${opts.queueItem.lastError}`);\n const progress = goal.checklist.length\n ? goal.checklist.filter((it) => it.status === 'completed' || it.status === 'impossible').length\n : 0;\n if (goal.checklist.length) lines.push(`Checklist: ${progress}/${goal.checklist.length}`);\n lines.push(`Turns: ${goal.turnsUsed}/${goal.maxTurns}`);\n return lines.join('\\n');\n}\n\nexport class GoalNotificationService {\n private readonly goals = new GoalService();\n private readonly sentKeys = new Set<string>();\n\n constructor(private readonly opts: GoalNotificationServiceOptions) {}\n\n handleGatewayEvent(type: string, payload: unknown): void {\n if (type === 'goal.queue.updated') {\n void this.handleQueueUpdated(payload).catch((err) => {\n log.warn({ err }, 'Goal queue notification failed');\n });\n return;\n }\n if (type === 'goal.status.updated') {\n void this.handleStatusUpdated(payload).catch((err) => {\n log.warn({ err }, 'Goal status notification failed');\n });\n }\n }\n\n private async handleQueueUpdated(payload: unknown): Promise<void> {\n const item = this.parseQueueItem(payload);\n if (!item) return;\n const event = eventForQueueStatus(item.status);\n if (!event) return;\n const goal = this.goals.get(item.goalId);\n if (!goal) return;\n await this.notify(event, goal, { queueItem: item, eventKey: `${item.id}:${item.status}:${item.attempts}` });\n }\n\n private async handleStatusUpdated(payload: unknown): Promise<void> {\n if (!payload || typeof payload !== 'object') return;\n const rec = payload as { goal?: unknown; status?: unknown; goalId?: unknown; previousStatus?: unknown };\n const goal =\n this.isGoal(rec.goal)\n ? rec.goal\n : typeof rec.goalId === 'string'\n ? this.goals.get(rec.goalId)\n : null;\n if (!goal) return;\n const status = typeof rec.status === 'string' ? rec.status : goal.status;\n const event = eventForGoalStatus(status as GoalWithDetails['status']);\n if (!event) return;\n if (rec.previousStatus === status) return;\n await this.notify(event, goal, { eventKey: `${goal.id}:${event}:${goal.updatedAt}` });\n }\n\n private async notify(\n event: GoalNotificationEvent,\n goal: GoalWithDetails,\n opts?: { queueItem?: GoalQueueItemSnapshot; eventKey?: string },\n ): Promise<void> {\n const policy = this.opts.getConfig().goals?.notifications;\n if (!policy?.enabled) return;\n if (!policy.events.includes(event)) return;\n\n const targets = this.resolveTargets(event, goal);\n if (targets.length === 0) return;\n\n const text = formatGoalNotification(event, goal, { queueItem: opts?.queueItem });\n for (const target of targets) {\n const dedupeKey = `${opts?.eventKey ?? `${goal.id}:${event}`}:${targetKey(target)}`;\n if (this.sentKeys.has(dedupeKey)) continue;\n this.sentKeys.add(dedupeKey);\n await this.opts.send({ ...target, text }).catch((err) => {\n this.sentKeys.delete(dedupeKey);\n throw err;\n });\n }\n }\n\n private resolveTargets(event: GoalNotificationEvent, goal: GoalWithDetails): GoalNotificationTarget[] {\n const policy = this.opts.getConfig().goals?.notifications;\n if (!policy?.enabled) return [];\n const byKey = new Map<string, GoalNotificationTarget>();\n\n if (policy.includeLinkedSessions !== false && goal.activeSessionKey) {\n const parsed = parseSessionKey(goal.activeSessionKey);\n const eligible = parsed && policy.channels.includes(parsed.source);\n if (eligible) {\n const target: GoalNotificationTarget = {\n channel: parsed.source,\n chatId: parsed.peerId,\n accountId: parsed.accountId,\n ...(parsed.threadId ? { threadId: parsed.threadId } : {}),\n };\n byKey.set(targetKey(target), target);\n }\n }\n\n for (const target of policy.targets ?? []) {\n const events = target.events;\n if (events && !events.includes(event)) continue;\n const normalized: GoalNotificationTarget = {\n channel: target.channel,\n chatId: target.chatId,\n ...(target.accountId ? { accountId: target.accountId } : {}),\n ...(target.threadId != null ? { threadId: target.threadId } : {}),\n ...(target.silent != null ? { silent: target.silent } : {}),\n };\n byKey.set(targetKey(normalized), normalized);\n }\n\n return [...byKey.values()];\n }\n\n private parseQueueItem(payload: unknown): GoalQueueItemSnapshot | null {\n if (!payload || typeof payload !== 'object') return null;\n const item = (payload as { item?: unknown }).item;\n if (!item || typeof item !== 'object') return null;\n const rec = item as Partial<GoalQueueItemSnapshot>;\n if (typeof rec.id !== 'string' || typeof rec.goalId !== 'string' || typeof rec.status !== 'string') return null;\n return rec as GoalQueueItemSnapshot;\n }\n\n private isGoal(value: unknown): value is GoalWithDetails {\n if (!value || typeof value !== 'object') return false;\n const rec = value as Partial<GoalWithDetails>;\n return typeof rec.id === 'string' && typeof rec.title === 'string' && Array.isArray(rec.checklist);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { GoalQueueItemSnapshot, GoalQueueStatus } from './goal-queue-types.js';
2
+ export declare class GoalQueueStore {
3
+ enqueue(input: {
4
+ goalId: string;
5
+ message?: string;
6
+ maxRetries: number;
7
+ source: GoalQueueItemSnapshot['source'];
8
+ }): GoalQueueItemSnapshot;
9
+ claimNext(now?: number): GoalQueueItemSnapshot | null;
10
+ markRetry(itemId: string, error: string, nextRunAt: number): GoalQueueItemSnapshot | null;
11
+ markFinished(itemId: string, status: GoalQueueStatus, error?: string): GoalQueueItemSnapshot | null;
12
+ setSessionKey(itemId: string, sessionKey: string): GoalQueueItemSnapshot | null;
13
+ list(limit?: number): GoalQueueItemSnapshot[];
14
+ resetRunningToRetry(reason?: string): number;
15
+ private update;
16
+ }
@@ -0,0 +1,131 @@
1
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
2
+ import { randomUUID } from "node:crypto";
3
+ //#region src/goals/goal-queue-store.ts
4
+ function parsePayload(raw) {
5
+ try {
6
+ const parsed = JSON.parse(raw);
7
+ return parsed && typeof parsed === "object" ? parsed : {};
8
+ } catch {
9
+ return {};
10
+ }
11
+ }
12
+ function rowToSnapshot(row) {
13
+ const payload = parsePayload(row.payload_json);
14
+ return {
15
+ id: row.queue_id,
16
+ goalId: row.goal_id,
17
+ status: row.status,
18
+ attempts: row.attempts,
19
+ maxRetries: row.max_retries,
20
+ enqueuedAt: row.enqueued_at,
21
+ startedAt: row.started_at ?? void 0,
22
+ finishedAt: row.finished_at ?? void 0,
23
+ nextRunAt: row.next_run_at ?? void 0,
24
+ sessionKey: row.session_key ?? void 0,
25
+ message: payload.message,
26
+ lastError: row.last_error ?? void 0,
27
+ source: row.source
28
+ };
29
+ }
30
+ var GoalQueueStore = class {
31
+ enqueue(input) {
32
+ return runSqliteWriteTransaction((db) => {
33
+ const existing = db.prepare(`SELECT * FROM goal_queue
34
+ WHERE goal_id = ?
35
+ AND status IN ('queued', 'running', 'retry_waiting')
36
+ ORDER BY enqueued_at DESC
37
+ LIMIT 1`).get(input.goalId);
38
+ if (existing) return rowToSnapshot(existing);
39
+ const now = Date.now();
40
+ const row = {
41
+ queue_id: randomUUID(),
42
+ goal_id: input.goalId,
43
+ status: "queued",
44
+ payload_json: JSON.stringify({ message: input.message }),
45
+ attempts: 0,
46
+ max_retries: input.maxRetries,
47
+ enqueued_at: now,
48
+ started_at: null,
49
+ finished_at: null,
50
+ next_run_at: null,
51
+ session_key: null,
52
+ last_error: null,
53
+ source: input.source
54
+ };
55
+ db.prepare(`INSERT INTO goal_queue (
56
+ queue_id, goal_id, status, payload_json, attempts, max_retries,
57
+ enqueued_at, source
58
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(row.queue_id, row.goal_id, row.status, row.payload_json, row.attempts, row.max_retries, row.enqueued_at, row.source);
59
+ return rowToSnapshot(row);
60
+ });
61
+ }
62
+ claimNext(now = Date.now()) {
63
+ return runSqliteWriteTransaction((db) => {
64
+ const row = db.prepare(`SELECT * FROM goal_queue
65
+ WHERE status = 'queued'
66
+ OR (status = 'retry_waiting' AND COALESCE(next_run_at, 0) <= ?)
67
+ ORDER BY enqueued_at ASC
68
+ LIMIT 1`).get(now);
69
+ if (!row) return null;
70
+ const startedAt = Date.now();
71
+ db.prepare(`UPDATE goal_queue
72
+ SET status = 'running',
73
+ started_at = ?,
74
+ attempts = attempts + 1,
75
+ last_error = NULL
76
+ WHERE queue_id = ?`).run(startedAt, row.queue_id);
77
+ return rowToSnapshot(db.prepare(`SELECT * FROM goal_queue WHERE queue_id = ?`).get(row.queue_id));
78
+ });
79
+ }
80
+ markRetry(itemId, error, nextRunAt) {
81
+ return this.update(itemId, {
82
+ status: "retry_waiting",
83
+ next_run_at: nextRunAt,
84
+ last_error: error,
85
+ finished_at: null
86
+ });
87
+ }
88
+ markFinished(itemId, status, error) {
89
+ return this.update(itemId, {
90
+ status,
91
+ finished_at: Date.now(),
92
+ last_error: error ?? null
93
+ });
94
+ }
95
+ setSessionKey(itemId, sessionKey) {
96
+ return this.update(itemId, { session_key: sessionKey });
97
+ }
98
+ list(limit = 200) {
99
+ const safeLimit = Math.min(500, Math.max(1, Math.floor(limit)));
100
+ return getSqliteDatabase().prepare(`SELECT * FROM goal_queue ORDER BY enqueued_at DESC LIMIT ?`).all(safeLimit).map(rowToSnapshot);
101
+ }
102
+ resetRunningToRetry(reason = "Gateway restarted during goal run") {
103
+ return runSqliteWriteTransaction((db) => {
104
+ const result = db.prepare(`UPDATE goal_queue
105
+ SET status = 'retry_waiting',
106
+ next_run_at = ?,
107
+ last_error = ?
108
+ WHERE status = 'running'`).run(Date.now(), reason);
109
+ return Number(result.changes ?? 0);
110
+ });
111
+ }
112
+ update(itemId, patch) {
113
+ return runSqliteWriteTransaction((db) => {
114
+ const row = db.prepare(`SELECT * FROM goal_queue WHERE queue_id = ?`).get(itemId);
115
+ if (!row) return null;
116
+ const next = {
117
+ ...row,
118
+ ...patch
119
+ };
120
+ db.prepare(`UPDATE goal_queue SET
121
+ status = ?, attempts = ?, started_at = ?, finished_at = ?,
122
+ next_run_at = ?, session_key = ?, last_error = ?
123
+ WHERE queue_id = ?`).run(next.status, next.attempts, next.started_at, next.finished_at, next.next_run_at, next.session_key, next.last_error, itemId);
124
+ return rowToSnapshot(db.prepare(`SELECT * FROM goal_queue WHERE queue_id = ?`).get(itemId));
125
+ });
126
+ }
127
+ };
128
+ //#endregion
129
+ export { GoalQueueStore };
130
+
131
+ //# sourceMappingURL=goal-queue-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-queue-store.js","names":[],"sources":["../../../src/goals/goal-queue-store.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { getSqliteDatabase, runSqliteWriteTransaction } from '../storage/sqlite/transaction.js';\n\nimport type { GoalQueueItemSnapshot, GoalQueueStatus } from './goal-queue-types.js';\n\ntype GoalQueueRow = {\n queue_id: string;\n goal_id: string;\n status: GoalQueueStatus;\n payload_json: string;\n attempts: number;\n max_retries: number;\n enqueued_at: number;\n started_at: number | null;\n finished_at: number | null;\n next_run_at: number | null;\n session_key: string | null;\n last_error: string | null;\n source: GoalQueueItemSnapshot['source'];\n};\n\ntype GoalQueuePayload = {\n message?: string;\n};\n\nfunction parsePayload(raw: string): GoalQueuePayload {\n try {\n const parsed = JSON.parse(raw) as GoalQueuePayload;\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction rowToSnapshot(row: GoalQueueRow): GoalQueueItemSnapshot {\n const payload = parsePayload(row.payload_json);\n return {\n id: row.queue_id,\n goalId: row.goal_id,\n status: row.status,\n attempts: row.attempts,\n maxRetries: row.max_retries,\n enqueuedAt: row.enqueued_at,\n startedAt: row.started_at ?? undefined,\n finishedAt: row.finished_at ?? undefined,\n nextRunAt: row.next_run_at ?? undefined,\n sessionKey: row.session_key ?? undefined,\n message: payload.message,\n lastError: row.last_error ?? undefined,\n source: row.source,\n };\n}\n\nexport class GoalQueueStore {\n enqueue(input: {\n goalId: string;\n message?: string;\n maxRetries: number;\n source: GoalQueueItemSnapshot['source'];\n }): GoalQueueItemSnapshot {\n return runSqliteWriteTransaction((db) => {\n const existing = db\n .prepare(\n `SELECT * FROM goal_queue\n WHERE goal_id = ?\n AND status IN ('queued', 'running', 'retry_waiting')\n ORDER BY enqueued_at DESC\n LIMIT 1`,\n )\n .get(input.goalId) as GoalQueueRow | undefined;\n if (existing) return rowToSnapshot(existing);\n\n const now = Date.now();\n const row: GoalQueueRow = {\n queue_id: randomUUID(),\n goal_id: input.goalId,\n status: 'queued',\n payload_json: JSON.stringify({ message: input.message }),\n attempts: 0,\n max_retries: input.maxRetries,\n enqueued_at: now,\n started_at: null,\n finished_at: null,\n next_run_at: null,\n session_key: null,\n last_error: null,\n source: input.source,\n };\n db.prepare(\n `INSERT INTO goal_queue (\n queue_id, goal_id, status, payload_json, attempts, max_retries,\n enqueued_at, source\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n row.queue_id,\n row.goal_id,\n row.status,\n row.payload_json,\n row.attempts,\n row.max_retries,\n row.enqueued_at,\n row.source,\n );\n return rowToSnapshot(row);\n });\n }\n\n claimNext(now = Date.now()): GoalQueueItemSnapshot | null {\n return runSqliteWriteTransaction((db) => {\n const row = db\n .prepare(\n `SELECT * FROM goal_queue\n WHERE status = 'queued'\n OR (status = 'retry_waiting' AND COALESCE(next_run_at, 0) <= ?)\n ORDER BY enqueued_at ASC\n LIMIT 1`,\n )\n .get(now) as GoalQueueRow | undefined;\n if (!row) return null;\n\n const startedAt = Date.now();\n db.prepare(\n `UPDATE goal_queue\n SET status = 'running',\n started_at = ?,\n attempts = attempts + 1,\n last_error = NULL\n WHERE queue_id = ?`,\n ).run(startedAt, row.queue_id);\n\n const next = db\n .prepare(`SELECT * FROM goal_queue WHERE queue_id = ?`)\n .get(row.queue_id) as GoalQueueRow;\n return rowToSnapshot(next);\n });\n }\n\n markRetry(itemId: string, error: string, nextRunAt: number): GoalQueueItemSnapshot | null {\n return this.update(itemId, {\n status: 'retry_waiting',\n next_run_at: nextRunAt,\n last_error: error,\n finished_at: null,\n });\n }\n\n markFinished(itemId: string, status: GoalQueueStatus, error?: string): GoalQueueItemSnapshot | null {\n return this.update(itemId, {\n status,\n finished_at: Date.now(),\n last_error: error ?? null,\n });\n }\n\n setSessionKey(itemId: string, sessionKey: string): GoalQueueItemSnapshot | null {\n return this.update(itemId, { session_key: sessionKey });\n }\n\n list(limit = 200): GoalQueueItemSnapshot[] {\n const safeLimit = Math.min(500, Math.max(1, Math.floor(limit)));\n const rows = getSqliteDatabase()\n .prepare(`SELECT * FROM goal_queue ORDER BY enqueued_at DESC LIMIT ?`)\n .all(safeLimit) as GoalQueueRow[];\n return rows.map(rowToSnapshot);\n }\n\n resetRunningToRetry(reason = 'Gateway restarted during goal run'): number {\n return runSqliteWriteTransaction((db) => {\n const result = db\n .prepare(\n `UPDATE goal_queue\n SET status = 'retry_waiting',\n next_run_at = ?,\n last_error = ?\n WHERE status = 'running'`,\n )\n .run(Date.now(), reason);\n return Number(result.changes ?? 0);\n });\n }\n\n private update(itemId: string, patch: Partial<GoalQueueRow>): GoalQueueItemSnapshot | null {\n return runSqliteWriteTransaction((db) => {\n const row = db\n .prepare(`SELECT * FROM goal_queue WHERE queue_id = ?`)\n .get(itemId) as GoalQueueRow | undefined;\n if (!row) return null;\n const next = { ...row, ...patch };\n db.prepare(\n `UPDATE goal_queue SET\n status = ?, attempts = ?, started_at = ?, finished_at = ?,\n next_run_at = ?, session_key = ?, last_error = ?\n WHERE queue_id = ?`,\n ).run(\n next.status,\n next.attempts,\n next.started_at,\n next.finished_at,\n next.next_run_at,\n next.session_key,\n next.last_error,\n itemId,\n );\n const updated = db\n .prepare(`SELECT * FROM goal_queue WHERE queue_id = ?`)\n .get(itemId) as GoalQueueRow;\n return rowToSnapshot(updated);\n });\n }\n}\n\n"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { GoalWithDetails } from './types.js';
2
+ export type GoalQueueStatus = 'queued' | 'running' | 'retry_waiting' | 'succeeded' | 'failed' | 'skipped';
3
+ export interface GoalQueueItemSnapshot {
4
+ id: string;
5
+ goalId: string;
6
+ status: GoalQueueStatus;
7
+ attempts: number;
8
+ maxRetries: number;
9
+ enqueuedAt: number;
10
+ startedAt?: number;
11
+ finishedAt?: number;
12
+ nextRunAt?: number;
13
+ sessionKey?: string;
14
+ message?: string;
15
+ lastError?: string;
16
+ source: 'api' | 'cron' | 'workflow' | 'system';
17
+ }
18
+ export interface GoalRunnerOptions {
19
+ maxConcurrent?: number;
20
+ defaultMaxRetries?: number;
21
+ retryBaseMs?: number;
22
+ ensureSession: (goal: GoalWithDetails) => Promise<string>;
23
+ hasActiveRun: (sessionKey: string) => boolean;
24
+ runContinuation: (sessionKey: string, message: string) => Promise<void>;
25
+ emit?: (type: string, payload: unknown) => void;
26
+ }
27
+ export interface EnqueueGoalRunOptions {
28
+ message?: string;
29
+ maxRetries?: number;
30
+ source?: GoalQueueItemSnapshot['source'];
31
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { EnqueueGoalRunOptions, GoalQueueItemSnapshot, GoalRunnerOptions } from './goal-queue-types.js';
2
+ export declare class GoalRunner {
3
+ private readonly opts;
4
+ private readonly goals;
5
+ private readonly store;
6
+ private active;
7
+ private pumpTimer;
8
+ constructor(opts: GoalRunnerOptions);
9
+ enqueue(goalId: string, options?: EnqueueGoalRunOptions): GoalQueueItemSnapshot;
10
+ snapshot(): GoalQueueItemSnapshot[];
11
+ private schedulePump;
12
+ private pump;
13
+ private runItem;
14
+ private retry;
15
+ private finish;
16
+ private emit;
17
+ }
@@ -0,0 +1,127 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ import { GoalService } from "./goal-service.js";
4
+ import { GoalQueueStore } from "./goal-queue-store.js";
5
+ //#region src/goals/goal-runner.ts
6
+ init_logger();
7
+ const log = createLogger("GoalRunner");
8
+ function terminalGoalStatus(status) {
9
+ return status === "done" || status === "archived";
10
+ }
11
+ var GoalRunner = class {
12
+ goals = new GoalService();
13
+ store = new GoalQueueStore();
14
+ active = 0;
15
+ pumpTimer = null;
16
+ constructor(opts) {
17
+ this.opts = opts;
18
+ this.store.resetRunningToRetry();
19
+ this.schedulePump(0);
20
+ }
21
+ enqueue(goalId, options = {}) {
22
+ const item = this.store.enqueue({
23
+ goalId,
24
+ maxRetries: Math.max(0, Math.floor(options.maxRetries ?? this.opts.defaultMaxRetries ?? 2)),
25
+ message: options.message?.trim() || void 0,
26
+ source: options.source ?? "api"
27
+ });
28
+ this.emit("goal.queue.updated", item);
29
+ this.schedulePump(0);
30
+ return item;
31
+ }
32
+ snapshot() {
33
+ return this.store.list();
34
+ }
35
+ schedulePump(delayMs) {
36
+ if (this.pumpTimer) return;
37
+ this.pumpTimer = setTimeout(() => {
38
+ this.pumpTimer = null;
39
+ this.pump();
40
+ }, delayMs);
41
+ }
42
+ async pump() {
43
+ const maxConcurrent = Math.max(1, Math.floor(this.opts.maxConcurrent ?? 1));
44
+ while (this.active < maxConcurrent) {
45
+ const item = this.store.claimNext();
46
+ if (!item) break;
47
+ this.active += 1;
48
+ this.runItem(item).finally(() => {
49
+ this.active -= 1;
50
+ this.schedulePump(0);
51
+ });
52
+ }
53
+ const nextRetry = this.store.list().filter((item) => item.status === "retry_waiting" && item.nextRunAt).sort((a, b) => (a.nextRunAt ?? 0) - (b.nextRunAt ?? 0))[0];
54
+ if (nextRetry) this.schedulePump(Math.max(0, (nextRetry.nextRunAt ?? Date.now()) - Date.now()));
55
+ }
56
+ async runItem(item) {
57
+ this.emit("goal.queue.updated", item);
58
+ try {
59
+ const goal = this.goals.get(item.goalId);
60
+ if (!goal) {
61
+ this.finish(item, "failed", "Goal not found");
62
+ return;
63
+ }
64
+ if (terminalGoalStatus(goal.status)) {
65
+ this.finish(item, "skipped", `Goal is ${goal.status}`);
66
+ return;
67
+ }
68
+ const activeGoal = goal.status === "paused" || goal.status === "blocked" || goal.status === "needs_input" ? this.goals.resume(goal.id) : goal;
69
+ if (!activeGoal) {
70
+ this.finish(item, "failed", "Goal not found");
71
+ return;
72
+ }
73
+ const sessionKey = activeGoal.activeSessionKey ?? await this.opts.ensureSession(activeGoal);
74
+ item = this.store.setSessionKey(item.id, sessionKey) ?? {
75
+ ...item,
76
+ sessionKey
77
+ };
78
+ if (this.opts.hasActiveRun(sessionKey)) {
79
+ this.retry(item, "Goal session already has an active run");
80
+ return;
81
+ }
82
+ const message = item.message || activeGoal.nextAction || activeGoal.title;
83
+ await this.opts.runContinuation(sessionKey, message);
84
+ this.finish(item, "succeeded");
85
+ } catch (err) {
86
+ const message = err instanceof Error ? err.message : String(err);
87
+ if (item.attempts <= item.maxRetries) this.retry(item, message);
88
+ else this.finish(item, "failed", message);
89
+ }
90
+ }
91
+ retry(item, error) {
92
+ const base = Math.max(1e3, this.opts.retryBaseMs ?? 5e3);
93
+ item.status = "retry_waiting";
94
+ item.lastError = error;
95
+ item.nextRunAt = Date.now() + base * 2 ** Math.max(0, item.attempts - 1);
96
+ item = this.store.markRetry(item.id, error, item.nextRunAt) ?? item;
97
+ log.warn({
98
+ goalId: item.goalId,
99
+ attempts: item.attempts,
100
+ nextRunAt: item.nextRunAt,
101
+ errorMessage: error
102
+ }, `Goal run queued for retry: ${error}`);
103
+ this.emit("goal.queue.updated", item);
104
+ this.schedulePump(Math.max(0, item.nextRunAt - Date.now()));
105
+ }
106
+ finish(item, status, error) {
107
+ item = this.store.markFinished(item.id, status, error) ?? {
108
+ ...item,
109
+ status,
110
+ finishedAt: Date.now(),
111
+ lastError: error
112
+ };
113
+ if (status === "failed") log.warn({
114
+ goalId: item.goalId,
115
+ attempts: item.attempts,
116
+ errorMessage: error
117
+ }, `Goal run failed: ${error}`);
118
+ this.emit("goal.queue.updated", item);
119
+ }
120
+ emit(type, item) {
121
+ this.opts.emit?.(type, { item: { ...item } });
122
+ }
123
+ };
124
+ //#endregion
125
+ export { GoalRunner };
126
+
127
+ //# sourceMappingURL=goal-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-runner.js","names":[],"sources":["../../../src/goals/goal-runner.ts"],"sourcesContent":["import { GoalQueueStore } from './goal-queue-store.js';\nimport { GoalService } from './goal-service.js';\nimport type { EnqueueGoalRunOptions, GoalQueueItemSnapshot, GoalQueueStatus, GoalRunnerOptions } from './goal-queue-types.js';\nimport type { GoalWithDetails } from './types.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst log = createLogger('GoalRunner');\n\nfunction terminalGoalStatus(status: GoalWithDetails['status']): boolean {\n return status === 'done' || status === 'archived';\n}\n\nexport class GoalRunner {\n private readonly goals = new GoalService();\n private readonly store = new GoalQueueStore();\n private active = 0;\n private pumpTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(private readonly opts: GoalRunnerOptions) {\n this.store.resetRunningToRetry();\n this.schedulePump(0);\n }\n\n enqueue(goalId: string, options: EnqueueGoalRunOptions = {}): GoalQueueItemSnapshot {\n const item = this.store.enqueue({\n goalId,\n maxRetries: Math.max(0, Math.floor(options.maxRetries ?? this.opts.defaultMaxRetries ?? 2)),\n message: options.message?.trim() || undefined,\n source: options.source ?? 'api',\n });\n this.emit('goal.queue.updated', item);\n this.schedulePump(0);\n return item;\n }\n\n snapshot(): GoalQueueItemSnapshot[] {\n return this.store.list();\n }\n\n private schedulePump(delayMs: number): void {\n if (this.pumpTimer) return;\n this.pumpTimer = setTimeout(() => {\n this.pumpTimer = null;\n void this.pump();\n }, delayMs);\n }\n\n private async pump(): Promise<void> {\n const maxConcurrent = Math.max(1, Math.floor(this.opts.maxConcurrent ?? 1));\n while (this.active < maxConcurrent) {\n const item = this.store.claimNext();\n if (!item) break;\n this.active += 1;\n void this.runItem(item).finally(() => {\n this.active -= 1;\n this.schedulePump(0);\n });\n }\n\n const nextRetry = this.store.list()\n .filter((item) => item.status === 'retry_waiting' && item.nextRunAt)\n .sort((a, b) => (a.nextRunAt ?? 0) - (b.nextRunAt ?? 0))[0];\n if (nextRetry) this.schedulePump(Math.max(0, (nextRetry.nextRunAt ?? Date.now()) - Date.now()));\n }\n\n private async runItem(item: GoalQueueItemSnapshot): Promise<void> {\n this.emit('goal.queue.updated', item);\n try {\n const goal = this.goals.get(item.goalId);\n if (!goal) {\n this.finish(item, 'failed', 'Goal not found');\n return;\n }\n if (terminalGoalStatus(goal.status)) {\n this.finish(item, 'skipped', `Goal is ${goal.status}`);\n return;\n }\n const activeGoal =\n goal.status === 'paused' || goal.status === 'blocked' || goal.status === 'needs_input'\n ? this.goals.resume(goal.id)\n : goal;\n if (!activeGoal) {\n this.finish(item, 'failed', 'Goal not found');\n return;\n }\n const sessionKey = activeGoal.activeSessionKey ?? (await this.opts.ensureSession(activeGoal));\n item = this.store.setSessionKey(item.id, sessionKey) ?? { ...item, sessionKey };\n if (this.opts.hasActiveRun(sessionKey)) {\n this.retry(item, 'Goal session already has an active run');\n return;\n }\n const message = item.message || activeGoal.nextAction || activeGoal.title;\n await this.opts.runContinuation(sessionKey, message);\n this.finish(item, 'succeeded');\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (item.attempts <= item.maxRetries) {\n this.retry(item, message);\n } else {\n this.finish(item, 'failed', message);\n }\n }\n }\n\n private retry(item: GoalQueueItemSnapshot, error: string): void {\n const base = Math.max(1_000, this.opts.retryBaseMs ?? 5_000);\n item.status = 'retry_waiting';\n item.lastError = error;\n item.nextRunAt = Date.now() + base * 2 ** Math.max(0, item.attempts - 1);\n item = this.store.markRetry(item.id, error, item.nextRunAt) ?? item;\n log.warn({ goalId: item.goalId, attempts: item.attempts, nextRunAt: item.nextRunAt, errorMessage: error }, `Goal run queued for retry: ${error}`);\n this.emit('goal.queue.updated', item);\n this.schedulePump(Math.max(0, item.nextRunAt - Date.now()));\n }\n\n private finish(item: GoalQueueItemSnapshot, status: GoalQueueStatus, error?: string): void {\n item = this.store.markFinished(item.id, status, error) ?? { ...item, status, finishedAt: Date.now(), lastError: error };\n if (status === 'failed') {\n log.warn({ goalId: item.goalId, attempts: item.attempts, errorMessage: error }, `Goal run failed: ${error}`);\n }\n this.emit('goal.queue.updated', item);\n }\n\n private emit(type: string, item: GoalQueueItemSnapshot): void {\n this.opts.emit?.(type, { item: { ...item } });\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import type { Config } from '../config/schema.js';
2
+ import { GoalStore } from './goal-store.js';
3
+ import type { CreateGoalInput, Goal, GoalChecklistAddedBy, GoalChecklistStatus, GoalJudgeDecision, GoalListQuery, GoalSource, GoalStatus, GoalUiLocale, GoalWithDetails } from './types.js';
4
+ export declare class GoalService {
5
+ private readonly store;
6
+ constructor(store?: GoalStore);
7
+ create(input: Omit<CreateGoalInput, 'maxTurns' | 'agentId'> & {
8
+ maxTurns?: number;
9
+ agentId?: string;
10
+ config?: Config;
11
+ }): Goal;
12
+ get(goalId: string): GoalWithDetails | null;
13
+ getActiveForSession(sessionKey: string): GoalWithDetails | null;
14
+ list(query?: GoalListQuery): GoalWithDetails[];
15
+ update(goalId: string, patch: Partial<Pick<Goal, 'title' | 'description' | 'priority' | 'deadlineAt' | 'maxTurns' | 'judgeModelRef' | 'nextAction' | 'blockedReason' | 'activeSessionKey' | 'uiLocale'>>): GoalWithDetails | null;
16
+ setStatus(goalId: string, status: GoalStatus, opts?: {
17
+ reason?: string;
18
+ }): GoalWithDetails | null;
19
+ pause(goalId: string, reason?: string): GoalWithDetails | null;
20
+ resume(goalId: string): GoalWithDetails | null;
21
+ reopen(goalId: string): GoalWithDetails | null;
22
+ complete(goalId: string): GoalWithDetails | null;
23
+ archive(goalId: string): GoalWithDetails | null;
24
+ unarchive(goalId: string): GoalWithDetails | null;
25
+ attachSession(goalId: string, sessionKey: string): GoalWithDetails | null;
26
+ updateChecklist(goalId: string, op: {
27
+ type: 'add';
28
+ text: string;
29
+ addedBy?: GoalChecklistAddedBy;
30
+ } | {
31
+ type: 'mark';
32
+ itemId: string;
33
+ status: GoalChecklistStatus;
34
+ evidenceSummary?: string;
35
+ } | {
36
+ type: 'remove';
37
+ itemId: string;
38
+ } | {
39
+ type: 'reset';
40
+ }): GoalWithDetails | null;
41
+ recordJudgeDecision(input: {
42
+ goalId: string;
43
+ sessionKey: string;
44
+ source: GoalSource;
45
+ decision: GoalJudgeDecision;
46
+ }): GoalWithDetails | null;
47
+ syncPostTurnState(input: {
48
+ goalId: string;
49
+ sessionKey: string;
50
+ source: GoalSource;
51
+ status: GoalStatus;
52
+ turnsUsed: number;
53
+ maxTurns: number;
54
+ reason?: string;
55
+ nextAction?: string;
56
+ assistantPreview?: string;
57
+ verdict: 'continue' | 'done' | 'blocked' | 'needs_input' | 'decompose';
58
+ confidence?: number;
59
+ missingEvidence?: string[];
60
+ userQuestion?: string;
61
+ completedChecklistItemIds?: string[];
62
+ checklist?: Array<{
63
+ text: string;
64
+ status: 'pending' | 'completed' | 'impossible';
65
+ addedBy: 'user' | 'judge';
66
+ addedAt?: number;
67
+ completedAt?: number;
68
+ evidenceSummary?: string;
69
+ }>;
70
+ }): GoalWithDetails | null;
71
+ listRuns(goalId: string, limit?: number): import("./types.js").GoalRun[];
72
+ listRunsForSession(sessionKey: string, limit?: number): import("./types.js").GoalRun[];
73
+ listEvents(goalId: string, limit?: number): import("./types.js").GoalEvent[];
74
+ addEvidence(input: Parameters<GoalStore['addEvidence']>[0]): import("./types.js").GoalEvidence;
75
+ listEvidence(goalId: string, limit?: number): import("./types.js").GoalEvidence[];
76
+ }
77
+ export declare function normalizeGoalUiLocale(raw: unknown): GoalUiLocale | undefined;