@xopcai/xopc 0.0.384 → 0.0.386

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 (280) 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-BSel9yf8.js → agent-avatar-dicebear-D-86VOlb.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-DgHMyhuY.js → agent-defaults-settings-panel-SmeUVHY8.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-plugin-dialog-BosuN4dO.js → agent-plugin-dialog-BVT3wXq5.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agents-B-pw5RKI.js → agents-D7rLQFhX.js} +3 -3
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-DuOqKkfH.js → app-management-settings-panel-CUR7n5iP.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-8JF9rXFr.js → appearance-settings-BCotSGep.js} +1 -1
  9. package/dist/gateway/static/root/assets/{apps-page-Cuclpk0A.js → apps-page-hk0bo9LT.js} +1 -1
  10. package/dist/gateway/static/root/assets/{automations-page-D7NwNy2I.js → automations-page-CqxuUwox.js} +1 -1
  11. package/dist/gateway/static/root/assets/{automations-workspace-CSxW4wX0.js → automations-workspace-11_Z69pr.js} +1 -1
  12. package/dist/gateway/static/root/assets/{block-editor-Dnb7CH_l.js → block-editor-eldB84Mj.js} +1 -1
  13. package/dist/gateway/static/root/assets/{browser-automations-page-GBgDe21o.js → browser-automations-page-D4TaUPYT.js} +1 -1
  14. package/dist/gateway/static/root/assets/{browser-settings-page-B2FXaO3n.js → browser-settings-page-BXRlxeGV.js} +1 -1
  15. package/dist/gateway/static/root/assets/{capabilities-XFwwUNU3.js → capabilities-BkKgImWi.js} +1 -1
  16. package/dist/gateway/static/root/assets/{capabilities-2Do3eKMM.js → capabilities-DVj9n65C.js} +1 -1
  17. package/dist/gateway/static/root/assets/{capabilities-page-f2-MquJn.js → capabilities-page-CyYlueEd.js} +2 -2
  18. package/dist/gateway/static/root/assets/{capabilities-settings-panel-D9F0mw16.js → capabilities-settings-panel-uVEgfvo0.js} +1 -1
  19. package/dist/gateway/static/root/assets/{capability-header-actions-DVRxJPQP.js → capability-header-actions-BXv0xu56.js} +1 -1
  20. package/dist/gateway/static/root/assets/{channels-CnDm5T1t.js → channels-fNb3SOzm.js} +1 -1
  21. package/dist/gateway/static/root/assets/{chat-terminal-dock-BxSCDbK7.js → chat-terminal-dock-CnLtparQ.js} +1 -1
  22. package/dist/gateway/static/root/assets/{computer-settings-page-DVAB-kQw.js → computer-settings-page-xM0AnOlP.js} +1 -1
  23. package/dist/gateway/static/root/assets/{connector-service-page-D2EeLXei.js → connector-service-page-CdG2WUb6.js} +1 -1
  24. package/dist/gateway/static/root/assets/{connectors-page-DK9n4hgZ.js → connectors-page-BRd08GH6.js} +1 -1
  25. package/dist/gateway/static/root/assets/constants-CpWu0oHS.js +1 -0
  26. package/dist/gateway/static/root/assets/{date-picker-Cl9KfFj8.js → date-picker-DIBbE-O8.js} +1 -1
  27. package/dist/gateway/static/root/assets/{dependency-picker-Ei6aX5WM.js → dependency-picker-DDD8zokD.js} +1 -1
  28. package/dist/gateway/static/root/assets/{desktop-pet-4Evl4RKX.js → desktop-pet-KlF390Xn.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-settings-DAD_OWcX.js → desktop-pet-settings-CgqQMKDC.js} +1 -1
  30. package/dist/gateway/static/root/assets/{device-pairing-wizard-BA21epMn.js → device-pairing-wizard-BR6isfG2.js} +1 -1
  31. package/dist/gateway/static/root/assets/{directory-picker-path-field-B_Zb5nNR.js → directory-picker-path-field-vPQsW05P.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-debug-page-DtHNy4TE.js → extension-debug-page-ZHLPrLbH.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-page-8gWSThWP.js → extension-page-DJ42KFRN.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-provider-nbgU7xBS.js → extension-provider-6IcsyNaV.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-CunUbB09.js → extension-settings-page-D7-5v0V4.js} +1 -1
  36. package/dist/gateway/static/root/assets/{fallback-models-BSAfzXby.js → fallback-models-DnYn7qOV.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-settings-CN-2229W.js → gateway-settings-Bwe3JWX-.js} +1 -1
  38. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-DktBCtHF.js → highlighted-body-KQOG7T2V-DefTxF3q.js} +1 -1
  39. package/dist/gateway/static/root/assets/{home-page-CUJcNW3H.js → home-page-BtSy2hRV.js} +1 -1
  40. package/dist/gateway/static/root/assets/{imports-page-DQm1MNNC.js → imports-page-CTdBYZib.js} +1 -1
  41. package/dist/gateway/static/root/assets/{index-BPNL54bv.js → index-B08iR7fT.js} +10 -10
  42. package/dist/gateway/static/root/assets/index-DBRwvWzm.css +1 -0
  43. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DaC5YjuJ.js → keyboard-shortcuts-settings-CXKp57O_.js} +1 -1
  44. package/dist/gateway/static/root/assets/{local-app-workbench-page-DwQyyo7a.js → local-app-workbench-page-DzD_OzGY.js} +1 -1
  45. package/dist/gateway/static/root/assets/{local-apps-page-CpZhivpf.js → local-apps-page-B0E0vttg.js} +1 -1
  46. package/dist/gateway/static/root/assets/{logs-page-Db43nh1M.js → logs-page-eL4fYcMl.js} +1 -1
  47. package/dist/gateway/static/root/assets/{management-settings-DrKejBEZ.js → management-settings-DSpjodMC.js} +1 -1
  48. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-BTrk2wWv.js +1 -0
  49. package/dist/gateway/static/root/assets/{note-detail-panel-a8NSwmmW.js → note-detail-panel-CsY5tQp5.js} +3 -3
  50. package/dist/gateway/static/root/assets/{notes-page-BKRke43F.js → notes-page-D09LjNoj.js} +1 -1
  51. package/dist/gateway/static/root/assets/{page-context-capture-button-DUaMkmxv.js → page-context-capture-button-DO-aP3D9.js} +1 -1
  52. package/dist/gateway/static/root/assets/{personal-page-BqF-HHw1.js → personal-page-E8F2aGNB.js} +1 -1
  53. package/dist/gateway/static/root/assets/{product-open-page-GrhtTQIz.js → product-open-page-aUoA-uPw.js} +1 -1
  54. package/dist/gateway/static/root/assets/{product-preview-content-zdP7gN0y.js → product-preview-content-B-cz-pIV.js} +1 -1
  55. package/dist/gateway/static/root/assets/{project-detail-page-9Vd_AqDW.js → project-detail-page-WhefAh8E.js} +1 -1
  56. package/dist/gateway/static/root/assets/{projects-page-DGunhjoM.js → projects-page-CyqAs0tO.js} +1 -1
  57. package/dist/gateway/static/root/assets/{remote-access-hub-BoRsF3Lx.js → remote-access-hub-BwhRGL6m.js} +1 -1
  58. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-W0HDm--J.js → runtime-tools-settings-panel-o26dmPNq.js} +1 -1
  59. package/dist/gateway/static/root/assets/{scenes-page-CYsFOfVJ.js → scenes-page-D_e19kv_.js} +1 -1
  60. package/dist/gateway/static/root/assets/{schema-form-CBxEbBQq.js → schema-form-DLLdqUC3.js} +1 -1
  61. package/dist/gateway/static/root/assets/{send-session-input-BCAF-Ikt.js → send-session-input-2I-nFJcE.js} +1 -1
  62. package/dist/gateway/static/root/assets/session-manager-Co5ozD0l.js +16 -0
  63. package/dist/gateway/static/root/assets/{sessions-page-Dthfx_vc.js → sessions-page-DX6INsiS.js} +1 -1
  64. package/dist/gateway/static/root/assets/settings-advanced-gate-C4_gW1vw.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-page-CFs-WP_2.js → settings-page-Bc_zxxRu.js} +1 -1
  66. package/dist/gateway/static/root/assets/{setup-status-panel-D2-9fXYL.js → setup-status-panel-FpF_cPPr.js} +1 -1
  67. package/dist/gateway/static/root/assets/{share-preview-page-nJ2FWAEP.js → share-preview-page-BOCcPBqQ.js} +1 -1
  68. package/dist/gateway/static/root/assets/{shares-settings-DTb88RHD.js → shares-settings-CInxjxgJ.js} +1 -1
  69. package/dist/gateway/static/root/assets/{skill-api-DJ8UBsxq.js → skill-api-Bjd8WAA4.js} +1 -1
  70. package/dist/gateway/static/root/assets/{skills-page-DjbBOikT.js → skills-page-8CKS3Oo2.js} +1 -1
  71. package/dist/gateway/static/root/assets/{system-settings-panel-Dt5GkLhM.js → system-settings-panel-BgQdsrNw.js} +1 -1
  72. package/dist/gateway/static/root/assets/task-detail-page-BnG5ehZ6.js +2 -0
  73. package/dist/gateway/static/root/assets/task-expandable-content-BCuc70Vc.js +1 -0
  74. package/dist/gateway/static/root/assets/{tasks-DJIeIk9C.js → tasks-PuIUgF9L.js} +1 -1
  75. package/dist/gateway/static/root/assets/{tunnel-api-JHttXi63.js → tunnel-api-CY7MoDGf.js} +1 -1
  76. package/dist/gateway/static/root/assets/{usage-page-B3rUa0fW.js → usage-page-s8Sv_PIG.js} +1 -1
  77. package/dist/gateway/static/root/assets/{use-composer-attachments-BFP3k6oC.js → use-composer-attachments-D0S2iZF4.js} +1 -1
  78. package/dist/gateway/static/root/assets/{use-file-preview-expanded-B1BiTQNS.js → use-file-preview-expanded-BElqELib.js} +1 -1
  79. package/dist/gateway/static/root/assets/{user-model-page-Cq1VSsZw.js → user-model-page-CyWrEtHY.js} +1 -1
  80. package/dist/gateway/static/root/assets/{work-discovery-overlay-BAtG_JHv.js → work-discovery-overlay-DmZXLs1v.js} +1 -1
  81. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Cw12NFgx.js → workflow-run-setup-panel-BdLOzHm4.js} +1 -1
  82. package/dist/gateway/static/root/assets/{workflows-page-kR5ouOuM.js → workflows-page-Cx3I3AV5.js} +1 -1
  83. package/dist/gateway/static/root/assets/{workspace-api-Xr3wz8T3.js → workspace-api-Du7-xJ0q.js} +2 -2
  84. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-BTBVKpSg.js → xopc-cloud-account-card-D8B136vW.js} +1 -1
  85. package/dist/gateway/static/root/index.html +12 -12
  86. package/dist/package.js +1 -1
  87. package/dist/packages/gateway-contract/src/index.js +2 -0
  88. package/dist/packages/gateway-contract/src/task-research-result.js +89 -0
  89. package/dist/packages/gateway-contract/src/tasks.js +7 -1
  90. package/dist/packages/gateway-contract/src/turn-outcome.js +3 -0
  91. package/dist/src/agent/child-agent-factory.d.ts +4 -1
  92. package/dist/src/agent/child-agent-factory.js +91 -11
  93. package/dist/src/agent/context/connection-objective-context.d.ts +1 -0
  94. package/dist/src/agent/context/connection-objective-context.js +33 -0
  95. package/dist/src/agent/data-acquisition/service.js +41 -6
  96. package/dist/src/agent/data-acquisition/types.d.ts +2 -0
  97. package/dist/src/agent/embedded/agent-profile-context.d.ts +7 -0
  98. package/dist/src/agent/embedded/agent-profile-context.js +92 -0
  99. package/dist/src/agent/embedded/execution-tool-policy.d.ts +1 -1
  100. package/dist/src/agent/embedded/execution-tool-policy.js +3 -2
  101. package/dist/src/agent/embedded/run-for-session.js +37 -14
  102. package/dist/src/agent/embedded/run-turn.js +123 -26
  103. package/dist/src/agent/embedded/runs.d.ts +9 -2
  104. package/dist/src/agent/embedded/runs.js +30 -7
  105. package/dist/src/agent/embedded/session-runner.js +14 -3
  106. package/dist/src/agent/embedded/types.d.ts +6 -1
  107. package/dist/src/agent/external-tools/cliProvider.d.ts +1 -0
  108. package/dist/src/agent/external-tools/cliProvider.js +1 -0
  109. package/dist/src/agent/external-tools/composio-provider.js +2 -0
  110. package/dist/src/agent/external-tools/gateway-tools.js +15 -5
  111. package/dist/src/agent/external-tools/service.d.ts +1 -0
  112. package/dist/src/agent/external-tools/service.js +3 -1
  113. package/dist/src/agent/external-tools/types.d.ts +4 -0
  114. package/dist/src/agent/orchestration/agent-run-supervisor.js +2 -1
  115. package/dist/src/agent/orchestration/agent-turn-policy.d.ts +1 -0
  116. package/dist/src/agent/orchestration/agent-turn-policy.js +5 -1
  117. package/dist/src/agent/orchestration/delegation-budget.d.ts +7 -1
  118. package/dist/src/agent/orchestration/delegation-budget.js +19 -10
  119. package/dist/src/agent/orchestration/llm-turn-retry.d.ts +5 -0
  120. package/dist/src/agent/orchestration/llm-turn-retry.js +15 -5
  121. package/dist/src/agent/orchestration/research-checkpoint.d.ts +56 -0
  122. package/dist/src/agent/orchestration/research-checkpoint.js +64 -0
  123. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +3 -1
  124. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +15 -2
  125. package/dist/src/agent/orchestration/run-termination.d.ts +12 -0
  126. package/dist/src/agent/orchestration/run-termination.js +24 -0
  127. package/dist/src/agent/orchestration/turn-recovery.d.ts +9 -0
  128. package/dist/src/agent/orchestration/turn-recovery.js +45 -0
  129. package/dist/src/agent/prompt/sections/agent-identity.js +12 -7
  130. package/dist/src/agent/prompt/sections/messaging-runtime.js +1 -1
  131. package/dist/src/agent/prompt/sections/project-context.js +1 -1
  132. package/dist/src/agent/prompt/sections/response-language.d.ts +1 -1
  133. package/dist/src/agent/prompt/sections/response-language.js +6 -2
  134. package/dist/src/agent/prompt/subagent-context.js +1 -1
  135. package/dist/src/agent/prompt/system-prompt.js +4 -6
  136. package/dist/src/agent/service/direct-turn-helpers.js +6 -5
  137. package/dist/src/agent/service/process-direct-streaming.js +7 -1
  138. package/dist/src/agent/tasks/task-judge-service.js +30 -10
  139. package/dist/src/agent/tools/apply-patch.js +1 -1
  140. package/dist/src/agent/tools/delegate-tool.js +216 -121
  141. package/dist/src/agent/tools/delegation-policy.js +13 -1
  142. package/dist/src/agent/tools/factory.js +12 -1
  143. package/dist/src/agent/tools/index.d.ts +2 -0
  144. package/dist/src/agent/tools/index.js +3 -1
  145. package/dist/src/agent/tools/language-diagnostics.js +1 -1
  146. package/dist/src/agent/tools/personal-request-result-tool.js +20 -3
  147. package/dist/src/agent/tools/personal-request-tool.js +165 -23
  148. package/dist/src/agent/tools/personal-task-tool.d.ts +6 -3
  149. package/dist/src/agent/tools/personal-task-tool.js +146 -23
  150. package/dist/src/agent/tools/publish-artifacts.js +1 -1
  151. package/dist/src/agent/tools/research-checkpoint-tool.d.ts +3 -0
  152. package/dist/src/agent/tools/research-checkpoint-tool.js +28 -0
  153. package/dist/src/agent/tools/review-workspace.js +1 -1
  154. package/dist/src/agent/tools/search/cache.d.ts +20 -0
  155. package/dist/src/agent/tools/search/cache.js +19 -0
  156. package/dist/src/agent/tools/search/errors.d.ts +19 -0
  157. package/dist/src/agent/tools/search/errors.js +69 -0
  158. package/dist/src/agent/tools/search/providers/bing-api.js +2 -1
  159. package/dist/src/agent/tools/search/providers/bing-html.js +2 -1
  160. package/dist/src/agent/tools/search/providers/brave.js +2 -1
  161. package/dist/src/agent/tools/search/providers/duckduckgo-html.js +2 -1
  162. package/dist/src/agent/tools/search/providers/searxng.js +2 -1
  163. package/dist/src/agent/tools/search/providers/tavily.js +2 -1
  164. package/dist/src/agent/tools/search/providers/xopc-cloud.d.ts +1 -0
  165. package/dist/src/agent/tools/search/providers/xopc-cloud.js +7 -2
  166. package/dist/src/agent/tools/search/registry.d.ts +21 -5
  167. package/dist/src/agent/tools/search/registry.js +252 -25
  168. package/dist/src/agent/tools/search/types.d.ts +25 -0
  169. package/dist/src/agent/tools/task-collaboration-tool.d.ts +16 -0
  170. package/dist/src/agent/tools/task-collaboration-tool.js +153 -0
  171. package/dist/src/agent/tools/task-result-tool.d.ts +2 -0
  172. package/dist/src/agent/tools/task-result-tool.js +73 -0
  173. package/dist/src/agent/tools/web.d.ts +16 -2
  174. package/dist/src/agent/tools/web.js +74 -29
  175. package/dist/src/agent/tools/xopc-use-tool.js +3 -3
  176. package/dist/src/automations/capabilities/write.d.ts +4 -4
  177. package/dist/src/automations/domain/validation.d.ts +8 -8
  178. package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
  179. package/dist/src/browser/automations/schema.d.ts +2 -2
  180. package/dist/src/browser/automations/service.d.ts +2 -2
  181. package/dist/src/cli/commands/channels.js +1 -1
  182. package/dist/src/cli/commands/connectors.js +1 -1
  183. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  184. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  185. package/dist/src/cli/commands/models.js +1 -1
  186. package/dist/src/cli/commands/onboard.js +1 -1
  187. package/dist/src/config/index.js +2 -2
  188. package/dist/src/config/schema.d.ts +1 -0
  189. package/dist/src/config/schema.js +4 -1
  190. package/dist/src/connectors/connection-recovery-service.d.ts +9 -1
  191. package/dist/src/connectors/connection-recovery-service.js +213 -33
  192. package/dist/src/discussions/action-tasks.d.ts +2 -2
  193. package/dist/src/extensions/sdk/index.js +1 -1
  194. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  195. package/dist/src/gateway/hono/routes/connection-waits.js +3 -1
  196. package/dist/src/gateway/hono/routes/projects.js +1 -1
  197. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +16 -0
  198. package/dist/src/gateway/hono/routes/tasks.js +1 -1
  199. package/dist/src/gateway/service/agent-runner.d.ts +2 -0
  200. package/dist/src/gateway/service/agent-runner.js +30 -17
  201. package/dist/src/gateway/service/run-gateway-agent.js +21 -6
  202. package/dist/src/gateway/service/session-input-coordinator.d.ts +10 -1
  203. package/dist/src/gateway/service/session-input-coordinator.js +216 -27
  204. package/dist/src/gateway/service.d.ts +1 -0
  205. package/dist/src/gateway/service.js +6 -4
  206. package/dist/src/gateway/session-context-summary.js +1 -1
  207. package/dist/src/personal-agent/prompts.js +10 -3
  208. package/dist/src/personal-agent/reply-composer.d.ts +1 -0
  209. package/dist/src/personal-agent/reply-composer.js +91 -19
  210. package/dist/src/personal-agent/reply-style.d.ts +1 -1
  211. package/dist/src/personal-agent/reply-style.js +1 -0
  212. package/dist/src/personal-agent/repository.d.ts +1 -1
  213. package/dist/src/personal-agent/repository.js +1 -1
  214. package/dist/src/personal-agent/request-access.d.ts +3 -0
  215. package/dist/src/personal-agent/request-access.js +31 -0
  216. package/dist/src/personal-agent/request-delivery.js +9 -4
  217. package/dist/src/personal-agent/request-repository.d.ts +3 -0
  218. package/dist/src/personal-agent/request-service.d.ts +6 -0
  219. package/dist/src/personal-agent/request-service.js +121 -25
  220. package/dist/src/personal-agent/result-file-links.d.ts +3 -0
  221. package/dist/src/personal-agent/result-file-links.js +21 -0
  222. package/dist/src/personal-agent/task-cancel.js +85 -35
  223. package/dist/src/providers/model-response.js +13 -2
  224. package/dist/src/scenes/taskFollowUp/service.d.ts +15 -5
  225. package/dist/src/session/session-context-for-llm.js +2 -2
  226. package/dist/src/session/store.d.ts +3 -1
  227. package/dist/src/session/store.js +30 -7
  228. package/dist/src/storage/sqlite/connection-wait-repository.d.ts +7 -2
  229. package/dist/src/storage/sqlite/connection-wait-repository.js +124 -20
  230. package/dist/src/storage/sqlite/index.d.ts +1 -0
  231. package/dist/src/storage/sqlite/index.js +3 -1
  232. package/dist/src/storage/sqlite/migrations/250_research_checkpoints.sql +15 -0
  233. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  234. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  235. package/dist/src/storage/sqlite/research-checkpoint-repository.d.ts +24 -0
  236. package/dist/src/storage/sqlite/research-checkpoint-repository.js +91 -0
  237. package/dist/src/storage/sqlite/schema.js +1 -1
  238. package/dist/src/storage/sqlite/session-creation-repository.js +3 -2
  239. package/dist/src/storage/sqlite/session-input-repository.d.ts +16 -0
  240. package/dist/src/storage/sqlite/session-input-repository.js +41 -7
  241. package/dist/src/storage/sqlite/transcript-repository.d.ts +2 -0
  242. package/dist/src/storage/sqlite/transcript-repository.js +25 -1
  243. package/dist/src/tasks/capabilities/management.d.ts +2 -2
  244. package/dist/src/tasks/capabilities/relations.d.ts +7 -7
  245. package/dist/src/tasks/capabilities/write.d.ts +2 -2
  246. package/dist/src/tasks/index.js +1 -1
  247. package/dist/src/tasks/task-allocation-service.d.ts +2 -0
  248. package/dist/src/tasks/task-allocation-service.js +43 -2
  249. package/dist/src/tasks/task-application-service.js +3 -3
  250. package/dist/src/tasks/task-collaboration-delivery.js +4 -1
  251. package/dist/src/tasks/task-collaboration-repository.d.ts +3 -0
  252. package/dist/src/tasks/task-collaboration-repository.js +11 -1
  253. package/dist/src/tasks/task-context-assembler.js +19 -6
  254. package/dist/src/tasks/task-continuation.d.ts +6 -0
  255. package/dist/src/tasks/task-continuation.js +33 -0
  256. package/dist/src/tasks/task-contract-planner.d.ts +1 -0
  257. package/dist/src/tasks/task-contract-planner.js +22 -15
  258. package/dist/src/tasks/task-main-update-delivery.js +13 -8
  259. package/dist/src/tasks/task-model-call.d.ts +7 -0
  260. package/dist/src/tasks/task-model-call.js +35 -0
  261. package/dist/src/tasks/task-read-model-projector.js +1 -1
  262. package/dist/src/tasks/task-research-repair.d.ts +19 -0
  263. package/dist/src/tasks/task-research-repair.js +75 -0
  264. package/dist/src/tasks/task-research-result.d.ts +85 -0
  265. package/dist/src/tasks/task-research-result.js +394 -0
  266. package/dist/src/tasks/task-result-delivery-repository.js +13 -2
  267. package/dist/src/tasks/task-result-delivery-service.js +1 -1
  268. package/dist/src/tasks/task-run-coordinator.d.ts +1 -0
  269. package/dist/src/tasks/task-run-coordinator.js +80 -11
  270. package/dist/src/tasks/task-run-dispatcher.js +12 -0
  271. package/dist/src/tasks/task-run-repository.d.ts +13 -0
  272. package/dist/src/tasks/task-run-repository.js +120 -2
  273. package/package.json +7 -3
  274. package/dist/gateway/static/root/assets/constants-Dy8Gw0sF.js +0 -1
  275. package/dist/gateway/static/root/assets/index-yseLAt9D.css +0 -1
  276. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-C4VzqE9z.js +0 -1
  277. package/dist/gateway/static/root/assets/session-manager-_yy4bxhT.js +0 -16
  278. package/dist/gateway/static/root/assets/settings-advanced-gate-O_0Lk38S.js +0 -1
  279. package/dist/gateway/static/root/assets/task-detail-page-88EShcbs.js +0 -2
  280. package/dist/gateway/static/root/assets/task-expandable-content-CF6Bj-Qa.js +0 -1
