@xopcai/xopc 0.0.332 → 0.0.333

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 (329) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-C2wg3xC_.js → agent-avatar-dicebear-DiI2O7lC.js} +1 -1
  4. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CVp3J969.js +1 -0
  5. package/dist/gateway/static/root/assets/{agent-plugin-dialog-BeNnu1Ts.js → agent-plugin-dialog-CacyndrS.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-DXYZSuUV.js +70 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-etFSkfzl.js → app-management-settings-panel-BcszTlqr.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-DKmU2VAP.js → appearance-settings-B1XPe8qz.js} +1 -1
  9. package/dist/gateway/static/root/assets/{apps-page-DVNySL58.js → apps-page-ZqANbUZv.js} +1 -1
  10. package/dist/gateway/static/root/assets/{archive-plugin-D0z_Fr2G.js → archive-plugin-MjUsJcNb.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-DNCDbeOX.js → attachment-load-DHa-BI9a.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automations-page-B7_C-p66.js → automations-page-Dsjivdxs.js} +1 -1
  13. package/dist/gateway/static/root/assets/automations-workspace-B37vs5tk.js +7 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-BYn2hScX.js → binary-plugins-DQYcuBHP.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-ChWW8Z9L.js → block-editor-Bx0uXbJP.js} +3 -3
  16. package/dist/gateway/static/root/assets/{browser-automation-inputs-C5s1yHOu.js → browser-automation-inputs-1ZIPGDeq.js} +1 -1
  17. package/dist/gateway/static/root/assets/{browser-automations-page-BV00BXRb.js → browser-automations-page-CCjYipHc.js} +2 -2
  18. package/dist/gateway/static/root/assets/browser-settings-page-CSv4rvmx.js +3 -0
  19. package/dist/gateway/static/root/assets/capabilities-BnO9LV7U.js +1 -0
  20. package/dist/gateway/static/root/assets/{capabilities-page-v0WkhV5o.js → capabilities-page-BfvDvIY1.js} +2 -2
  21. package/dist/gateway/static/root/assets/capabilities-settings-panel-CoW7-ESq.js +8 -0
  22. package/dist/gateway/static/root/assets/{capability-header-actions-vmx35sbu.js → capability-header-actions-D_hbWRRF.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-BhMaRh1x.js +1 -0
  24. package/dist/gateway/static/root/assets/{chat-terminal-dock-C41mXCAi.js → chat-terminal-dock-Fnum_IEm.js} +1 -1
  25. package/dist/gateway/static/root/assets/{computer-settings-page-BJkqok2G.js → computer-settings-page-DI1zfCTA.js} +1 -1
  26. package/dist/gateway/static/root/assets/{connector-service-page-BKCZMmwm.js → connector-service-page-CiGDAubm.js} +1 -1
  27. package/dist/gateway/static/root/assets/connectors-page-Ono0Pha1.js +2 -0
  28. package/dist/gateway/static/root/assets/{date-picker-CrOV4Ynd.js → date-picker-D-JhzZyW.js} +1 -1
  29. package/dist/gateway/static/root/assets/{dependency-picker-CqADAHZp.js → dependency-picker-DpD3xaEB.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-Bab-iWED.js → desktop-pet-CCoDxKqh.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-settings-BqgzLOdi.js → desktop-pet-settings-GxndKfCx.js} +1 -1
  32. package/dist/gateway/static/root/assets/{device-pairing-wizard-DFg7FDPf.js → device-pairing-wizard-B71w3ptm.js} +1 -1
  33. package/dist/gateway/static/root/assets/{directory-picker-path-field-hqJ9sFCR.js → directory-picker-path-field-CUzjJvjs.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-debug-page-DX3PFhRE.js → extension-debug-page-BtDY8ntX.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-page-DkREdHLs.js → extension-page-D9_XF-XC.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-settings-page-wF-HNTM-.js → extension-settings-page-CjhUFAaC.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-swr-cR-tz7-Q.js → gateway-config-swr-CgIjCxM8.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-settings-Du-Dos9O.js → gateway-settings-BWaCnwT1.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-6jLRcQsu.js → gateway-startup-retry-i-1lTrwY.js} +1 -1
  40. package/dist/gateway/static/root/assets/home-page-BTjGLngn.js +1 -0
  41. package/dist/gateway/static/root/assets/{image-generation-api-CSSkwsyC.js → image-generation-api-gilc-u7M.js} +1 -1
  42. package/dist/gateway/static/root/assets/{imports-page-B80Cv043.js → imports-page-BEtq5BRU.js} +1 -1
  43. package/dist/gateway/static/root/assets/index-DHL16aYZ.js +121 -0
  44. package/dist/gateway/static/root/assets/index-N1e6PDwx.css +1 -0
  45. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BgoFaTwv.js → keyboard-shortcuts-settings-JUYY_18v.js} +1 -1
  46. package/dist/gateway/static/root/assets/local-app-workbench-page-uI7mtoVz.js +1 -0
  47. package/dist/gateway/static/root/assets/{local-apps-page-HO6OQlQT.js → local-apps-page-BlYESNqz.js} +1 -1
  48. package/dist/gateway/static/root/assets/{locale-store-wNXWkWu5.js → locale-store-BY30D6tg.js} +1 -1
  49. package/dist/gateway/static/root/assets/{logs-page-CjzR9Rpj.js → logs-page-BbLQreeN.js} +2 -2
  50. package/dist/gateway/static/root/assets/management-settings-c4krhYU7.js +1 -0
  51. package/dist/gateway/static/root/assets/{markdown-view-DlT9KqwF.js → markdown-view-BEeXMfDw.js} +1 -1
  52. package/dist/gateway/static/root/assets/{media-plugins-Dlj6TD3M.js → media-plugins-DEFN1I73.js} +1 -1
  53. package/dist/gateway/static/root/assets/messages-_6IXbP2u.js +3 -0
  54. package/dist/gateway/static/root/assets/note-detail-panel--09xGxyE.js +5 -0
  55. package/dist/gateway/static/root/assets/notes-page-DsxcVBXF.js +8 -0
  56. package/dist/gateway/static/root/assets/{page-context-capture-button-BArPtqp5.js → page-context-capture-button-D43aVpCj.js} +1 -1
  57. package/dist/gateway/static/root/assets/{page-tabs-vqI30Yrg.js → page-tabs-BhYBCqls.js} +1 -1
  58. package/dist/gateway/static/root/assets/{preview-open-alternatives-B-mwPBJW.js → preview-open-alternatives-CP8agNlc.js} +1 -1
  59. package/dist/gateway/static/root/assets/{product-open-page-D--sj_uN.js → product-open-page-CU7fRhfT.js} +1 -1
  60. package/dist/gateway/static/root/assets/project-detail-page-U-EdDfAW.js +1 -0
  61. package/dist/gateway/static/root/assets/{projects-page-DBsBwAQ6.js → projects-page-DUOKZLt7.js} +1 -1
  62. package/dist/gateway/static/root/assets/{registry-api-BIpltJ47.js → registry-api-BvVx0G1o.js} +1 -1
  63. package/dist/gateway/static/root/assets/{remote-access-hub-BurdDY0m.js → remote-access-hub-fVPQe5YS.js} +1 -1
  64. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CAnb0PNY.js → runtime-tools-settings-panel-Czvzsuj_.js} +2 -2
  65. package/dist/gateway/static/root/assets/scenes-page-C0-WHOY3.js +2 -0
  66. package/dist/gateway/static/root/assets/{schema-form-BKj6wIMb.js → schema-form-B9Ni5O93.js} +1 -1
  67. package/dist/gateway/static/root/assets/sessions-page-DdXvW09N.js +1 -0
  68. package/dist/gateway/static/root/assets/settings-advanced-gate-BtF83fBY.js +1 -0
  69. package/dist/gateway/static/root/assets/{settings-form-section-78ycUHfv.js → settings-form-section-jquf1P7n.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-BOdxIVzo.js → settings-page-DPomsvba.js} +1 -1
  71. package/dist/gateway/static/root/assets/{setup-status-panel-CbKHBjrU.js → setup-status-panel-BvVlqpHf.js} +1 -1
  72. package/dist/gateway/static/root/assets/{share-preview-page-DyLfktib.js → share-preview-page-b9DI0N1J.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-R_qwc4DN.js +1 -0
  74. package/dist/gateway/static/root/assets/{skill-api-CiBGQ0Jg.js → skill-api-Bu7-3w-L.js} +1 -1
  75. package/dist/gateway/static/root/assets/skill-reload-api-CNJAQ_e-.js +1 -0
  76. package/dist/gateway/static/root/assets/{skills-page-C35VKjhb.js → skills-page-D7XPEQu_.js} +1 -1
  77. package/dist/gateway/static/root/assets/{system-settings-panel-CyJUeREH.js → system-settings-panel-BwFR0Uci.js} +1 -1
  78. package/dist/gateway/static/root/assets/task-detail-page-PFjGW2g1.js +1 -0
  79. package/dist/gateway/static/root/assets/{tunnel-api-Day9zhKi.js → tunnel-api-PfucxMP3.js} +1 -1
  80. package/dist/gateway/static/root/assets/usage-page-t_zdQHcy.js +1 -0
  81. package/dist/gateway/static/root/assets/{use-autosave-Bj9hC6ML.js → use-autosave-DLyy2wHz.js} +1 -1
  82. package/dist/gateway/static/root/assets/user-model-page-OyfPVfB9.js +2 -0
  83. package/dist/gateway/static/root/assets/{voice-api-key-field-fWRD6B8r.js → voice-api-key-field-CQDY5EBK.js} +1 -1
  84. package/dist/gateway/static/root/assets/{voice-config-api-ujEySjyc.js → voice-config-api-Bwy3Al3J.js} +1 -1
  85. package/dist/gateway/static/root/assets/{work-discovery-overlay-CnxdvIk8.js → work-discovery-overlay-CJzqJ47I.js} +1 -1
  86. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DlWNN1VA.js → workflow-run-setup-panel-sCOk-esV.js} +2 -2
  87. package/dist/gateway/static/root/assets/workflows-page-DYBGjN7C.js +6 -0
  88. package/dist/gateway/static/root/index.html +9 -9
  89. package/dist/package.js +1 -1
  90. package/dist/packages/gateway-contract/src/automations.js +44 -14
  91. package/dist/packages/gateway-contract/src/capabilities.js +106 -8
  92. package/dist/packages/gateway-contract/src/index.js +2 -0
  93. package/dist/packages/gateway-contract/src/scenes.js +7 -6
  94. package/dist/packages/gateway-contract/src/sessions.js +2 -1
  95. package/dist/packages/gateway-contract/src/usage.js +6 -0
  96. package/dist/src/agent/agent-manager.js +9 -3
  97. package/dist/src/agent/background-review/run-background-review.js +6 -1
  98. package/dist/src/agent/embedded/run-turn.js +7 -1
  99. package/dist/src/agent/external-tools/gateway-tools.d.ts +2 -1
  100. package/dist/src/agent/external-tools/gateway-tools.js +44 -11
  101. package/dist/src/agent/external-tools/index.js +1 -1
  102. package/dist/src/agent/image/understanding/pi-ai-provider.js +1 -1
  103. package/dist/src/agent/memory/compaction.js +4 -0
  104. package/dist/src/agent/service/btw-query.js +8 -2
  105. package/dist/src/agent/service.js +1 -1
  106. package/dist/src/agent/skills/filesystem-watcher.js +1 -1
  107. package/dist/src/agent/skills/hub-pull.js +2 -2
  108. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +1 -1
  109. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +1 -1
  110. package/dist/src/agent/tasks/task-judge-service.js +4 -0
  111. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  112. package/dist/src/agent/tool-manuals/xopc-use.js +5 -4
  113. package/dist/src/agent/tools/automation-tool.d.ts +4 -1
  114. package/dist/src/agent/tools/automation-tool.js +42 -4
  115. package/dist/src/agent/tools/session-search-tool.js +1 -1
  116. package/dist/src/agent/tools/web-extract.js +1 -1
  117. package/dist/src/agent/tools/xopc-use-tool.js +49 -8
  118. package/dist/src/ai-assist/text-assist.js +5 -1
  119. package/dist/src/automations/api/routes.js +65 -0
  120. package/dist/src/automations/capabilities/read.js +24 -0
  121. package/dist/src/automations/capabilities/write.d.ts +52 -14
  122. package/dist/src/automations/capabilities/write.js +52 -3
  123. package/dist/src/automations/delivery/delivery-router.d.ts +50 -0
  124. package/dist/src/automations/delivery/delivery-router.js +318 -0
  125. package/dist/src/automations/delivery/index.d.ts +1 -0
  126. package/dist/src/automations/delivery/index.js +2 -0
  127. package/dist/src/automations/domain/defaults.d.ts +0 -1
  128. package/dist/src/automations/domain/defaults.js +1 -1
  129. package/dist/src/automations/domain/index.js +2 -2
  130. package/dist/src/automations/domain/types.d.ts +158 -7
  131. package/dist/src/automations/domain/validation.d.ts +104 -22
  132. package/dist/src/automations/domain/validation.js +66 -13
  133. package/dist/src/automations/draft/automation-draft-prompt.js +3 -4
  134. package/dist/src/automations/draft/automation-draft-service.js +6 -0
  135. package/dist/src/automations/draft/automation-draft-validator.d.ts +22 -3
  136. package/dist/src/automations/draft/automation-draft-validator.js +4 -4
  137. package/dist/src/automations/events/event-catalog.d.ts +14 -0
  138. package/dist/src/automations/events/event-catalog.js +117 -0
  139. package/dist/src/automations/events/event-dispatcher.d.ts +27 -0
  140. package/dist/src/automations/events/event-dispatcher.js +140 -0
  141. package/dist/src/automations/events/event-repository.d.ts +59 -0
  142. package/dist/src/automations/events/event-repository.js +361 -0
  143. package/dist/src/automations/events/index.d.ts +3 -0
  144. package/dist/src/automations/events/index.js +4 -0
  145. package/dist/src/automations/index.d.ts +3 -1
  146. package/dist/src/automations/index.js +9 -3
  147. package/dist/src/automations/service/action-executor.d.ts +20 -1
  148. package/dist/src/automations/service/action-executor.js +80 -40
  149. package/dist/src/automations/service/automation-service.d.ts +21 -4
  150. package/dist/src/automations/service/automation-service.js +150 -100
  151. package/dist/src/automations/storage/automation-repository.js +4 -5
  152. package/dist/src/automations/storage/automation-run-repository.d.ts +1 -0
  153. package/dist/src/automations/storage/automation-run-repository.js +26 -1
  154. package/dist/src/automations/storage/index.js +2 -2
  155. package/dist/src/automations/webhook-secrets.d.ts +1 -0
  156. package/dist/src/automations/webhook-secrets.js +16 -0
  157. package/dist/src/capabilities/store-connector.d.ts +17 -1
  158. package/dist/src/capabilities/store-connector.js +69 -3
  159. package/dist/src/cli/commands/connectors.js +4 -3
  160. package/dist/src/cli/commands/doctor/checks/automation-integrity.d.ts +2 -0
  161. package/dist/src/cli/commands/doctor/checks/automation-integrity.js +55 -0
  162. package/dist/src/cli/commands/doctor/checks/database-relations.d.ts +2 -0
  163. package/dist/src/cli/commands/doctor/checks/database-relations.js +81 -0
  164. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  165. package/dist/src/cli/commands/doctor/flow.js +5 -1
  166. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  167. package/dist/src/cli/commands/skills.js +1 -1
  168. package/dist/src/connectors/approval-resume.js +1 -1
  169. package/dist/src/connectors/cli/store.js +1 -1
  170. package/dist/src/connectors/composio-backends.js +14 -4
  171. package/dist/src/connectors/composio-managed-events.d.ts +5 -2
  172. package/dist/src/connectors/composio-managed-events.js +4 -1
  173. package/dist/src/connectors/connection-recovery-service.d.ts +2 -1
  174. package/dist/src/connectors/connection-recovery-service.js +89 -4
  175. package/dist/src/discussions/analyzer.js +4 -4
  176. package/dist/src/extensions/update.js +1 -1
  177. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  178. package/dist/src/gateway/home-intelligence-automation-reconciler.js +4 -1
  179. package/dist/src/gateway/hono/routes/capabilities.js +1 -1
  180. package/dist/src/gateway/hono/routes/connection-waits.js +3 -2
  181. package/dist/src/gateway/hono/routes/lazy-bundles.js +14 -1
  182. package/dist/src/gateway/hono/routes/public-gateway.js +93 -3
  183. package/dist/src/gateway/hono/routes/scenes.js +57 -41
  184. package/dist/src/gateway/hono/routes/sessions.js +15 -0
  185. package/dist/src/gateway/hono/routes/usage.d.ts +3 -0
  186. package/dist/src/gateway/hono/routes/usage.js +61 -0
  187. package/dist/src/gateway/hono/routes/voice.js +1 -1
  188. package/dist/src/gateway/memory-maintenance-automation-reconciler.js +5 -2
  189. package/dist/src/gateway/scenes/host.js +27 -14
  190. package/dist/src/gateway/scenes/slackThreadSource.d.ts +2 -2
  191. package/dist/src/gateway/security/gateway-scopes.js +1 -0
  192. package/dist/src/gateway/service/active-execution.d.ts +19 -0
  193. package/dist/src/gateway/service/active-execution.js +16 -0
  194. package/dist/src/gateway/service/agent-runner.d.ts +4 -0
  195. package/dist/src/gateway/service/agent-runner.js +19 -1
  196. package/dist/src/gateway/service/marketplace-service.js +2 -2
  197. package/dist/src/gateway/service/run-gateway-agent.d.ts +2 -0
  198. package/dist/src/gateway/service/run-gateway-agent.js +9 -1
  199. package/dist/src/gateway/service/sessions-api.d.ts +13 -0
  200. package/dist/src/gateway/service/sessions-api.js +23 -0
  201. package/dist/src/gateway/service.d.ts +6 -3
  202. package/dist/src/gateway/service.js +82 -85
  203. package/dist/src/gateway/side-chat/run-service.js +10 -7
  204. package/dist/src/home-intelligence/generator.js +4 -1
  205. package/dist/src/home-intelligence/host.js +1 -1
  206. package/dist/src/infra/domain-outbox-dispatcher.d.ts +0 -3
  207. package/dist/src/infra/domain-outbox-dispatcher.js +15 -7
  208. package/dist/src/local-apps/service.js +1 -1
  209. package/dist/src/notes/service.js +2 -3
  210. package/dist/src/projects/project-service.js +1 -2
  211. package/dist/src/projects/project-skill-service.js +2 -2
  212. package/dist/src/providers/model-call.d.ts +3 -2
  213. package/dist/src/providers/model-call.js +30 -5
  214. package/dist/src/scenes/activationAdapter.d.ts +19 -0
  215. package/dist/src/scenes/activationAdapter.js +1 -0
  216. package/dist/src/scenes/agentExecutor.js +3 -10
  217. package/dist/src/scenes/contracts.d.ts +3 -9
  218. package/dist/src/scenes/contracts.js +1 -0
  219. package/dist/src/scenes/execution.d.ts +9 -3
  220. package/dist/src/scenes/execution.js +12 -11
  221. package/dist/src/scenes/httpServices.d.ts +5 -2
  222. package/dist/src/scenes/mailContext.d.ts +4 -0
  223. package/dist/src/scenes/mailContext.js +9 -0
  224. package/dist/src/scenes/maintenance.js +1 -5
  225. package/dist/src/scenes/metrics.d.ts +0 -6
  226. package/dist/src/scenes/metrics.js +0 -11
  227. package/dist/src/scenes/registry.d.ts +11 -0
  228. package/dist/src/scenes/registry.js +28 -0
  229. package/dist/src/scenes/repository.d.ts +6 -3
  230. package/dist/src/scenes/repository.js +43 -5
  231. package/dist/src/scenes/service.d.ts +2 -1
  232. package/dist/src/scenes/service.js +9 -7
  233. package/dist/src/scenes/taskFollowUp/contracts.d.ts +37 -7
  234. package/dist/src/scenes/taskFollowUp/contracts.js +36 -17
  235. package/dist/src/scenes/taskFollowUp/service.d.ts +35 -7
  236. package/dist/src/scenes/taskFollowUp/service.js +86 -28
  237. package/dist/src/scenes/templates.d.ts +2 -2
  238. package/dist/src/scenes/userNotes.d.ts +3 -0
  239. package/dist/src/scenes/userNotes.js +6 -0
  240. package/dist/src/session/client-history.d.ts +3 -0
  241. package/dist/src/session/client-history.js +10 -5
  242. package/dist/src/session/manager.d.ts +1 -0
  243. package/dist/src/session/resolve-session.js +4 -3
  244. package/dist/src/session/session-title.js +1 -1
  245. package/dist/src/session/store.d.ts +1 -0
  246. package/dist/src/session/store.js +3 -2
  247. package/dist/src/storage/sqlite/ai-usage-repository.d.ts +137 -0
  248. package/dist/src/storage/sqlite/ai-usage-repository.js +175 -0
  249. package/dist/src/storage/sqlite/connector-account-repository.js +7 -5
  250. package/dist/src/storage/sqlite/connector-repository.js +36 -34
  251. package/dist/src/storage/sqlite/index.d.ts +2 -2
  252. package/dist/src/storage/sqlite/index.js +3 -3
  253. package/dist/src/storage/sqlite/migrations/209_automation_event_hub.sql +48 -0
  254. package/dist/src/storage/sqlite/migrations/210_remove_legacy_automation_timeout.sql +14 -0
  255. package/dist/src/storage/sqlite/migrations/211_automation_result_deliveries.sql +16 -0
  256. package/dist/src/storage/sqlite/migrations/212_automation_delivery_policy.sql +30 -0
  257. package/dist/src/storage/sqlite/migrations/213_automation_reliability_contract.sql +188 -0
  258. package/dist/src/storage/sqlite/migrations/214_ai_usage_ledger.sql +41 -0
  259. package/dist/src/storage/sqlite/migrations/215_scene_execution_adapters.sql +6 -0
  260. package/dist/src/storage/sqlite/migrations/216_remove_scene_model_usage.sql +1 -0
  261. package/dist/src/storage/sqlite/migrations/217_remove_legacy_memory_tables.sql +4 -0
  262. package/dist/src/storage/sqlite/migrations/218_core_relation_indexes.sql +26 -0
  263. package/dist/src/storage/sqlite/migrations/219_json_contracts.sql +123 -0
  264. package/dist/src/storage/sqlite/migrations/220_normalize_timestamps.sql +339 -0
  265. package/dist/src/storage/sqlite/migrations/221_ai_usage_retention_index.sql +2 -0
  266. package/dist/src/storage/sqlite/migrations/222_session_config_authority.sql +13 -0
  267. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  268. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  269. package/dist/src/storage/sqlite/row-mappers.d.ts +3 -7
  270. package/dist/src/storage/sqlite/row-mappers.js +6 -6
  271. package/dist/src/storage/sqlite/scenes-schema.d.ts +1 -1
  272. package/dist/src/storage/sqlite/scenes-schema.js +0 -1
  273. package/dist/src/storage/sqlite/schema.js +1 -1
  274. package/dist/src/storage/sqlite/schema.sql +0 -52
  275. package/dist/src/storage/sqlite/schemas/scenes.sql +0 -7
  276. package/dist/src/storage/sqlite/session-input-repository.d.ts +8 -0
  277. package/dist/src/storage/sqlite/session-input-repository.js +18 -1
  278. package/dist/src/storage/sqlite/session-read-repository.d.ts +1 -1
  279. package/dist/src/storage/sqlite/session-read-repository.js +0 -1
  280. package/dist/src/storage/sqlite/session-repository.d.ts +0 -4
  281. package/dist/src/storage/sqlite/session-repository.js +8 -18
  282. package/dist/src/storage/sqlite/timestamps.d.ts +4 -0
  283. package/dist/src/storage/sqlite/timestamps.js +20 -0
  284. package/dist/src/storage/sqlite/transcript-repository.d.ts +1 -0
  285. package/dist/src/storage/sqlite/transcript-repository.js +23 -15
  286. package/dist/src/storage/sqlite/user-trust-repository.js +4 -2
  287. package/dist/src/tasks/capabilities/write.d.ts +1 -1
  288. package/dist/src/tasks/home-query-service.js +3 -3
  289. package/dist/src/tasks/task-contract-planner.js +1 -1
  290. package/dist/src/usage/cost.d.ts +4 -0
  291. package/dist/src/usage/cost.js +28 -0
  292. package/dist/src/usage/recorder.d.ts +13 -0
  293. package/dist/src/usage/recorder.js +117 -0
  294. package/dist/src/usage/scenario-registry.d.ts +8 -0
  295. package/dist/src/usage/scenario-registry.js +117 -0
  296. package/dist/src/usage/types.d.ts +55 -0
  297. package/dist/src/usage/types.js +1 -0
  298. package/dist/src/voice/tts/summarize.js +1 -1
  299. package/dist/src/work-discovery/analyzer.js +2 -2
  300. package/dist/src/work-discovery/investigator.js +1 -1
  301. package/dist/src/workflows/service/workflow-run-service.js +15 -2
  302. package/package.json +3 -3
  303. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Se1Z72VG.js +0 -1
  304. package/dist/gateway/static/root/assets/agents-udIitwV8.js +0 -70
  305. package/dist/gateway/static/root/assets/automations-workspace-BMgJvdcv.js +0 -7
  306. package/dist/gateway/static/root/assets/browser-settings-page-xwTmuZjS.js +0 -3
  307. package/dist/gateway/static/root/assets/capabilities-CHA-sTAZ.js +0 -1
  308. package/dist/gateway/static/root/assets/capabilities-settings-panel-DefBGjhV.js +0 -8
  309. package/dist/gateway/static/root/assets/channels-Eo4ONF5X.js +0 -1
  310. package/dist/gateway/static/root/assets/connectors-page-DZYgogQw.js +0 -2
  311. package/dist/gateway/static/root/assets/home-page-D7YoMHq4.js +0 -1
  312. package/dist/gateway/static/root/assets/index-BEw0xrde.css +0 -1
  313. package/dist/gateway/static/root/assets/index-DalslRUx.js +0 -121
  314. package/dist/gateway/static/root/assets/local-app-workbench-page-BKL5UZAj.js +0 -1
  315. package/dist/gateway/static/root/assets/management-settings-Dk_gTJb9.js +0 -1
  316. package/dist/gateway/static/root/assets/messages-fmf0dnr4.js +0 -3
  317. package/dist/gateway/static/root/assets/note-detail-panel-BebJPjjk.js +0 -5
  318. package/dist/gateway/static/root/assets/notes-page-CmS_hvz8.js +0 -8
  319. package/dist/gateway/static/root/assets/project-detail-page-BFUdtWXF.js +0 -1
  320. package/dist/gateway/static/root/assets/scenes-page-Cj8xtr5t.js +0 -2
  321. package/dist/gateway/static/root/assets/sessions-page-BCsjgkCs.js +0 -1
  322. package/dist/gateway/static/root/assets/settings-advanced-gate-BLL7csOJ.js +0 -1
  323. package/dist/gateway/static/root/assets/shares-settings-BzvSNouj.js +0 -1
  324. package/dist/gateway/static/root/assets/skill-reload-api-BHnru0F5.js +0 -1
  325. package/dist/gateway/static/root/assets/task-detail-page-Bd1_Fguk.js +0 -1
  326. package/dist/gateway/static/root/assets/user-model-page-DuYzuR1T.js +0 -2
  327. package/dist/gateway/static/root/assets/workflows-page-B45YDiEw.js +0 -6
  328. package/dist/src/automations/product-events.d.ts +0 -5
  329. package/dist/src/automations/product-events.js +0 -19
