@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
@@ -0,0 +1,92 @@
1
+ import { isXopcDatabaseOpen } from "../../storage/sqlite/connection.js";
2
+ import { getSessionMetadata } from "../../storage/sqlite/session-read-repository.js";
3
+ import { getSessionConfig } from "../../storage/sqlite/config-repository.js";
4
+ import { init_sqlite } from "../../storage/sqlite/index.js";
5
+ import { AgentCatalogRepository, init_repository } from "../../agent-catalog/repository.js";
6
+ import { createHash } from "node:crypto";
7
+ import { getCurrentTools } from "@earendil-works/pi-ai";
8
+ //#region src/agent/embedded/agent-profile-context.ts
9
+ init_repository();
10
+ init_sqlite();
11
+ const AGENT_PROFILE_CONTEXT_STATE = "xopc.agent-profile-context";
12
+ const AGENT_PROFILE_UPDATE_EVENT = "xopc.agent-profile-update";
13
+ function agentProfileContextFingerprint(agentId, profile, responseLanguage) {
14
+ return createHash("sha256").update(JSON.stringify({
15
+ agentId,
16
+ responseLanguage: responseLanguage ?? "auto",
17
+ name: profile?.name,
18
+ description: profile?.description,
19
+ creature: profile?.creature,
20
+ style: profile?.style,
21
+ language: profile?.language,
22
+ instructions: profile?.instructions
23
+ })).digest("hex");
24
+ }
25
+ /** Keep profile transitions separate from user messages and model-authored conversation. */
26
+ function createAgentProfileContextExtension(conversationId) {
27
+ return (pi) => {
28
+ const snapshotForTurn = (context) => {
29
+ if (!isXopcDatabaseOpen()) return;
30
+ const agentId = getSessionMetadata(conversationId)?.agentId;
31
+ if (!agentId) return;
32
+ const profile = new AgentCatalogRepository().get(agentId)?.profile;
33
+ const responseLanguage = getSessionConfig(conversationId)?.responseLanguage ?? "auto";
34
+ const fingerprint = agentProfileContextFingerprint(agentId, profile, responseLanguage);
35
+ const configuration = {
36
+ agentId,
37
+ name: profile?.name ?? agentId,
38
+ role: profile?.description || null,
39
+ type: profile?.creature || null,
40
+ style: profile?.style || null,
41
+ primaryLanguage: profile?.language || null,
42
+ responseLanguageOverride: responseLanguage
43
+ };
44
+ const previous = context.sessionManager.getBranch().findLast((entry) => entry.type === "custom" && entry.customType === "xopc.agent-profile-context");
45
+ const data = previous?.type === "custom" ? previous.data : void 0;
46
+ const changed = data?.fingerprint !== fingerprint || JSON.stringify(data?.configuration) !== JSON.stringify(configuration);
47
+ if (changed) pi.appendEntry(AGENT_PROFILE_CONTEXT_STATE, {
48
+ fingerprint,
49
+ configuration
50
+ });
51
+ const changedFields = Object.keys(configuration).filter((key) => configuration[key] !== data?.configuration?.[key]);
52
+ const updates = Object.fromEntries(changedFields.map((key) => [key, {
53
+ previous: data?.configuration?.[key] ?? null,
54
+ current: configuration[key] ?? null
55
+ }]));
56
+ return {
57
+ role: "custom",
58
+ timestamp: Date.now(),
59
+ customType: AGENT_PROFILE_UPDATE_EVENT,
60
+ content: JSON.stringify({
61
+ event: changed ? "agent_configuration_updated" : "agent_configuration_current",
62
+ source: "xopc-runtime",
63
+ ...changed ? {
64
+ changedFields: changedFields.length ? changedFields : ["instructions"],
65
+ updates
66
+ } : {},
67
+ current: configuration
68
+ }),
69
+ display: false
70
+ };
71
+ };
72
+ let snapshot;
73
+ pi.on("before_agent_start", (_event, context) => {
74
+ snapshot = snapshotForTurn(context);
75
+ });
76
+ pi.on("context_with_system", (event, context) => {
77
+ snapshot ??= snapshotForTurn(context);
78
+ if (!snapshot) return;
79
+ const messages = event.messages.filter((message) => message.role !== "system" && !(message.role === "custom" && message.customType === "xopc.agent-profile-update"));
80
+ const inputIndex = messages.findLastIndex((message) => message.role === "user" || message.role === "custom");
81
+ messages.splice(inputIndex < 0 ? messages.length : inputIndex, 0, snapshot);
82
+ return { messages: [{
83
+ role: "system",
84
+ content: context.getSystemPrompt(),
85
+ toolsAdded: getCurrentTools(event.messages),
86
+ timestamp: Date.now()
87
+ }, ...messages] };
88
+ });
89
+ };
90
+ }
91
+ //#endregion
92
+ export { AGENT_PROFILE_CONTEXT_STATE, AGENT_PROFILE_UPDATE_EVENT, agentProfileContextFingerprint, createAgentProfileContextExtension };
@@ -1,5 +1,5 @@
1
1
  import type { AgentTool } from '@earendil-works/pi-agent-core';