@@ -9,12 +9,13 @@ import "./types.js";
9
9
  import { estimateTokensFromMessages } from "../storage/sqlite/row-mappers.js";
10
10
  import { getSessionMetadata } from "../storage/sqlite/session-read-repository.js";
11
11
  import { deleteSessionRecord, ensureSessionRecord, findConversationIdByTranscriptId, getGlobalSessionStats, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord } from "../storage/sqlite/session-repository.js";
12
- import { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript } from "../storage/sqlite/transcript-repository.js";
12
+ import { appendCompactionBoundaryIfUnchanged, appendTranscriptEntry, archiveFailedModelAttempts, init_transcript_repository, listCompactionBoundaries, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRowsForSession, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript } from "../storage/sqlite/transcript-repository.js";
13
13
  import { getSessionConfig, setSessionConfig } from "../storage/sqlite/config-repository.js";
14
14
  import { init_sqlite } from "../storage/sqlite/index.js";
15
15
  import { init_agent_session_key, resolveAgentIdFromConversationId } from "../routing/agent-session-key.js";
16
16
  import { resolveUserContextSessionAccess } from "../user-context/access-policy.js";
17
17
  import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
18
+ import { ACCEPTANCE_REPAIR_READ_TOOLS, canResumeAfterModelFailure } from "../agent/orchestration/turn-recovery.js";
18
19
  import { DurableState } from "../storage/sqlite/durable-state.js";