@@ -1,6 +1,3 @@
1
- import type { AutomationEvent } from '../automations/domain/types.js';
2
1
  export declare class DomainOutboxDispatcher {
3
- private readonly publish;
4
- constructor(publish: (event: AutomationEvent) => void);
5
2
  drain(limit?: number, subjectKind?: string): number;
6
3
  }
@@ -1,26 +1,34 @@
1
1
  import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
2
+ import { automationEventPublisher } from "../automations/events/event-repository.js";
2
3
  //#region src/infra/domain-outbox-dispatcher.ts
3
4
  init_transaction();
4
5
  var DomainOutboxDispatcher = class {
5
- constructor(publish) {
6
- this.publish = publish;
7
- }
8
6
  drain(limit = 100, subjectKind) {
9
- const rows = getSqliteDatabase().prepare(`SELECT event_id, event_type, payload_json, created_at, subject_kind, operation_id
7
+ const rows = getSqliteDatabase().prepare(`SELECT event_id, event_type, payload_json, created_at, subject_kind, subject_id, operation_id
10
8
  FROM domain_outbox WHERE published_at IS NULL AND (? IS NULL OR subject_kind = ?)
11
- ORDER BY created_at, event_id LIMIT ?`).all(subjectKind ?? null, subjectKind ?? null, Math.max(1, Math.min(500, Math.floor(limit))));
9
+ ORDER BY created_at, rowid LIMIT ?`).all(subjectKind ?? null, subjectKind ?? null, Math.max(1, Math.min(500, Math.floor(limit))));
12
10
  let published = 0;
13
11
  for (const row of rows) try {
14
12
  const payload = JSON.parse(row.payload_json);
15
- this.publish({
13
+ automationEventPublisher.publish({
14
+ id: row.event_id,
16
15
  type: row.event_type,
17
16
  source: row.subject_kind === "note" ? "notes" : row.subject_kind === "project" ? "projects" : row.subject_kind === "scene" ? "scenes" : row.subject_kind === "local_app" ? "local_apps" : "tasks",
17
+ schemaVersion: 1,
18
+ subject: {
19
+ kind: row.subject_kind,
20
+ id: row.subject_id
21
+ },
18
22
  payload: {
19
23
  ...payload,
20
24
  sourceEventId: row.event_id,
21
25
  ...row.operation_id ? { operationId: row.operation_id } : {}
22
26
  },
23
- occurredAtMs: row.created_at
27
+ occurredAtMs: row.created_at,
28
+ correlationId: typeof payload.correlationId === "string" ? payload.correlationId : row.event_id,
29
+ causationId: typeof payload.causationId === "string" ? payload.causationId : void 0,
30
+ dedupeKey: row.event_id,
31
+ trust: "system"
24
32
  });
25
33
  runSqliteWriteTransaction((db) => {
26
34
  db.prepare(`UPDATE domain_outbox SET published_at = ?, attempts = attempts + 1
@@ -511,7 +511,7 @@ var LocalAppService = class {
511
511
  });
512
512
  }
513
513
  flushAcceptanceEvents() {
514
- new DomainOutboxDispatcher((event) => this.options.emit(event.type, event.payload)).drain(100, "local_app");
514
+ new DomainOutboxDispatcher().drain(100, "local_app");
515
515
  }
516
516
  releaseRoot(appId) {
517
517
  return join(resolveStateDir(), "local-apps", "releases", appId);
@@ -8,7 +8,6 @@ import { init_notes_repository, listNoteProjectSummaries } from "../storage/sqli
8
8
  import { changedFieldsFromPatch, emitActivity, previewText, systemActivityActor, systemActivitySource } from "../activity/emitter.js";
9
9
  import { getDefaultModelSync, init_providers, resolveModel } from "../providers/index.js";
10
10
  import { DomainOutboxDispatcher } from "../infra/domain-outbox-dispatcher.js";
11
- import { publishAutomationProductEvent } from "../automations/product-events.js";
12
11
  import { completeWithResolvedCredentials } from "../providers/model-call.js";
13
12
  import { partitionAttachmentsByReference } from "./note-attachment-sync.js";
14
13
  import { buildNoteAgentContextArtifact, getCachedNoteAgentContextArtifact } from "./agent-context.js";
@@ -153,7 +152,7 @@ async function buildAiCatalysisReport(note, config) {
153
152
  role: "user",
154
153
  content: buildCatalysisPrompt(note),
155
154
  timestamp: Date.now()
156
- }] }, { temperature: .2 });
155
+ }] }, { temperature: .2 }, void 0, { operation: "note.generate" });
157
156
  let responseText = "";
158
157
  if (Array.isArray(response.content)) {
159
158
  for (const part of response.content) if (part && typeof part === "object" && part.type === "text") responseText += String(part.text || "");
@@ -173,7 +172,7 @@ var NotesService = class {
173
172
  flushCommittedEffects() {
174
173
  this.store.drainAttachmentCleanup();
175
174
  this.store.drainDeletionCleanup();
176
- new DomainOutboxDispatcher(publishAutomationProductEvent).drain(100, "note");
175
+ new DomainOutboxDispatcher().drain(100, "note");
177
176
  }
178
177
  async quickCapture(markdown, source, idempotencyKey) {
179
178
  const note = this.quickCaptureAtomically(markdown, source, idempotencyKey);
@@ -8,7 +8,6 @@ import { enqueueProjectChanged } from "./project-change-events.js";
8
8
  import { ProjectWorkspaceConflictError, ProjectWorkspaceMissingError, canonicalWorkspacePath, inferProjectNameFromWorkspaceRoot, isPathSameOrInsideWorkspace, isSafeAutoCreateWorkspaceRoot, resolveWorkspaceProjectRoot, workspaceDirectoryExists } from "./workspace-project.js";
9
9
  import { drainProjectWorkspaceCreation, queueProjectWorkspaceCreation } from "./project-workspace-creation.js";
10
10
  import { DomainOutboxDispatcher } from "../infra/domain-outbox-dispatcher.js";
11
- import { publishAutomationProductEvent } from "../automations/product-events.js";
12
11
  import { listPendingProjectUnderstandingRuns } from "../work-discovery/repository.js";
13
12
  import { inferProjectExecutionMode } from "./project-kind.js";
14
13
  import { bindSessionToProject, listProjectConversationIds, unbindSessionFromProject } from "./session-bind.js";
@@ -280,7 +279,7 @@ var ProjectService = class {
280
279
  }
281
280
  flushCommittedEffects(projectId) {
282
281
  drainProjectWorkspaceCreation(projectId);
283
- new DomainOutboxDispatcher(publishAutomationProductEvent).drain(100, "project");
282
+ new DomainOutboxDispatcher().drain(100, "project");
284
283
  }
285
284
  listUpdates(projectId, limit) {
286
285
  return this.store.listUpdates(projectId, limit);
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveBundledSkillsDir } from "../config/paths.js";
2
- import { resolveWorkspaceSkillsDir, resolveWorkspaceSkillsLockPath } from "../agent/skills/workspace-skills-dir.js";
3
- import { loadSkills, loadWorkspaceSkillInventory } from "../agent/skills/index.js";
4
2
  import { removeSkillsLockEntry } from "../agent/skills/hub-lock.js";
5
3
  import { deleteManagedSkill, installSkillFromZip, isValidSkillId } from "../agent/skills/managed-store.js";
4
+ import { resolveWorkspaceSkillsDir, resolveWorkspaceSkillsLockPath } from "../agent/skills/workspace-skills-dir.js";
5
+ import { loadSkills, loadWorkspaceSkillInventory } from "../agent/skills/index.js";
6
6
  import { pullSkillFromSource } from "../agent/skills/hub-pull.js";
7
7
  import { downloadFromMarketplace } from "../agent/skills/skills-marketplace.js";
8
8
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
@@ -1,5 +1,6 @@
1
1
  import { type Api, type AssistantMessage, type Context, type Model, type SimpleStreamOptions } from '@earendil-works/pi-ai/compat';
2
2
  import type { CredentialResolverOptions } from '../auth/credentials.js';
3
+ import type { AiUsageContext } from '../usage/types.js';
3
4
  export declare function isLocalModelBaseUrl(baseUrl: string | undefined): boolean;
4
5
  /** Codex Responses rejects the temperature request parameter. */
5
6
  export declare function supportsModelTemperature(model: Model<Api>): boolean;
@@ -8,10 +9,10 @@ export declare function resolveModelCallOptions(model: Model<Api>, options?: Sim
8
9
  /**
9
10
  * Complete a one-shot request with xopc credential resolution and extension-provider routing.
10
11
  */
11
- export declare function completeWithResolvedCredentials(model: Model<Api>, context: Context, options?: SimpleStreamOptions, credentialOptions?: CredentialResolverOptions): Promise<AssistantMessage>;
12
+ export declare function completeWithResolvedCredentials(model: Model<Api>, context: Context, options: SimpleStreamOptions, credentialOptions: CredentialResolverOptions | undefined, usageContext: AiUsageContext): Promise<AssistantMessage>;
12
13
  /**
13
14
  * Start a model stream with xopc credential resolution and extension-provider routing.
14
15
  * Callers that need live visible output should consume the returned stream before calling
15
16
  * its `result()` method.
16
17
  */
17
- export declare function createResolvedModelStream(model: Model<Api>, context: Context, options?: SimpleStreamOptions, credentialOptions?: CredentialResolverOptions): Promise<import("@earendil-works/pi-ai/compat").AssistantMessageEventStream>;
18
+ export declare function createResolvedModelStream(model: Model<Api>, context: Context, options: SimpleStreamOptions, credentialOptions: CredentialResolverOptions | undefined, usageContext: AiUsageContext): Promise<import("@earendil-works/pi-ai/compat").AssistantMessageEventStream>;
@@ -1,6 +1,7 @@
1
1
  import { init_constants } from "./constants.js";
2
2
  import { getApiKey, init_providers } from "./index.js";
3
3
  import { createExtensionAwareStreamFn } from "./extension-stream-bridge.js";
4
+ import { finishAiUsageFromMessage, observeAiUsageStream, startAiUsageCall } from "../usage/recorder.js";
4
5
  import { completeSimple, normalizeContext } from "@earendil-works/pi-ai/compat";
5
6
  //#region src/providers/model-call.ts
6
7
  init_constants();
@@ -40,19 +41,43 @@ async function resolveModelCallOptions(model, options = {}, credentialOptions) {
40
41
  /**
41
42
  * Complete a one-shot request with xopc credential resolution and extension-provider routing.
42
43
  */
43
- async function completeWithResolvedCredentials(model, context, options = {}, credentialOptions) {
44
+ async function completeWithResolvedCredentials(model, context, options, credentialOptions, usageContext) {
44
45
  const resolvedOptions = await resolveModelCallOptions(model, options, credentialOptions);
45
- if (model.baseUrl === "extension://provider-plugin") return await (await createExtensionAwareStreamFn()(model, normalizeContext(context), resolvedOptions)).result();
46
- return await completeSimple(model, context, resolvedOptions);
46
+ const usageCall = startAiUsageCall(model, usageContext);
47
+ try {
48
+ if (model.baseUrl === "extension://provider-plugin") {
49
+ const result = await (await createExtensionAwareStreamFn()(model, normalizeContext(context), resolvedOptions)).result();
50
+ finishAiUsageFromMessage(usageCall, result);
51
+ return result;
52
+ }
53
+ const result = await completeSimple(model, context, resolvedOptions);
54
+ finishAiUsageFromMessage(usageCall, result);
55
+ return result;
56
+ } catch (error) {
57
+ usageCall?.finish({
58
+ status: "failed",
59
+ errorSummary: error instanceof Error ? error.message : String(error)
60
+ });
61
+ throw error;
62
+ }
47
63
  }
48
64
  /**
49
65
  * Start a model stream with xopc credential resolution and extension-provider routing.
50
66
  * Callers that need live visible output should consume the returned stream before calling
51
67
  * its `result()` method.
52
68
  */
53
- async function createResolvedModelStream(model, context, options = {}, credentialOptions) {
69
+ async function createResolvedModelStream(model, context, options, credentialOptions, usageContext) {
54
70
  const resolvedOptions = await resolveModelCallOptions(model, options, credentialOptions);
55
- return await createExtensionAwareStreamFn()(model, normalizeContext(context), resolvedOptions);
71
+ const usageCall = startAiUsageCall(model, usageContext);
72
+ try {
73
+ return observeAiUsageStream(await createExtensionAwareStreamFn()(model, normalizeContext(context), resolvedOptions), usageCall);
74
+ } catch (error) {
75
+ usageCall?.finish({
76
+ status: "failed",
77
+ errorSummary: error instanceof Error ? error.message : String(error)
78
+ });
79
+ throw error;
80
+ }
56
81
  }
57
82
  //#endregion
58
83
  export { completeWithResolvedCredentials, createResolvedModelStream, isLocalModelBaseUrl, resolveModelCallApiKey, resolveModelCallOptions, supportsModelTemperature };
@@ -0,0 +1,19 @@
1
+ import type { ScenePrincipal, SceneTemplate } from './contracts.js';
2
+ /** Extension point for activation shapes that need more than the core read-only setup. */
3
+ export interface SceneActivationAdapter {
4
+ id: string;
5
+ preflight(principal: ScenePrincipal, template: SceneTemplate, configuration: unknown): Promise<{
6
+ ready: boolean;
7
+ missing: string[];
8
+ }>;
9
+ create(principal: ScenePrincipal, template: SceneTemplate, configuration: unknown): Promise<unknown>;
10
+ get(principal: ScenePrincipal, activationId: string): unknown;
11
+ configure(principal: ScenePrincipal, activationId: string, expectedRevision: number, configuration: unknown): Promise<unknown>;
12
+ transition(principal: ScenePrincipal, activationId: string, expectedRevision: number, status: 'active' | 'paused' | 'archived'): Promise<unknown>;
13
+ tick(): Promise<void>;
14
+ stop(): Promise<void>;
15
+ executeTask?(runId: string, conversationId: string): Promise<boolean>;
16
+ allowsTaskNotification?(taskId: string): boolean;
17
+ listProjectBranches?(principal: ScenePrincipal, projectId: string): Promise<unknown>;
18
+ associateBranch?(principal: ScenePrincipal, input: unknown): Promise<unknown>;
19
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,7 @@
1
1
  import { init_sync_provider_auth, resolveProviderApiKeySync } from "../auth/sync-provider-auth.js";
2
2
  import { getApiKeySync, init_providers } from "../providers/index.js";
3
3
  import { createExtensionAwareStreamFn } from "../providers/extension-stream-bridge.js";
4
+ import { trackAiUsageStream } from "../usage/recorder.js";
4
5
  import { readOnlyResultSchema } from "./execution.js";
5
6
  import { Agent } from "@earendil-works/pi-agent-core";
6
7
  //#region src/scenes/agentExecutor.ts
@@ -25,10 +26,10 @@ var SceneAgentExecutor = class {
25
26
  },
26
27
  streamFn: (model, context, options) => {
27
28
  if (++calls > 1) throw new Error("Scene executor permits one model call");
28
- return stream(model, context, {
29
+ return trackAiUsageStream(model, input.usage, () => stream(model, context, {
29
30
  ...options,
30
31
  maxTokens: input.template.execution.limits.maxOutputTokens
31
- });
32
+ }));
32
33
  },
33
34
  getApiKey: (provider) => resolveProviderApiKeySync(provider) ?? getApiKeySync(provider) ?? ""
34
35
  });
@@ -42,14 +43,6 @@ var SceneAgentExecutor = class {
42
43
  }));
43
44
  input.signal.throwIfAborted();
44
45
  const response = agent.state.messages.findLast((message) => message.role === "assistant");
45
- if (response?.role === "assistant") input.onUsage?.({
46
- provider: response.provider,
47
- model: response.model,
48
- inputTokens: response.usage.input,
49
- outputTokens: response.usage.output,
50
- totalTokens: response.usage.totalTokens,
51
- estimatedCost: response.usage.cost.total
52
- });
53
46
  if (!response || response.role !== "assistant" || response.stopReason !== "stop") throw new Error("Scene model did not complete a read-only result");
54
47
  if (response.content.some((block) => block.type === "toolCall")) throw new Error("Scene model attempted an unavailable tool");
55
48
  const text = response.content.filter((block) => block.type === "text").map((block) => block.text).join("");
@@ -2,14 +2,8 @@ export { sceneOutcomeKinds, activationStatuses, sceneScopeSchema, sceneTemplateS
2
2
  import { type SceneTemplate, type ScenePermission, type ActivationStatus } from '@xopcai/gateway-contract';
3
3
  /** Stable JSON hashing binds approvals and immutable versions to exact content. */
4
4
  export declare function sceneContentHash(value: unknown): string;
5
- export declare function validateTemplate(value: unknown, registered: Pick<ScenePermission, 'contextProviders' | 'effectHandlers'>): SceneTemplate;
5
+ export declare function validateTemplate(value: unknown, registered: Pick<ScenePermission, 'contextProviders' | 'effectHandlers'> & {
6
+ executionAdapters?: string[];
7
+ }): SceneTemplate;
6
8
  export declare function intersectPermissions(...permissions: ScenePermission[]): ScenePermission;
7
9
  export declare function canTransitionActivation(from: ActivationStatus, to: ActivationStatus): boolean;
8
- export type SceneModelUsage = {
9
- provider: string;
10
- model: string;
11
- inputTokens: number;
12
- outputTokens: number;
13
- totalTokens: number;
14
- estimatedCost: number;
15
- };
@@ -18,6 +18,7 @@ function validateTemplate(value, registered) {
18
18
  const template = sceneTemplateSchema.parse(value);
19
19
  for (const provider of template.contextProviders) if (!registered.contextProviders.includes(provider)) throw new Error(`Unknown scene context provider: ${provider}`);
20
20
  for (const handler of template.allowedEffectHandlers) if (!registered.effectHandlers.includes(handler)) throw new Error(`Unknown scene effect handler: ${handler}`);
21
+ if (registered.executionAdapters && !registered.executionAdapters.includes(template.execution.kind)) throw new Error(`Unknown scene execution adapter: ${template.execution.kind}`);
21
22
  return template;
22
23
  }
23
24
  function intersectPermissions(...permissions) {
@@ -1,6 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { type SceneModelUsage, type SceneActivation, type ScenePermission, type SceneTemplate } from './contracts.js';
2
+ import type { AiUsageContext } from '../usage/types.js';
3
+ import { type SceneActivation, type ScenePermission, type SceneTemplate } from './contracts.js';
3
4
  import { SceneRepository } from './repository.js';
5
+ import { SceneCapabilityRegistry } from './registry.js';
4
6
  export declare const readOnlyResultSchema: z.ZodObject<{
5
7
  kind: z.ZodEnum<{
6
8
  artifact: "artifact";
@@ -27,6 +29,10 @@ export interface SceneEvidence {
27
29
  }
28
30
  export interface SceneContextProvider {
29
31
  id: string;
32
+ setupIssues?(activation: SceneActivation): string[];
33
+ authorization?(activation: SceneActivation): string[] | null;
34
+ tracksHealth?: boolean;
35
+ requiresAccountIdentity?: boolean;
30
36
  read(input: {
31
37
  activation: SceneActivation;
32
38
  subjectId: string;
@@ -41,7 +47,7 @@ export interface SceneReadOnlyExecutor {
41
47
  goal: string;
42
48
  evidence: SceneEvidence[];
43
49
  signal: AbortSignal;
44
- onUsage?: (usage: SceneModelUsage) => void;
50
+ usage: AiUsageContext;
45
51
  }): Promise<unknown>;
46
52
  }
47
53
  /** Runs one durable claim without exposing messaging, filesystem or write tools. */
@@ -51,6 +57,6 @@ export declare class SceneExecutionService {
51
57
  private readonly executor;
52
58
  private readonly authorize;
53
59
  private readonly clock;
54
- constructor(repository: SceneRepository, providers: readonly SceneContextProvider[], executor: SceneReadOnlyExecutor, authorize: (activation: SceneActivation) => Promise<ScenePermission>, clock?: () => number);
60
+ constructor(repository: SceneRepository, providers: SceneCapabilityRegistry<SceneContextProvider>, executor: SceneReadOnlyExecutor, authorize: (activation: SceneActivation) => Promise<ScenePermission>, clock?: () => number);
55
61
  runNext(worker: string, outerSignal?: AbortSignal): Promise<'idle' | 'completed' | 'discarded' | 'failed' | 'deferred'>;
56
62
  }
@@ -36,7 +36,6 @@ var SceneExecutionService = class {
36
36
  this.executor = executor;
37
37
  this.authorize = authorize;
38
38
  this.clock = clock;
39
- if (new Set(providers.map((provider) => provider.id)).size !== providers.length) throw new Error("Duplicate scene context providers");
40
39
  }
41
40
  async runNext(worker, outerSignal) {
42
41
  outerSignal?.throwIfAborted();
@@ -46,6 +45,7 @@ var SceneExecutionService = class {
46
45
  if (!runInput) return "discarded";
47
46
  const { activation, subjectId, accountId, notBefore } = runInput;
48
47
  const template = this.repository.getTemplate(activation.templateKey, activation.templateVersion);
48
+ if (template.execution.kind !== "agent") throw new SceneExecutionRejected("executor_unavailable");
49
49
  if (!this.repository.renewLease(claim, this.clock(), template.execution.limits.timeoutSeconds * 1e3 + 5e3)) return "discarded";
50
50
  const controller = new AbortController();
51
51
  const abort = () => controller.abort(outerSignal?.reason);
@@ -69,7 +69,7 @@ var SceneExecutionService = class {
69
69
  try {
70
70
  granted = await this.authorize(activation);
71
71
  } catch (error) {
72
- if (template.contextProviders.includes("mail")) this.repository.recordSourceHealth(activation, sceneSourceFailureReason(error), this.clock(), this.clock() + 6e4);
72
+ if (template.contextProviders.some((id) => this.providers.get(id).tracksHealth)) this.repository.recordSourceHealth(activation, sceneSourceFailureReason(error), this.clock(), this.clock() + 6e4);
73
73
  throw error;
74
74
  }
75
75
  assertCurrent();
@@ -80,12 +80,11 @@ var SceneExecutionService = class {
80
80
  });
81
81
  const evidence = [];
82
82
  for (const providerId of template.contextProviders) {
83
+ const provider = this.providers.get(providerId);
83
84
  if (!permissions.contextProviders.includes(providerId)) {
84
- if (providerId === "mail") this.repository.recordSourceHealth(activation, "needs_permission", this.clock(), this.clock() + 6e4);
85
+ if (provider.tracksHealth) this.repository.recordSourceHealth(activation, "needs_permission", this.clock(), this.clock() + 6e4);
85
86
  throw new SceneExecutionRejected("needs_permission");
86
87
  }
87
- const provider = this.providers.find((item) => item.id === providerId);
88
- if (!provider) throw new SceneExecutionRejected("provider_unavailable");
89
88
  let items;
90
89
  try {
91
90
  items = await provider.read({
@@ -96,11 +95,11 @@ var SceneExecutionService = class {
96
95
  signal: controller.signal
97
96
  });
98
97
  } catch (error) {
99
- if (providerId === "mail" && !outerSignal?.aborted) this.repository.recordSourceHealth(activation, sceneSourceFailureReason(error), this.clock(), this.clock() + 6e4);
98
+ if (provider.tracksHealth && !outerSignal?.aborted) this.repository.recordSourceHealth(activation, sceneSourceFailureReason(error), this.clock(), this.clock() + 6e4);
100
99
  throw error;
101
100
  }
102
101
  assertCurrent();
103
- if (providerId === "mail" && items.some((item) => item.accountId === void 0)) throw new SceneExecutionRejected("missing_account_identity");
102
+ if (provider.requiresAccountIdentity && items.some((item) => item.accountId === void 0)) throw new SceneExecutionRejected("missing_account_identity");
104
103
  if (items.some((item) => !evidenceAllowed(item, activation, permissions, this.clock()))) throw new SceneExecutionRejected("unauthorized_or_stale_evidence");
105
104
  evidence.push(...items);
106
105
  }
@@ -108,7 +107,7 @@ var SceneExecutionService = class {
108
107
  if (new Set(evidence.map((item) => item.id)).size !== evidence.length) throw new SceneExecutionRejected("duplicate_evidence");
109
108
  evidence.sort((left, right) => left.id.localeCompare(right.id));
110
109
  const fingerprint = sceneContentHash(evidence.map(({ freshUntil: _freshUntil, ...item }) => item));
111
- if (template.contextProviders.includes("mail")) this.repository.recordSourceHealth(activation, null, this.clock());
110
+ if (template.contextProviders.some((id) => this.providers.get(id).tracksHealth)) this.repository.recordSourceHealth(activation, null, this.clock());
112
111
  return {
113
112
  evidence,
114
113
  fingerprint,
@@ -137,9 +136,11 @@ var SceneExecutionService = class {
137
136
  goal: activation.goal,
138
137
  evidence: snapshot.evidence,
139
138
  signal: controller.signal,
140
- onUsage: (usage) => {
141
- assertCurrent();
142
- this.repository.recordModelUsage(claim, usage, this.clock());
139
+ usage: {
140
+ operation: "scene.execute",
141
+ traceId: claim.id,
142
+ runId: claim.id,
143
+ ...activation.scope.kind === "conversation" ? { conversationId: activation.scope.id } : {}
143
144
  }
144
145
  });
145
146
  assertCurrent();
@@ -6,10 +6,13 @@ import type { SceneApplicationService } from './service.js';
6
6
  import type { SceneMailContextProvider } from './mailContext.js';
7
7
  import type { ScenePreferenceService } from './preferences.js';
8
8
  import type { SceneMetrics } from './metrics.js';
9
- import type { TaskFollowUpService } from './taskFollowUp/service.js';
9
+ import type { SceneActivationAdapter } from './activationAdapter.js';
10
+ import type { SceneCapabilityRegistry } from './registry.js';
11
+ import type { SceneSourceRegistry } from './taskFollowUp/contracts.js';
10
12
  /** An explicitly installed scene domain; never resolves to the old runtime. */
11
13
  export interface SceneHttpServices {
12
- followUps?: TaskFollowUpService;
14
+ activationAdapters: SceneCapabilityRegistry<SceneActivationAdapter>;
15
+ sourceProviders: SceneSourceRegistry;
13
16
  repository: SceneRepository;
14
17
  application: SceneApplicationService;
15
18
  inbox: SceneInboxService;
@@ -6,7 +6,11 @@ export declare class SceneMailContextProvider implements SceneContextProvider {
6
6
  private readonly db;
7
7
  private readonly clock;
8
8
  readonly id = "mail";
9
+ readonly tracksHealth = true;
10
+ readonly requiresAccountIdentity = true;
9
11
  constructor(db: DatabaseSync, clock?: () => number);
12
+ setupIssues(activation: SceneActivation): string[];
13
+ authorization(activation: SceneActivation): string[] | null;
10
14
  /** Resolve current account grants for the exact delegated source, including reconnects and revocation. */
11
15
  authorizedAccounts(activation: SceneActivation): string[];
12
16
  /** Picker metadata only; choosing an item still requires explicit activation consent. */
@@ -11,10 +11,19 @@ const accountPolicy = `a.enabled = 1 AND installation.enabled = 1 AND c.status =
11
11
  /** Reads a bounded, account-scoped thread from synchronized connector knowledge. */
12
12
  var SceneMailContextProvider = class {
13
13
  id = "mail";
14
+ tracksHealth = true;
15
+ requiresAccountIdentity = true;
14
16
  constructor(db, clock = Date.now) {
15
17
  this.db = db;
16
18
  this.clock = clock;
17
19
  }
20
+ setupIssues(activation) {
21
+ return activation.scope.kind === "objects" && activation.scope.ids.length === 1 && activation.permissions.accountIds.length === 1 ? [] : ["one_mail_thread_and_account"];
22
+ }
23
+ authorization(activation) {
24
+ const accounts = this.authorizedAccounts(activation);
25
+ return accounts.length ? accounts : null;
26
+ }
18
27
  /** Resolve current account grants for the exact delegated source, including reconnects and revocation. */
19
28
  authorizedAccounts(activation) {
20
29
  if (activation.scope.kind !== "objects" || activation.scope.ids.length !== 1) return [];
@@ -11,11 +11,7 @@ function maintainSceneStorage(db, now = Date.now()) {
11
11
  db.prepare(`DELETE FROM scene_mail_sources WHERE id IN (SELECT s.id FROM scene_mail_sources s
12
12
  WHERE s.selected_at < ? AND NOT EXISTS (SELECT 1 FROM scene_activations a, json_each(a.scope_json, '$.ids') ids WHERE ids.value = s.id)
13
13
  ORDER BY selected_at LIMIT 100)`).run(now - 30 * 864e5);
14
- for (const table of [
15
- "scene_context_snapshots",
16
- "scene_model_reservations",
17
- "scene_model_usage"
18
- ]) db.prepare(`DELETE FROM ${table} WHERE run_id IN (SELECT DISTINCT r.id FROM scene_runs r JOIN ${table} t ON t.run_id = r.id
14
+ for (const table of ["scene_context_snapshots", "scene_model_reservations"]) db.prepare(`DELETE FROM ${table} WHERE run_id IN (SELECT DISTINCT r.id FROM scene_runs r JOIN ${table} t ON t.run_id = r.id
19
15
  WHERE r.status NOT IN ('running', 'retry_wait') AND r.created_at < ? ORDER BY r.created_at LIMIT 100)`).run(cutoff);
20
16
  db.prepare("DELETE FROM notification_attention_budget WHERE dedupe_key IN (SELECT dedupe_key FROM notification_attention_budget WHERE created_at < ? LIMIT 100)").run(cutoff);
21
17
  });
@@ -11,12 +11,6 @@ export declare class SceneMetrics {
11
11
  currentModel: string;
12
12
  pendingChecks: number;
13
13
  oldestDueWaitMs: number;
14
- lastSevenDays: {
15
- modelCalls: number;
16
- connectorReads: number;
17
- tokens: number;
18
- estimatedCost: number;
19
- };
20
14
  notifications: Record<string, import("node:sqlite").SQLOutputValue>[];
21
15
  activations: Record<string, import("node:sqlite").SQLOutputValue>[];
22
16
  };
@@ -12,11 +12,6 @@ var SceneMetrics = class {
12
12
  const queue = this.db.prepare(`SELECT COUNT(*) AS depth, MIN(i.due_at) AS oldest
13
13
  FROM scene_trigger_intents i JOIN scene_activations a ON a.id = i.activation_id
14
14
  WHERE a.owner_id = ? AND a.workspace_id = ? AND i.status = 'pending'`).get(principal.ownerId, principal.workspaceId);
15
- const usage = this.db.prepare(`SELECT COUNT(*) AS calls, COALESCE(SUM(u.total_tokens), 0) AS tokens,
16
- COALESCE(SUM(u.estimated_cost), 0) AS cost FROM scene_model_usage u JOIN scene_runs r ON r.id = u.run_id
17
- JOIN scene_activations a ON a.id = r.activation_id WHERE a.owner_id = ? AND a.workspace_id = ? AND u.recorded_at >= ?`).get(principal.ownerId, principal.workspaceId, now - 7 * 864e5);
18
- const connectorReads = Number(this.db.prepare(`SELECT COALESCE(SUM(request_count), 0) AS count FROM scene_connector_usage
19
- WHERE owner_id = ? AND workspace_id = ? AND utc_day >= ?`).get(principal.ownerId, principal.workspaceId, Math.floor(now / 864e5) - 6)?.count);
20
15
  const notifications = this.db.prepare(`SELECT status, COUNT(*) AS count FROM notification_dispatches
21
16
  WHERE owner_id = ? AND workspace_id = ? GROUP BY status`).all(principal.ownerId, principal.workspaceId);
22
17
  const activations = this.db.prepare(`SELECT a.id, a.status,
@@ -49,12 +44,6 @@ var SceneMetrics = class {
49
44
  currentModel,
50
45
  pendingChecks: Number(queue.depth),
51
46
  oldestDueWaitMs: queue.oldest == null ? 0 : Math.max(0, now - Number(queue.oldest)),
52
- lastSevenDays: {
53
- modelCalls: Number(usage.calls),
54
- connectorReads,
55
- tokens: Number(usage.tokens),
56
- estimatedCost: Number(usage.cost)
57
- },
58
47
  notifications,
59
48
  activations
60
49
  };
@@ -0,0 +1,11 @@
1
+ /** Small immutable registry used by scene capabilities at the composition root. */
2
+ export declare class SceneCapabilityRegistry<T extends {
3
+ id: string;
4
+ }> {
5
+ private readonly items;
6
+ constructor(items: readonly T[]);
7
+ ids(): string[];
8
+ list(): T[];
9
+ has(id: string): boolean;
10
+ get(id: string): T;
11
+ }
@@ -0,0 +1,28 @@
1
+ //#region src/scenes/registry.ts
2
+ /** Small immutable registry used by scene capabilities at the composition root. */
3
+ var SceneCapabilityRegistry = class {
4
+ items = /* @__PURE__ */ new Map();
5
+ constructor(items) {
6
+ for (const item of items) {
7
+ if (!item.id.trim()) throw new Error("Scene capability id is required");
8
+ if (this.items.has(item.id)) throw new Error(`Duplicate scene capability: ${item.id}`);
9
+ this.items.set(item.id, item);
10
+ }
11
+ }
12
+ ids() {
13
+ return [...this.items.keys()];
14
+ }
15
+ list() {
16
+ return [...this.items.values()];
17
+ }
18
+ has(id) {
19
+ return this.items.has(id);
20
+ }
21
+ get(id) {
22
+ const item = this.items.get(id);
23
+ if (!item) throw new Error(`Scene capability unavailable: ${id}`);
24
+ return item;
25
+ }
26
+ };
27
+ //#endregion
28
+ export { SceneCapabilityRegistry };
@@ -1,4 +1,3 @@
1
- import type { SceneModelUsage } from './contracts.js';
2
1
  import type { DatabaseSync } from 'node:sqlite';
3
2
  import { type ActivationStatus, type SceneActivation, type ScenePrincipal, type SceneTemplate } from './contracts.js';
4
3
  export interface SceneEventInput {
@@ -70,8 +69,6 @@ export declare class SceneRepository {
70
69
  accountId: string;
71
70
  dueAt: number;
72
71
  }, now: number): SceneWorkItem;
73
- /** Internal worker scan; identity comes from persisted ownership, never an event payload. */
74
- recordModelUsage(claim: SceneRunClaim, usage: SceneModelUsage, now: number): void;
75
72
  listMailObservationItems(afterId?: string, now?: number): Array<{
76
73
  principal: ScenePrincipal;
77
74
  item: SceneWorkItem;
@@ -99,6 +96,7 @@ export declare class SceneRepository {
99
96
  }, now: number): string;
100
97
  acceptManualCheck(principal: ScenePrincipal, activationId: string, triggerKey: string, requestId: string, now: number): string;
101
98
  claimNext(worker: string, now: number, leaseMs?: number): SceneRunClaim | null;
99
+ claimIntentForAdapter(principal: ScenePrincipal, activationId: string, intentId: string, adapterId: string, worker: string, now: number, leaseMs: number): SceneRunClaim;
102
100
  renewLease(claim: SceneRunClaim, now: number, leaseMs: number): boolean;
103
101
  reserveModelCall(claim: SceneRunClaim, now: number, limits?: {
104
102
  activation: number;
@@ -117,6 +115,11 @@ export declare class SceneRepository {
117
115
  summary: string;
118
116
  evidenceIds: string[];
119
117
  }, now: number): boolean;
118
+ finishAdapterRun(claim: SceneRunClaim, result: {
119
+ kind: 'artifact' | 'decision' | 'receipt';
120
+ summary: string;
121
+ [key: string]: unknown;
122
+ }, now: number): boolean;
120
123
  listInbox(principal: ScenePrincipal, limit?: number, afterId?: string, activationId?: string | null): {
121
124
  createdAt: number;
122
125
  sources: {