@xopcai/xopc 0.0.323 → 0.0.325

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 (572) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/extensions/weixin/src/plugin.js +1 -9
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-DFzmThVi.js → agent-avatar-dicebear-CxfXpPWs.js} +1 -1
  5. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CDHe8gJf.js +1 -0
  6. package/dist/gateway/static/root/assets/{agent-plugin-dialog-DYFYiuig.js → agent-plugin-dialog-DMv-udoZ.js} +1 -1
  7. package/dist/gateway/static/root/assets/{agents-BqIlB5Co.js → agents-D_xOAXgj.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-BgvMRGWe.js → app-management-settings-panel-p7fZB4dT.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-CliHU03A.js → appearance-settings-C-clVcfp.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-Dz2g7eAN.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-DnuPpm0u.js → archive-plugin-Xm6xChUX.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-BiwaK0ie.js → attachment-load-Di8kuG4L.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-CJSISGQH.js → automations-page-GUZgDhKj.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-workspace-BUZhG9aJ.js +7 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-KDjduQZO.js → binary-plugins-OCrDjC9O.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-bclvgove.js → block-editor-m9tqvu7x.js} +3 -3
  17. package/dist/gateway/static/root/assets/{browser-automation-inputs-CfQ2T9t6.js → browser-automation-inputs-DSWXq9lI.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-automations-page-Cxq38Nnp.js → browser-automations-page-DuOaridE.js} +2 -2
  19. package/dist/gateway/static/root/assets/browser-settings-page-D2_PgHep.js +3 -0
  20. package/dist/gateway/static/root/assets/capabilities-sAZT4brT.js +1 -0
  21. package/dist/gateway/static/root/assets/capabilities-settings-panel-7Y_pJqyt.js +8 -0
  22. package/dist/gateway/static/root/assets/channels-settings-B-Igy1ro.js +1 -0
  23. package/dist/gateway/static/root/assets/{chat-terminal-dock-DKQC62nQ.js → chat-terminal-dock-BfnVh8oo.js} +1 -1
  24. package/dist/gateway/static/root/assets/{computer-settings-page-D1whpIqL.js → computer-settings-page-aRG2lU4w.js} +1 -1
  25. package/dist/gateway/static/root/assets/{connector-service-page-BAuYTgf5.js → connector-service-page-B5EhnfJH.js} +1 -1
  26. package/dist/gateway/static/root/assets/connectors-page-7HfRt1LW.js +2 -0
  27. package/dist/gateway/static/root/assets/date-picker-CtDyij_x.js +1 -0
  28. package/dist/gateway/static/root/assets/{dependency-picker-DOuVO2M1.js → dependency-picker-z6ouWxmz.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-D9tu6Bhu.js → desktop-pet-BsIYCAkG.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-settings-CQPXub2f.js → desktop-pet-settings-z-0aQ5ct.js} +1 -1
  31. package/dist/gateway/static/root/assets/{device-pairing-wizard-DxkOYSut.js → device-pairing-wizard-DlmhQvY5.js} +1 -1
  32. package/dist/gateway/static/root/assets/dist-3h6cXXhT.js +1 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-CtWClPz-.js → extension-debug-page-Ct9pABNW.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-BHh9HLCz.js → extension-page-BktsR4hj.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-BdT3v5Uh.js → extension-settings-page-BQJc-vXH.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-config-swr-1eqyz9vZ.js → gateway-config-swr-CoQVulMd.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-settings-CZas_Ekx.js → gateway-settings-BfDVlvy6.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-startup-retry-C4rsW6vJ.js → gateway-startup-retry-B5GJ-CQV.js} +1 -1
  39. package/dist/gateway/static/root/assets/home-page-CI_eQTPL.js +1 -0
  40. package/dist/gateway/static/root/assets/{image-generation-api-B5DXMylk.js → image-generation-api-DvWDkbk1.js} +1 -1
  41. package/dist/gateway/static/root/assets/{imports-page-B1JH0G5j.js → imports-page-DFpQfHVU.js} +1 -1
  42. package/dist/gateway/static/root/assets/index-19rMUT3d.js +121 -0
  43. package/dist/gateway/static/root/assets/{index-CNc4N4TX.css → index-BKL5tg2f.css} +1 -1
  44. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DGrLJ8Yh.js → keyboard-shortcuts-settings-ctJLm8TP.js} +1 -1
  45. package/dist/gateway/static/root/assets/local-app-workbench-page-C9kaP3Dy.js +1 -0
  46. package/dist/gateway/static/root/assets/{local-apps-page-DqjStqbL.js → local-apps-page-BxC_LTqq.js} +1 -1
  47. package/dist/gateway/static/root/assets/{locale-store-BIkcRr3t.js → locale-store-BPZR8x9b.js} +1 -1
  48. package/dist/gateway/static/root/assets/logs-page-Ok5SpG-G.js +2 -0
  49. package/dist/gateway/static/root/assets/{management-settings-gCfH4cwH.js → management-settings-aOzRaQHM.js} +1 -1
  50. package/dist/gateway/static/root/assets/{markdown-view-Ck_5MADq.js → markdown-view-Dft8ASFD.js} +1 -1
  51. package/dist/gateway/static/root/assets/{media-plugins-DTsZqgo6.js → media-plugins-ni5zJ4Ok.js} +1 -1
  52. package/dist/gateway/static/root/assets/messages-kFWhF6_t.js +3 -0
  53. package/dist/gateway/static/root/assets/note-detail-panel-C9OEltN9.js +5 -0
  54. package/dist/gateway/static/root/assets/notes-page-Dj9rMgdi.js +8 -0
  55. package/dist/gateway/static/root/assets/{page-context-capture-button-DTI_g4tz.js → page-context-capture-button-BJA3d8vU.js} +1 -1
  56. package/dist/gateway/static/root/assets/{page-tabs-CfW_Q-K5.js → page-tabs-Dyc3wKkl.js} +1 -1
  57. package/dist/gateway/static/root/assets/popover-select-DcsFzD_i.js +1 -0
  58. package/dist/gateway/static/root/assets/{preview-open-alternatives-CuPN-vAn.js → preview-open-alternatives-tIOIQbNX.js} +1 -1
  59. package/dist/gateway/static/root/assets/{product-open-page-BHjxRz1E.js → product-open-page-DQctU8z3.js} +1 -1
  60. package/dist/gateway/static/root/assets/project-detail-page-Dy-EwZcc.js +1 -0
  61. package/dist/gateway/static/root/assets/{projects-page-Bk-es4i9.js → projects-page-JaGKa6rM.js} +1 -1
  62. package/dist/gateway/static/root/assets/{registry-api-BAAZUGnU.js → registry-api-DWWO6ajd.js} +1 -1
  63. package/dist/gateway/static/root/assets/remote-access-hub-Cb8-nd60.js +1 -0
  64. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CHJBJKL1.js → runtime-tools-settings-panel-xhOSYfiX.js} +1 -1
  65. package/dist/gateway/static/root/assets/scenes-page-ClBkFdRY.js +2 -0
  66. package/dist/gateway/static/root/assets/{schema-form-FQAit5HL.js → schema-form-z8IeSdBp.js} +1 -1
  67. package/dist/gateway/static/root/assets/sessions-page-BYW5l_nY.js +1 -0
  68. package/dist/gateway/static/root/assets/settings-advanced-gate-CDNwmXuH.js +1 -0
  69. package/dist/gateway/static/root/assets/{settings-form-section-BDc6bw1q.js → settings-form-section-BXTJAser.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-DnhxBJjV.js → settings-page-Br9no5e4.js} +1 -1
  71. package/dist/gateway/static/root/assets/{settings-page-layout-D3KNSQ5g.js → settings-page-layout-D6745w0p.js} +1 -1
  72. package/dist/gateway/static/root/assets/setup-status-panel-D2N9764S.js +1 -0
  73. package/dist/gateway/static/root/assets/{share-preview-page-DVQCRxwK.js → share-preview-page-CE0SER59.js} +1 -1
  74. package/dist/gateway/static/root/assets/shares-settings-Dk3_QOKQ.js +1 -0
  75. package/dist/gateway/static/root/assets/skill-reload-api-CPt61fEv.js +1 -0
  76. package/dist/gateway/static/root/assets/skills-page-Db6PB2C6.js +2 -0
  77. package/dist/gateway/static/root/assets/{skills-page.utils-mDwC9UJ-.js → skills-page.utils-DrtW5FBy.js} +1 -1
  78. package/dist/gateway/static/root/assets/{system-settings-panel-Bk7GrMij.js → system-settings-panel-CuY1Zh5s.js} +1 -1
  79. package/dist/gateway/static/root/assets/task-detail-page-o7RiDUMi.js +1 -0
  80. package/dist/gateway/static/root/assets/{tunnel-api-D3Aquraj.js → tunnel-api-PGHDgvWb.js} +1 -1
  81. package/dist/gateway/static/root/assets/{use-autosave-C1xQ-sHn.js → use-autosave-B55oBQUt.js} +1 -1
  82. package/dist/gateway/static/root/assets/user-model-page-DspelwAa.js +2 -0
  83. package/dist/gateway/static/root/assets/{voice-api-key-field-DCNECvcp.js → voice-api-key-field-By6Lgbse.js} +1 -1
  84. package/dist/gateway/static/root/assets/{voice-config-api-B-_niUTU.js → voice-config-api-BaxITrwZ.js} +1 -1
  85. package/dist/gateway/static/root/assets/{work-discovery-overlay-BrGx_JS_.js → work-discovery-overlay-DdhgIlyf.js} +1 -1
  86. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CmmC2Pdr.js → workflow-run-setup-panel-BOJYQaxX.js} +2 -2
  87. package/dist/gateway/static/root/assets/workflows-page-6ObD0IQZ.js +6 -0
  88. package/dist/gateway/static/root/index.html +11 -10
  89. package/dist/package.js +1 -1
  90. package/dist/packages/gateway-contract/src/home.js +284 -55
  91. package/dist/packages/gateway-contract/src/index.js +0 -2
  92. package/dist/packages/gateway-contract/src/notifications.js +3 -10
  93. package/dist/src/activity/emitter.js +2 -1
  94. package/dist/src/activity/service.js +2 -1
  95. package/dist/src/agent/agent-manager.d.ts +3 -2
  96. package/dist/src/agent/agent-manager.js +36 -44
  97. package/dist/src/agent/agent-scope.d.ts +19 -48
  98. package/dist/src/agent/agent-scope.js +47 -169
  99. package/dist/src/agent/background-review/run-background-review.js +5 -4
  100. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +1 -1
  101. package/dist/src/agent/commands/command-registry.js +7 -3
  102. package/dist/src/agent/context/coordinator.js +1 -1
  103. package/dist/src/agent/context/execution-context.js +2 -1
  104. package/dist/src/agent/context/execution-scope.js +2 -1
  105. package/dist/src/agent/context/workspace-seed.d.ts +1 -2
  106. package/dist/src/agent/context/workspace-seed.js +3 -3
  107. package/dist/src/agent/context/workspace-state.js +1 -1
  108. package/dist/src/agent/embedded/run-for-session.js +2 -2
  109. package/dist/src/agent/embedded/run-turn.js +2 -1
  110. package/dist/src/agent/embedded/sqlite-hydrating-session-manager.js +2 -1
  111. package/dist/src/agent/external-tools/cliProvider.js +2 -1
  112. package/dist/src/agent/external-tools/composio-provider.js +2 -1
  113. package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
  114. package/dist/src/agent/external-tools/index.js +2 -3
  115. package/dist/src/agent/external-tools/mcp-provider.js +2 -2
  116. package/dist/src/agent/image/tool-model-config.js +4 -5
  117. package/dist/src/agent/inbound/attachment-pipeline.js +1 -1
  118. package/dist/src/agent/ipc/bus.js +1 -1
  119. package/dist/src/agent/ipc/socket.js +3 -3
  120. package/dist/src/agent/media-generation/runtime-shared.d.ts +1 -1
  121. package/dist/src/agent/media-generation/runtime-shared.js +1 -1
  122. package/dist/src/agent/memory/plugin-discovery.js +1 -2
  123. package/dist/src/agent/models/manager.d.ts +1 -1
  124. package/dist/src/agent/models/manager.js +2 -2
  125. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +1 -1
  126. package/dist/src/agent/prompt/response-language.js +2 -1
  127. package/dist/src/agent/prompt/service-prompt-builder.js +6 -3
  128. package/dist/src/agent/prompt/system-prompt.js +2 -1
  129. package/dist/src/agent/reply/post-compaction-context.js +2 -2
  130. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  131. package/dist/src/agent/service/direct-turn-helpers.js +2 -1
  132. package/dist/src/agent/service/parse-outbound-session-key.js +2 -1
  133. package/dist/src/agent/service/process-direct-streaming.js +3 -2
  134. package/dist/src/agent/service/webchat-tts.js +2 -1
  135. package/dist/src/agent/service.d.ts +1 -1
  136. package/dist/src/agent/service.js +12 -11
  137. package/dist/src/agent/service.types.d.ts +2 -0
  138. package/dist/src/agent/session/session-inspector.js +4 -5
  139. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +5 -0
  140. package/dist/src/agent/starter-agents.d.ts +4 -5
  141. package/dist/src/agent/starter-agents.js +21 -20
  142. package/dist/src/agent/tasks/task-judge-service.js +2 -2
  143. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  144. package/dist/src/agent/tool-manuals/xopc-use.js +31 -1
  145. package/dist/src/agent/tools/delegation-parent-policy.js +2 -3
  146. package/dist/src/agent/tools/factory.d.ts +2 -0
  147. package/dist/src/agent/tools/factory.js +10 -9
  148. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  149. package/dist/src/agent/tools/workflow-tool.js +2 -3
  150. package/dist/src/agent/tools/xopc-use-tool.d.ts +3 -2
  151. package/dist/src/agent/tools/xopc-use-tool.js +54 -6
  152. package/dist/src/agent/workflow/workflow-child-tools.js +1 -2
  153. package/dist/src/agent/workspace-runtime/registry.d.ts +1 -1
  154. package/dist/src/agent/workspace-runtime/registry.js +2 -2
  155. package/dist/src/agent-catalog/capabilities.d.ts +3 -0
  156. package/dist/src/agent-catalog/capabilities.js +238 -0
  157. package/dist/src/agent-catalog/id.d.ts +15 -0
  158. package/dist/src/agent-catalog/id.js +101 -0
  159. package/dist/src/agent-catalog/index.d.ts +6 -0
  160. package/dist/src/agent-catalog/index.js +10 -0
  161. package/dist/src/agent-catalog/migrations/legacy-config-cutover.d.ts +11 -0
  162. package/dist/src/agent-catalog/migrations/legacy-config-cutover.js +195 -0
  163. package/dist/src/agent-catalog/repository.d.ts +39 -0
  164. package/dist/src/agent-catalog/repository.js +319 -0
  165. package/dist/src/agent-catalog/service.d.ts +33 -0
  166. package/dist/src/agent-catalog/service.js +202 -0
  167. package/dist/src/agent-catalog/test-support.d.ts +14 -0
  168. package/dist/src/agent-catalog/test-support.js +34 -0
  169. package/dist/src/agent-catalog/types.d.ts +26 -0
  170. package/dist/src/agent-catalog/types.js +1 -0
  171. package/dist/src/agent-config/index.js +2 -2
  172. package/dist/src/agent-config/schema.d.ts +1 -172
  173. package/dist/src/agent-config/schema.js +2 -41
  174. package/dist/src/auth/credentials.js +3 -3
  175. package/dist/src/auth/oauth/xopc-cloud.js +1 -1
  176. package/dist/src/auth/sync-provider-auth.d.ts +1 -1
  177. package/dist/src/auth/sync-provider-auth.js +5 -9
  178. package/dist/src/automations/capabilities/drafts.js +8 -7
  179. package/dist/src/automations/service/action-executor.js +2 -1
  180. package/dist/src/bootstrap/application-state.d.ts +10 -0
  181. package/dist/src/bootstrap/application-state.js +26 -0
  182. package/dist/src/browser/automations/repository.js +2 -1
  183. package/dist/src/browser/automations/schema.d.ts +1 -1
  184. package/dist/src/browser/automations/service.d.ts +1 -1
  185. package/dist/src/browser/native-messaging-host.js +5 -4
  186. package/dist/src/browser/providers/extension.js +4 -2
  187. package/dist/src/browser/providers/realtime-extension.js +2 -1
  188. package/dist/src/capabilities/readiness/from-config.js +7 -4
  189. package/dist/src/capabilities/runtime/dispatcher.d.ts +1 -0
  190. package/dist/src/capabilities/runtime/dispatcher.js +10 -4
  191. package/dist/src/capabilities/runtime/product.js +2 -0
  192. package/dist/src/channels/catalog/channel-catalog-service.js +7 -13
  193. package/dist/src/chat-commands/agent-edit.js +4 -3
  194. package/dist/src/chat-commands/builtins/config.js +6 -8
  195. package/dist/src/chat-commands/builtins/review.js +1 -1
  196. package/dist/src/chat-commands/builtins/workflow.js +1 -1
  197. package/dist/src/chat-commands/config-paths.js +1 -1
  198. package/dist/src/chat-commands/context.js +2 -3
  199. package/dist/src/chat-previews/store.js +2 -1
  200. package/dist/src/cli/command-manifest.js +1 -1
  201. package/dist/src/cli/commands/agent.js +4 -4
  202. package/dist/src/cli/commands/agents.d.ts +1 -1
  203. package/dist/src/cli/commands/agents.js +36 -48
  204. package/dist/src/cli/commands/auth.js +2 -1
  205. package/dist/src/cli/commands/browser-cli-helpers.js +1 -2
  206. package/dist/src/cli/commands/channels.js +2 -4
  207. package/dist/src/cli/commands/config.js +4 -5
  208. package/dist/src/cli/commands/connectors.js +1 -2
  209. package/dist/src/cli/commands/doctor/checks/channel-config.js +2 -4
  210. package/dist/src/cli/commands/doctor/checks/channel-pairing-pending.js +1 -2
  211. package/dist/src/cli/commands/doctor/checks/channel-plugins.js +1 -2
  212. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -2
  213. package/dist/src/cli/commands/doctor/checks/database-schema.js +4 -4
  214. package/dist/src/cli/commands/doctor/checks/gateway-health.js +1 -2
  215. package/dist/src/cli/commands/doctor/checks/gateway-service.js +1 -2
  216. package/dist/src/cli/commands/doctor/checks/provider-auth.js +13 -11
  217. package/dist/src/cli/commands/doctor/checks/security-audit.js +1 -2
  218. package/dist/src/cli/commands/doctor/checks/session-integrity.js +3 -3
  219. package/dist/src/cli/commands/doctor/checks/tool-runtimes.js +1 -2
  220. package/dist/src/cli/commands/doctor/checks/workspace-status.js +5 -7
  221. package/dist/src/cli/commands/extension-agent-plugin.js +1 -2
  222. package/dist/src/cli/commands/extension-dev.js +2 -4
  223. package/dist/src/cli/commands/extension-marketplace.js +1 -2
  224. package/dist/src/cli/commands/extension-pack.js +1 -2
  225. package/dist/src/cli/commands/extension.js +1 -2
  226. package/dist/src/cli/commands/gateway/run-foreground.js +3 -3
  227. package/dist/src/cli/commands/gateway/shared.js +1 -1
  228. package/dist/src/cli/commands/history.js +2 -1
  229. package/dist/src/cli/commands/image.js +2 -2
  230. package/dist/src/cli/commands/init.js +11 -30
  231. package/dist/src/cli/commands/mcp.js +1 -2
  232. package/dist/src/cli/commands/models.js +13 -11
  233. package/dist/src/cli/commands/onboard/channels/registry.js +1 -2
  234. package/dist/src/cli/commands/onboard/gateway.js +1 -2
  235. package/dist/src/cli/commands/onboard/model.d.ts +1 -1
  236. package/dist/src/cli/commands/onboard/model.js +18 -26
  237. package/dist/src/cli/commands/onboard.js +4 -2
  238. package/dist/src/cli/commands/platform.js +1 -0
  239. package/dist/src/cli/commands/project.js +3 -3
  240. package/dist/src/cli/commands/providers.js +2 -1
  241. package/dist/src/cli/commands/runtime.js +1 -2
  242. package/dist/src/cli/commands/search.js +1 -2
  243. package/dist/src/cli/commands/skills.js +1 -2
  244. package/dist/src/cli/commands/tui-runner.js +3 -2
  245. package/dist/src/cli/commands/tui.js +6 -8
  246. package/dist/src/cli/commands/tunnel.js +1 -1
  247. package/dist/src/cli/commands/voice.js +1 -2
  248. package/dist/src/cli/extension-cli-register.js +1 -1
  249. package/dist/src/cli/index.js +4 -2
  250. package/dist/src/cli/utils/gateway-client.js +1 -1
  251. package/dist/src/cli/utils/init-workspace-core.js +15 -16
  252. package/dist/src/cli/utils/session.js +1 -2
  253. package/dist/src/computer/model-config.d.ts +3 -3
  254. package/dist/src/computer/model-config.js +10 -20
  255. package/dist/src/computer/runtime.js +1 -1
  256. package/dist/src/config/agent-model-intents.js +2 -2
  257. package/dist/src/config/agent-profile.d.ts +5 -6
  258. package/dist/src/config/agent-profile.js +19 -19
  259. package/dist/src/config/config-surface.d.ts +0 -3
  260. package/dist/src/config/default-model.js +2 -6
  261. package/dist/src/config/index.js +7 -8
  262. package/dist/src/config/loader.js +12 -18
  263. package/dist/src/config/models-json.d.ts +6 -6
  264. package/dist/src/config/paths.d.ts +18 -19
  265. package/dist/src/config/paths.js +35 -35
  266. package/dist/src/config/reload.d.ts +0 -1
  267. package/dist/src/config/reload.js +1 -6
  268. package/dist/src/config/rules.js +0 -15
  269. package/dist/src/config/schema.d.ts +3 -406
  270. package/dist/src/config/schema.js +24 -86
  271. package/dist/src/config/validate-channel-configs.js +8 -14
  272. package/dist/src/config/workspace-dirs.d.ts +3 -4
  273. package/dist/src/config/workspace-dirs.js +9 -8
  274. package/dist/src/config/workspace-path-helpers.d.ts +1 -1
  275. package/dist/src/config/workspace-path-helpers.js +2 -2
  276. package/dist/src/connectors/cli/lifecycle.js +2 -1
  277. package/dist/src/connectors/composio-managed-events.js +2 -1
  278. package/dist/src/connectors/connected-source-ingestion.js +2 -1
  279. package/dist/src/connectors/connected-source-understanding.js +4 -2
  280. package/dist/src/connectors/content-enrichment.js +2 -1
  281. package/dist/src/connectors/learning-coordinator.js +2 -1
  282. package/dist/src/connectors/runtime-adapter-registry.js +2 -1
  283. package/dist/src/connectors/workflow-preflight.d.ts +8 -1
  284. package/dist/src/connectors/workflow-preflight.js +11 -3
  285. package/dist/src/discussions/analyzer.js +2 -2
  286. package/dist/src/endpoint-tools/runtime.js +2 -1
  287. package/dist/src/execution-environments/subject.js +2 -1
  288. package/dist/src/extensions/activation-context.js +3 -16
  289. package/dist/src/extensions/agent-plugins/validation.js +1 -1
  290. package/dist/src/extensions/discover-extensions.js +9 -15
  291. package/dist/src/extensions/extension-metadata-snapshot.d.ts +1 -1
  292. package/dist/src/extensions/extension-metadata-snapshot.js +9 -16
  293. package/dist/src/extensions/index.js +4 -10
  294. package/dist/src/extensions/install.js +1 -1
  295. package/dist/src/extensions/loader.js +7 -14
  296. package/dist/src/extensions/manifest-registry.js +93 -98
  297. package/dist/src/extensions/marketplace.js +5 -2
  298. package/dist/src/extensions/normalize-manifest.js +12 -17
  299. package/dist/src/extensions/update.js +1 -2
  300. package/dist/src/files/file-service.js +7 -8
  301. package/dist/src/gateway/agents-admin.d.ts +23 -27
  302. package/dist/src/gateway/agents-admin.js +109 -130
  303. package/dist/src/gateway/file-path-classifier.js +3 -3
  304. package/dist/src/gateway/file-space-service.js +2 -1
  305. package/dist/src/gateway/global-defaults-admin.d.ts +6 -4
  306. package/dist/src/gateway/global-defaults-admin.js +21 -20
  307. package/dist/src/gateway/hono/app.js +2 -1
  308. package/dist/src/gateway/hono/lib/config-payload.js +12 -9
  309. package/dist/src/gateway/hono/middleware/auth.js +2 -1
  310. package/dist/src/gateway/hono/middleware/scopes.js +2 -1
  311. package/dist/src/gateway/hono/routes/agents.js +22 -49
  312. package/dist/src/gateway/hono/routes/browser.js +4 -2
  313. package/dist/src/gateway/hono/routes/channels.js +1 -2
  314. package/dist/src/gateway/hono/routes/cli-connectors.js +2 -1
  315. package/dist/src/gateway/hono/routes/commands-skills.js +3 -1
  316. package/dist/src/gateway/hono/routes/composer-history.js +2 -1
  317. package/dist/src/gateway/hono/routes/config-patch/index.d.ts +1 -3
  318. package/dist/src/gateway/hono/routes/config-patch/index.js +1 -2
  319. package/dist/src/gateway/hono/routes/config-patch/misc.js +18 -11
  320. package/dist/src/gateway/hono/routes/config.js +0 -2
  321. package/dist/src/gateway/hono/routes/connectors.js +8 -4
  322. package/dist/src/gateway/hono/routes/context-sources.js +4 -3
  323. package/dist/src/gateway/hono/routes/device-pairing-approval.js +2 -1
  324. package/dist/src/gateway/hono/routes/device-push.js +3 -2
  325. package/dist/src/gateway/hono/routes/devices.js +6 -3
  326. package/dist/src/gateway/hono/routes/discussions.js +2 -1
  327. package/dist/src/gateway/hono/routes/endpoint-tools.js +2 -1
  328. package/dist/src/gateway/hono/routes/global-defaults.js +8 -16
  329. package/dist/src/gateway/hono/routes/home.js +93 -4
  330. package/dist/src/gateway/hono/routes/interaction-state.js +2 -1
  331. package/dist/src/gateway/hono/routes/models.js +8 -7
  332. package/dist/src/gateway/hono/routes/notes.js +4 -5
  333. package/dist/src/gateway/hono/routes/projects.js +6 -6
  334. package/dist/src/gateway/hono/routes/public-gateway.js +2 -1
  335. package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
  336. package/dist/src/gateway/hono/routes/sessions.js +4 -2
  337. package/dist/src/gateway/hono/routes/shares.js +4 -3
  338. package/dist/src/gateway/hono/routes/site-shares.js +2 -2
  339. package/dist/src/gateway/hono/routes/status.js +2 -3
  340. package/dist/src/gateway/hono/routes/tasks.js +1 -2
  341. package/dist/src/gateway/hono/routes/user-model-refresh.js +2 -1
  342. package/dist/src/gateway/hono/routes/user-model.js +3 -2
  343. package/dist/src/gateway/hono/routes/work-discovery.js +1 -1
  344. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  345. package/dist/src/gateway/image-generation-setup.d.ts +19 -10
  346. package/dist/src/gateway/image-generation-setup.js +59 -23
  347. package/dist/src/gateway/index.js +1 -4
  348. package/dist/src/gateway/lock.js +13 -18
  349. package/dist/src/gateway/memory-maintenance-automation-reconciler.js +4 -3
  350. package/dist/src/gateway/run-loop.js +2 -3
  351. package/dist/src/gateway/security/gateway-scopes.js +6 -2
  352. package/dist/src/gateway/security/index.js +4 -1
  353. package/dist/src/gateway/service/agent-runner.js +4 -2
  354. package/dist/src/gateway/service/app-context-access.js +2 -1
  355. package/dist/src/gateway/service/config-coordinator.d.ts +0 -1
  356. package/dist/src/gateway/service/config-coordinator.js +4 -22
  357. package/dist/src/gateway/service/marketplace-service.js +3 -1
  358. package/dist/src/gateway/service/run-gateway-agent.js +4 -2
  359. package/dist/src/gateway/service/session-input-coordinator.js +4 -2
  360. package/dist/src/gateway/service.d.ts +5 -0
  361. package/dist/src/gateway/service.js +109 -33
  362. package/dist/src/gateway/session-context-summary.js +4 -2
  363. package/dist/src/gateway/xopc-cloud-capability-setup.d.ts +2 -0
  364. package/dist/src/gateway/xopc-cloud-capability-setup.js +15 -10
  365. package/dist/src/home-intelligence/application-service.d.ts +31 -0
  366. package/dist/src/home-intelligence/application-service.js +134 -0
  367. package/dist/src/home-intelligence/capability-preflight.d.ts +32 -0
  368. package/dist/src/home-intelligence/capability-preflight.js +118 -0
  369. package/dist/src/home-intelligence/evaluation.d.ts +34 -0
  370. package/dist/src/home-intelligence/evaluation.js +49 -0
  371. package/dist/src/home-intelligence/generator.d.ts +125 -0
  372. package/dist/src/home-intelligence/generator.js +227 -0
  373. package/dist/src/home-intelligence/host.d.ts +53 -0
  374. package/dist/src/home-intelligence/host.js +257 -0
  375. package/dist/src/home-intelligence/notification.d.ts +8 -0
  376. package/dist/src/home-intelligence/notification.js +20 -0
  377. package/dist/src/home-intelligence/policy.d.ts +16 -0
  378. package/dist/src/home-intelligence/policy.js +152 -0
  379. package/dist/src/home-intelligence/repository.d.ts +81 -0
  380. package/dist/src/home-intelligence/repository.js +495 -0
  381. package/dist/src/home-intelligence/snapshot.d.ts +43 -0
  382. package/dist/src/home-intelligence/snapshot.js +133 -0
  383. package/dist/src/home-intelligence/strategy.d.ts +14 -0
  384. package/dist/src/home-intelligence/strategy.js +10 -0
  385. package/dist/src/home-intelligence/types.d.ts +13 -0
  386. package/dist/src/home-intelligence/types.js +1 -0
  387. package/dist/src/infra/update-restart.js +4 -2
  388. package/dist/src/knowledge/connected-knowledge-pipeline.js +2 -1
  389. package/dist/src/knowledge/ingestion-service.js +2 -1
  390. package/dist/src/knowledge-memory/repository.js +2 -1
  391. package/dist/src/local-apps/service.js +1 -1
  392. package/dist/src/local-apps/store.js +2 -1
  393. package/dist/src/mcp/channel-bridge.js +1 -2
  394. package/dist/src/mcp/channel-server.js +1 -2
  395. package/dist/src/mcp/gateway-http-client.js +1 -2
  396. package/dist/src/media/session-references.js +2 -1
  397. package/dist/src/memory-maintenance/service.js +2 -1
  398. package/dist/src/migrations/memory-config.js +1 -2
  399. package/dist/src/notes/agent-context.js +2 -1
  400. package/dist/src/notes/attachment-ref.js +8 -4
  401. package/dist/src/notes/note-attachment-sync.js +2 -1
  402. package/dist/src/notes/note-index-meta.js +14 -7
  403. package/dist/src/notes/note-markdown.js +13 -7
  404. package/dist/src/notes/service.js +6 -3
  405. package/dist/src/notes/store.js +4 -2
  406. package/dist/src/notifications/device-store.js +1 -1
  407. package/dist/src/notifications/planner.js +24 -0
  408. package/dist/src/notifications/service.d.ts +7 -14
  409. package/dist/src/notifications/service.js +13 -3
  410. package/dist/src/notifications/store.js +1 -1
  411. package/dist/src/notifications/types.d.ts +1 -1
  412. package/dist/src/notifications/types.js +1 -1
  413. package/dist/src/projects/capabilities/write.js +2 -1
  414. package/dist/src/projects/project-agent-suggestion.js +1 -1
  415. package/dist/src/projects/project-agent.js +4 -4
  416. package/dist/src/projects/project-service.js +2 -1
  417. package/dist/src/projects/workspace.js +3 -2
  418. package/dist/src/providers/index.js +3 -3
  419. package/dist/src/providers/model-reference-auditor.d.ts +1 -2
  420. package/dist/src/providers/model-reference-auditor.js +8 -5
  421. package/dist/src/realtime/runtime.js +2 -1
  422. package/dist/src/routing/binding-schema.d.ts +41 -0
  423. package/dist/src/routing/binding-schema.js +26 -0
  424. package/dist/src/routing/bindings.d.ts +4 -2
  425. package/dist/src/routing/bindings.js +4 -4
  426. package/dist/src/routing/index.d.ts +1 -1
  427. package/dist/src/routing/resolve-route.d.ts +7 -24
  428. package/dist/src/routing/resolve-route.js +17 -18
  429. package/dist/src/routing/resolve-tui-session-key.d.ts +1 -4
  430. package/dist/src/routing/resolve-tui-session-key.js +10 -9
  431. package/dist/src/scenes/execution.d.ts +1 -1
  432. package/dist/src/scenes/model.js +1 -1
  433. package/dist/src/scenes/taskFollowUp/contracts.d.ts +1 -1
  434. package/dist/src/scenes/taskFollowUp/service.js +6 -4
  435. package/dist/src/scenes/templates.d.ts +2 -2
  436. package/dist/src/session/config-store.js +2 -1
  437. package/dist/src/session/init-session-turn.js +2 -1
  438. package/dist/src/session/resolve-session.js +2 -1
  439. package/dist/src/session/session-workspace.js +1 -1
  440. package/dist/src/session/store.js +3 -2
  441. package/dist/src/storage/sqlite/activity-repository.js +6 -2
  442. package/dist/src/storage/sqlite/browser-tab-binding-repository.js +6 -2
  443. package/dist/src/storage/sqlite/clarification-wait-repository.js +13 -8
  444. package/dist/src/storage/sqlite/collaboration-rule-repository.d.ts +1 -1
  445. package/dist/src/storage/sqlite/collaboration-rule-repository.js +8 -3
  446. package/dist/src/storage/sqlite/composer-input-history-repository.js +8 -3
  447. package/dist/src/storage/sqlite/config-repository.js +9 -5
  448. package/dist/src/storage/sqlite/connector-learning-repository.js +6 -2
  449. package/dist/src/storage/sqlite/connector-sync-policy-repository.js +6 -2
  450. package/dist/src/storage/sqlite/context-evidence-repository.js +8 -3
  451. package/dist/src/storage/sqlite/context-extraction-repository.js +8 -3
  452. package/dist/src/storage/sqlite/device-access-repository.js +15 -9
  453. package/dist/src/storage/sqlite/device-pairing-approval.js +6 -2
  454. package/dist/src/storage/sqlite/device-pairing-repository.js +10 -5
  455. package/dist/src/storage/sqlite/endpoint-principal-repository.js +6 -2
  456. package/dist/src/storage/sqlite/endpoint-session-binding-repository.js +6 -2
  457. package/dist/src/storage/sqlite/endpoint-tool-invocation-repository.js +6 -2
  458. package/dist/src/storage/sqlite/gateway-identity-repository.js +6 -2
  459. package/dist/src/storage/sqlite/home-attention-repository.js +6 -2
  460. package/dist/src/storage/sqlite/index.d.ts +0 -1
  461. package/dist/src/storage/sqlite/index.js +72 -42
  462. package/dist/src/storage/sqlite/interaction-state-repository.js +10 -4
  463. package/dist/src/storage/sqlite/knowledge-repository.js +6 -2
  464. package/dist/src/storage/sqlite/migrations/203_remove_retired_proactive_contracts.sql +70 -0
  465. package/dist/src/storage/sqlite/migrations/204_home_intelligence.sql +78 -0
  466. package/dist/src/storage/sqlite/migrations/205_agent_catalog.sql +66 -0
  467. package/dist/src/storage/sqlite/migrations/206_home_advice_strategy_version.sql +3 -0
  468. package/dist/src/storage/sqlite/migrations/conversation-backup.d.ts +2 -0
  469. package/dist/src/storage/sqlite/migrations/conversation-backup.js +8 -4
  470. package/dist/src/storage/sqlite/migrations/conversation-windows-owners.d.ts +7 -1
  471. package/dist/src/storage/sqlite/migrations/conversation-windows-owners.js +2 -2
  472. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  473. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  474. package/dist/src/storage/sqlite/note-agent-context-repository.js +6 -2
  475. package/dist/src/storage/sqlite/notes-repository.js +9 -4
  476. package/dist/src/storage/sqlite/schema.js +1 -1
  477. package/dist/src/storage/sqlite/session-task-plan-repository.js +14 -9
  478. package/dist/src/storage/sqlite/session-turn-replace-repository.js +9 -5
  479. package/dist/src/storage/sqlite/sidebar-layout-repository.js +14 -9
  480. package/dist/src/storage/sqlite/transcript-repository.js +10 -6
  481. package/dist/src/storage/sqlite/user-people-repository.js +8 -3
  482. package/dist/src/storage/sqlite/user-trust-repository.js +8 -3
  483. package/dist/src/tasks/attention-governor.d.ts +0 -1
  484. package/dist/src/tasks/attention-governor.js +1 -7
  485. package/dist/src/tasks/capabilities/read.js +2 -2
  486. package/dist/src/tasks/capabilities/write.d.ts +1 -1
  487. package/dist/src/tasks/execution-context.d.ts +2 -2
  488. package/dist/src/tasks/execution-context.js +6 -5
  489. package/dist/src/tasks/home-query-service.d.ts +3 -2
  490. package/dist/src/tasks/home-query-service.js +23 -44
  491. package/dist/src/tasks/task-context-assembler.js +2 -1
  492. package/dist/src/tasks/task-context-repository.d.ts +1 -1
  493. package/dist/src/tasks/task-contract-planner.d.ts +0 -3
  494. package/dist/src/tasks/task-contract-planner.js +1 -4
  495. package/dist/src/tasks/task-handoff-service.d.ts +0 -2
  496. package/dist/src/tasks/task-handoff-service.js +3 -3
  497. package/dist/src/tasks/task-value-metrics-service.js +2 -1
  498. package/dist/src/tui/backends/embedded-backend.js +12 -14
  499. package/dist/src/tui/extension-host/load-extensions.js +1 -1
  500. package/dist/src/tui/tui-commands.js +5 -3
  501. package/dist/src/tui/tui-skills-autocomplete.js +1 -1
  502. package/dist/src/tui/tui-startup-resources.js +3 -3
  503. package/dist/src/tui/tui.js +5 -5
  504. package/dist/src/tunnel/registration-proof.js +2 -1
  505. package/dist/src/user-context/access-policy.js +2 -1
  506. package/dist/src/user-context/domain.d.ts +1 -1
  507. package/dist/src/user-context/domain.js +18 -13
  508. package/dist/src/user-context/extraction/registry.js +2 -1
  509. package/dist/src/user-context/interaction-state.js +4 -1
  510. package/dist/src/user-context/relationship-continuity.js +2 -1
  511. package/dist/src/user-context/trust-policy.js +13 -8
  512. package/dist/src/user-model/bootstrap.js +2 -1
  513. package/dist/src/user-model/capture/executor.js +4 -2
  514. package/dist/src/user-model/capture/semantic.d.ts +1 -1
  515. package/dist/src/user-model/capture/semantic.js +1 -1
  516. package/dist/src/user-model/domain.js +7 -2
  517. package/dist/src/user-model/goals.js +2 -1
  518. package/dist/src/user-model/index.js +4 -1
  519. package/dist/src/user-model/repository.js +2 -1
  520. package/dist/src/utils/helpers.js +1 -4
  521. package/dist/src/utils/index.js +2 -2
  522. package/dist/src/utils/logger/index.d.ts +1 -1
  523. package/dist/src/utils/logger/index.js +2 -2
  524. package/dist/src/utils/logger/redact.d.ts +2 -0
  525. package/dist/src/utils/logger/redact.js +11 -3
  526. package/dist/src/utils/logger.js +2 -2
  527. package/dist/src/voice/realtime/memory-context.js +2 -1
  528. package/dist/src/voice/realtime/persona-context.js +6 -6
  529. package/dist/src/voice/tts/audio.js +1 -1
  530. package/dist/src/work-discovery/analyzer.js +3 -3
  531. package/dist/src/work-discovery/investigator.js +1 -1
  532. package/dist/src/work-discovery/service.js +12 -11
  533. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  534. package/dist/src/workflows/service/workflow-run-service.js +4 -5
  535. package/dist/src/workflows/store/paths.js +1 -1
  536. package/package.json +5 -5
  537. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CAFHadiy.js +0 -1
  538. package/dist/gateway/static/root/assets/apps-page-Drt3Foi9.js +0 -1
  539. package/dist/gateway/static/root/assets/automations-workspace-B-Eduqwz.js +0 -7
  540. package/dist/gateway/static/root/assets/browser-settings-page-Dwgir6mu.js +0 -3
  541. package/dist/gateway/static/root/assets/capabilities-settings-panel-H5L5vynP.js +0 -8
  542. package/dist/gateway/static/root/assets/capabilities-uFKh3Hd0.js +0 -1
  543. package/dist/gateway/static/root/assets/channels-settings-RFBRYe5S.js +0 -1
  544. package/dist/gateway/static/root/assets/connectors-page-Px-v3Q6Q.js +0 -2
  545. package/dist/gateway/static/root/assets/date-picker-CfCo3lqh.js +0 -1
  546. package/dist/gateway/static/root/assets/home-page-w3_aWeNt.js +0 -1
  547. package/dist/gateway/static/root/assets/index--3c0awkr.js +0 -121
  548. package/dist/gateway/static/root/assets/local-app-workbench-page-BYKrJpFF.js +0 -1
  549. package/dist/gateway/static/root/assets/logs-page-Dl4kM4Na.js +0 -2
  550. package/dist/gateway/static/root/assets/messages-7VAhscYe.js +0 -3
  551. package/dist/gateway/static/root/assets/note-detail-panel-j6sioeL1.js +0 -5
  552. package/dist/gateway/static/root/assets/notes-page-CMvvHv0f.js +0 -8
  553. package/dist/gateway/static/root/assets/popover-select-B-GDnZO9.js +0 -1
  554. package/dist/gateway/static/root/assets/project-detail-page-C9K_e-EV.js +0 -1
  555. package/dist/gateway/static/root/assets/remote-access-hub-CLGJNA42.js +0 -1
  556. package/dist/gateway/static/root/assets/scenes-page-ClLAD1pz.js +0 -2
  557. package/dist/gateway/static/root/assets/sessions-page-Xj8MkXN1.js +0 -1
  558. package/dist/gateway/static/root/assets/settings-advanced-gate-DwALV8mi.js +0 -1
  559. package/dist/gateway/static/root/assets/setup-status-panel-F0rCQ-2a.js +0 -1
  560. package/dist/gateway/static/root/assets/shares-settings-C7hf6Cov.js +0 -1
  561. package/dist/gateway/static/root/assets/skill-reload-api-xPrFejRE.js +0 -1
  562. package/dist/gateway/static/root/assets/skills-page-RdDYu7Yj.js +0 -2
  563. package/dist/gateway/static/root/assets/task-detail-page-2A966jFY.js +0 -1
  564. package/dist/gateway/static/root/assets/user-model-page-CnBxPBVe.js +0 -2
  565. package/dist/gateway/static/root/assets/workflows-page-BZVpqw4T.js +0 -6
  566. package/dist/packages/gateway-contract/src/proactive.js +0 -136
  567. package/dist/src/commands/agents.config.d.ts +0 -31
  568. package/dist/src/commands/agents.config.js +0 -129
  569. package/dist/src/gateway/hono/routes/config-patch/agents.d.ts +0 -2
  570. package/dist/src/gateway/hono/routes/config-patch/agents.js +0 -6
  571. package/dist/src/storage/sqlite/relationship-settings-repository.d.ts +0 -17
  572. package/dist/src/storage/sqlite/relationship-settings-repository.js +0 -65