2
- export declare const PERSONAL_REQUEST_TOOL_IDS: readonly ["xopc_tool_search", "xopc_tool_describe", "xopc_tool_execute", "personal_request_result", "personal_request_connection"];
2
+ export declare const PERSONAL_REQUEST_TOOL_IDS: readonly ["xopc_tool_search", "xopc_tool_describe", "xopc_tool_execute", "personal_request_result", "personal_request_connection", "task_collaboration"];
3
3
  export type ExecutionToolPolicy = Readonly<{
4
4
  surface: 'agent' | 'personal_main' | 'personal_request_worker';
5
5
  nativeMcp: boolean;
@@ -13,7 +13,8 @@ const PERSONAL_REQUEST_TOOL_IDS = [
13
13
  "xopc_tool_describe",
14
14
  "xopc_tool_execute",
15
15
  "personal_request_result",
16
- "personal_request_connection"
16
+ "personal_request_connection",
17
+ "task_collaboration"
17
18
  ];
18
19
  /** Resolve from persisted execution identity, never from tool names or model input. */
19
20
  function resolveExecutionToolPolicy(conversationId) {
@@ -27,7 +28,7 @@ function resolveExecutionToolPolicy(conversationId) {
27
28
  externalMaterialization: configured,
28
29
  discovery: configured,
29
30
  codemode: configured,
30
- revision: "personal-tool-boundaries-v1"
31
+ revision: "personal-tool-boundaries-v2"
31
32
  };
32
33
  }
33
34
  function allowsExecutionTool(policy, name) {
@@ -17,10 +17,12 @@ import { assessContext, recoverContext as recoverContext$1 } from "../memory/con
17
17
  import { resolveCompactionPolicy } from "../memory/compaction-policy.js";
18
18
  import { runXopcEmbeddedTurn } from "./run-turn.js";
19
19
  import { projectTurnOutcome } from "../../session/turn-outcome-projector.js";
20
+ import { connectionObjectiveContext } from "../context/connection-objective-context.js";
20
21
  import { voicePresentationPrompt } from "../prompt/voice-presentation.js";
21
22
  import { applyStartupContextToUserMessage } from "../reply/apply-turn-user-enrichment.js";
22
23
  import { AgentRunSupervisor } from "../orchestration/agent-run-supervisor.js";
23
24
  import { materializeNativeExternalTools } from "./external-tool-discovery.js";
25
+ import { getTaskContinuation, getTaskExecutionDeadline } from "../../tasks/task-continuation.js";
24
26
  import crypto from "node:crypto";
25
27
  //#region src/agent/embedded/run-for-session.ts
26
28
  init_src();
@@ -45,14 +47,22 @@ async function runEmbeddedTurnForSessionInner(params) {
45
47
  let idleJob;
46
48
  let turnCompleted = false;
47
49
  const runId = params.runId ?? crypto.randomUUID();
50
+ const taskContinuation = getTaskContinuation(conversationId, runId);
48
51
  const config = params.getConfig?.();
49
52
  if (config) setTraceIdentity({ agentId: resolveEffectiveAgentProfileForSession(conversationId).agentId });
50
53
  const supervisor = new AgentRunSupervisor({
51
54
  timeoutMs: resolveAgentTurnTimeoutMs(config, conversationId),
52
- deadlineAtMs: params.deadlineAtMs,
55
+ deadlineAtMs: params.deadlineAtMs ?? getTaskExecutionDeadline(conversationId, runId),
53
56
  parentSignal: params.abortSignal
54
57
  });
55
58
  const finish = async (result) => {
59
+ if (supervisor.signal.aborted && supervisor.signal.reason instanceof Error && supervisor.signal.reason.message === "Agent run deadline expired") result = {
60
+ ...result,
61
+ ok: false,
62
+ retryable: false,
63
+ terminationReason: "deadline_exceeded",
64
+ errorMessage: supervisor.signal.reason.message
65
+ };
56
66
  turnCompleted = result.ok && result.stopReason !== "connection_required" && result.stopReason !== "clarification_required";
57
67
  if (result.stopReason === "connection_required" || result.stopReason === "clarification_required") return result;
58
68
  try {
@@ -91,15 +101,15 @@ async function runEmbeddedTurnForSessionInner(params) {
91
101
  };
92
102
  try {
93
103
  await params.beforeTurn?.();
94
- if (supervisor.signal.aborted) return {
104
+ if (supervisor.signal.aborted) return await finish({
95
105
  ok: false,
96
106
  errorMessage: "aborted"
97
- };
107
+ });
98
108
  await agentManager.ensureMemoryReadyForSession?.(conversationId);
99
- if (supervisor.signal.aborted) return {
109
+ if (supervisor.signal.aborted) return await finish({
100
110
  ok: false,
101
111
  errorMessage: "aborted"
102
- };
112
+ });
103
113
  const agent = agentManager.getOrCreateAgent(conversationId);
104
114
  const mm = modelManager;
105
115
  const configuredModelRef = String(mm.getModelForSession(conversationId));
@@ -130,7 +140,7 @@ async function runEmbeddedTurnForSessionInner(params) {
130
140
  const executionToolPolicy = resolveExecutionToolPolicy(conversationId);
131
141
  const tools = filterExecutionTools(executionToolPolicy, agent.state.tools);
132
142
  const turnPolicy = agentManager.createAgentTurnPolicy(conversationId);
133
- const systemPrompt = appendDynamicPromptSection([agent.state.systemPrompt ?? "", params.presentation === "voice" ? voicePresentationPrompt : ""].filter(Boolean).join("\n\n"), params.dynamicSystemContext ?? "");
143
+ const systemPrompt = appendDynamicPromptSection([agent.state.systemPrompt ?? "", params.presentation === "voice" ? voicePresentationPrompt : ""].filter(Boolean).join("\n\n"), [params.dynamicSystemContext, connectionObjectiveContext(conversationId)].filter(Boolean).join("\n\n"));
134
144
  const idlePolicy = resolveCompactionPolicy(config);
135
145
  if (personal && idlePolicy.enabled && idlePolicy.personalIdle.enabled) idleJob = async (signal, isCurrent) => {
136
146
  const messages = await sessionStore.load(conversationId);
@@ -185,10 +195,10 @@ async function runEmbeddedTurnForSessionInner(params) {
185
195
  startupAction: params.startupAction,
186
196
  force: params.forceStartupContext
187
197
  });
188
- if (supervisor.signal.aborted) return {
198
+ if (supervisor.signal.aborted) return await finish({
189
199
  ok: false,
190
200
  errorMessage: "aborted"
191
- };
201
+ });
192
202
  }
193
203
  try {
194
204
  await maybeAutoCompactBeforeTurn({
@@ -206,16 +216,16 @@ async function runEmbeddedTurnForSessionInner(params) {
206
216
  onEvent: params.onEvent
207
217
  });
208
218
  } catch (err) {
209
- if (supervisor.signal.aborted) return {
219
+ if (supervisor.signal.aborted) return await finish({
210
220
  ok: false,
211
221
  errorMessage: "aborted"
212
- };
222
+ });
213
223
  throw err;
214
224
  }
215
- if (supervisor.signal.aborted) return {
225
+ if (supervisor.signal.aborted) return await finish({
216
226
  ok: false,
217
227
  errorMessage: "aborted"
218
- };
228
+ });
219
229
  log.info({
220
230
  conversationId,
221
231
  runId,
@@ -281,9 +291,22 @@ async function runEmbeddedTurnForSessionInner(params) {
281
291
  timeoutMs: attemptPlan.timeoutMs,
282
292
  turnPolicy,
283
293
  abortSignal: supervisor.signal,
284
- onEvent: params.onEvent,
294
+ onEvent: (event) => {
295
+ if (event.type === "error") {
296
+ log.warn({
297
+ conversationId,
298
+ runId,
299
+ modelRef: candidateModelRef,
300
+ errorMessage: event.content
301
+ }, "Model attempt failed");
302
+ return;
303
+ }
304
+ params.onEvent?.(event);
305
+ },
285
306
  onAgentEvent: (event) => agentManager.emitRuntimeEvent(conversationId, event),
286
307
  resumeLastUserMessage,
308
+ recoveryMessage: taskContinuation?.message,
309
+ recoveryReason: taskContinuation?.reason,
287
310
  requireVisibleReply: params.requireVisibleReply
288
311
  }), runId));
289
312
  attempt.finish(turnResult.ok ? "success" : "error", turnResult.errorMessage);
@@ -330,7 +353,7 @@ async function runEmbeddedTurnForSessionInner(params) {
330
353
  }, hasNextCandidate ? "Agent model call threw, trying fallback" : "Agent model call threw, no fallback remains");
331
354
  }
332
355
  if (hasNextCandidate && rowsBeforeAttempt) {
333
- const preparation = await sessionStore.prepareModelFallback(conversationId, rowsBeforeAttempt);
356
+ const preparation = await sessionStore.prepareModelFallback(conversationId, rowsBeforeAttempt, { resumeTaskContinuation: Boolean(taskContinuation?.message) });
334
357
  if (preparation === "unsafe") {
335
358
  log.warn({
336
359
  conversationId,
@@ -10,12 +10,14 @@ import { resolveEffectiveAgentConfigForSession } from "../../config/agent-profil
10
10
  import { setTraceIdentity, traceOperation, traceRun, traceTools } from "../../observability/runtime.js";
11
11
  import { continuesAfterTool, trackAiUsageStream } from "../../usage/recorder.js";
12
12
  import { cloudCreditBudgetStopMessage, isCloudCreditBudgetExhausted, reportCloudCreditError, withCloudCreditBudget } from "../../providers/xopc-cloud-credit-budget.js";
13
- import { isAgentTurnUnsettledError, resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
13
+ import { resolveAgentAbortReason } from "../orchestration/run-termination.js";
14
+ import { isAgentTurnTimeoutError, isAgentTurnUnsettledError, resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
14
15
  import { isContextOverflowError } from "../orchestration/context-overflow.js";
16
+ import { ACCEPTANCE_REPAIR_READ_TOOLS, canResumeAfterModelFailure, completedRecoveryToolResult } from "../orchestration/turn-recovery.js";
15
17
  import { getAssistantTurnErrorMessage, isAssistantTurnAborted, isAssistantTurnFailed, maybeRetryTurnAfterTransientLlmFailure, stripTrailingErrorAssistantMessages } from "../orchestration/llm-turn-retry.js";
16
18
  import { allowsExecutionTool, filterExecutionTools, resolveExecutionToolPolicy } from "./execution-tool-policy.js";
17
19
  import { runWithEmbeddedExecutionSession } from "./execution-context.js";
18
- import { externalPolicyContext } from "./tool-metadata.js";
20
+ import { externalPolicyContext, getXopcToolMetadata } from "./tool-metadata.js";
19
21
  import { isComputerControlActive, isComputerLeaseTool, stopComputerControl } from "../../computer/control-guard.js";
20
22
  import { EmbeddedRunConflictError, abortEmbeddedRun, acquireEmbeddedRunLease, queueEmbeddedSteer } from "./runs.js";
21
23
  import { lastAssistantPlainText, subscribeEmbeddedSessionEvents } from "./subscribe-session.js";
@@ -46,6 +48,17 @@ init_sqlite();
46
48
  init_session_repository();
47
49
  const log = createLogger("EmbeddedRun");
48
50
  const LOG_PREVIEW_MAX_CHARS = 300;
51
+ const RECOVERY_READ_TOOLS = new Set([
52
+ "read_file",
53
+ "find",
54
+ "grep",
55
+ "list_dir",
56
+ "tool_manual",
57
+ "tool_search",
58
+ "review_workspace",
59
+ "language_diagnostics",
60
+ "session_status"
61
+ ]);
49
62
  function truncateForLog(value, maxChars = LOG_PREVIEW_MAX_CHARS) {
50
63
  return value.length > maxChars ? `${value.slice(0, maxChars)}…` : value;
51
64
  }
@@ -216,6 +229,11 @@ async function maybeRecoverInterruptedContext(params) {
216
229
  const overflow = !!errorMessage && isContextOverflowError(errorMessage);
217
230
  const recoverableLength = !!assistant && isRecoverableLengthForModel(assistant, params.model);
218
231
  if (!overflow && !recoverableLength) return false;
232
+ const discardedCalls = new Set(recoverableLength && assistant ? discardedAttempt(assistant).toolCallIds : []);
233
+ if (!canResumeAfterModelFailure(params.agent.state.messages.filter((message) => !recoverableLength || message !== assistant && !(message.role === "toolResult" && discardedCalls.has(message.toolCallId))))) {
234
+ log.warn({ conversationId: params.conversationId }, "Context recovery stopped because a tool outcome is unconfirmed");
235
+ return false;
236
+ }
219
237
  if (recoverableLength && (!params.policy.enabled || params.recoveryState.interruptedAttempts >= 1)) {
220
238
  log.warn({
221
239
  conversationId: params.conversationId,
@@ -343,12 +361,14 @@ async function runXopcEmbeddedTurnInner(params) {
343
361
  await session.abort();
344
362
  return {
345
363
  ok: false,
364
+ terminationReason: resolveAgentAbortReason(runAbortSignal.reason),
346
365
  errorMessage: "aborted"
347
366
  };
348
367
  }
349
368
  session.agent.state.messages = stripTrailingErrorAssistantMessages(await transcriptRuntime.loadMessages());
350
369
  runner.piSm.setActiveTurnId?.(runId);
351
370
  const recoveryState = { interruptedAttempts: 0 };
371
+ const requestRetryBudget = { continues: 0 };
352
372
  let useAuthoritativeProjection = false;
353
373
  const basePrepareNextTurn = session.agent.prepareNextTurnWithContext;
354
374
  const inTurnPrepareNextTurn = async (turn, signal) => {
@@ -566,10 +586,11 @@ async function runXopcEmbeddedTurnInner(params) {
566
586
  session.agent.streamFunction = loggingStreamFn;
567
587
  const verification = await RunVerification.open(workspaceDir);
568
588
  const checkpoints = runner.piSm.getBranch?.() ?? [];
589
+ const recoveryTurn = params.resumeLastUserMessage === true || Boolean(params.recoveryMessage);
569
590
  const lastStart = checkpoints.findLastIndex((entry) => entry.type === "custom" && entry.customType === "coding_run_started");
570
591
  const lastSummary = checkpoints.findLastIndex((entry) => entry.type === "custom" && entry.customType === "coding_verification");
571
- const checkpoint = checkpoints[params.resumeLastUserMessage && lastSummary >= lastStart ? lastSummary : lastStart];
572
- if (checkpoint?.type === "custom" && (params.resumeLastUserMessage || lastStart > lastSummary)) verification.restore(checkpoint.data, params.resumeLastUserMessage === true && lastSummary >= lastStart);
592
+ const checkpoint = checkpoints[recoveryTurn && lastSummary >= lastStart ? lastSummary : lastStart];
593
+ if (checkpoint?.type === "custom" && (recoveryTurn || lastStart > lastSummary)) verification.restore(checkpoint.data, recoveryTurn && lastSummary >= lastStart);
573
594
  runner.piSm.appendCustomEntry("coding_run_started", {
574
595
  runId,
575
596
  workspace: workspaceDir,
@@ -577,6 +598,11 @@ async function runXopcEmbeddedTurnInner(params) {
577
598
  ...await verification.summary()
578
599
  });
579
600
  let policyStopped = false;
601
+ let policyCompleted = false;
602
+ let recoveringModel = params.resumeLastUserMessage === true || Boolean(params.recoveryMessage);
603
+ let recoveryMessages = [...session.agent.state.messages];
604
+ let policyStopReason;
605
+ let lengthRecoveryExhausted = false;
580
606
  let connectionStopped = false;
581
607
  let clarificationStopped = false;
582
608
  let sentVisibleMessage = false;
@@ -588,6 +614,7 @@ async function runXopcEmbeddedTurnInner(params) {
588
614
  };
589
615
  if (executionToolPolicy.surface !== "agent" && resolveExecutionToolPolicy(toolPolicyConversationId).surface !== executionToolPolicy.surface) {
590
616
  policyStopped = true;
617
+ policyStopReason = "Execution identity changed during the run";
591
618
  quarantineRunner = true;
592
619
  return {
593
620
  block: true,
@@ -615,8 +642,24 @@ async function runXopcEmbeddedTurnInner(params) {
615
642
  const decision = await params.turnPolicy?.beforeToolCall(externalPolicyContext(context, tools), signal);
616
643
  if (decision?.block) {
617
644
  policyStopped ||= decision.terminate === true;
645
+ if (decision.terminate) policyStopReason = decision.reason;
618
646
  return decision;
619
647
  }
648
+ const tool = tools.find((candidate) => candidate.name === context.toolCall.name);
649
+ const metadata = tool && getXopcToolMetadata(tool);
650
+ const readOnly = RECOVERY_READ_TOOLS.has(context.toolCall.name) || metadata?.external?.readOnly === true || metadata?.annotations?.readOnlyHint === true || context.toolCall.name === "task_collaboration" && context.args.command === "get" || context.toolCall.name === "managed_job" && [
651
+ "wait",
652
+ "status",
653
+ "list"
654
+ ].includes(String(context.args.action));
655
+ const repairPublication = ["acceptance_repair", "model_failure"].includes(params.recoveryReason ?? "") && ["publish_artifacts", "publish_task_result"].includes(context.toolCall.name);
656
+ if (recoveringModel && !readOnly && !repairPublication) {
657
+ const recorded = completedRecoveryToolResult(recoveryMessages, context.toolCall.name, context.args);
658
+ if (recorded) return {
659
+ block: true,
660
+ reason: recorded
661
+ };
662
+ }
620
663
  if (context.toolCall.name !== "read_file") {
621
664
  const scoped = await instructions.forTool(context.toolCall.name, context.args);
622
665
  if (scoped) return {
@@ -661,9 +704,12 @@ async function runXopcEmbeddedTurnInner(params) {
661
704
  conversationId,
662
705
  runId
663
706
  }, "Stopping after the bounded truncated-response recovery attempt");
707
+ lengthRecoveryExhausted = true;
664
708
  return { action: "end" };
665
709
  }
666
710
  policyStopped ||= params.turnPolicy?.shouldStopAfterTurn(context) ?? false;
711
+ policyCompleted ||= policyStopped && params.turnPolicy?.stopReason?.() === "completed";
712
+ if (policyStopped) policyStopReason ??= "Agent execution policy stopped before completion";
667
713
  if (policyStopped || connectionStopped || clarificationStopped) return { action: "end" };
668
714
  const continuation = params.turnPolicy?.takeContinuationMessage?.();
669
715
  if (continuation) {
@@ -705,10 +751,16 @@ async function runXopcEmbeddedTurnInner(params) {
705
751
  };
706
752
  runAbortSignal.addEventListener("abort", abortListener, { once: true });
707
753
  try {
754
+ if (runAbortSignal.aborted) return {
755
+ ok: false,
756
+ terminationReason: resolveAgentAbortReason(runAbortSignal.reason),
757
+ errorMessage: "aborted"
758
+ };
708
759
  await runAgentTurnWithTimeout(session.agent, () => withDelegationScope({
709
760
  tools,
710
761
  authorizeToolCall: params.turnPolicy ? (context, signal) => runWithEmbeddedExecutionSession(conversationId, () => params.turnPolicy.beforeToolCall(context, signal), runId) : void 0
711
762
  }, async () => {
763
+ if (runAbortSignal.aborted) return;
712
764
  const connectionResume = getConnectionResumeInput(conversationId, runId);
713
765
  const clarificationResume = getClarificationResumeInput(conversationId, runId);
714
766
  if (connectionResume) await session.sendCustomMessage({
@@ -721,7 +773,14 @@ async function runXopcEmbeddedTurnInner(params) {
721
773
  content: clarificationResume.content,
722
774
  display: false
723
775
  }, { triggerTurn: true });
724
- else if (params.resumeLastUserMessage) await session.agent.continue();
776
+ else if (params.recoveryMessage && !params.resumeLastUserMessage) {
777
+ if (!canResumeAfterModelFailure(session.agent.state.messages, ["acceptance_repair", "model_failure"].includes(params.recoveryReason ?? "") ? { allowFailedReadTools: ACCEPTANCE_REPAIR_READ_TOOLS } : void 0)) throw new Error("Cannot resume because a tool outcome is unconfirmed");
778
+ await session.sendCustomMessage({
779
+ customType: "task_continuation",
780
+ content: params.recoveryMessage,
781
+ display: false
782
+ }, { triggerTurn: true });
783
+ } else if (params.resumeLastUserMessage) await session.agent.continue();
725
784
  else {
726
785
  const text = userMessageToPromptText(userMessage);
727
786
  const images = params.images ?? [];
@@ -730,25 +789,47 @@ async function runXopcEmbeddedTurnInner(params) {
730
789
  await session.agent.waitForIdle();
731
790
  clarificationStopped ||= isClarificationSuspended(conversationId, runId);
732
791
  if (connectionStopped || clarificationStopped) return;
733
- await maybeRetryTurnAfterTransientLlmFailure(session.agent, {
734
- conversationId,
735
- log,
736
- signal: runAbortSignal
737
- });
738
- await maybeRecoverInterruptedContext({
739
- agent: session.agent,
740
- model: resolvedModel,
741
- conversationId,
742
- transcriptRuntime,
743
- policy: compactionPolicy,
744
- systemPrompt: [systemPrompt, rootInstructions].filter(Boolean).join("\n\n"),
745
- abortSignal: runAbortSignal,
746
- onEvent,
747
- recoveryState,
748
- onContextRecovered: () => {
749
- useAuthoritativeProjection = true;
750
- }
751
- });
792
+ const recoverSettledTurn = async () => {
793
+ if (policyStopped || connectionStopped || clarificationStopped) return;
794
+ await maybeRetryTurnAfterTransientLlmFailure(session.agent, {
795
+ conversationId,
796
+ log,
797
+ signal: runAbortSignal,
798
+ budget: requestRetryBudget,
799
+ shouldRetry: () => !policyStopped && !connectionStopped && !clarificationStopped,
800
+ onRetry: () => {
801
+ recoveringModel = true;
802
+ recoveryMessages = [...session.agent.state.messages];
803
+ }
804
+ });
805
+ if (policyStopped || connectionStopped || clarificationStopped) return;
806
+ if (await maybeRecoverInterruptedContext({
807
+ agent: session.agent,
808
+ model: resolvedModel,
809
+ conversationId,
810
+ transcriptRuntime,
811
+ policy: compactionPolicy,
812
+ systemPrompt: [systemPrompt, rootInstructions].filter(Boolean).join("\n\n"),
813
+ abortSignal: runAbortSignal,
814
+ onEvent,
815
+ recoveryState,
816
+ onContextRecovered: () => {
817
+ useAuthoritativeProjection = true;
818
+ recoveringModel = true;
819
+ }
820
+ })) await maybeRetryTurnAfterTransientLlmFailure(session.agent, {
821
+ conversationId,
822
+ log,
823
+ signal: runAbortSignal,
824
+ budget: requestRetryBudget,
825
+ shouldRetry: () => !policyStopped && !connectionStopped && !clarificationStopped,
826
+ onRetry: () => {
827
+ recoveringModel = true;
828
+ recoveryMessages = [...session.agent.state.messages];
829
+ }
830
+ });
831
+ };
832
+ await recoverSettledTurn();
752
833
  if (params.requireVisibleReply && !sentVisibleMessage && !policyStopped && !runAbortSignal.aborted && !isAssistantTurnFailed(session.agent) && !isAssistantTurnAborted(session.agent) && lastAssistantPlainText(session).trim() === "NO_REPLY") {
753
834
  await session.sendCustomMessage({
754
835
  customType: "visible_reply_required",
@@ -756,6 +837,7 @@ async function runXopcEmbeddedTurnInner(params) {
756
837
  display: false
757
838
  }, { triggerTurn: true });
758
839
  await session.agent.waitForIdle();
840
+ await recoverSettledTurn();
759
841
  }
760
842
  const pending = await verification.pendingContext();
761
843
  if ((params.verifyChanges ?? false) && pending && !policyStopped && !runAbortSignal.aborted && !isAssistantTurnFailed(session.agent) && !isAssistantTurnAborted(session.agent)) {
@@ -765,8 +847,9 @@ async function runXopcEmbeddedTurnInner(params) {
765
847
  display: false
766
848
  }, { triggerTurn: true });
767
849
  await session.agent.waitForIdle();
850
+ await recoverSettledTurn();
768
851
  }
769
- }), timeoutMs);
852
+ }), timeoutMs, { timeoutExtensionMs: params.timeoutExtensionMs });
770
853
  if (connectionStopped) runner.piSm.appendCustomEntry("connection_required", {
771
854
  runId,
772
855
  conversationId
@@ -784,14 +867,27 @@ async function runXopcEmbeddedTurnInner(params) {
784
867
  if (runAbortSignal.aborted) return {
785
868
  ok: false,
786
869
  retryable: false,
870
+ terminationReason: resolveAgentAbortReason(runAbortSignal.reason),
787
871
  errorMessage: "aborted"
788
872
  };
789
873
  if (isAssistantTurnAborted(session.agent)) return {
790
- ok: true,
874
+ ok: false,
875
+ retryable: false,
876
+ terminationReason: "provider_error",
877
+ errorMessage: "aborted",
878
+ lastAssistantText: lastAssistantPlainText(session)
879
+ };
880
+ if (policyStopped && !policyCompleted || lengthRecoveryExhausted || lastAssistantMessage(session.agent.state.messages)?.stopReason === "length") return {
881
+ ok: false,
882
+ retryable: false,
883
+ errorMessage: policyStopReason ?? "Assistant response was truncated before completion",
884
+ stopReason: policyStopped ? "policy_limit" : "response_truncated",
791
885
  lastAssistantText: lastAssistantPlainText(session)
792
886
  };
793
887
  if (isAssistantTurnFailed(session.agent)) return {
794
888
  ok: false,
889
+ retryable: canResumeAfterModelFailure(session.agent.state.messages, { allowFailedReadTools: ACCEPTANCE_REPAIR_READ_TOOLS }),
890
+ terminationReason: "provider_error",
795
891
  errorMessage: getAssistantTurnErrorMessage(session.agent) ?? "Assistant turn failed",
796
892
  lastAssistantText: lastAssistantPlainText(session)
797
893
  };
@@ -851,6 +947,7 @@ async function runXopcEmbeddedTurnInner(params) {
851
947
  });
852
948
  return {
853
949
  ok: false,
950
+ terminationReason: isAgentTurnTimeoutError(err) ? "deadline_exceeded" : params.abortSignal?.aborted ? resolveAgentAbortReason(params.abortSignal.reason) : "runtime_error",
854
951
  errorMessage: em
855
952
  };
856
953
  } finally {
@@ -18,16 +18,23 @@ export type EmbeddedRunLease = {
18
18
  attach(session: AgentSession, abort: () => Promise<void>): Promise<void>;
19
19
  release(): void;
20
20
  };
21
+ export type EmbeddedRunCancellation = {
22
+ signal: AbortSignal;
23
+ release(): void;
24
+ };
21
25
  /** Owns one process-local execution lease per session while leaving steer/abort on the control plane. */
22
26
  export declare class EmbeddedRunRegistry {
23
27
  private readonly byConversationId;
28
+ private readonly prepared;
29
+ reserveCancellation(identity: Pick<EmbeddedRunIdentity, 'conversationId' | 'runId'>): EmbeddedRunCancellation;
24
30
  acquire(identity: EmbeddedRunIdentity): EmbeddedRunLease;
25
31
  getByConversationId(conversationId: string): EmbeddedRunHandle | undefined;
26
- abortByConversationId(conversationId: string): Promise<boolean>;
32
+ abortByConversationId(conversationId: string, reason?: 'user_cancelled' | 'parent_cancelled', expectedRunId?: string): Promise<boolean>;
27
33
  steerByConversationId(conversationId: string, text: string): Promise<boolean>;
28
34
  size(): number;
29
35
  }
30
36
  export declare function acquireEmbeddedRunLease(identity: EmbeddedRunIdentity): EmbeddedRunLease;
37
+ export declare function reserveEmbeddedRunCancellation(identity: Pick<EmbeddedRunIdentity, 'conversationId' | 'runId'>): EmbeddedRunCancellation;
31
38
  export declare function getEmbeddedRunByConversationId(conversationId: string): EmbeddedRunHandle | undefined;
32
- export declare function abortEmbeddedRun(conversationId: string): Promise<boolean>;
39
+ export declare function abortEmbeddedRun(conversationId: string, reason?: 'user_cancelled' | 'parent_cancelled', expectedRunId?: string): Promise<boolean>;
33
40
  export declare function queueEmbeddedSteer(conversationId: string, text: string): Promise<boolean>;
@@ -1,3 +1,4 @@
1
+ import { AgentRunCancelledError } from "../orchestration/run-termination.js";
1
2
  //#region src/agent/embedded/runs.ts
2
3
  var EmbeddedRunConflictError = class extends Error {
3
4
  constructor(conversationId, activeRunId) {
@@ -10,12 +11,26 @@ var EmbeddedRunConflictError = class extends Error {
10
11
  /** Owns one process-local execution lease per session while leaving steer/abort on the control plane. */
11
12
  var EmbeddedRunRegistry = class {
12
13
  byConversationId = /* @__PURE__ */ new Map();
14
+ prepared = /* @__PURE__ */ new Map();
15
+ reserveCancellation(identity) {
16
+ const key = JSON.stringify([identity.conversationId, identity.runId]);
17
+ if (this.prepared.has(key)) throw new EmbeddedRunConflictError(identity.conversationId, identity.runId);
18
+ const controller = new AbortController();
19
+ this.prepared.set(key, controller);
20
+ return {
21
+ signal: controller.signal,
22
+ release: () => {
23
+ if (this.prepared.get(key) === controller) this.prepared.delete(key);
24
+ }
25
+ };
26
+ }
13
27
  acquire(identity) {
14
28
  const active = this.byConversationId.get(identity.conversationId);
15
29
  if (active) throw new EmbeddedRunConflictError(identity.conversationId, active.runId);
30
+ const controller = this.prepared.get(JSON.stringify([identity.conversationId, identity.runId]));
16
31
  const entry = {
17
32
  ...identity,
18
- abortController: new AbortController()
33
+ abortController: controller ?? new AbortController()
19
34
  };
20
35
  this.byConversationId.set(identity.conversationId, entry);
21
36
  return {
@@ -36,10 +51,15 @@ var EmbeddedRunRegistry = class {
36
51
  getByConversationId(conversationId) {
37
52
  return this.byConversationId.get(conversationId)?.handle;
38
53
  }
39
- async abortByConversationId(conversationId) {
54
+ async abortByConversationId(conversationId, reason = "parent_cancelled", expectedRunId) {
40
55
  const entry = this.byConversationId.get(conversationId);
41
- if (!entry) return false;
42
- entry.abortController.abort(/* @__PURE__ */ new Error("Embedded run aborted"));
56
+ if (!entry || expectedRunId !== void 0 && entry.runId !== expectedRunId) {
57
+ const prepared = expectedRunId === void 0 ? void 0 : this.prepared.get(JSON.stringify([conversationId, expectedRunId]));
58
+ if (!prepared) return false;
59
+ prepared.abort(new AgentRunCancelledError("Embedded run aborted", reason));
60
+ return true;
61
+ }
62
+ entry.abortController.abort(new AgentRunCancelledError("Embedded run aborted", reason));
43
63
  if (entry.handle) await entry.handle.abort();
44
64
  return true;
45
65
  }
@@ -57,14 +77,17 @@ const embeddedRunRegistry = new EmbeddedRunRegistry();
57
77
  function acquireEmbeddedRunLease(identity) {
58
78
  return embeddedRunRegistry.acquire(identity);
59
79
  }
80
+ function reserveEmbeddedRunCancellation(identity) {
81
+ return embeddedRunRegistry.reserveCancellation(identity);
82
+ }
60
83
  function getEmbeddedRunByConversationId(conversationId) {
61
84
  return embeddedRunRegistry.getByConversationId(conversationId);
62
85
  }
63
- function abortEmbeddedRun(conversationId) {
64
- return embeddedRunRegistry.abortByConversationId(conversationId);
86
+ function abortEmbeddedRun(conversationId, reason = "parent_cancelled", expectedRunId) {
87
+ return embeddedRunRegistry.abortByConversationId(conversationId, reason, expectedRunId);
65
88
  }
66
89
  function queueEmbeddedSteer(conversationId, text) {
67
90
  return embeddedRunRegistry.steerByConversationId(conversationId, text);
68
91
  }
69
92
  //#endregion
70
- export { EmbeddedRunConflictError, EmbeddedRunRegistry, abortEmbeddedRun, acquireEmbeddedRunLease, getEmbeddedRunByConversationId, queueEmbeddedSteer };
93
+ export { EmbeddedRunConflictError, EmbeddedRunRegistry, abortEmbeddedRun, acquireEmbeddedRunLease, getEmbeddedRunByConversationId, queueEmbeddedSteer, reserveEmbeddedRunCancellation };