@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,19 @@
1
+ export type SearchFailureKind = 'permission_denied' | 'rate_limited' | 'timeout' | 'cancelled' | 'unsupported_batch' | 'provider_error';
2
+ export interface SearchFailureInfo {
3
+ kind: SearchFailureKind;
4
+ scope: 'request' | 'batch' | 'provider';
5
+ message: string;
6
+ status?: number;
7
+ retryAfterMs?: number;
8
+ }
9
+ /** Only a host adapter may explicitly identify a refusal as batch-only. */
10
+ export declare class SearchError extends Error implements SearchFailureInfo {
11
+ readonly kind: SearchFailureKind;
12
+ readonly scope: 'request' | 'batch' | 'provider';
13
+ readonly status?: number;
14
+ readonly retryAfterMs?: number;
15
+ constructor(info: SearchFailureInfo);
16
+ }
17
+ export declare function classifySearchError(error: unknown, signal?: AbortSignal): SearchError;
18
+ export declare function searchFailureInfo(error: SearchError): SearchFailureInfo;
19
+ export declare function searchHttpError(response: Response, message?: string): SearchError;
@@ -0,0 +1,69 @@
1
+ //#region src/agent/tools/search/errors.ts
2
+ /** Only a host adapter may explicitly identify a refusal as batch-only. */
3
+ var SearchError = class extends Error {
4
+ kind;
5
+ scope;
6
+ status;
7
+ retryAfterMs;
8
+ constructor(info) {
9
+ super(info.message);
10
+ this.name = "SearchError";
11
+ this.kind = info.kind;
12
+ this.scope = info.scope;
13
+ this.status = info.status;
14
+ this.retryAfterMs = info.retryAfterMs;
15
+ }
16
+ };
17
+ function classifySearchError(error, signal) {
18
+ if (signal?.aborted) {
19
+ const reason = signal.reason;
20
+ const timedOut = reason?.name === "TimeoutError" || reason?.code === "deadline_exceeded";
21
+ return new SearchError({
22
+ kind: timedOut ? "timeout" : "cancelled",
23
+ scope: "request",
24
+ message: timedOut ? "Search caller deadline exceeded" : "Search cancelled by its caller"
25
+ });
26
+ }
27
+ if (error instanceof SearchError) return error;
28
+ const value = error;
29
+ const message = error instanceof Error ? error.message : String(error);
30
+ const legacyStatus = /^HTTP (\d{3})\b/.exec(message)?.[1];
31
+ const status = typeof value?.status === "number" ? value.status : typeof value?.statusCode === "number" ? value.statusCode : legacyStatus ? Number(legacyStatus) : void 0;
32
+ const denied = [
33
+ "EACCES",
34
+ "EPERM",
35
+ "PERMISSION_DENIED",
36
+ "permission_denied",
37
+ "ACCESS_DENIED"
38
+ ].includes(String(value?.code)) || /\b(permission denied|access denied|forbidden|unauthorized|not authorized)\b/i.test(message);
39
+ const kind = status === 401 || status === 403 || denied ? "permission_denied" : status === 429 ? "rate_limited" : status === 408 || status === 504 || value?.name === "TimeoutError" || value?.code === "ETIMEDOUT" ? "timeout" : value?.name === "AbortError" ? "cancelled" : "provider_error";
40
+ return new SearchError({
41
+ kind,
42
+ scope: kind === "permission_denied" ? "provider" : "request",
43
+ status,
44
+ message: message.slice(0, 500)
45
+ });
46
+ }
47
+ function searchFailureInfo(error) {
48
+ return {
49
+ kind: error.kind,
50
+ scope: error.scope,
51
+ message: error.message.slice(0, 500),
52
+ status: error.status,
53
+ retryAfterMs: error.retryAfterMs
54
+ };
55
+ }
56
+ function searchHttpError(response, message = `Search request failed (${response.status})`) {
57
+ const retryAfter = response.headers.get("retry-after");
58
+ const seconds = retryAfter === null ? NaN : Number(retryAfter);
59
+ const retryAfterMs = retryAfter === null ? void 0 : Number.isFinite(seconds) ? Math.max(0, seconds * 1e3) : Math.max(0, Date.parse(retryAfter) - Date.now());
60
+ return new SearchError({
61
+ kind: response.status === 401 || response.status === 403 ? "permission_denied" : response.status === 429 ? "rate_limited" : response.status === 408 || response.status === 504 ? "timeout" : "provider_error",
62
+ scope: response.status === 401 || response.status === 403 ? "provider" : "request",
63
+ message: message.slice(0, 500),
64
+ status: response.status,
65
+ retryAfterMs: retryAfterMs !== void 0 && Number.isFinite(retryAfterMs) ? retryAfterMs : void 0
66
+ });
67
+ }
68
+ //#endregion
69
+ export { SearchError, classifySearchError, searchFailureInfo, searchHttpError };
@@ -1,3 +1,4 @@
1
+ import { searchHttpError } from "../errors.js";
1
2
  //#region src/agent/tools/search/providers/bing-api.ts