@@ -0,0 +1,495 @@
1
+ import { init_transaction, runSqliteSavepoint } from "../storage/sqlite/transaction.js";
2
+ import { HomeAdvisorSchema, HomeOpportunitySchema } from "../../packages/gateway-contract/src/home.js";
3
+ import { init_src } from "../../packages/gateway-contract/src/index.js";
4
+ import { HOME_ADVICE_STRATEGY_VERSION, HOME_FEEDBACK_WINDOW_MS, homePatternKey } from "./strategy.js";
5
+ import { randomUUID } from "node:crypto";
6
+ //#region src/home-intelligence/repository.ts
7
+ init_src();
8
+ init_transaction();
9
+ function parseJson(value, fallback) {
10
+ try {
11
+ return JSON.parse(value);
12
+ } catch {
13
+ return fallback;
14
+ }
15
+ }
16
+ function uniqueReasons(reasons) {
17
+ return [...new Set(reasons)];
18
+ }
19
+ function ratio(numerator, denominator) {
20
+ return denominator > 0 ? numerator / denominator : 0;
21
+ }
22
+ function parseOpportunity(row) {
23
+ return HomeOpportunitySchema.parse({
24
+ ...parseJson(row.content_json, {}),
25
+ id: row.opportunity_id,
26
+ revision: row.revision
27
+ });
28
+ }
29
+ var HomeIntelligenceRepository = class {
30
+ constructor(db) {
31
+ this.db = db;
32
+ }
33
+ enqueue(principal, input) {
34
+ return runSqliteSavepoint(this.db, () => {
35
+ const duplicate = this.db.prepare(`SELECT generation_id FROM home_advice_generations
36
+ WHERE owner_id = ? AND workspace_id = ? AND idempotency_key = ?`).get(principal.ownerId, principal.workspaceId, input.idempotencyKey);
37
+ if (duplicate) return {
38
+ generationId: duplicate.generation_id,
39
+ created: false
40
+ };
41
+ const active = this.db.prepare(`SELECT * FROM home_advice_generations
42
+ WHERE owner_id = ? AND workspace_id = ?
43
+ AND status IN ('queued', 'running', 'retry_wait')
44
+ LIMIT 1`).get(principal.ownerId, principal.workspaceId);
45
+ if (active) {
46
+ const reasons = uniqueReasons([...parseJson(active.reasons_json, []), ...input.reasons]);
47
+ this.db.prepare(`UPDATE home_advice_generations SET
48
+ reasons_json = ?, requested_at = MAX(requested_at, ?),
49
+ dirty_after_start = CASE WHEN status = 'running' THEN 1 ELSE dirty_after_start END
50
+ WHERE generation_id = ?`).run(JSON.stringify(reasons), input.requestedAt, active.generation_id);
51
+ return {
52
+ generationId: active.generation_id,
53
+ created: false
54
+ };
55
+ }
56
+ const generationId = randomUUID();
57
+ this.db.prepare(`INSERT INTO home_advice_generations (
58
+ generation_id, owner_id, workspace_id, idempotency_key, status, reasons_json, requested_at, strategy_version
59
+ ) VALUES (?, ?, ?, ?, 'queued', ?, ?, ?)`).run(generationId, principal.ownerId, principal.workspaceId, input.idempotencyKey, JSON.stringify(uniqueReasons(input.reasons)), input.requestedAt, HOME_ADVICE_STRATEGY_VERSION);
60
+ return {
61
+ generationId,
62
+ created: true
63
+ };
64
+ });
65
+ }
66
+ claimNext(principal, workerId, now, leaseMs = 6e4) {
67
+ return runSqliteSavepoint(this.db, () => {
68
+ const row = this.db.prepare(`SELECT * FROM home_advice_generations
69
+ WHERE owner_id = ? AND workspace_id = ?
70
+ AND (status = 'queued' OR (status = 'retry_wait' AND retry_at <= ?)
71
+ OR (status = 'running' AND lease_until < ?))
72
+ ORDER BY requested_at ASC LIMIT 1`).get(principal.ownerId, principal.workspaceId, now, now);
73
+ if (!row) return void 0;
74
+ const nextEpoch = row.lease_epoch + 1;
75
+ const changed = this.db.prepare(`UPDATE home_advice_generations SET
76
+ status = 'running', started_at = ?, lease_owner = ?, lease_until = ?,
77
+ lease_epoch = ?, attempt = attempt + 1, dirty_after_start = 0, retry_at = NULL
78
+ WHERE generation_id = ? AND owner_id = ? AND workspace_id = ? AND lease_epoch = ?
79
+ AND (status = 'queued' OR (status = 'retry_wait' AND retry_at <= ?)
80
+ OR (status = 'running' AND lease_until < ?))`).run(now, workerId, now + leaseMs, nextEpoch, row.generation_id, principal.ownerId, principal.workspaceId, row.lease_epoch, now, now);
81
+ if (Number(changed.changes) !== 1) return void 0;
82
+ return {
83
+ generationId: row.generation_id,
84
+ ownerId: row.owner_id,
85
+ workspaceId: row.workspace_id,
86
+ leaseOwner: workerId,
87
+ leaseEpoch: nextEpoch,
88
+ attempt: row.attempt + 1,
89
+ reasons: parseJson(row.reasons_json, [])
90
+ };
91
+ });
92
+ }
93
+ complete(claim, completion) {
94
+ return runSqliteSavepoint(this.db, () => {
95
+ const current = this.requireClaim(claim);
96
+ const opportunities = [];
97
+ if (completion.result.state === "ready") {
98
+ const seen = /* @__PURE__ */ new Set();
99
+ for (const candidate of completion.result.opportunities) {
100
+ const opportunity = HomeOpportunitySchema.parse(candidate);
101
+ const key = this.opportunityDedupeKey(opportunity);
102
+ if (seen.has(key)) continue;
103
+ seen.add(key);
104
+ opportunities.push(opportunity);
105
+ if (opportunities.length === 3) break;
106
+ }
107
+ if (opportunities.length === 0) throw new Error("A ready home generation requires an opportunity");
108
+ }
109
+ if (completion.result.state !== "quiet" || completion.result.reason === "insufficient_value") this.db.prepare(`UPDATE home_opportunity_projections SET state = 'superseded', updated_at = ?
110
+ WHERE owner_id = ? AND workspace_id = ? AND state IN ('active', 'snoozed')`).run(completion.completedAt, claim.ownerId, claim.workspaceId);
111
+ const parsedResult = completion.result.state === "ready" ? {
112
+ state: "ready",
113
+ placement: completion.result.placement ?? "primary",
114
+ opportunityIds: opportunities.map((item) => item.id)
115
+ } : HomeAdvisorSchema.parse(completion.result);
116
+ if (completion.result.state === "ready") opportunities.forEach((opportunity, rank) => {
117
+ this.db.prepare(`INSERT INTO home_opportunity_projections (
118
+ opportunity_id, generation_id, owner_id, workspace_id, rank, kind, project_id,
119
+ dedupe_key, content_json, evidence_refs_json, snapshot_hash, state, revision,
120
+ created_at, updated_at, expires_at
121
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', ?, ?, ?, ?)`).run(opportunity.id, claim.generationId, claim.ownerId, claim.workspaceId, rank, opportunity.kind, opportunity.projectId ?? null, this.opportunityDedupeKey(opportunity), JSON.stringify(opportunity), JSON.stringify(opportunity.evidence.map(({ id, revision, sourceRef, freshUntil }) => ({
122
+ id,
123
+ revision,
124
+ sourceRef,
125
+ freshUntil
126
+ }))), completion.snapshotHash, opportunity.revision, completion.completedAt, completion.completedAt, opportunity.expiresAt);
127
+ });
128
+ const status = completion.result.state === "quiet" ? "skipped" : "succeeded";
129
+ const changed = this.db.prepare(`UPDATE home_advice_generations SET
130
+ status = ?, completed_at = ?, lease_owner = NULL, lease_until = NULL,
131
+ snapshot_hash = ?, evidence_ids_json = ?, result_json = ?, model_ref = ?,
132
+ input_tokens = ?, output_tokens = ?, estimated_cost_usd = ?, outcome_reason = ?,
133
+ strategy_version = ?, error_code = NULL
134
+ WHERE generation_id = ? AND status = 'running' AND lease_owner = ? AND lease_epoch = ?`).run(status, completion.completedAt, completion.snapshotHash, JSON.stringify([...new Set(completion.evidenceIds)]), JSON.stringify(parsedResult), completion.modelRef ?? null, completion.inputTokens ?? null, completion.outputTokens ?? null, completion.estimatedCostUsd ?? null, completion.outcomeReason ?? null, HOME_ADVICE_STRATEGY_VERSION, claim.generationId, claim.leaseOwner, claim.leaseEpoch);
135
+ if (Number(changed.changes) !== 1) throw new Error("Home generation lease was lost");
136
+ return { dirty: current.dirty_after_start === 1 };
137
+ });
138
+ }
139
+ fail(claim, now, errorCode, retryAt) {
140
+ const status = claim.attempt < 3 && retryAt !== void 0 ? "retry_wait" : "failed";
141
+ const changed = this.db.prepare(`UPDATE home_advice_generations SET
142
+ status = ?, retry_at = ?, completed_at = CASE WHEN ? = 'failed' THEN ? ELSE NULL END,
143
+ lease_owner = NULL, lease_until = NULL, error_code = ?
144
+ WHERE generation_id = ? AND status = 'running' AND lease_owner = ? AND lease_epoch = ?`).run(status, status === "retry_wait" ? retryAt : null, status, now, errorCode, claim.generationId, claim.leaseOwner, claim.leaseEpoch);
145
+ if (Number(changed.changes) !== 1) throw new Error("Home generation lease was lost");
146
+ }
147
+ getLatestSnapshotHash(principal) {
148
+ return this.db.prepare(`SELECT snapshot_hash FROM home_advice_generations
149
+ WHERE owner_id = ? AND workspace_id = ? AND status IN ('succeeded', 'skipped')
150
+ AND (model_ref IS NOT NULL OR outcome_reason IS NULL
151
+ OR outcome_reason NOT IN ('no_change', 'budget_exhausted'))
152
+ ORDER BY completed_at DESC, rowid DESC LIMIT 1`).get(principal.ownerId, principal.workspaceId)?.snapshot_hash ?? void 0;
153
+ }
154
+ countModelGenerationAttemptsSince(principal, since, currentGenerationId) {
155
+ const row = this.db.prepare(`SELECT COALESCE(SUM(CASE
156
+ WHEN generation_id = ? THEN MAX(attempt - 1, 0)
157
+ WHEN model_ref IS NOT NULL THEN 1
158
+ WHEN status IN ('failed', 'retry_wait') THEN attempt
159
+ ELSE 0
160
+ END), 0) AS count
161
+ FROM home_advice_generations
162
+ WHERE owner_id = ? AND workspace_id = ? AND COALESCE(started_at, requested_at) >= ?`).get(currentGenerationId, principal.ownerId, principal.workspaceId, since);
163
+ return Number(row.count);
164
+ }
165
+ listSuppressionKeys(principal) {
166
+ const rows = this.db.prepare(`SELECT f.scope_json, p.kind, p.project_id
167
+ FROM home_opportunity_feedback f
168
+ JOIN home_opportunity_projections p ON p.opportunity_id = f.opportunity_id
169
+ WHERE p.owner_id = ? AND p.workspace_id = ? AND f.kind = 'less_like_this'
170
+ ORDER BY f.created_at DESC LIMIT 100`).all(principal.ownerId, principal.workspaceId);
171
+ return new Set(rows.map((row) => {
172
+ const scope = parseJson(row.scope_json, {});
173
+ return `${typeof scope.kind === "string" ? scope.kind : row.kind}:${(typeof scope.projectId === "string" ? scope.projectId : row.project_id) ?? "global"}`;
174
+ }));
175
+ }
176
+ getSuccessfulPatterns(principal) {
177
+ const rows = this.db.prepare(`SELECT p.content_json
178
+ FROM home_opportunity_projections p
179
+ JOIN tasks t ON p.resolution_kind = 'task' AND p.resolution_ref = t.task_id
180
+ WHERE p.owner_id = ? AND p.workspace_id = ?
181
+ AND p.state = 'accepted' AND t.phase = 'closed' AND t.resolution = 'done'`).all(principal.ownerId, principal.workspaceId);
182
+ const patterns = /* @__PURE__ */ new Map();
183
+ for (const row of rows) {
184
+ const opportunity = HomeOpportunitySchema.parse(parseJson(row.content_json, null));
185
+ const key = homePatternKey(opportunity.projectId, opportunity.outcome);
186
+ const current = patterns.get(key);
187
+ patterns.set(key, {
188
+ projectId: opportunity.projectId,
189
+ title: opportunity.title,
190
+ outcome: opportunity.outcome,
191
+ successCount: (current?.successCount ?? 0) + 1
192
+ });
193
+ }
194
+ return [...patterns.values()].sort((left, right) => right.successCount - left.successCount || left.outcome.localeCompare(right.outcome));
195
+ }
196
+ getPersonalization(principal, now) {
197
+ const rows = this.db.prepare(`SELECT p.kind,
198
+ SUM(CASE WHEN f.kind IN ('irrelevant', 'source_incorrect') THEN 1 ELSE 0 END) AS negative_count,
199
+ SUM(CASE WHEN f.kind = 'started' THEN 1 ELSE 0 END) AS positive_count
200
+ FROM home_opportunity_feedback f
201
+ JOIN home_opportunity_projections p ON p.opportunity_id = f.opportunity_id
202
+ WHERE p.owner_id = ? AND p.workspace_id = ? AND f.created_at >= ?
203
+ GROUP BY p.kind`).all(principal.ownerId, principal.workspaceId, now - HOME_FEEDBACK_WINDOW_MS);
204
+ return { highConfidenceKinds: new Set(rows.filter((row) => Number(row.negative_count) >= 3 && Number(row.negative_count) - Number(row.positive_count) >= 2).map((row) => row.kind)) };
205
+ }
206
+ getMetrics(principal, since, until) {
207
+ const generation = this.db.prepare(`SELECT
208
+ COUNT(*) AS total,
209
+ SUM(CASE WHEN status = 'succeeded' THEN 1 ELSE 0 END) AS succeeded,
210
+ SUM(CASE WHEN status = 'skipped' THEN 1 ELSE 0 END) AS quiet,
211
+ SUM(CASE WHEN status IN ('failed', 'cancelled') THEN 1 ELSE 0 END) AS failed,
212
+ COALESCE(SUM(estimated_cost_usd), 0) AS estimated_cost_usd
213
+ FROM home_advice_generations
214
+ WHERE owner_id = ? AND workspace_id = ? AND requested_at BETWEEN ? AND ?`).get(principal.ownerId, principal.workspaceId, since, until);
215
+ const outcome = this.db.prepare(`SELECT
216
+ COUNT(*) AS opportunities,
217
+ SUM(CASE WHEN state = 'accepted' THEN 1 ELSE 0 END) AS started,
218
+ SUM(CASE WHEN state = 'discussing' THEN 1 ELSE 0 END) AS discussed,
219
+ SUM(CASE WHEN state = 'expired' THEN 1 ELSE 0 END) AS expired
220
+ FROM home_opportunity_projections
221
+ WHERE owner_id = ? AND workspace_id = ? AND created_at BETWEEN ? AND ?`).get(principal.ownerId, principal.workspaceId, since, until);
222
+ const completed = this.db.prepare(`SELECT COUNT(*) AS count
223
+ FROM home_opportunity_projections p
224
+ JOIN tasks t ON p.resolution_kind = 'task' AND p.resolution_ref = t.task_id
225
+ WHERE p.owner_id = ? AND p.workspace_id = ? AND p.created_at BETWEEN ? AND ?
226
+ AND t.phase = 'closed' AND t.resolution = 'done'`).get(principal.ownerId, principal.workspaceId, since, until);
227
+ const feedbackRows = this.db.prepare(`SELECT f.kind, COUNT(*) AS count
228
+ FROM home_opportunity_feedback f
229
+ JOIN home_opportunity_projections p ON p.opportunity_id = f.opportunity_id
230
+ WHERE p.owner_id = ? AND p.workspace_id = ? AND f.created_at BETWEEN ? AND ?
231
+ GROUP BY f.kind`).all(principal.ownerId, principal.workspaceId, since, until);
232
+ const feedback = new Map(feedbackRows.map((row) => [row.kind, Number(row.count)]));
233
+ const corrected = [
234
+ "already_done",
235
+ "irrelevant",
236
+ "too_early",
237
+ "source_incorrect",
238
+ "less_like_this"
239
+ ].reduce((count, kind) => count + (feedback.get(kind) ?? 0), 0);
240
+ const strategyRows = this.db.prepare(`SELECT
241
+ g.strategy_version AS version,
242
+ COUNT(DISTINCT g.generation_id) AS generations,
243
+ COUNT(DISTINCT p.opportunity_id) AS opportunities,
244
+ COUNT(DISTINCT CASE WHEN f.kind = 'started' THEN p.opportunity_id END) AS started,
245
+ COUNT(DISTINCT CASE WHEN t.phase = 'closed' AND t.resolution = 'done' THEN p.opportunity_id END) AS completed
246
+ FROM home_advice_generations g
247
+ LEFT JOIN home_opportunity_projections p ON p.generation_id = g.generation_id
248
+ LEFT JOIN home_opportunity_feedback f ON f.opportunity_id = p.opportunity_id
249
+ LEFT JOIN tasks t ON p.resolution_kind = 'task' AND p.resolution_ref = t.task_id
250
+ WHERE g.owner_id = ? AND g.workspace_id = ? AND g.requested_at BETWEEN ? AND ?
251
+ GROUP BY g.strategy_version
252
+ ORDER BY g.strategy_version`).all(principal.ownerId, principal.workspaceId, since, until);
253
+ const opportunities = Number(outcome.opportunities);
254
+ const started = Number(outcome.started);
255
+ return {
256
+ window: {
257
+ since,
258
+ until
259
+ },
260
+ currentStrategyVersion: HOME_ADVICE_STRATEGY_VERSION,
261
+ generations: {
262
+ total: Number(generation.total),
263
+ succeeded: Number(generation.succeeded),
264
+ quiet: Number(generation.quiet),
265
+ failed: Number(generation.failed),
266
+ estimatedCostUsd: Number(generation.estimated_cost_usd)
267
+ },
268
+ outcomes: {
269
+ opportunities,
270
+ started,
271
+ discussed: Number(outcome.discussed),
272
+ completed: Number(completed.count),
273
+ corrected,
274
+ expired: Number(outcome.expired)
275
+ },
276
+ rates: {
277
+ start: ratio(started, opportunities),
278
+ completionFromStarted: ratio(Number(completed.count), started),
279
+ correction: ratio(corrected, opportunities)
280
+ },
281
+ feedback: {
282
+ alreadyDone: feedback.get("already_done") ?? 0,
283
+ irrelevant: feedback.get("irrelevant") ?? 0,
284
+ tooEarly: feedback.get("too_early") ?? 0,
285
+ sourceIncorrect: feedback.get("source_incorrect") ?? 0,
286
+ lessLikeThis: feedback.get("less_like_this") ?? 0
287
+ },
288
+ strategies: strategyRows.map((row) => ({
289
+ version: row.version,
290
+ generations: Number(row.generations),
291
+ opportunities: Number(row.opportunities),
292
+ started: Number(row.started),
293
+ completed: Number(row.completed)
294
+ }))
295
+ };
296
+ }
297
+ invalidateOpportunitiesByEvidenceSources(principal, sourceTypes, now) {
298
+ if (!sourceTypes.size) return 0;
299
+ return runSqliteSavepoint(this.db, () => {
300
+ const ids = this.db.prepare(`SELECT opportunity_id, generation_id, content_json, revision, state, expires_at, snoozed_until
301
+ FROM home_opportunity_projections
302
+ WHERE owner_id = ? AND workspace_id = ? AND state IN ('active', 'snoozed')`).all(principal.ownerId, principal.workspaceId).filter((row) => parseOpportunity(row).evidence.some((item) => sourceTypes.has(item.sourceType))).map((row) => row.opportunity_id);
303
+ const invalidate = this.db.prepare(`UPDATE home_opportunity_projections
304
+ SET state = 'superseded', revision = revision + 1, updated_at = ?
305
+ WHERE opportunity_id = ? AND owner_id = ? AND workspace_id = ? AND state IN ('active', 'snoozed')`);
306
+ return ids.reduce((count, id) => count + Number(invalidate.run(now, id, principal.ownerId, principal.workspaceId).changes), 0);
307
+ });
308
+ }
309
+ getAdvisor(principal, now) {
310
+ const active = this.db.prepare(`SELECT requested_at FROM home_advice_generations
311
+ WHERE owner_id = ? AND workspace_id = ? AND status IN ('queued', 'running', 'retry_wait')
312
+ ORDER BY requested_at DESC LIMIT 1`).get(principal.ownerId, principal.workspaceId);
313
+ const rows = this.db.prepare(`SELECT opportunity_id, generation_id, content_json, revision, state, expires_at, snoozed_until
314
+ FROM home_opportunity_projections
315
+ WHERE owner_id = ? AND workspace_id = ? AND state IN ('active', 'snoozed')
316
+ AND expires_at > ? AND (state = 'active' OR snoozed_until <= ?)
317
+ ORDER BY rank ASC LIMIT 3`).all(principal.ownerId, principal.workspaceId, now, now);
318
+ const opportunities = rows.map(parseOpportunity);
319
+ if (opportunities.length > 0) {
320
+ const generatedAt = Math.min(...opportunities.map((item) => item.generatedAt));
321
+ const expiresAt = Math.min(...opportunities.map((item) => item.expiresAt));
322
+ const generation = this.db.prepare(`SELECT result_json FROM home_advice_generations
323
+ WHERE generation_id = ?`).get(rows[0].generation_id);
324
+ const placement = (generation?.result_json ? parseJson(generation.result_json, {}) : {}).placement === "compact" ? "compact" : "primary";
325
+ return HomeAdvisorSchema.parse({
326
+ state: "ready",
327
+ primary: opportunities[0],
328
+ alternatives: opportunities.slice(1),
329
+ placement,
330
+ generatedAt,
331
+ expiresAt,
332
+ stale: Boolean(active)
333
+ });
334
+ }
335
+ if (active) return {
336
+ state: "refreshing",
337
+ requestedAt: active.requested_at
338
+ };
339
+ const latest = this.db.prepare(`SELECT status, result_json, error_code FROM home_advice_generations
340
+ WHERE owner_id = ? AND workspace_id = ? AND status IN ('succeeded', 'skipped', 'failed')
341
+ ORDER BY COALESCE(completed_at, requested_at) DESC, rowid DESC LIMIT 1`).get(principal.ownerId, principal.workspaceId);
342
+ if (latest?.status === "failed") return {
343
+ state: "quiet",
344
+ reason: "generation_failed"
345
+ };
346
+ const result = latest?.result_json ? parseJson(latest.result_json, null) : null;
347
+ if (result && typeof result === "object" && "state" in result && (result.state === "quiet" || result.state === "clarification")) {
348
+ const advisor = HomeAdvisorSchema.parse(result);
349
+ return advisor.state === "clarification" && advisor.expiresAt <= now ? {
350
+ state: "quiet",
351
+ reason: "no_change"
352
+ } : advisor;
353
+ }
354
+ return {
355
+ state: "quiet",
356
+ reason: "no_change"
357
+ };
358
+ }
359
+ getOpportunity(principal, opportunityId, now) {
360
+ const row = this.db.prepare(`SELECT opportunity_id, generation_id, content_json, revision, state, expires_at, snoozed_until
361
+ FROM home_opportunity_projections WHERE opportunity_id = ? AND owner_id = ? AND workspace_id = ?
362
+ AND state IN ('active', 'snoozed') AND expires_at > ?`).get(opportunityId, principal.ownerId, principal.workspaceId, now);
363
+ return row ? parseOpportunity(row) : void 0;
364
+ }
365
+ getOpportunitySnapshot(principal, opportunityId) {
366
+ const row = this.db.prepare(`SELECT opportunity_id, generation_id, content_json, revision, state, expires_at, snoozed_until
367
+ FROM home_opportunity_projections WHERE opportunity_id = ? AND owner_id = ? AND workspace_id = ?`).get(opportunityId, principal.ownerId, principal.workspaceId);
368
+ return row ? parseOpportunity(row) : void 0;
369
+ }
370
+ listHistory(principal) {
371
+ return this.db.prepare(`SELECT
372
+ p.opportunity_id, p.generation_id, p.content_json, p.revision, p.state,
373
+ p.expires_at, p.snoozed_until, p.updated_at, p.resolution_kind, p.resolution_ref,
374
+ f.kind AS feedback_kind, t.phase AS task_phase, t.resolution AS task_resolution
375
+ FROM home_opportunity_projections p
376
+ LEFT JOIN home_opportunity_feedback f ON f.feedback_id = (
377
+ SELECT latest.feedback_id FROM home_opportunity_feedback latest
378
+ WHERE latest.opportunity_id = p.opportunity_id
379
+ ORDER BY latest.created_at DESC, latest.rowid DESC LIMIT 1
380
+ )
381
+ LEFT JOIN tasks t ON p.resolution_kind = 'task' AND p.resolution_ref = t.task_id
382
+ WHERE p.owner_id = ? AND p.workspace_id = ?
383
+ ORDER BY p.updated_at DESC, p.opportunity_id ASC LIMIT 100`).all(principal.ownerId, principal.workspaceId).map((row) => {
384
+ const opportunity = parseOpportunity(row);
385
+ const status = row.feedback_kind === "already_done" || row.task_phase === "closed" && row.task_resolution === "done" ? "completed" : row.state === "accepted" ? "started" : row.state === "discussing" ? "discussing" : row.state === "active" ? "available" : row.state;
386
+ const href = row.resolution_kind === "task" && row.resolution_ref ? `/tasks/${encodeURIComponent(row.resolution_ref)}` : row.resolution_kind === "session" && row.resolution_ref && row.resolution_ref !== "draft" ? `/chat/${encodeURIComponent(row.resolution_ref)}` : void 0;
387
+ return {
388
+ opportunity,
389
+ status,
390
+ ...row.feedback_kind ? { feedbackKind: row.feedback_kind } : {},
391
+ updatedAt: row.updated_at,
392
+ ...row.snoozed_until === null ? {} : { snoozedUntil: row.snoozed_until },
393
+ ...href ? { href } : {}
394
+ };
395
+ });
396
+ }
397
+ isFeedbackRecorded(opportunityId, idempotencyKey) {
398
+ const row = this.db.prepare(`SELECT opportunity_id FROM home_opportunity_feedback
399
+ WHERE idempotency_key = ?`).get(idempotencyKey);
400
+ if (!row) return false;
401
+ if (row.opportunity_id !== opportunityId) throw new Error("Feedback idempotency key belongs to another opportunity");
402
+ return true;
403
+ }
404
+ recordFeedback(principal, opportunityId, input) {
405
+ return runSqliteSavepoint(this.db, () => {
406
+ const duplicate = this.db.prepare(`SELECT opportunity_id FROM home_opportunity_feedback
407
+ WHERE idempotency_key = ?`).get(input.idempotencyKey);
408
+ if (duplicate) {
409
+ if (duplicate.opportunity_id !== opportunityId) throw new Error("Feedback idempotency key belongs to another opportunity");
410
+ return this.getOpportunity(principal, opportunityId, input.createdAt);
411
+ }
412
+ const next = this.feedbackTransition(input);
413
+ const changed = this.db.prepare(`UPDATE home_opportunity_projections SET
414
+ state = ?, revision = revision + 1, updated_at = ?, snoozed_until = ?,
415
+ resolution_kind = ?, resolution_ref = ?
416
+ WHERE opportunity_id = ? AND owner_id = ? AND workspace_id = ?
417
+ AND revision = ? AND state IN ('active', 'snoozed')`).run(next.state, input.createdAt, next.snoozedUntil, input.resolution?.kind ?? null, input.resolution?.ref ?? null, opportunityId, principal.ownerId, principal.workspaceId, input.expectedRevision);
418
+ if (Number(changed.changes) !== 1) throw new Error("Home opportunity is stale or unavailable");
419
+ this.db.prepare(`INSERT INTO home_opportunity_feedback (
420
+ feedback_id, opportunity_id, idempotency_key, kind, reason_code, note, scope_json, created_at
421
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(input.feedbackId ?? randomUUID(), opportunityId, input.idempotencyKey, input.kind, input.reasonCode ?? null, input.note ?? null, JSON.stringify(input.scope ?? {}), input.createdAt);
422
+ return this.getOpportunity(principal, opportunityId, input.createdAt);
423
+ });
424
+ }
425
+ undoFeedback(principal, opportunityId, idempotencyKey, now) {
426
+ return runSqliteSavepoint(this.db, () => {
427
+ const feedback = this.db.prepare(`SELECT f.feedback_id, f.idempotency_key, f.kind,
428
+ p.state, p.expires_at
429
+ FROM home_opportunity_feedback f
430
+ JOIN home_opportunity_projections p ON p.opportunity_id = f.opportunity_id
431
+ WHERE f.opportunity_id = ? AND p.owner_id = ? AND p.workspace_id = ?
432
+ ORDER BY f.created_at DESC, f.rowid DESC LIMIT 1`).get(opportunityId, principal.ownerId, principal.workspaceId);
433
+ if (!feedback || feedback.idempotency_key !== idempotencyKey) throw new Error("Only the latest home opportunity feedback can be undone");
434
+ if (feedback.kind === "started" || feedback.kind === "discussed") throw new Error("Started or discussed opportunities cannot be undone here");
435
+ if (!["dismissed", "snoozed"].includes(feedback.state) || feedback.expires_at <= now) throw new Error("Home opportunity feedback can no longer be undone");
436
+ this.db.prepare(`DELETE FROM home_opportunity_feedback WHERE feedback_id = ?`).run(feedback.feedback_id);
437
+ const changed = this.db.prepare(`UPDATE home_opportunity_projections SET
438
+ state = 'active', revision = revision + 1, updated_at = ?, snoozed_until = NULL,
439
+ resolution_kind = NULL, resolution_ref = NULL
440
+ WHERE opportunity_id = ? AND owner_id = ? AND workspace_id = ?
441
+ AND state IN ('dismissed', 'snoozed') AND expires_at > ?`).run(now, opportunityId, principal.ownerId, principal.workspaceId, now);
442
+ if (Number(changed.changes) !== 1) throw new Error("Home opportunity feedback can no longer be undone");
443
+ const opportunity = this.getOpportunity(principal, opportunityId, now);
444
+ if (!opportunity) throw new Error("Home opportunity feedback can no longer be undone");
445
+ return opportunity;
446
+ });
447
+ }
448
+ maintain(now) {
449
+ return runSqliteSavepoint(this.db, () => {
450
+ const expired = this.db.prepare(`UPDATE home_opportunity_projections
451
+ SET state = 'expired', revision = revision + 1, updated_at = ?
452
+ WHERE state IN ('active', 'snoozed') AND expires_at <= ?`).run(now, now);
453
+ const awakened = this.db.prepare(`UPDATE home_opportunity_projections
454
+ SET state = 'active', revision = revision + 1, updated_at = ?, snoozed_until = NULL
455
+ WHERE state = 'snoozed' AND snoozed_until <= ? AND expires_at > ?`).run(now, now, now);
456
+ return {
457
+ expired: Number(expired.changes),
458
+ awakened: Number(awakened.changes)
459
+ };
460
+ });
461
+ }
462
+ requireClaim(claim) {
463
+ const row = this.db.prepare(`SELECT * FROM home_advice_generations
464
+ WHERE generation_id = ? AND status = 'running' AND lease_owner = ? AND lease_epoch = ?`).get(claim.generationId, claim.leaseOwner, claim.leaseEpoch);
465
+ if (!row) throw new Error("Home generation lease was lost");
466
+ return row;
467
+ }
468
+ feedbackTransition(input) {
469
+ if (input.kind === "started") return {
470
+ state: "accepted",
471
+ snoozedUntil: null
472
+ };
473
+ if (input.kind === "discussed") return {
474
+ state: "discussing",
475
+ snoozedUntil: null
476
+ };
477
+ if (input.kind === "snoozed" || input.kind === "too_early") {
478
+ if (!input.snoozedUntil || input.snoozedUntil <= input.createdAt) throw new Error("A future snoozedUntil is required");
479
+ return {
480
+ state: "snoozed",
481
+ snoozedUntil: input.snoozedUntil
482
+ };
483
+ }
484
+ return {
485
+ state: "dismissed",
486
+ snoozedUntil: null
487
+ };
488
+ }
489
+ opportunityDedupeKey(opportunity) {
490
+ const outcome = opportunity.outcome.toLocaleLowerCase().replace(/[\p{P}\p{S}\s]+/gu, "");
491
+ return `${opportunity.kind}:${opportunity.projectId ?? "global"}:${outcome}`;
492
+ }
493
+ };
494
+ //#endregion
495
+ export { HomeIntelligenceRepository };
@@ -0,0 +1,43 @@
1
+ import type { HomeEvidence } from '@xopcai/gateway-contract';
2
+ import type { Task } from '@xopcai/gateway-contract';
3
+ import type { KnowledgeItem, KnowledgeReadPolicy } from '../knowledge-memory/domain.js';
4
+ import type { Project } from '../projects/types.js';
5
+ import type { SessionMetadata } from '../session/types.js';
6
+ import type { HomeSuccessfulPattern } from './strategy.js';
7
+ export interface HomeContextSnapshot {
8
+ generatedAt: number;
9
+ locale: 'en' | 'zh';
10
+ projects: Array<Pick<Project, 'id' | 'name' | 'status' | 'health' | 'brief' | 'outcome' | 'successCriteria' | 'targetAt' | 'updatedAt'>>;
11
+ tasks: Array<Pick<Task, 'id' | 'projectId' | 'title' | 'phase' | 'priority' | 'dueAt' | 'updatedAt'> & {
12
+ objective?: string;
13
+ }>;
14
+ knowledge: Array<Pick<KnowledgeItem, 'id' | 'kind' | 'content' | 'scope' | 'updatedAt' | 'expiresAt' | 'validTo'> & {
15
+ sourceType: Extract<HomeEvidence['sourceType'], 'calendar' | 'mail' | 'communication' | 'user_model'>;
16
+ provider?: string;
17
+ }>;
18
+ recentSessions: Array<{
19
+ id: string;
20
+ title: string;
21
+ projectId?: string;
22
+ updatedAt: number;
23
+ }>;
24
+ successfulPatterns: HomeSuccessfulPattern[];
25
+ evidence: HomeEvidence[];
26
+ hash: string;
27
+ }
28
+ export interface HomeSnapshotSources {
29
+ projects(): Project[];
30
+ tasks(): Task[];
31
+ knowledge(): KnowledgeItem[];
32
+ knowledgePolicy?(): KnowledgeReadPolicy;
33
+ sessions?(): SessionMetadata[];
34
+ }
35
+ export declare class HomeSnapshotBuilder {
36
+ private readonly sources;
37
+ constructor(sources: HomeSnapshotSources);
38
+ build(input: {
39
+ now: number;
40
+ locale: 'en' | 'zh';
41
+ successfulPatterns?: HomeSuccessfulPattern[];
42
+ }): HomeContextSnapshot;
43
+ }
@@ -0,0 +1,133 @@
1
+ import { knowledgeItemAllowed } from "../knowledge-memory/repository.js";
2
+ import { createHash } from "node:crypto";
3
+ //#region src/home-intelligence/snapshot.ts
4
+ function contentHash(value) {
5
+ return createHash("sha256").update(JSON.stringify(value)).digest("hex");
6
+ }
7
+ function knowledgeSourceType(item) {
8
+ if (item.recordClass !== "source_index") return "user_model";
9
+ const identity = [
10
+ item.source.provider,
11
+ item.source.kind,
12
+ item.source.sourceInstanceId
13
+ ].filter((value) => typeof value === "string").join(":").toLocaleLowerCase();
14
+ if (identity.includes("calendar")) return "calendar";
15
+ if (/gmail|outlook|\bmail\b/.test(identity)) return "mail";
16
+ if (/slack|teams|dingtalk|wecom|feishu|lark/.test(identity)) return "communication";
17
+ return "user_model";
18
+ }
19
+ function knowledgeFreshUntil(item, now) {
20
+ const ttl = item.sourceType === "calendar" ? 360 * 6e4 : item.sourceType === "mail" || item.sourceType === "communication" ? 720 * 6e4 : 1440 * 6e4;
21
+ return Math.min(item.expiresAt ?? Number.MAX_SAFE_INTEGER, item.validTo ?? Number.MAX_SAFE_INTEGER, now + ttl);
22
+ }
23
+ var HomeSnapshotBuilder = class {
24
+ constructor(sources) {
25
+ this.sources = sources;
26
+ }
27
+ build(input) {
28
+ const projects = this.sources.projects().filter((project) => project.status === "active" || project.status === "planned" || project.status === "paused").sort((left, right) => (right.lastActiveAt ?? right.updatedAt) - (left.lastActiveAt ?? left.updatedAt)).slice(0, 8).map(({ id, name, status, health, brief, outcome, successCriteria, targetAt, updatedAt }) => ({
29
+ id,
30
+ name,
31
+ status,
32
+ health,
33
+ brief,
34
+ outcome,
35
+ successCriteria,
36
+ targetAt,
37
+ updatedAt
38
+ }));
39
+ const projectIds = new Set(projects.map((project) => project.id));
40
+ const tasks = this.sources.tasks().filter((task) => task.phase !== "closed" && (!task.projectId || projectIds.has(task.projectId))).sort((left, right) => (left.dueAt ?? Number.MAX_SAFE_INTEGER) - (right.dueAt ?? Number.MAX_SAFE_INTEGER) || right.updatedAt - left.updatedAt).slice(0, 30).map(({ id, projectId, title, phase, priority, dueAt, updatedAt, contract }) => ({
41
+ id,
42
+ projectId,
43
+ title,
44
+ phase,
45
+ priority,
46
+ dueAt,
47
+ updatedAt,
48
+ objective: contract?.objective
49
+ }));
50
+ const knowledgePolicy = this.sources.knowledgePolicy?.();
51
+ const knowledge = this.sources.knowledge().filter((item) => item.status === "active" && (!item.expiresAt || item.expiresAt > input.now) && (!item.validTo || item.validTo > input.now) && (!knowledgePolicy || knowledgeItemAllowed(item, knowledgePolicy)) && (item.scope.type !== "project" || item.scope.id && projectIds.has(item.scope.id))).sort((left, right) => right.importance - left.importance || right.updatedAt - left.updatedAt).slice(0, 30).map((item) => ({
52
+ id: item.id,
53
+ kind: item.kind,
54
+ content: item.content,
55
+ scope: item.scope,
56
+ updatedAt: item.updatedAt,
57
+ expiresAt: item.expiresAt,
58
+ validTo: item.validTo,
59
+ sourceType: knowledgeSourceType(item),
60
+ ...typeof item.source.provider === "string" ? { provider: item.source.provider } : {}
61
+ }));
62
+ const recentSessions = (this.sources.sessions?.() ?? []).filter((session) => session.messageCount > 0).map((session) => ({
63
+ id: session.key,
64
+ title: session.name?.trim() || (input.locale === "zh" ? "未命名会话" : "Untitled conversation"),
65
+ projectId: session.projectId,
66
+ updatedAt: Date.parse(session.lastInteractionAt ?? session.updatedAt)
67
+ })).filter((session) => Number.isFinite(session.updatedAt)).sort((left, right) => right.updatedAt - left.updatedAt).slice(0, 12);
68
+ const evidence = [
69
+ ...projects.map((project) => ({
70
+ id: `project:${project.id}:v${project.updatedAt}`,
71
+ sourceType: "project",
72
+ sourceRef: project.id,
73
+ revision: String(project.updatedAt),
74
+ observation: [project.name, project.outcome || project.brief].filter(Boolean).join(":").slice(0, 1e3),
75
+ observedAt: project.updatedAt,
76
+ freshUntil: input.now + 1440 * 6e4,
77
+ href: `/projects/${encodeURIComponent(project.id)}`
78
+ })),
79
+ ...tasks.map((task) => ({
80
+ id: `task:${task.id}:v${task.updatedAt}`,
81
+ sourceType: "task",
82
+ sourceRef: task.id,
83
+ revision: String(task.updatedAt),
84
+ observation: [task.title, task.objective].filter(Boolean).join(":").slice(0, 1e3),
85
+ observedAt: task.updatedAt,
86
+ freshUntil: input.now + 720 * 6e4,
87
+ href: `/tasks?task=${encodeURIComponent(task.id)}`
88
+ })),
89
+ ...knowledge.map((item) => ({
90
+ id: `knowledge:${item.id}:v${item.updatedAt}`,
91
+ sourceType: item.sourceType,
92
+ sourceRef: item.id,
93
+ revision: String(item.updatedAt),
94
+ observation: item.content.slice(0, 1e3),
95
+ observedAt: item.updatedAt,
96
+ freshUntil: knowledgeFreshUntil(item, input.now),
97
+ ...item.provider ? { href: `/connectors?connector=${encodeURIComponent(item.provider)}` } : item.scope.type === "project" && item.scope.id ? { href: `/projects/${encodeURIComponent(item.scope.id)}` } : {}
98
+ })),
99
+ ...recentSessions.map((session) => ({
100
+ id: `conversation:${session.id}:v${session.updatedAt}`,
101
+ sourceType: "conversation",
102
+ sourceRef: session.id,
103
+ revision: String(session.updatedAt),
104
+ observation: session.title.slice(0, 1e3),
105
+ observedAt: session.updatedAt,
106
+ freshUntil: input.now + 720 * 6e4,
107
+ href: `/chat/${encodeURIComponent(session.id)}`
108
+ }))
109
+ ];
110
+ const successfulPatterns = [...input.successfulPatterns ?? []].filter((item) => item.successCount > 0).sort((left, right) => right.successCount - left.successCount || left.outcome.localeCompare(right.outcome)).slice(0, 20);
111
+ const stableContent = {
112
+ locale: input.locale,
113
+ projects,
114
+ tasks,
115
+ knowledge,
116
+ recentSessions,
117
+ successfulPatterns
118
+ };
119
+ return {
120
+ generatedAt: input.now,
121
+ locale: input.locale,
122
+ projects,
123
+ tasks,
124
+ knowledge,
125
+ recentSessions,
126
+ successfulPatterns,
127
+ evidence,
128
+ hash: contentHash(stableContent)
129
+ };
130
+ }
131
+ };
132
+ //#endregion
133
+ export { HomeSnapshotBuilder };