19
20
  import { transcriptRowsToClientHistory } from "./client-history.js";
20
21
  import { SessionCompactor } from "../agent/memory/compaction.js";
@@ -34,6 +35,7 @@ init_agent_session_key();
34
35
  init_logger();
35
36
  init_sqlite();
36
37
  init_session_context_for_llm();
38
+ init_transcript_repository();
37
39
  const log = createLogger("SessionStore");
38
40
  const INDEX_VERSION = "1.0";
39
41
  function isTranscriptMessageRole(row, role) {
@@ -270,23 +272,44 @@ var SessionStore = class {
270
272
  requireXopcDatabase();
271
273
  return loadTranscriptHistoryRowsForSession(key);
272
274
  }
273
- async prepareModelFallback(key, rowsBeforeAttempt) {
275
+ async prepareModelFallback(key, rowsBeforeAttempt, options) {
274
276
  return this.runStoreMutation(async () => {
275
277
  requireXopcDatabase();
276
278
  const currentRows = loadTranscriptRowsForSession(key);
277
279
  if (!transcriptPrefixMatches(rowsBeforeAttempt, currentRows)) return "unsafe";
278
- let preparedRows = currentRows;
280
+ let preparedRows = [...currentRows];
279
281
  let removedError = false;
280
- if (isErrorAssistantRow(preparedRows.at(-1))) {
281
- preparedRows = preparedRows.slice(0, -1);
282
+ for (let index = preparedRows.length - 1; index >= rowsBeforeAttempt.length; index--) if (isErrorAssistantRow(preparedRows[index])) {
283
+ preparedRows.splice(index, 1);
282
284
  removedError = true;
283
285
  }
284
286
  const appendedRows = preparedRows.slice(rowsBeforeAttempt.length);
285
- if (appendedRows.length === 1 && isTranscriptMessageRole(appendedRows[0], "user") || removedError && appendedRows.length === 0 && isTranscriptMessageRole(preparedRows.at(-1), "user")) {
286
- if (removedError) replaceTranscriptRows(key, preparedRows);
287
+ const tail = preparedRows.findLast((row) => "role" in row && [
288
+ "user",
289
+ "assistant",
290
+ "toolResult"
291
+ ].includes(String(row.role)));
292
+ const onlyRecoveryMetadata = appendedRows.every((row) => "type" in row && row.type === "custom" && [
293
+ "coding_run_started",
294
+ "coding_verification",
295
+ "codemode-store",
296
+ "xopc-tool-discovery-state"
297
+ ].includes(String(row.customType)));
298
+ if (removedError && options?.resumeTaskContinuation && onlyRecoveryMetadata && canResumeAfterModelFailure(preparedRows, { allowFailedReadTools: ACCEPTANCE_REPAIR_READ_TOOLS })) {
299
+ archiveFailedModelAttempts(key, rowsBeforeAttempt.length);
300
+ return "prompt";
301
+ }
302
+ if (appendedRows.some((row) => isTranscriptMessageRole(row, "user")) && appendedRows.filter((row) => isTranscriptMessageRole(row, "user")).length === 1 && (isTranscriptMessageRole(tail, "user") || isTranscriptMessageRole(tail, "toolResult")) && canResumeAfterModelFailure(preparedRows, { allowFailedReadTools: ACCEPTANCE_REPAIR_READ_TOOLS }) || appendedRows.length === 1 && isTranscriptMessageRole(appendedRows[0], "user") || removedError && appendedRows.length === 0 && isTranscriptMessageRole(preparedRows.at(-1), "user") || removedError && onlyRecoveryMetadata && (isTranscriptMessageRole(tail, "user") || isTranscriptMessageRole(tail, "toolResult")) && canResumeAfterModelFailure(preparedRows, { allowFailedReadTools: ACCEPTANCE_REPAIR_READ_TOOLS })) {
303
+ if (removedError) archiveFailedModelAttempts(key, rowsBeforeAttempt.length);
287
304
  return "resume";
288
305
  }
289
306
  if (!removedError && appendedRows.length === 0) return "prompt";
307
+ if (!removedError && appendedRows.every((row) => "type" in row && row.type === "custom" && [
308
+ "coding_run_started",
309
+ "coding_verification",
310
+ "codemode-store",
311
+ "xopc-tool-discovery-state"
312
+ ].includes(String(row.customType)))) return "prompt";
290
313
  return "unsafe";
291
314
  });
292
315
  }
@@ -21,6 +21,9 @@ export declare function requireSessionConnection(input: {
21
21
  status: 'connection_required' | 'skipped' | 'objective_conflict';
22
22
  waitId?: string;
23
23
  };
24
+ /** Pending messages may revise the goal; controls cannot become a competing model execution. */
25
+ export declare function interruptedConnectionMessage(wait: ConnectionWait): SessionInput | undefined;
26
+ export declare function hasPendingConnectionMessages(wait: ConnectionWait, includeControls?: boolean): boolean;
24
27
  /** The input and the wait transition commit together, using the existing queue's unique key. */
25
28
  export declare function queueConnectionResolution(wait: ConnectionWait, resolution: 'continued' | 'skipped', resolvePersonal?: (wait: ConnectionWait, resolution: 'continued' | 'skipped') => unknown): ConnectionWait;
26
29
  export declare function consumeConnectionResume(input: SessionInput): boolean;
@@ -29,9 +32,11 @@ export declare function connectionBindings(conversationId: string): ConnectionNe
29
32
  export declare function connectorObjectiveScope(conversationId: string): string | undefined;
30
33
  export declare function bindObjectiveAccount(conversationId: string, connectorId: string, accountId: string): void;
31
34
  export declare function connectionBinding(conversationId: string, connectorId: string): string | undefined;
32
- /** New input wins over an outstanding auto-resume intent, including an already queued resume. */
35
+ /** Explicit objective changes invalidate an outstanding auto-resume intent. */
33
36
  export declare function invalidateConnectionResumeIntent(conversationId: string): void;
34
37
  export declare function reviseCurrentConnectionObjective(conversationId: string, summary: string | undefined): void;
35
- export declare function cancelConnectionObjective(conversationId: string): void;
38
+ export declare function cancelConnectionObjective(conversationId: string, expectedWaitId?: string, expectedObjectiveRevision?: number): void;
36
39
  export declare function getConnectionResumeInput(conversationId: string, runId: string): SessionInput | undefined;
37
40
  export declare function listConnectionWaitsToCheck(): ConnectionWait[];
41
+ /** A queued wait has not crossed consumeConnectionResume's execution boundary. */
42
+ export declare function reconcileConnectionWaits(afterRestart?: boolean): string[];
@@ -73,7 +73,7 @@ function requireSessionConnection(input) {
73
73
  const origin = originId ? getSessionInputById(input.conversationId, originId) : void 0;
74
74
  const originRunId = input.origin?.runId ?? runtime.activeRunId;
75
75
  if (!transcriptId || !origin || !originRunId || origin.expectedTranscriptId && origin.expectedTranscriptId !== transcriptId) throw new Error("Connection recovery requires a queued chat execution.");
76
- const resumed = origin.payload ? getConnectionWait(origin.payload.waitId) : void 0;
76
+ const resumed = origin.kind === "connection_resume" && origin.payload ? getConnectionWait(origin.payload.waitId) : void 0;
77
77
  if (resumed?.resolution === "skipped") return { status: "skipped" };
78
78
  const active = getActiveConnectionWait(input.conversationId);
79
79
  if (active) {
@@ -162,11 +162,23 @@ function requireSessionConnection(input) {
162
162
  };
163
163
  });
164
164
  }
165
+ /** Pending messages may revise the goal; controls cannot become a competing model execution. */
166
+ function interruptedConnectionMessage(wait) {
167
+ return getSessionInputState(wait.conversationId).inputs.find((input) => input.status === "interrupted" && input.kind === "message" && input.payload?.connectionBarrier && input.payload.waitId === wait.id && input.payload.objectiveRevision === wait.objectiveRevision);
168
+ }
169
+ function hasPendingConnectionMessages(wait, includeControls = false) {
170
+ return Boolean(interruptedConnectionMessage(wait)) || getSessionInputState(wait.conversationId).inputs.some((input) => input.id !== wait.originInputId && input.kind === "message" && (includeControls || !input.payload?.connectionAction) && [
171
+ "queued",
172
+ "running",
173
+ "injecting"
174
+ ].includes(input.status));
175
+ }
165
176
  /** The input and the wait transition commit together, using the existing queue's unique key. */
166
177
  function queueConnectionResolution(wait, resolution, resolvePersonal) {
167
178
  return runSqliteWriteTransaction(() => {
168
179
  const current = getConnectionWait(wait.id);
169
180
  if (!current || current.version !== wait.version || current.status !== "open") throw new Error("WAIT_CHANGED");
181
+ if (resolution === "continued" && hasPendingConnectionMessages(wait)) return current;
170
182
  if (resolvePersonal?.(wait, resolution)) return updateConnectionWait({
171
183
  ...wait,
172
184
  status: "closed",
@@ -203,15 +215,18 @@ function queueConnectionResolution(wait, resolution, resolvePersonal) {
203
215
  ...wait,
204
216
  status: "queued",
205
217
  resolution,
206
- queuedInputId: input.id
218
+ queuedInputId: input.id,
219
+ checking: void 0,
220
+ recoveryError: void 0
207
221
  }, wait.version);
208
222
  });
209
223
  }
210
224
  function consumeConnectionResume(input) {
211
225
  if (input.kind !== "connection_resume") return true;
212
226
  return runSqliteWriteTransaction(() => {
213
- const wait = input.payload ? getConnectionWait(input.payload.waitId) : void 0;
227
+ const wait = input.kind === "connection_resume" && input.payload ? getConnectionWait(input.payload.waitId) : void 0;
214
228
  if (!wait || wait.status !== "queued" || wait.queuedInputId !== input.id || wait.objectiveRevision !== input.payload?.objectiveRevision) return false;
229
+ if (hasPendingConnectionMessages(wait, true)) return false;
215
230
  if (readCurrentTranscriptId(getSqliteDatabase(), input.conversationId) !== wait.transcriptId) return false;
216
231
  if (wait.taskRunId) {
217
232
  const runs = new TaskRunRepository();
@@ -243,7 +258,8 @@ function consumeConnectionResume(input) {
243
258
  }
244
259
  updateConnectionWait({
245
260
  ...wait,
246
- status: "closed"
261
+ status: "closed",
262
+ checking: void 0
247
263
  }, wait.version);
248
264
  return true;
249
265
  });
@@ -286,7 +302,7 @@ function connectionBindings(conversationId) {
286
302
  const state = getSessionInputState(conversationId);
287
303
  const input = state.activeInputId ? getSessionInputById(conversationId, state.activeInputId) : void 0;
288
304
  if (!input) return [];
289
- const wait = input.payload ? getConnectionWait(input.payload.waitId) : void 0;
305
+ const wait = input.kind === "connection_resume" && input.payload ? getConnectionWait(input.payload.waitId) : void 0;
290
306
  const stored = getSqliteDatabase().prepare(`SELECT connector_id, account_id FROM connector_objective_accounts
291
307
  WHERE conversation_id = ? AND transcript_id = ? AND objective_id = ?`).all(conversationId, readCurrentTranscriptId(getSqliteDatabase(), conversationId) ?? "", wait?.objectiveId ?? input.id);
292
308
  return (wait?.needs ?? stored.map((row) => ({
@@ -314,7 +330,7 @@ function connectorObjectiveScope(conversationId) {
314
330
  const input = state.activeInputId ? getSessionInputById(conversationId, state.activeInputId) : void 0;
315
331
  if (!input) return void 0;
316
332
  const active = getActiveConnectionWait(conversationId);
317
- const wait = input.payload ? getConnectionWait(input.payload.waitId) : active?.originInputId === input.id ? active : void 0;
333
+ const wait = input.kind === "connection_resume" && input.payload ? getConnectionWait(input.payload.waitId) : active?.originInputId === input.id ? active : void 0;
318
334
  return JSON.stringify([
319
335
  readCurrentTranscriptId(getSqliteDatabase(), conversationId),
320
336
  wait?.objectiveId ?? input.id,
@@ -326,7 +342,7 @@ function bindObjectiveAccount(conversationId, connectorId, accountId) {
326
342
  const state = getSessionInputState(conversationId);
327
343
  const input = state.activeInputId ? getSessionInputById(conversationId, state.activeInputId) : void 0;
328
344
  if (!input) return;
329
- const wait = input.payload ? getConnectionWait(input.payload.waitId) : void 0;
345
+ const wait = input.kind === "connection_resume" && input.payload ? getConnectionWait(input.payload.waitId) : void 0;
330
346
  db.prepare(`INSERT OR IGNORE INTO connector_objective_accounts
331
347
  (conversation_id, transcript_id, objective_id, connector_id, account_id) VALUES (?, ?, ?, ?, ?)`).run(conversationId, readCurrentTranscriptId(db, conversationId) ?? "", wait?.objectiveId ?? input.id, connectorId, accountId);
332
348
  }
@@ -334,7 +350,7 @@ function connectionBinding(conversationId, connectorId) {
334
350
  const matches = connectionBindings(conversationId).filter((need) => need.target.type === "connector" && need.target.connectorId === connectorId);
335
351
  return matches.length === 1 ? matches[0].connectionId : void 0;
336
352
  }
337
- /** New input wins over an outstanding auto-resume intent, including an already queued resume. */
353
+ /** Explicit objective changes invalidate an outstanding auto-resume intent. */
338
354
  function invalidateConnectionResumeIntent(conversationId) {
339
355
  const wait = getActiveConnectionWait(conversationId);
340
356
  if (!wait) return;
@@ -345,6 +361,8 @@ function invalidateConnectionResumeIntent(conversationId) {
345
361
  status: "open",
346
362
  intent: void 0,
347
363
  queuedInputId: void 0,
364
+ checking: void 0,
365
+ recoveryError: void 0,
348
366
  objectiveRevision: wait.objectiveRevision + 1,
349
367
  scopeConfirmedAt: void 0,
350
368
  reviewRequired: true
@@ -372,32 +390,46 @@ function reviseCurrentConnectionObjective(conversationId, summary) {
372
390
  },
373
391
  status: "open",
374
392
  resolution: void 0,
393
+ checking: void 0,
394
+ recoveryError: void 0,
375
395
  intent: void 0,
376
396
  queuedInputId: void 0,
377
397
  scopeConfirmedAt: void 0,
378
398
  reviewRequired: true,
379
399
  objectiveRevision: wait.objectiveRevision + 1
380
400
  }, wait.version);
401
+ getSqliteDatabase().prepare(`UPDATE session_inputs SET payload_json = json_set(payload_json, '$.objectiveRevision', ?),
402
+ version = version + 1, updated_at_ms = ? WHERE conversation_id = ? AND kind = 'message'
403
+ AND status IN ('queued','running','injecting') AND json_extract(payload_json, '$.connectionBarrier') = 1
404
+ AND json_extract(payload_json, '$.waitId') = ?`).run(wait.objectiveRevision + 1, Date.now(), conversationId, wait.id);
381
405
  });
382
406
  publishConnectionWait(conversationId);
383
407
  }
384
- function cancelConnectionObjective(conversationId) {
385
- const wait = getActiveConnectionWait(conversationId);
408
+ function cancelConnectionObjective(conversationId, expectedWaitId, expectedObjectiveRevision) {
409
+ const runtime = getSessionInputState(conversationId);
410
+ const executing = runtime.activeInputId ? getSessionInputById(conversationId, runtime.activeInputId) : void 0;
411
+ const wait = getActiveConnectionWait(conversationId) ?? (expectedWaitId && executing?.kind === "connection_resume" && executing.payload?.waitId === expectedWaitId ? getConnectionWait(expectedWaitId) : void 0);
386
412
  if (!wait) return;
413
+ if (expectedWaitId && wait.id !== expectedWaitId) return;
414
+ if (expectedObjectiveRevision !== void 0 && wait.objectiveRevision !== expectedObjectiveRevision) return;
387
415
  runSqliteWriteTransaction(() => {
388
416
  if (wait.queuedInputId) setSessionInputStatus(wait.queuedInputId, "cancelled");
389
417
  const personalRequest = personalRequestForWait(wait.id);
390
418
  const runs = new TaskRunRepository();
391
- const taskRunId = wait.taskRunId ?? (personalRequest?.taskId ? runs.getActiveRoot(personalRequest.taskId)?.id : void 0);
419
+ const personalTaskWait = personalRequest?.taskId ? getSqliteDatabase().prepare(`SELECT task_run_id FROM task_waits
420
+ WHERE task_id = ? AND json_extract(condition_json, '$.connectionWaitId') = ? LIMIT 1`).get(personalRequest.taskId, wait.id) : void 0;
421
+ const taskRunId = wait.taskRunId ?? personalRequest?.parameters.taskRunId ?? personalTaskWait?.task_run_id;
392
422
  if (taskRunId) {
393
423
  const run = runs.get(taskRunId);
394
- if (run?.status === "waiting") {
395
- for (const taskWait of runs.listActiveWaits(run.taskId)) if (taskWait.condition.connectionWaitId === wait.id) runs.resolveWait({
396
- waitId: taskWait.id,
397
- actor: { kind: "system" },
398
- resolution: { cancelled: true }
399
- });
400
- runs.finalize({
424
+ if (run && [
425
+ "queued",
426
+ "running",
427
+ "waiting",
428
+ "verifying",
429
+ "cancelled"
430
+ ].includes(run.status)) {
431
+ runs.resolveCancelledRunWaits(run.id, { kind: "system" });
432
+ if (run.status !== "cancelled") runs.finalize({
401
433
  runId: run.id,
402
434
  expectedVersion: run.version,
403
435
  receipt: {
@@ -420,7 +452,8 @@ function cancelConnectionObjective(conversationId) {
420
452
  ...wait,
421
453
  status: "closed",
422
454
  resolution: "cancelled",
423
- intent: void 0
455
+ intent: void 0,
456
+ checking: void 0
424
457
  }, wait.version);
425
458
  if (personalRequest && personalRequest.state !== "cancelled") updatePersonalRequest(personalRequest, { state: "cancelled" });
426
459
  });
@@ -439,6 +472,77 @@ function listConnectionWaitsToCheck() {
439
472
  JOIN sessions session ON session.active_transcript_id = wait.transcript_id
440
473
  WHERE wait.status = 'open'`).all().map((row) => JSON.parse(row.data_json)).filter((wait) => wait.principalId === "local-owner" && wait.intent && wait.intent.validUntil > Date.now());
441
474
  }
475
+ /** A queued wait has not crossed consumeConnectionResume's execution boundary. */
476
+ function reconcileConnectionWaits(afterRestart = false) {
477
+ if (!isXopcDatabaseOpen()) return [];
478
+ return runSqliteWriteTransaction((db) => {
479
+ const rows = db.prepare(`SELECT wait.data_json FROM session_connection_waits wait
480
+ JOIN sessions session ON session.active_transcript_id = wait.transcript_id
481
+ WHERE wait.status IN ('open', 'queued')`).all();
482
+ const wake = /* @__PURE__ */ new Set();
483
+ for (const row of rows) {
484
+ const wait = JSON.parse(row.data_json);
485
+ if (wait.status === "open") {
486
+ if (afterRestart && wait.checking) {
487
+ updateConnectionWait({
488
+ ...wait,
489
+ checking: void 0,
490
+ lastAction: void 0,
491
+ recoveryError: "restart_interrupted"
492
+ }, wait.version);
493
+ log.info({
494
+ conversationId: wait.conversationId,
495
+ waitId: wait.id,
496
+ phase: "restart_reconcile"
497
+ }, "Interrupted connection check preserved for recovery");
498
+ publishConnectionWait(wait.conversationId);
499
+ }
500
+ continue;
501
+ }
502
+ const input = wait.queuedInputId ? getSessionInputById(wait.conversationId, wait.queuedInputId) : void 0;
503
+ const matches = input?.kind === "connection_resume" && input.payload?.waitId === wait.id && input.payload.objectiveRevision === wait.objectiveRevision && input.expectedTranscriptId === wait.transcriptId;
504
+ if (matches && input.status === "running") continue;
505
+ if (matches && (input.status === "queued" || input.status === "interrupted")) {
506
+ if (input.status === "interrupted") {
507
+ setSessionInputStatus(input.id, "queued");
508
+ updateConnectionWait({
509
+ ...wait,
510
+ checking: void 0,
511
+ recoveryError: "restart_interrupted"
512
+ }, wait.version);
513
+ log.info({
514
+ conversationId: wait.conversationId,
515
+ waitId: wait.id,
516
+ inputId: input.id,
517
+ phase: "restart_reconcile"
518
+ }, "Unconsumed connection continuation requeued");
519
+ publishConnectionWait(wait.conversationId);
520
+ }
521
+ wake.add(wait.conversationId);
522
+ continue;
523
+ }
524
+ updateConnectionWait({
525
+ ...wait,
526
+ status: "open",
527
+ queuedInputId: void 0,
528
+ intent: void 0,
529
+ checking: void 0,
530
+ recoveryError: "restart_interrupted",
531
+ resolution: void 0,
532
+ objectiveRevision: wait.objectiveRevision + 1
533
+ }, wait.version);
534
+ log.warn({
535
+ conversationId: wait.conversationId,
536
+ waitId: wait.id,
537
+ inputId: wait.queuedInputId,
538
+ inputStatus: input?.status,
539
+ phase: "resume_reconcile"
540
+ }, "Unavailable connection continuation preserved for retry");
541
+ publishConnectionWait(wait.conversationId);
542
+ }
543
+ return [...wake];
544
+ });
545
+ }
442
546
  var log, events;
443
547
  var init_connection_wait_repository = __esmMin((() => {
444
548
  init_logger();
@@ -455,4 +559,4 @@ var init_connection_wait_repository = __esmMin((() => {
455
559
  }));
456
560
  //#endregion
457
561
  init_connection_wait_repository();
458
- export { bindObjectiveAccount, cancelConnectionObjective, connectionBinding, connectionBindings, connectorObjectiveScope, consumeConnectionResume, getActiveConnectionWait, getConnectionResumeInput, getConnectionWait, init_connection_wait_repository, invalidateConnectionResumeIntent, isConnectionSuspended, listConnectionWaitsToCheck, onConnectionWaitChanged, publishConnectionWait, queueConnectionResolution, requireSessionConnection, reviseCurrentConnectionObjective, updateConnectionWait };
562
+ export { bindObjectiveAccount, cancelConnectionObjective, connectionBinding, connectionBindings, connectorObjectiveScope, consumeConnectionResume, getActiveConnectionWait, getConnectionResumeInput, getConnectionWait, hasPendingConnectionMessages, init_connection_wait_repository, interruptedConnectionMessage, invalidateConnectionResumeIntent, isConnectionSuspended, listConnectionWaitsToCheck, onConnectionWaitChanged, publishConnectionWait, queueConnectionResolution, reconcileConnectionWaits, requireSessionConnection, reviseCurrentConnectionObjective, updateConnectionWait };
@@ -38,3 +38,4 @@ export { appendConnectorExecutionAudit, claimConnectorWebhookDelivery, completeC
38
38
  export { getConnectorAccount, listConnectorAccounts, refreshConnectorAccountCurrent, reconcileConnectorAccount, } from './connector-account-repository.js';
39
39
  export { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, listConnectorSyncPolicies, upsertConnectorSyncPolicy, type ConnectorSyncPolicy, } from './connector-sync-policy-repository.js';
40
40
  export { getUserTrustPolicy, setUserTrustPolicy, } from './user-trust-repository.js';
41
+ export { createResearchCheckpoint, getResearchCheckpoint, claimResearchCheckpoint, saveResearchCheckpoint, recordResearchEvidence, recordResearchSearch, finishResearchCheckpoint, type StoredResearchCheckpoint, } from './research-checkpoint-repository.js';
@@ -42,6 +42,7 @@ import { deleteSessionConfig, getSessionConfig, hasSessionConfig, init_config_re
42
42
  import { createObjectLinkRecord, deleteObjectLinkRecord, getActivityEventRecord, init_activity_repository, listActivityRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, recordActivityEvent } from "./activity-repository.js";
43
43
  import { getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, init_connector_sync_policy_repository, listConnectorSyncPolicies, upsertConnectorSyncPolicy } from "./connector-sync-policy-repository.js";
44
44
  import { getUserTrustPolicy, init_user_trust_repository, setUserTrustPolicy } from "./user-trust-repository.js";
45
+ import { claimResearchCheckpoint, createResearchCheckpoint, finishResearchCheckpoint, getResearchCheckpoint, init_research_checkpoint_repository, recordResearchEvidence, recordResearchSearch, saveResearchCheckpoint } from "./research-checkpoint-repository.js";
45
46
  //#region src/storage/sqlite/index.ts
46
47
  var init_sqlite = __esmMin((() => {
47
48
  init_paths();
@@ -84,7 +85,8 @@ var init_sqlite = __esmMin((() => {
84
85
  init_connector_account_repository();
85
86
  init_connector_sync_policy_repository();
86
87
  init_user_trust_repository();
88
+ init_research_checkpoint_repository();
87
89
  }));
88
90
  //#endregion
89
91
  init_sqlite();
90
- export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, DatabaseSchemaTooOldError, SCHEMA_META_SCHEMA_VERSION_KEY, SidebarLayoutConflictError, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendMediaToAssistantTranscriptEntry, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, decideConnectorApproval, deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findConversationIdByTranscriptId, findLatestAssistantTranscriptEntryId, findSessionInput, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getBrowserTabBinding, getBrowserTabBindingById, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentTranscriptId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionTaskPlan, getSidebarLayout, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasSessionConfig, incrementSessionStatsOnAppend, init_sqlite, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isXopcDatabaseOpen, issueDeviceTokenPair, listActiveSessionInputExecutions, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listDevices, listEndpointPrincipals, listEndpointToolInvocationAuditPage, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTaskUpdateRunIds, listTaskUpdateTriggers, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceSidebarLayout, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setBrowserTabBinding, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, sortBySidebarLayout, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
92
+ export { COMPOSER_INPUT_HISTORY_LIMIT, DatabaseSchemaMigrationGapError, DatabaseSchemaTooNewError, DatabaseSchemaTooOldError, SCHEMA_META_SCHEMA_VERSION_KEY, SidebarLayoutConflictError, XOPC_DB_BASELINE_SCHEMA_VERSION, XOPC_DB_FILENAME, XOPC_DB_SCHEMA_VERSION, acknowledgeHomeAttention, appendCompactionBoundaryIfUnchanged, appendComposerInputHistory, appendConnectorExecutionAudit, appendMediaToAssistantTranscriptEntry, appendTranscriptEntry, applyPendingMigrations, authenticateDeviceAccessToken, bindEndpointPrincipal, buildDefaultSessionMetadata, buildGlobalSessionStats, buildRefreshProofMessage, cancelQueuedSessionInput, claimConnectorWebhookDelivery, claimContextExtractionRun, claimKnowledgeSourceItems, claimNextConnectorLearningJob, claimNextSessionInput, claimResearchCheckpoint, classifyStoredRow, clearComposerInputHistory, clearGatewayIdentityForTest, closeXopcDatabase, completeConnectorWebhookDelivery, completeKnowledgeSourceItemSynthesis, consumeClarificationApproval, consumeClarificationResume, consumeConnectorApproval, countKnowledgeSourceItems, createClarificationWait, createCollaborationRule, createConnectorApproval, createContextEvidence, createDevice, createDevicePairingSetup, createEndpointPrincipal, createObjectLinkRecord, createResearchCheckpoint, decideConnectorApproval, deleteBrowserTabBinding, deleteBrowserTabBindingsByEndpoint, deleteBrowserTabBindingsByPrincipal, deleteConnectorConnection, deleteConnectorInstallation, deleteEndpointSessionBinding, deleteEndpointSessionBindingsByPrincipal, deleteKnowledgeSourceItems, deleteNoteAgentContextRecord, deleteNoteRecord, deleteObjectLinkRecord, deleteSessionConfig, deleteSessionRecord, discoverSqlMigrations, enqueueConnectorLearningJob, ensureSessionRecord, ensureXopcDatabaseSchema, estimateTokensFromMessages, extractFtsContent, findConversationIdByTranscriptId, findLatestAssistantTranscriptEntryId, findSessionInput, finishContextExtractionRun, finishEndpointToolInvocationAudit, finishKnowledgeSyncRun, finishResearchCheckpoint, finishSessionInputRun, getActiveClarification, getActivityEventRecord, getBrowserTabBinding, getBrowserTabBindingById, getCachedConnectorCatalogEntry, getClarification, getClarificationResumeInput, getClarificationSnapshot, getCollaborationRule, getConnectorAccount, getConnectorApproval, getConnectorConnection, getConnectorInstallation, getConnectorSyncPolicy, getConnectorSyncPolicyForConnection, getContextExtractionRun, getCurrentTranscriptId, getDevice, getEndpointPrincipal, getEndpointSessionBinding, getGlobalSessionStats, getInteractionState, getKnowledgeConsumerWatermark, getKnowledgeSourceCursor, getKnowledgeSourceItem, getNoteAgentContextRecord, getNoteRecord, getOrCreateGatewayIdentity, getResearchCheckpoint, getSessionConfig, getSessionInputById, getSessionInputState, getSessionMetadata, getSessionTaskPlan, getSidebarLayout, getSqliteDatabase, getUserPeopleIndexState, getUserPerson, getUserTrustPolicy, getXopcDatabase, hasSessionConfig, incrementSessionStatsOnAppend, init_sqlite, insertSessionInput, inspectSchemaMigrationStatus, isClarificationSuspended, isDevicePairingSetupActive, isHomeAttentionAcknowledged, isXopcDatabaseOpen, issueDeviceTokenPair, listActiveSessionInputExecutions, listActiveSessionInputRuns, listActivityRecords, listCachedConnectorCatalogEntries, listCollaborationRules, listCompactionBoundaries, listComposerInputHistory, listConnectorAccounts, listConnectorActionMetadata, listConnectorApprovals, listConnectorConnections, listConnectorExecutionAudit, listConnectorInstallations, listConnectorLearningJobs, listConnectorSyncPolicies, listContextExtractionOutputs, listContextExtractionRuns, listDevices, listEndpointPrincipals, listEndpointToolInvocationAuditPage, listKnowledgeSourceChanges, listKnowledgeSourceItems, listKnowledgeSyncRuns, listNoteRecords, listObjectActivityRecords, listObjectLinkRecords, listProjectActivityRecords, listRegisteredMigrationTargets, listSessionMetadata, listSessionsByAgent, listTaskUpdateRunIds, listTaskUpdateTriggers, listUserPeople, loadCompactionSourceSnapshot, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, mergeUserPeople, metadataToSessionInsert, mutateQueuedSessionInput, openXopcDatabase, paginateTranscriptMessages, patchSessionMetadata, pruneBoundedKnowledgeSourceItems, readSchemaVersion, readSchemaVersionForTest, reconcileConnectorAccount, recordActivityEvent, recordResearchEvidence, recordResearchSearch, recoverSessionInputState, recoverStaleConnectorLearningJobs, refreshConnectorAccountCurrent, releaseConnectorWebhookDelivery, replaceConnectorCatalogEntries, replaceLatestSessionTurnAndQueueInput, replaceSidebarLayout, replaceTranscriptRows, replaceUserPeopleIndex, requireXopcDatabase, resetSessionRecord, resetXopcDatabaseSingletonForTest, resolveClarification, resolveMigrationsDir, resolveSessionAgentId, resolveXopcDatabasePath, restoreBeforeCompactionBoundary, revokeDevice, revokeEndpointPrincipal, rotateDeviceRefreshToken, runSqliteWriteTransaction, saveResearchCheckpoint, searchSessionTranscript, sessionConfigRowToConfig, sessionRowToMetadata, setBrowserTabBinding, setCollaborationRuleStatus, setConnectorLearningPaused, setEndpointSessionBinding, setInteractionState, setKnowledgeConsumerWatermark, setKnowledgeSourceCursor, setKnowledgeSourceItemSynthesisStatus, setSessionConfig, setSessionInputStatus, setSessionTaskPlan, setUserTrustPolicy, signGatewayPayload, sortBySidebarLayout, startEndpointToolInvocationAudit, startKnowledgeSyncRun, summarizeUserPeople, supersedeActiveClarification, touchEndpointPrincipal, transcriptEntryRowToStoredRow, updateConnectorLearningJob, updateInteractionStateFromMessage, updateSessionConfig, updateSessionStats, updateUserPerson, upsertConnectorActionMetadata, upsertConnectorCatalogEntry, upsertConnectorConnection, upsertConnectorInstallation, upsertConnectorSyncPolicy, upsertKnowledgeSourceItems, upsertNoteAgentContextRecord, upsertNoteRecord, validateLatestSessionTurnTarget };
@@ -0,0 +1,15 @@
1
+ CREATE TABLE research_checkpoints (
2
+ id TEXT PRIMARY KEY,
3
+ conversation_id TEXT NOT NULL REFERENCES sessions(conversation_id) ON DELETE CASCADE,
4
+ workspace TEXT NOT NULL,
5
+ goal TEXT NOT NULL,
6
+ checkpoint_json TEXT NOT NULL CHECK(json_valid(checkpoint_json)),
7
+ status TEXT NOT NULL CHECK(status IN ('running','partial','completed','failed','cancelled')),
8
+ attempts INTEGER NOT NULL DEFAULT 0,
9
+ stop_reason TEXT,
10
+ summary TEXT NOT NULL DEFAULT '',
11
+ lease_token TEXT,
12
+ lease_expires_at INTEGER,
13
+ updated_at INTEGER NOT NULL
14
+ );
15
+ CREATE INDEX research_checkpoints_conversation ON research_checkpoints(conversation_id, updated_at);
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
3
3
  /** Baseline schema version applied from schema.sql on first open. */
4
4
  export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 165;
5
5
  /** Latest schema version this release supports (increment when adding migrations). */
6
- export declare const XOPC_DB_SCHEMA_VERSION = 249;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 250;
7
7
  export declare function resolveMigrationsDir(override?: string): string;
8
8
  /**
9
9
  * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
@@ -59,7 +59,7 @@ function applySingleMigration(db, migration, discardOldScenes = false) {
59
59
  function applyPendingMigrations(db, options = {}) {
60
60
  db.function("xopc_memory_search_text", { deterministic: true }, (value) => memorySearchText(String(value ?? "")));
61
61
  db.function("xopc_operation_id", () => currentOperationId() ?? null);
62
- const targetVersion = options.targetVersion ?? 249;
62
+ const targetVersion = options.targetVersion ?? 250;
63
63
  let currentVersion = readSchemaVersion(db);
64
64
  if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
65
65
  if (!options.migrationsDir && currentVersion < 165) throw new DatabaseSchemaTooOldError(currentVersion, 165);
@@ -97,7 +97,7 @@ function applyPendingMigrations(db, options = {}) {
97
97
  }
98
98
  /** Inspect schema version without mutating the database. */
99
99
  function inspectSchemaMigrationStatus(db, options = {}) {
100
- const appVersion = options.targetVersion ?? 249;
100
+ const appVersion = options.targetVersion ?? 250;
101
101
  const dbVersion = readSchemaVersion(db);
102
102
  if (dbVersion > appVersion) return {
103
103
  dbVersion,
@@ -140,7 +140,7 @@ var init_runner = __esmMin((() => {
140
140
  init_errors();
141
141
  log = createLogger("Sqlite:Migrations");
142
142
  XOPC_DB_BASELINE_SCHEMA_VERSION = 165;
143
- XOPC_DB_SCHEMA_VERSION = 249;
143
+ XOPC_DB_SCHEMA_VERSION = 250;
144
144
  }));
145
145
  //#endregion
146
146
  init_runner();
@@ -0,0 +1,24 @@
1
+ import type { SearchCacheEntry } from '../../agent/tools/search/cache.js';
2
+ import { type ResearchCheckpoint, type ResearchCheckpointUpdate, type ResearchEvidence } from '../../agent/orchestration/research-checkpoint.js';
3
+ export interface StoredResearchCheckpoint {
4
+ id: string;
5
+ conversationId: string;
6
+ workspace: string;
7
+ goal: string;
8
+ checkpoint: ResearchCheckpoint;
9
+ status: 'running' | 'partial' | 'completed' | 'failed' | 'cancelled';
10
+ attempts: number;
11
+ stopReason?: string;
12
+ summary: string;
13
+ leaseToken?: string;
14
+ leaseExpiresAt?: number;
15
+ }
16
+ export declare function getResearchCheckpoint(id: string, conversationId: string, workspace: string): StoredResearchCheckpoint | undefined;
17
+ export declare function createResearchCheckpoint(conversationId: string, workspace: string, goal: string): StoredResearchCheckpoint;
18
+ /** Lease ownership fences late tool callbacks and competing resume requests. */
19
+ export declare function claimResearchCheckpoint(record: StoredResearchCheckpoint, timeoutMs: number, now?: number): StoredResearchCheckpoint;
20
+ export declare function saveResearchCheckpoint(record: StoredResearchCheckpoint, update: ResearchCheckpointUpdate): ResearchCheckpoint;
21
+ export declare function recordResearchEvidence(record: StoredResearchCheckpoint, evidence: ResearchEvidence): void;
22
+ export declare function finishResearchCheckpoint(record: StoredResearchCheckpoint, status: StoredResearchCheckpoint['status'], stopReason: string, summary: string): void;
23
+ /** Keep successful public search results with the same task lease and a bounded envelope. */
24
+ export declare function recordResearchSearch(record: StoredResearchCheckpoint, entry: SearchCacheEntry): void;
@@ -0,0 +1,91 @@
1
+ import { __esmMin } from "../../../_virtual/_rolldown/runtime.js";
2
+ import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "./transaction.js";
3
+ import { init_research_checkpoint, mergeResearchCheckpoint } from "../../agent/orchestration/research-checkpoint.js";
4
+ import { randomUUID } from "node:crypto";
5
+ //#region src/storage/sqlite/research-checkpoint-repository.ts
6
+ function decode(row) {
7
+ return {
8
+ id: row.id,
9
+ conversationId: row.conversation_id,
10
+ workspace: row.workspace,
11
+ goal: row.goal,
12
+ checkpoint: JSON.parse(row.checkpoint_json),
13
+ status: row.status,
14
+ attempts: row.attempts,
15
+ stopReason: row.stop_reason ?? void 0,
16
+ summary: row.summary,
17
+ leaseToken: row.lease_token ?? void 0,
18
+ leaseExpiresAt: row.lease_expires_at ?? void 0
19
+ };
20
+ }
21
+ function getResearchCheckpoint(id, conversationId, workspace) {
22
+ const row = getSqliteDatabase().prepare("SELECT * FROM research_checkpoints WHERE id = ? AND conversation_id = ? AND workspace = ?").get(id, conversationId, workspace);
23
+ return row ? decode(row) : void 0;
24
+ }
25
+ function createResearchCheckpoint(conversationId, workspace, goal) {
26
+ const id = randomUUID();
27
+ const checkpoint = {
28
+ findings: [],
29
+ evidence: [],
30
+ nextSteps: [goal.slice(0, 500)]
31
+ };
32
+ runSqliteWriteTransaction((db) => db.prepare(`INSERT INTO research_checkpoints
33
+ (id, conversation_id, workspace, goal, checkpoint_json, status, updated_at) VALUES (?, ?, ?, ?, ?, 'partial', ?)`).run(id, conversationId, workspace, goal, JSON.stringify(checkpoint), Date.now()));
34
+ return getResearchCheckpoint(id, conversationId, workspace);
35
+ }
36
+ /** Lease ownership fences late tool callbacks and competing resume requests. */
37
+ function claimResearchCheckpoint(record, timeoutMs, now = Date.now()) {
38
+ return runSqliteWriteTransaction((db) => {
39
+ const token = randomUUID();
40
+ if (!db.prepare(`UPDATE research_checkpoints SET status = 'running', attempts = attempts + 1,
41
+ lease_token = ?, lease_expires_at = ?, updated_at = ? WHERE id = ? AND conversation_id = ? AND workspace = ?
42
+ AND status != 'completed' AND (lease_token IS NULL OR lease_expires_at <= ?)`).run(token, now + timeoutMs, now, record.id, record.conversationId, record.workspace, now).changes) throw new Error("Research checkpoint is complete or already running");
43
+ return getResearchCheckpoint(record.id, record.conversationId, record.workspace);
44
+ });
45
+ }
46
+ function mutate(record, transform) {
47
+ return runSqliteWriteTransaction((db) => {
48
+ const current = getResearchCheckpoint(record.id, record.conversationId, record.workspace);
49
+ if (!current || !record.leaseToken || current.leaseToken !== record.leaseToken || current.status !== "running" || (current.leaseExpiresAt ?? 0) <= Date.now()) throw new Error("Research checkpoint lease expired");
50
+ const checkpoint = transform(current.checkpoint);
51
+ db.prepare("UPDATE research_checkpoints SET checkpoint_json = ?, updated_at = ? WHERE id = ? AND lease_token = ?").run(JSON.stringify(checkpoint), Date.now(), record.id, record.leaseToken);
52
+ return checkpoint;
53
+ });
54
+ }
55
+ function saveResearchCheckpoint(record, update) {
56
+ return mutate(record, (current) => mergeResearchCheckpoint(current, update));
57
+ }
58
+ function recordResearchEvidence(record, evidence) {
59
+ mutate(record, (current) => ({
60
+ ...current,
61
+ evidence: [...current.evidence.filter((item) => item.toolCallId !== evidence.toolCallId || item.runId !== evidence.runId), {
62
+ ...evidence,
63
+ excerpt: evidence.excerpt.slice(0, 2e3)
64
+ }].slice(-30)
65
+ }));
66
+ }
67
+ function finishResearchCheckpoint(record, status, stopReason, summary) {
68
+ if (!runSqliteWriteTransaction((db) => db.prepare(`UPDATE research_checkpoints SET status = ?, stop_reason = ?, summary = ?,
69
+ lease_token = NULL, lease_expires_at = NULL, updated_at = ? WHERE id = ? AND lease_token = ?`).run(status, stopReason, summary.slice(0, 8e3), Date.now(), record.id, record.leaseToken ?? "")).changes) throw new Error("Research checkpoint lease was replaced");
70
+ }
71
+ /** Keep successful public search results with the same task lease and a bounded envelope. */
72
+ function recordResearchSearch(record, entry) {
73
+ mutate(record, (current) => {
74
+ const searches = [...(current.searches ?? []).filter((item) => item.key !== entry.key), entry].slice(-20);
75
+ while (searches.length && JSON.stringify({
76
+ ...current,
77
+ searches
78
+ }).length > 2e5) searches.shift();
79
+ return {
80
+ ...current,
81
+ searches
82
+ };
83
+ });
84
+ }
85
+ var init_research_checkpoint_repository = __esmMin((() => {
86
+ init_research_checkpoint();
87
+ init_transaction();
88
+ }));
89
+ //#endregion
90
+ init_research_checkpoint_repository();
91
+ export { claimResearchCheckpoint, createResearchCheckpoint, finishResearchCheckpoint, getResearchCheckpoint, init_research_checkpoint_repository, recordResearchEvidence, recordResearchSearch, saveResearchCheckpoint };
@@ -28,7 +28,7 @@ function ensureXopcDatabaseSchema(db, options = {}) {
28
28
  currentVersion = 165;
29
29
  }
30
30
  applyPendingMigrations(db, {
31
- targetVersion: 249,
31
+ targetVersion: 250,
32
32
  databasePath: fresh ? void 0 : options.databasePath
33
33
  });
34
34
  }
@@ -3,7 +3,7 @@ import { sessionCommandIdentity } from "../../../packages/gateway-contract/src/s
3
3
  import { init_src } from "../../../packages/gateway-contract/src/index.js";
4
4
  import { init_session_input_repository, insertSessionInput } from "./session-input-repository.js";
5
5
  import { init_clarification_wait_repository, supersedeActiveClarification } from "./clarification-wait-repository.js";
6
- import { init_connection_wait_repository, invalidateConnectionResumeIntent } from "./connection-wait-repository.js";
6
+ import { cancelConnectionObjective, init_connection_wait_repository } from "./connection-wait-repository.js";
7
7
  import { getSessionMetadata } from "./session-read-repository.js";
8
8
  import { init_session_repository } from "./session-repository.js";
9
9
  import { init_config_repository, setSessionConfig } from "./config-repository.js";
@@ -113,7 +113,8 @@ function acceptSessionCommand(input) {
113
113
  expectedTranscriptId: transcriptId
114
114
  });
115
115
  if (inputId) {
116
- invalidateConnectionResumeIntent(conversationId);
116
+ const control = input.preparedInput?.payload;
117
+ if (control?.connectionAction === "cancel") cancelConnectionObjective(conversationId, control.waitId, control.objectiveRevision);
117
118
  supersedeActiveClarification(conversationId);
118
119
  }
119
120
  const receipt = {
@@ -8,10 +8,26 @@ export type SessionInputPayload = {
8
8
  waitId: string;
9
9
  objectiveRevision: number;
10
10
  resolution: 'continued' | 'skipped';
11
+ connectionAction?: never;
12
+ connectionBarrier?: never;
11
13
  } | {
12
14
  waitId: string;
13
15
  objectiveRevision: number;
14
16
  resolution: 'answered' | 'agent_decide' | 'cancelled';
17
+ connectionAction?: never;
18
+ connectionBarrier?: never;
19
+ } | {
20
+ waitId: string;
21
+ objectiveRevision: number;
22
+ connectionAction: 'continue' | 'cancel';
23
+ resolution?: never;
24
+ connectionBarrier?: never;
25
+ } | {
26
+ waitId: string;
27
+ objectiveRevision: number;
28
+ connectionBarrier: true;
29
+ connectionAction?: never;
30
+ resolution?: never;
15
31
  };
16
32
  export type SessionInput = {
17
33
  id: string;