2
3
  /** Azure Bing Web Search API (global endpoint; works without a proxy from many regions). */
3
4
  var BingApiProvider = class {
@@ -17,7 +18,7 @@ var BingApiProvider = class {
17
18
  headers: { "Ocp-Apim-Subscription-Key": this.apiKey },
18
19
  signal
19
20
  });
20
- if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
21
+ if (!response.ok) throw searchHttpError(response);
21
22
  return ((await response.json()).webPages?.value ?? []).map((r) => ({
22
23
  title: r.name ?? "",
23
24
  url: r.url ?? "",
@@ -1,3 +1,4 @@
1
+ import { searchHttpError } from "../errors.js";
1
2
  import { DEFAULT_HTML_SEARCH_TIMEOUT_MS, HTML_SEARCH_USER_AGENT, mergeAbortWithTimeout } from "../http.js";
2
3
  //#region src/agent/tools/search/providers/bing-html.ts
3
4
  const BING_CN_SEARCH = "https://cn.bing.com/search";
@@ -22,7 +23,7 @@ var BingHtmlProvider = class {
22
23
  "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8"
23
24
  }
24
25
  });
25
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
26
+ if (!response.ok) throw searchHttpError(response);
26
27
  return parseBingCnHtml(await response.text(), count);
27
28
  }
28
29
  };
@@ -1,3 +1,4 @@
1
+ import { searchHttpError } from "../errors.js";
1
2
  //#region src/agent/tools/search/providers/brave.ts
2
3
  var BraveProvider = class {
3
4
  name = "brave";
@@ -17,7 +18,7 @@ var BraveProvider = class {
17
18
  },
18
19
  signal
19
20
  });
20
- if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
21
+ if (!response.ok) throw searchHttpError(response);
21
22
  return ((await response.json()).web?.results ?? []).map((r) => ({
22
23
  title: r.title ?? "",
23
24
  url: r.url ?? "",
@@ -1,3 +1,4 @@
1
+ import { searchHttpError } from "../errors.js";
1
2
  import { DEFAULT_HTML_SEARCH_TIMEOUT_MS, HTML_SEARCH_USER_AGENT, mergeAbortWithTimeout } from "../http.js";
2
3
  //#region src/agent/tools/search/providers/duckduckgo-html.ts
3
4
  const DDG_HTML = "https://html.duckduckgo.com/html/";
@@ -23,7 +24,7 @@ var DuckDuckGoHtmlProvider = class {
23
24
  },
24
25
  body: body.toString()
25
26
  });
26
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
27
+ if (!response.ok) throw searchHttpError(response);
27
28
  return parseDdgHtml(await response.text(), count);
28
29
  }
29
30
  };
@@ -1,3 +1,4 @@
1
+ import { searchHttpError } from "../errors.js";
1
2
  //#region src/agent/tools/search/providers/searxng.ts
2
3
  var SearXNGProvider = class {
3
4
  name = "searxng";
@@ -14,7 +15,7 @@ var SearXNGProvider = class {
14
15
  url.searchParams.set("format", "json");
15
16
  url.searchParams.set("categories", "general");
16
17
  const response = await fetch(url, { signal });
17
- if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
18
+ if (!response.ok) throw searchHttpError(response);
18
19
  return ((await response.json()).results ?? []).slice(0, count).map((r) => ({
19
20
  title: r.title ?? "",
20
21
  url: r.url ?? "",
@@ -1,3 +1,4 @@
1
+ import { searchHttpError } from "../errors.js";
1
2
  //#region src/agent/tools/search/providers/tavily.ts
2
3
  var TavilyProvider = class {
3
4
  name = "tavily";
@@ -20,7 +21,7 @@ var TavilyProvider = class {
20
21
  }),
21
22
  signal
22
23
  });
23
- if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
24
+ if (!response.ok) throw searchHttpError(response);
24
25
  return ((await response.json()).results ?? []).map((r) => ({
25
26
  title: r.title ?? "",
26
27
  url: r.url ?? "",
@@ -14,6 +14,7 @@ export declare class XopcCloudSearchProvider implements SearchProvider {
14
14
  private readonly catalogStore;
15
15
  private readonly credentials;
16
16
  constructor(options: XopcCloudSearchProviderOptions);
17
+ cacheIdentity(): string;
17
18
  isAvailable(): boolean;
18
19
  search(query: string, count: number, signal?: AbortSignal): Promise<SearchResult[]>;
19
20
  }
@@ -1,5 +1,6 @@
1
1
  import { getModelCatalogStore, init_model_catalog_store } from "../../../../providers/model-catalog-store.js";
2
2
  import { getProviderAuthService, init_provider_auth_service } from "../../../../providers/provider-auth-service.js";
3
+ import { searchHttpError } from "../errors.js";
3
4
  //#region src/agent/tools/search/providers/xopc-cloud.ts
4
5
  init_model_catalog_store();
5
6
  init_provider_auth_service();
@@ -14,6 +15,10 @@ var XopcCloudSearchProvider = class {
14
15
  this.catalogStore = options.catalogStore ?? getModelCatalogStore();
15
16
  this.credentials = options.credentials ?? getProviderAuthService();
16
17
  }
18
+ cacheIdentity() {
19
+ const source = this.catalogStore.getSource("xopc-cloud");
20
+ return JSON.stringify([source?.baseUrl, source?.search]);
21
+ }
17
22
  isAvailable() {
18
23
  return Boolean(this.catalogStore.getSource("xopc-cloud")?.search);
19
24
  }
@@ -22,7 +27,7 @@ var XopcCloudSearchProvider = class {
22
27
  if (!source?.search) throw new Error("XOPC Cloud search is not available");
23
28
  const requestSignal = signal ? AbortSignal.any([signal, AbortSignal.timeout(3e4)]) : AbortSignal.timeout(3e4);
24
29
  const accessToken = await this.credentials.resolveApiKey("xopc-cloud", requestSignal);
25
- if (!accessToken) throw new Error("XOPC Cloud is not connected");
30
+ if (!accessToken) throw searchHttpError(new Response(null, { status: 401 }), "XOPC Cloud is not connected");
26
31
  const endpoint = `${source.baseUrl.replace(/\/+$/, "")}/${source.search.endpoint.replace(/^\/+/, "")}`;
27
32
  const response = await this.fetchImpl(endpoint, {
28
33
  method: "POST",
@@ -39,7 +44,7 @@ var XopcCloudSearchProvider = class {
39
44
  signal: requestSignal
40
45
  });
41
46
  const body = await response.json().catch(() => null);
42
- if (!response.ok) throw new Error(typeof body?.error?.message === "string" ? body.error.message : `XOPC Cloud search failed (${response.status})`);
47
+ if (!response.ok) throw searchHttpError(response, typeof body?.error?.message === "string" ? body.error.message : `XOPC Cloud search failed (${response.status})`);
43
48
  if (!Array.isArray(body?.results)) throw new Error("XOPC Cloud search returned an invalid response");
44
49
  return body.results.flatMap((result) => {
45
50
  if (typeof result.title !== "string" || typeof result.url !== "string" || typeof result.description !== "string") return [];
@@ -1,14 +1,30 @@
1
- import type { ResolvedWebSearchConfig, SearchProvider, SearchResult } from './types.js';
1
+ import { type SearchCache } from './cache.js';
2
+ import type { ResolvedWebSearchConfig, SearchProvider, SearchResponse, SearchRequest, SearchBatchResponse } from './types.js';
2
3
  export declare class SearchProviderRegistry {
3
4
  private readonly providers;
4
5
  private readonly fallbackProvider;
6
+ private readonly cache;
7
+ private readonly cachePrefix;
8
+ private readonly requestTimeoutMs;
9
+ private readonly retryDelayMs;
10
+ sourceRequests: number;
11
+ private readonly cooldowns;
5
12
  constructor(config: ResolvedWebSearchConfig, options?: {
6
13
  cloudProvider?: SearchProvider;
14
+ providers?: SearchProvider[];
15
+ fallbackProvider?: SearchProvider | null;
16
+ cache?: SearchCache;
17
+ requestTimeoutMs?: number;
18
+ retryDelayMs?: number;
7
19
  });
8
20
  private buildProviders;
9
21
  hasConfiguredApiProvider(): boolean;
10
- search(query: string, count: number, signal?: AbortSignal): Promise<{
11
- results: SearchResult[];
12
- provider: string;
13
- }>;
22
+ private key;
23
+ private cached;
24
+ private remember;
25
+ private attempt;
26
+ private backoff;
27
+ search(query: string, count: number, signal?: AbortSignal, authorize?: () => void): Promise<SearchResponse>;
28
+ /** Only unfinished, non-denied items degrade to sequential authorized searches. */
29
+ searchBatch(requests: SearchRequest[], signal?: AbortSignal, authorize?: () => void): Promise<SearchBatchResponse[]>;
14
30
  }
@@ -1,5 +1,8 @@
1
1
  import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
+ import { executeWithTimeout } from "../../lifecycle/timeout-wrapper.js";
4
+ import { SearchError, classifySearchError, searchFailureInfo } from "./errors.js";
5
+ import { SearchCacheWriteError, currentSearchCache } from "./cache.js";
3
6
  import { BraveProvider } from "./providers/brave.js";
4
7
  import { TavilyProvider } from "./providers/tavily.js";
5
8
  import { BingApiProvider } from "./providers/bing-api.js";
@@ -7,15 +10,40 @@ import { BingHtmlProvider } from "./providers/bing-html.js";
7
10
  import { DuckDuckGoHtmlProvider } from "./providers/duckduckgo-html.js";
8
11
  import { SearXNGProvider } from "./providers/searxng.js";
9
12
  import { XopcCloudSearchProvider } from "./providers/xopc-cloud.js";
13
+ import { createHash } from "node:crypto";
14
+ import { setTimeout } from "node:timers/promises";
10
15
  //#region src/agent/tools/search/registry.ts
11
16
  init_logger();
12
17
  const log = createLogger("Agent:WebSearch");
13
18
  var SearchProviderRegistry = class {
14
19
  providers;
15
20
  fallbackProvider;
21
+ cache;
22
+ cachePrefix;
23
+ requestTimeoutMs;
24
+ retryDelayMs;
25
+ sourceRequests = 0;
26
+ cooldowns = /* @__PURE__ */ new Map();
16
27
  constructor(config, options = {}) {
17
- this.providers = this.buildProviders(config, options.cloudProvider);
18
- this.fallbackProvider = config.region === "cn" ? new BingHtmlProvider() : new DuckDuckGoHtmlProvider();
28
+ this.providers = options.providers ?? this.buildProviders(config, options.cloudProvider);
29
+ this.fallbackProvider = options.fallbackProvider === void 0 ? config.region === "cn" ? new BingHtmlProvider() : new DuckDuckGoHtmlProvider() : options.fallbackProvider;
30
+ const cache = /* @__PURE__ */ new Map();
31
+ this.cache = options.cache ?? currentSearchCache() ?? {
32
+ get: (key) => cache.get(key),
33
+ set: (entry) => {
34
+ if (JSON.stringify(entry).length > 2e5) return;
35
+ cache.delete(entry.key);
36
+ cache.set(entry.key, entry);
37
+ while (cache.size > 20) cache.delete(cache.keys().next().value);
38
+ }
39
+ };
40
+ this.cachePrefix = createHash("sha256").update(JSON.stringify([
41
+ config,
42
+ this.providers.map((provider) => [provider.name, provider.cacheIdentity?.()]),
43
+ this.fallbackProvider?.name
44
+ ])).digest("hex");
45
+ this.requestTimeoutMs = options.requestTimeoutMs ?? 1e4;
46
+ this.retryDelayMs = options.retryDelayMs ?? 300;
19
47
  log.debug({
20
48
  region: config.region,
21
49
  configuredCount: this.providers.filter((p) => p.isAvailable()).length
@@ -50,33 +78,232 @@ var SearchProviderRegistry = class {
50
78
  hasConfiguredApiProvider() {
51
79
  return this.providers.some((p) => p.isAvailable());
52
80
  }
53
- async search(query, count, signal) {
54
- for (const provider of this.providers) {
81
+ key(query, count) {
82
+ return createHash("sha256").update(JSON.stringify([
83
+ this.cachePrefix,
84
+ query.trim(),
85
+ count
86
+ ])).digest("hex");
87
+ }
88
+ cached(query, count) {
89
+ const cached = this.cache.get(this.key(query, count));
90
+ return cached && Date.now() >= cached.capturedAt && Date.now() - cached.capturedAt < 6e5 ? {
91
+ results: structuredClone(cached.results),
92
+ provider: cached.provider,
93
+ cached: true,
94
+ capturedAt: cached.capturedAt
95
+ } : void 0;
96
+ }
97
+ remember(query, count, response) {
98
+ try {
99
+ this.cache.set({
100
+ key: this.key(query, count),
101
+ query: query.trim(),
102
+ count,
103
+ results: structuredClone(response.results),
104
+ provider: response.provider,
105
+ capturedAt: response.capturedAt ?? Date.now()
106
+ });
107
+ } catch (error) {
108
+ throw new SearchCacheWriteError(error);
109
+ }
110
+ }
111
+ async attempt(name, signal, execute) {
112
+ signal?.throwIfAborted();
113
+ this.sourceRequests++;
114
+ const controller = new AbortController();
115
+ const abort = () => controller.abort(signal?.reason);
116
+ signal?.addEventListener("abort", abort, { once: true });
117
+ try {
118
+ return await executeWithTimeout(() => execute(controller.signal), {
119
+ toolName: `web_search:${name}`,
120
+ timeoutMs: this.requestTimeoutMs,
121
+ signal,
122
+ onTimeout: (error) => controller.abort(error)
123
+ });
124
+ } catch (error) {
125
+ throw classifySearchError(error, signal);
126
+ } finally {
127
+ signal?.removeEventListener("abort", abort);
128
+ }
129
+ }
130
+ async backoff(error, signal) {
131
+ const waitMs = error.retryAfterMs ?? this.retryDelayMs;
132
+ if (waitMs > 2e3) return false;
133
+ await setTimeout(Math.max(0, waitMs), void 0, { signal });
134
+ return true;
135
+ }
136
+ async search(query, count, signal, authorize = () => {}) {
137
+ signal?.throwIfAborted();
138
+ authorize();
139
+ const hit = this.cached(query, count);
140
+ if (hit) return hit;
141
+ let lastError;
142
+ for (const provider of [...this.providers, ...this.fallbackProvider ? [this.fallbackProvider] : []]) {
143
+ signal?.throwIfAborted();
144
+ authorize();
55
145
  if (!provider.isAvailable()) continue;
56
- try {
57
- return {
58
- results: await provider.search(query, count, signal),
59
- provider: provider.name
60
- };
61
- } catch (err) {
62
- log.debug({
63
- provider: provider.name,
64
- err
65
- }, "Search provider failed, trying next");
146
+ const cooldown = this.cooldowns.get(provider.name);
147
+ if (cooldown && cooldown.until > Date.now()) {
148
+ lastError = cooldown.error;
149
+ continue;
150
+ }
151
+ for (let attempt = 0; attempt < 2; attempt++) {
152
+ signal?.throwIfAborted();
153
+ authorize();
154
+ try {
155
+ const results = await this.attempt(provider.name, signal, (requestSignal) => provider.search(query, count, requestSignal));
156
+ signal?.throwIfAborted();
157
+ authorize();
158
+ const response = {
159
+ results,
160
+ provider: provider.name,
161
+ capturedAt: Date.now()
162
+ };
163
+ this.remember(query, count, response);
164
+ return response;
165
+ } catch (error) {
166
+ if (error instanceof SearchCacheWriteError) throw error;
167
+ const failure = classifySearchError(error, signal);
168
+ if (signal?.aborted || failure.kind === "permission_denied" || failure.kind === "cancelled") throw failure;
169
+ lastError = failure;
170
+ if (failure.kind === "rate_limited") this.cooldowns.set(provider.name, {
171
+ until: Date.now() + (failure.retryAfterMs ?? this.retryDelayMs),
172
+ error: failure
173
+ });
174
+ log.debug({
175
+ provider: provider.name,
176
+ kind: failure.kind,
177
+ attempt
178
+ }, "Search provider attempt failed");
179
+ if (attempt || !["rate_limited", "timeout"].includes(failure.kind) || !await this.backoff(failure, signal)) break;
180
+ }
66
181
  }
67
182
  }
68
- try {
69
- return {
70
- results: await this.fallbackProvider.search(query, count, signal),
71
- provider: this.fallbackProvider.name
72
- };
73
- } catch (err) {
74
- log.warn({ err }, "HTML fallback search failed");
75
- return {
76
- results: [],
77
- provider: "none"
78
- };
183
+ throw lastError ?? new SearchError({
184
+ kind: "provider_error",
185
+ scope: "request",
186
+ message: "No search provider is available"
187
+ });
188
+ }
189
+ /** Only unfinished, non-denied items degrade to sequential authorized searches. */
190
+ async searchBatch(requests, signal, authorize = () => {}) {
191
+ if (!requests.length || requests.length > 8 || new Set(requests.map((request) => request.id)).size !== requests.length) throw new Error("Invalid search batch");
192
+ signal?.throwIfAborted();
193
+ authorize();
194
+ const outputs = /* @__PURE__ */ new Map();
195
+ const unique = /* @__PURE__ */ new Map();
196
+ for (const request of requests) {
197
+ const hit = this.cached(request.query, request.count);
198
+ if (hit) outputs.set(this.key(request.query, request.count), {
199
+ ...request,
200
+ response: hit
201
+ });
202
+ else unique.set(this.key(request.query, request.count), request);
203
+ }
204
+ const pending = [...unique.values()];
205
+ const provider = this.providers.find((provider) => provider.isAvailable() && (this.cooldowns.get(provider.name)?.until ?? 0) <= Date.now());
206
+ const itemFailures = /* @__PURE__ */ new Map();
207
+ if (pending.length > 1 && provider?.searchBatch) try {
208
+ authorize();
209
+ const items = await this.attempt(provider.name, signal, (requestSignal) => provider.searchBatch(pending, requestSignal));
210
+ const ids = new Set(pending.map((request) => request.id));
211
+ if (items.some((item) => !ids.has(item.id)) || new Set(items.map((item) => item.id)).size !== items.length) throw new Error("Invalid batch search response ids");
212
+ signal?.throwIfAborted();
213
+ authorize();
214
+ let providerRefusal;
215
+ for (const request of pending) {
216
+ const item = items.find((item) => item.id === request.id);
217
+ if (item?.results && !item.error) {
218
+ const response = {
219
+ results: item.results,
220
+ provider: provider.name,
221
+ capturedAt: Date.now()
222
+ };
223
+ this.remember(request.query, request.count, response);
224
+ outputs.set(this.key(request.query, request.count), {
225
+ ...request,
226
+ response
227
+ });
228
+ } else if (item?.error) {
229
+ if (item.error.kind === "permission_denied" && item.error.scope === "provider") providerRefusal = new SearchError(item.error);
230
+ if (["permission_denied", "cancelled"].includes(item.error.kind) && item.error.scope !== "batch") outputs.set(this.key(request.query, request.count), {
231
+ ...request,
232
+ error: item.error
233
+ });
234
+ else {
235
+ const failure = new SearchError(item.error);
236
+ itemFailures.set(this.key(request.query, request.count), failure);
237
+ if (failure.kind === "rate_limited") this.cooldowns.set(provider.name, {
238
+ until: Date.now() + (failure.retryAfterMs ?? this.retryDelayMs),
239
+ error: failure
240
+ });
241
+ }
242
+ }
243
+ }
244
+ if (providerRefusal) for (const request of pending) {
245
+ const key = this.key(request.query, request.count);
246
+ if (!outputs.has(key)) outputs.set(key, {
247
+ ...request,
248
+ error: searchFailureInfo(providerRefusal)
249
+ });
250
+ }
251
+ } catch (error) {
252
+ if (error instanceof SearchCacheWriteError) throw error;
253
+ const batchFailure = classifySearchError(error, signal);
254
+ if (signal?.aborted || batchFailure.kind === "permission_denied" && batchFailure.scope !== "batch" || batchFailure.kind === "cancelled") for (const request of pending) outputs.set(this.key(request.query, request.count), {
255
+ ...request,
256
+ error: searchFailureInfo(batchFailure)
257
+ });
258
+ else if (batchFailure.kind === "rate_limited") {
259
+ this.cooldowns.set(provider.name, {
260
+ until: Date.now() + (batchFailure.retryAfterMs ?? this.retryDelayMs),
261
+ error: batchFailure
262
+ });
263
+ if (!await this.backoff(batchFailure, signal)) for (const request of pending) outputs.set(this.key(request.query, request.count), {
264
+ ...request,
265
+ error: searchFailureInfo(batchFailure)
266
+ });
267
+ }
268
+ }
269
+ for (const request of pending) {
270
+ const key = this.key(request.query, request.count);
271
+ if (outputs.has(key)) continue;
272
+ try {
273
+ const itemFailure = itemFailures.get(key);
274
+ if (itemFailure?.kind === "rate_limited" && !await this.backoff(itemFailure, signal)) {
275
+ outputs.set(key, {
276
+ ...request,
277
+ error: searchFailureInfo(itemFailure)
278
+ });
279
+ continue;
280
+ }
281
+ const response = await this.search(request.query, request.count, signal, authorize);
282
+ outputs.set(key, {
283
+ ...request,
284
+ response,
285
+ ...provider?.searchBatch ? { fallback: "individual" } : {}
286
+ });
287
+ } catch (error) {
288
+ const failure = classifySearchError(error, signal);
289
+ outputs.set(key, {
290
+ ...request,
291
+ error: searchFailureInfo(failure),
292
+ ...provider?.searchBatch ? { fallback: "individual" } : {}
293
+ });
294
+ if (failure.kind === "permission_denied" && failure.scope === "provider") for (const remaining of pending) {
295
+ const remainingKey = this.key(remaining.query, remaining.count);
296
+ if (!outputs.has(remainingKey)) outputs.set(remainingKey, {
297
+ ...remaining,
298
+ error: searchFailureInfo(failure)
299
+ });
300
+ }
301
+ }
79
302
  }
303
+ return requests.map((request) => ({
304
+ ...outputs.get(this.key(request.query, request.count)),
305
+ ...request
306
+ }));
80
307
  }
81
308
  };
82
309
  //#endregion
@@ -1,3 +1,4 @@
1
+ import type { SearchFailureInfo } from './errors.js';
1
2
  export interface SearchResult {
2
3
  title: string;
3
4
  url: string;
@@ -8,7 +9,10 @@ export interface SearchResult {
8
9
  export interface SearchProvider {
9
10
  name: string;
10
11
  isAvailable(): boolean;
12
+ cacheIdentity?(): string;
11
13
  search(query: string, count: number, signal?: AbortSignal): Promise<SearchResult[]>;
14
+ /** Optional host-implemented batch transport; ids must be echoed for partial results. */
15
+ searchBatch?(requests: SearchRequest[], signal?: AbortSignal): Promise<SearchBatchItem[]>;
12
16
  }
13
17
  export interface ResolvedSearchProviderEntry {
14
18
  type: 'brave' | 'tavily' | 'bing' | 'searxng';
@@ -22,3 +26,24 @@ export interface ResolvedWebSearchConfig {
22
26
  maxResults: number;
23
27
  providers: ResolvedSearchProviderEntry[];
24
28
  }
29
+ export interface SearchRequest {
30
+ id: string;
31
+ query: string;
32
+ count: number;
33
+ }
34
+ export interface SearchBatchItem {
35
+ id: string;
36
+ results?: SearchResult[];
37
+ error?: SearchFailureInfo;
38
+ }
39
+ export interface SearchResponse {
40
+ results: SearchResult[];
41
+ provider: string;
42
+ cached?: boolean;
43
+ capturedAt?: number;
44
+ }
45
+ export interface SearchBatchResponse extends SearchRequest {
46
+ response?: SearchResponse;
47
+ error?: SearchFailureInfo;
48
+ fallback?: 'individual';
49
+ }
@@ -0,0 +1,16 @@
1
+ import type { AgentTool } from '@earendil-works/pi-agent-core';
2
+ import { type XopcUseToolDeps } from './xopc-use-tool.js';
3
+ declare const Schema: import("@sinclair/typebox").TObject<{
4
+ command: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"get">, import("@sinclair/typebox").TLiteral<"post">]>;
5
+ section: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"collaboration">, import("@sinclair/typebox").TLiteral<"task">]>>;
6
+ kind: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"progress">, import("@sinclair/typebox").TLiteral<"question">, import("@sinclair/typebox").TLiteral<"ack">]>>;
7
+ body: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
8
+ causationId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
9
+ entryId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
10
+ afterSequence: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
11
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TInteger>;
12
+ idempotencyKey: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
13
+ }>;
14
+ /** Collaboration only: no product mutations, connection selection or external operations. */
15
+ export declare function createTaskCollaborationTool(deps: XopcUseToolDeps): AgentTool<typeof Schema>;
16
+ export {};