@xopcai/xopc 0.0.387 → 0.0.389

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 (248) hide show
  1. package/dist/browser-ext/_locales/en/messages.json +6 -1
  2. package/dist/browser-ext/_locales/zh_CN/messages.json +6 -1
  3. package/dist/browser-ext/dist/assets/{page-context-BeworyNB.js → page-context-A5RCibM_.js} +1 -1
  4. package/dist/browser-ext/dist/background.js +1 -1
  5. package/dist/browser-ext/dist/sidepanel.html +1 -1
  6. package/dist/browser-ext/dist/sidepanel.js +98 -53
  7. package/dist/browser-ext/manifest.json +1 -1
  8. package/dist/extensions/telegram/src/plugin.js +5 -3
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/gateway/static/root/assets/{activity-store-CB2X4Gmu.js → activity-store-dvik6t7Z.js} +1 -1
  11. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Bv8M5ygD.js → agent-avatar-dicebear-bWMd5TDC.js} +1 -1
  12. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-UBy01-65.js → agent-defaults-settings-panel-Ds0Ue2FB.js} +1 -1
  13. package/dist/gateway/static/root/assets/{agent-plugin-dialog-Q9guA8kU.js → agent-plugin-dialog-UunIxc1q.js} +1 -1
  14. package/dist/gateway/static/root/assets/{agents-yfJFubD0.js → agents-BLRM4o-U.js} +3 -3
  15. package/dist/gateway/static/root/assets/{agents-admin-api-BkULgC6Q.js → agents-admin-api-BlNGyXpm.js} +1 -1
  16. package/dist/gateway/static/root/assets/{app-management-settings-panel-Cdyad8c1.js → app-management-settings-panel-Dmy828Pe.js} +1 -1
  17. package/dist/gateway/static/root/assets/{appearance-settings-DPPvnKH_.js → appearance-settings-CUAdx44v.js} +1 -1
  18. package/dist/gateway/static/root/assets/{apps-page-Bn_jwaeA.js → apps-page-D5zDB6gp.js} +1 -1
  19. package/dist/gateway/static/root/assets/{archive-plugin-De0ND0oA.js → archive-plugin-Du6dJNcl.js} +1 -1
  20. package/dist/gateway/static/root/assets/{automations-page-CAB2sLJ5.js → automations-page-BO8Ig5Z4.js} +1 -1
  21. package/dist/gateway/static/root/assets/{automations-workspace-CYRUhhH4.js → automations-workspace-UcCneEs3.js} +1 -1
  22. package/dist/gateway/static/root/assets/{binary-plugins-Do535ZGW.js → binary-plugins-D7VJjwnr.js} +1 -1
  23. package/dist/gateway/static/root/assets/{block-editor-B9DmMEa8.js → block-editor-CaJlWTAn.js} +1 -1
  24. package/dist/gateway/static/root/assets/{browser-automation-inputs-B9M1RYTm.js → browser-automation-inputs-iyMBJmQX.js} +1 -1
  25. package/dist/gateway/static/root/assets/{browser-automations-page-BHAWpZE2.js → browser-automations-page-BjvQnYfO.js} +1 -1
  26. package/dist/gateway/static/root/assets/{browser-settings-page-BG_17NcQ.js → browser-settings-page-D5ZghI28.js} +1 -1
  27. package/dist/gateway/static/root/assets/{capabilities-BX1rCiVm.js → capabilities-CEH1AnXc.js} +1 -1
  28. package/dist/gateway/static/root/assets/{capabilities-CW389yo6.js → capabilities-MCKRMZDK.js} +1 -1
  29. package/dist/gateway/static/root/assets/{capabilities-page-BAnBYWlY.js → capabilities-page-MC8qIrXo.js} +2 -2
  30. package/dist/gateway/static/root/assets/{capabilities-settings-panel-Ca-d6lXk.js → capabilities-settings-panel-Blz3hEzp.js} +1 -1
  31. package/dist/gateway/static/root/assets/{capability-header-actions-B3TL8TcF.js → capability-header-actions-BIA0Lwt5.js} +1 -1
  32. package/dist/gateway/static/root/assets/{channels-BadpS-nq.js → channels-DSg_iCVC.js} +1 -1
  33. package/dist/gateway/static/root/assets/{chat-terminal-dock-C_vntFpP.js → chat-terminal-dock-C97SJEwd.js} +1 -1
  34. package/dist/gateway/static/root/assets/{computer-settings-page-B-5kxk70.js → computer-settings-page-DvY3zgyY.js} +1 -1
  35. package/dist/gateway/static/root/assets/{connector-service-page-DTnfpLHL.js → connector-service-page-St2-Fj3y.js} +1 -1
  36. package/dist/gateway/static/root/assets/connectors-page-DXk-GAsd.js +1 -0
  37. package/dist/gateway/static/root/assets/{date-picker-D5zYeC8q.js → date-picker-C0-D80ny.js} +1 -1
  38. package/dist/gateway/static/root/assets/{dependency-picker-D72vT-tb.js → dependency-picker-CNd7mwMU.js} +1 -1
  39. package/dist/gateway/static/root/assets/{desktop-pet-DvoeVPf_.js → desktop-pet-C-2wDANn.js} +1 -1
  40. package/dist/gateway/static/root/assets/{desktop-pet-settings-Dfb392hs.js → desktop-pet-settings-DyhxLrdJ.js} +1 -1
  41. package/dist/gateway/static/root/assets/{device-pairing-wizard-B06Sqn5D.js → device-pairing-wizard-BeSuq__I.js} +1 -1
  42. package/dist/gateway/static/root/assets/{directory-picker-path-field-CA3H3bc-.js → directory-picker-path-field-CNivVIPT.js} +1 -1
  43. package/dist/gateway/static/root/assets/{extension-debug-page-B0wTBCx4.js → extension-debug-page-CGYO3JPw.js} +1 -1
  44. package/dist/gateway/static/root/assets/{extension-page-BeHiXhB1.js → extension-page-Dc51ALAg.js} +1 -1
  45. package/dist/gateway/static/root/assets/{extension-provider-CJZ5EVpQ.js → extension-provider-BXPILdlw.js} +1 -1
  46. package/dist/gateway/static/root/assets/{extension-settings-page-Q88-LFCJ.js → extension-settings-page-jYu6qpY2.js} +1 -1
  47. package/dist/gateway/static/root/assets/{fallback-models-BXoPCvzq.js → fallback-models-CoyzvDo7.js} +1 -1
  48. package/dist/gateway/static/root/assets/{gateway-config-swr-D0tBjSgj.js → gateway-config-swr-Bc2MytsF.js} +1 -1
  49. package/dist/gateway/static/root/assets/{gateway-realtime-BnHraJ3O.js → gateway-realtime-BFK-vlME.js} +1 -1
  50. package/dist/gateway/static/root/assets/gateway-realtime-store-C3vH-Iup.js +1 -0
  51. package/dist/gateway/static/root/assets/{gateway-settings-IICLMGDI.js → gateway-settings-JlT1dlSj.js} +1 -1
  52. package/dist/gateway/static/root/assets/{gateway-startup-retry-C1DQsIH3.js → gateway-startup-retry-BDPMttPx.js} +1 -1
  53. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-D336so8z.js → highlighted-body-KQOG7T2V-DAlRGMge.js} +1 -1
  54. package/dist/gateway/static/root/assets/{home-page--MvqsFhQ.js → home-page-DOVl8s-1.js} +1 -1
  55. package/dist/gateway/static/root/assets/{image-generation-api-DodU6GNC.js → image-generation-api-BZBiYDmV.js} +1 -1
  56. package/dist/gateway/static/root/assets/{imports-page-muV1SduS.js → imports-page-DgdBTp_0.js} +1 -1
  57. package/dist/gateway/static/root/assets/{index-D0qMv3jf.js → index-CmC8JkSM.js} +108 -108
  58. package/dist/gateway/static/root/assets/index-Dgzc0oBu.css +1 -0
  59. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-i1sDWcwl.js → keyboard-shortcuts-settings-BYYC9Qmw.js} +1 -1
  60. package/dist/gateway/static/root/assets/{local-app-workbench-page-DY9tXEO6.js → local-app-workbench-page-BKZfn-MS.js} +1 -1
  61. package/dist/gateway/static/root/assets/{local-apps-page-BHD73STy.js → local-apps-page-BU8pUsVM.js} +1 -1
  62. package/dist/gateway/static/root/assets/{local-session-drafts-Be4BGM4Z.js → local-session-drafts-kFc_MAA9.js} +1 -1
  63. package/dist/gateway/static/root/assets/{locale-store-uRu_DsWm.js → locale-store-Dr43FCty.js} +1 -1
  64. package/dist/gateway/static/root/assets/{logs-page-DsPpe8Ws.js → logs-page-BSepiACn.js} +1 -1
  65. package/dist/gateway/static/root/assets/{management-settings-Buwi2wQE.js → management-settings-dE_ykPNY.js} +1 -1
  66. package/dist/gateway/static/root/assets/{markdown-view-CBjl-XEc.js → markdown-view-CdKlPjJM.js} +1 -1
  67. package/dist/gateway/static/root/assets/{media-plugins-BombFqsX.js → media-plugins-DE9zt88i.js} +1 -1
  68. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-65SE6j-_.js +1 -0
  69. package/dist/gateway/static/root/assets/messages-DlTNQI92.js +3 -0
  70. package/dist/gateway/static/root/assets/models-hub-cache-C7FAsEe_.js +1 -0
  71. package/dist/gateway/static/root/assets/{note-detail-panel-D8n80Gbr.js → note-detail-panel-D9oqhdyk.js} +3 -3
  72. package/dist/gateway/static/root/assets/{notes-api-BlGP533W.js → notes-api-BHouNL6-.js} +1 -1
  73. package/dist/gateway/static/root/assets/{notes-page-Btf-jSS_.js → notes-page-Bd4_7ph8.js} +1 -1
  74. package/dist/gateway/static/root/assets/{page-context-capture-button-97RL8Gc7.js → page-context-capture-button-TQr8NnSc.js} +1 -1
  75. package/dist/gateway/static/root/assets/{personal-page-B04L8Oz5.js → personal-page-BvWzq4Wp.js} +1 -1
  76. package/dist/gateway/static/root/assets/{product-open-page-9zEDvZa7.js → product-open-page-BEl6syFp.js} +1 -1
  77. package/dist/gateway/static/root/assets/{product-preview-content-DynBrIXq.js → product-preview-content-BxSHnbqz.js} +1 -1
  78. package/dist/gateway/static/root/assets/{project-detail-page-BM7MsoVA.js → project-detail-page-D-qkIXVT.js} +1 -1
  79. package/dist/gateway/static/root/assets/{projects-page-pcyeEJnz.js → projects-page-BQtw1Dfn.js} +1 -1
  80. package/dist/gateway/static/root/assets/{registry-api-CYqA7bfl.js → registry-api-BD5IgDOA.js} +1 -1
  81. package/dist/gateway/static/root/assets/{remote-access-hub-CphyTu22.js → remote-access-hub-CYFNz0Jc.js} +1 -1
  82. package/dist/gateway/static/root/assets/{runtime-tools-api-zzoxjSuR.js → runtime-tools-api-CjTRoQWT.js} +1 -1
  83. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DPafoO0G.js → runtime-tools-settings-panel-Qq_NyYx_.js} +1 -1
  84. package/dist/gateway/static/root/assets/{scenes-page-j97FrDRW.js → scenes-page-hGr-ppYk.js} +1 -1
  85. package/dist/gateway/static/root/assets/{schema-form-CuJNwKHO.js → schema-form-ByG-R6N2.js} +1 -1
  86. package/dist/gateway/static/root/assets/{send-session-input-C293-Hbx.js → send-session-input-UAVStisp.js} +1 -1
  87. package/dist/gateway/static/root/assets/{session-api-CzVTrG8n.js → session-api-DvgEiNRS.js} +1 -1
  88. package/dist/gateway/static/root/assets/session-manager-BOb1tC_Z.js +16 -0
  89. package/dist/gateway/static/root/assets/{sessions-page-D8t_8fMl.js → sessions-page-CpX1Rluw.js} +1 -1
  90. package/dist/gateway/static/root/assets/settings-advanced-gate-D2s_MlxR.js +1 -0
  91. package/dist/gateway/static/root/assets/{settings-page-DS9DMYUe.js → settings-page-C1e9m23j.js} +1 -1
  92. package/dist/gateway/static/root/assets/{setup-status-panel-DRDvm9yZ.js → setup-status-panel-BiHRYDHq.js} +1 -1
  93. package/dist/gateway/static/root/assets/{share-link-dialog-BKGI8Kr0.js → share-link-dialog-kE_6v5Dp.js} +1 -1
  94. package/dist/gateway/static/root/assets/{share-preview-page-BF2WaO43.js → share-preview-page-BT-_yR1h.js} +1 -1
  95. package/dist/gateway/static/root/assets/{shares-api-B0HlMAzi.js → shares-api-Dg_SqHQE.js} +1 -1
  96. package/dist/gateway/static/root/assets/{shares-settings-DQTQZu6V.js → shares-settings-DfcAu08T.js} +1 -1
  97. package/dist/gateway/static/root/assets/{skill-api-DzVa7G-O.js → skill-api-BslUYMnX.js} +1 -1
  98. package/dist/gateway/static/root/assets/{skill-reload-api-CEJx5rPd.js → skill-reload-api-BQ2rTOP1.js} +1 -1
  99. package/dist/gateway/static/root/assets/{skills-page-CfJIjRdS.js → skills-page-CvKc5nBN.js} +1 -1
  100. package/dist/gateway/static/root/assets/{system-settings-panel-Bzhqed-a.js → system-settings-panel-GpbPfWwo.js} +1 -1
  101. package/dist/gateway/static/root/assets/{task-detail-page-BYQFC0-U.js → task-detail-page-5B5ZVAu0.js} +1 -1
  102. package/dist/gateway/static/root/assets/{task-expandable-content-C9ohICpw.js → task-expandable-content-DJrrEBB4.js} +1 -1
  103. package/dist/gateway/static/root/assets/{theme-store-BUfzeDvL.js → theme-store-BKpYnggg.js} +1 -1
  104. package/dist/gateway/static/root/assets/{tracing-settings-page-C2q5B3Kp.js → tracing-settings-page-D71w7dwV.js} +1 -1
  105. package/dist/gateway/static/root/assets/{tunnel-api-DrgpZ81I.js → tunnel-api-BV46CvS8.js} +1 -1
  106. package/dist/gateway/static/root/assets/{usage-page-Drk8FWnj.js → usage-page-rMuwNpJi.js} +1 -1
  107. package/dist/gateway/static/root/assets/{use-autosave-DgbCgsao.js → use-autosave-CzyqRffr.js} +1 -1
  108. package/dist/gateway/static/root/assets/{use-composer-attachments-rgW7h4sD.js → use-composer-attachments-Dviq-1f6.js} +1 -1
  109. package/dist/gateway/static/root/assets/{use-file-preview-expanded-DSKIxfz9.js → use-file-preview-expanded-D5Kk7Hon.js} +2 -2
  110. package/dist/gateway/static/root/assets/{user-model-page-07t2-nFE.js → user-model-page-Dhqw3v_u.js} +1 -1
  111. package/dist/gateway/static/root/assets/{voice-api-key-field-4AIkbm9R.js → voice-api-key-field-DWtbmacd.js} +1 -1
  112. package/dist/gateway/static/root/assets/{voice-config-api-Kw1pYlLN.js → voice-config-api-DnIjZm_9.js} +1 -1
  113. package/dist/gateway/static/root/assets/{work-discovery-overlay-TQ5bjVot.js → work-discovery-overlay-ChEG71hz.js} +1 -1
  114. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C9HP2uGG.js → workflow-run-setup-panel-pdiRKLxP.js} +1 -1
  115. package/dist/gateway/static/root/assets/{workflows-page-DK01JRI1.js → workflows-page-D9LMxINt.js} +1 -1
  116. package/dist/gateway/static/root/assets/{workspace-api-JWHOFos6.js → workspace-api-CZDvu7uA.js} +2 -2
  117. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-B-BhQdAf.js → xopc-cloud-account-card-CbUgg1SK.js} +1 -1
  118. package/dist/gateway/static/root/index.html +27 -27
  119. package/dist/package.js +1 -1
  120. package/dist/packages/gateway-contract/src/clarifications.js +79 -2
  121. package/dist/packages/realtime-protocol/src/voice.js +13 -2
  122. package/dist/src/agent/agent-manager.js +12 -8
  123. package/dist/src/agent/background-review/prompts.js +4 -0
  124. package/dist/src/agent/background-review/run-background-review.js +43 -5
  125. package/dist/src/agent/embedded/run-turn.js +1 -1
  126. package/dist/src/agent/embedded/session-runner.d.ts +4 -3
  127. package/dist/src/agent/embedded/session-runner.js +6 -1
  128. package/dist/src/agent/external-tools/cliProvider.js +1 -1
  129. package/dist/src/agent/external-tools/composio-provider.js +2 -2
  130. package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
  131. package/dist/src/agent/mcp/connection-drafts.d.ts +50 -0
  132. package/dist/src/agent/mcp/connection-drafts.js +278 -0
  133. package/dist/src/agent/mcp/connection-setup.d.ts +5 -2
  134. package/dist/src/agent/mcp/connection-setup.js +7 -5
  135. package/dist/src/agent/mcp/credential-store.d.ts +6 -0
  136. package/dist/src/agent/mcp/credential-store.js +24 -0
  137. package/dist/src/agent/mcp/native-mcp.d.ts +6 -1
  138. package/dist/src/agent/mcp/native-mcp.js +6 -0
  139. package/dist/src/agent/mcp/tool-catalog.d.ts +7 -2
  140. package/dist/src/agent/mcp/tool-catalog.js +25 -15
  141. package/dist/src/agent/service/process-direct-streaming.js +1 -1
  142. package/dist/src/agent/service.js +2 -2
  143. package/dist/src/agent/skills/index.js +1 -1
  144. package/dist/src/agent/skills/managed-store.js +1 -1
  145. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  146. package/dist/src/agent/tools/clarify-tool.d.ts +2 -3
  147. package/dist/src/agent/tools/clarify-tool.js +15 -9
  148. package/dist/src/agent/tools/cli-clarify.d.ts +0 -3
  149. package/dist/src/agent/tools/cli-clarify.js +18 -32
  150. package/dist/src/agent/tools/factory.js +1 -1
  151. package/dist/src/agent/tools/personal-read-tool.js +1 -1
  152. package/dist/src/agent/tools/personal-task-tool.d.ts +4 -4
  153. package/dist/src/agent/tools/xopc-use-tool.js +2 -2
  154. package/dist/src/agent/workspace-runtime/registry.js +1 -1
  155. package/dist/src/agent-catalog/capabilities.js +2 -2
  156. package/dist/src/automations/capabilities/drafts.js +1 -1
  157. package/dist/src/automations/capabilities/write.d.ts +2 -2
  158. package/dist/src/automations/domain/validation.d.ts +6 -6
  159. package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
  160. package/dist/src/automations/service/action-executor.js +1 -1
  161. package/dist/src/bootstrap/application-state.js +1 -1
  162. package/dist/src/capabilities/runtime/dispatcher.js +1 -1
  163. package/dist/src/capabilities/runtime/product.js +1 -1
  164. package/dist/src/chat-commands/agent-edit.js +1 -1
  165. package/dist/src/cli/commands/agent.js +1 -1
  166. package/dist/src/cli/commands/agents.js +1 -1
  167. package/dist/src/cli/commands/models.js +1 -1
  168. package/dist/src/cli/commands/onboard/model.d.ts +1 -1
  169. package/dist/src/cli/commands/onboard/model.js +22 -3
  170. package/dist/src/cli/utils/init-workspace-core.js +1 -1
  171. package/dist/src/config/agent-profile.js +2 -2
  172. package/dist/src/config/loader.js +1 -1
  173. package/dist/src/config/models-json.js +1 -1
  174. package/dist/src/config/schema.d.ts +7 -1
  175. package/dist/src/config/schema.js +3 -1
  176. package/dist/src/extensions/agent-plugins/validation.js +1 -1
  177. package/dist/src/gateway/agents-admin.js +2 -2
  178. package/dist/src/gateway/chat-stream/mapper.js +2 -2
  179. package/dist/src/gateway/chat-stream/protocol.d.ts +2 -3
  180. package/dist/src/gateway/clarify-runtime.d.ts +2 -0
  181. package/dist/src/gateway/clarify-runtime.js +4 -1
  182. package/dist/src/gateway/ephemeral-clarification-waiter.d.ts +2 -1
  183. package/dist/src/gateway/ephemeral-clarification-waiter.js +19 -6
  184. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -1
  185. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  186. package/dist/src/gateway/hono/lib/config-write-lock.d.ts +2 -0
  187. package/dist/src/gateway/hono/lib/config-write-lock.js +14 -0
  188. package/dist/src/gateway/hono/routes/agent-stream.js +4 -9
  189. package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
  190. package/dist/src/gateway/hono/routes/config.js +7 -5
  191. package/dist/src/gateway/hono/routes/connectors.js +1 -1
  192. package/dist/src/gateway/hono/routes/context-sources.js +1 -1
  193. package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -1
  194. package/dist/src/gateway/hono/routes/mcp.js +73 -6
  195. package/dist/src/gateway/hono/routes/notes.js +2 -2
  196. package/dist/src/gateway/hono/routes/projects.js +2 -2
  197. package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
  198. package/dist/src/gateway/hono/routes/side-chats.js +4 -3
  199. package/dist/src/gateway/hono/routes/tasks.js +1 -1
  200. package/dist/src/gateway/image-generation-setup.js +1 -1
  201. package/dist/src/gateway/lock.js +1 -1
  202. package/dist/src/gateway/service/agent-runner.d.ts +5 -4
  203. package/dist/src/gateway/service/agent-runner.js +32 -16
  204. package/dist/src/gateway/service/config-coordinator.d.ts +619 -1
  205. package/dist/src/gateway/service/config-coordinator.js +36 -24
  206. package/dist/src/gateway/service.d.ts +6 -3
  207. package/dist/src/gateway/service.js +5 -4
  208. package/dist/src/gateway/side-chat/run-service.d.ts +2 -1
  209. package/dist/src/gateway/side-chat/run-service.js +6 -3
  210. package/dist/src/gateway/side-chat/types.d.ts +3 -3
  211. package/dist/src/gateway/xopc-cloud-capability-setup.d.ts +2 -2
  212. package/dist/src/gateway/xopc-cloud-capability-setup.js +8 -5
  213. package/dist/src/local-apps/service.js +1 -1
  214. package/dist/src/memory-learning/service.js +3 -2
  215. package/dist/src/personal-agent/proactivity/service.js +1 -1
  216. package/dist/src/personal-agent/service.js +2 -2
  217. package/dist/src/providers/model-catalog-persistence.js +1 -1
  218. package/dist/src/routing/resolve-route.js +1 -1
  219. package/dist/src/routing/resolve-tui-session-key.js +1 -1
  220. package/dist/src/scenes/execution.d.ts +1 -1
  221. package/dist/src/scenes/taskFollowUp/contracts.d.ts +2 -2
  222. package/dist/src/scenes/taskFollowUp/service.d.ts +5 -5
  223. package/dist/src/scenes/templates.d.ts +2 -2
  224. package/dist/src/storage/sqlite/clarification-wait-repository.d.ts +3 -5
  225. package/dist/src/storage/sqlite/clarification-wait-repository.js +48 -28
  226. package/dist/src/tasks/capabilities/management.d.ts +2 -2
  227. package/dist/src/tasks/capabilities/read.js +2 -2
  228. package/dist/src/tasks/capabilities/relations.d.ts +6 -6
  229. package/dist/src/tasks/capabilities/write.d.ts +6 -6
  230. package/dist/src/tasks/capabilities/write.js +1 -1
  231. package/dist/src/tasks/task-handoff-service.js +1 -1
  232. package/dist/src/tui/backends/embedded-backend.js +2 -2
  233. package/dist/src/tui/tui-agent-events.js +1 -1
  234. package/dist/src/user-context/config.d.ts +2 -2
  235. package/dist/src/user-model/capture/semantic.d.ts +8 -1
  236. package/dist/src/user-model/capture/semantic.js +26 -5
  237. package/dist/src/voice/realtime/agentEngine.js +4 -2
  238. package/dist/src/voice/realtime/omniEngine.js +2 -2
  239. package/dist/src/voice/realtime/persona-context.js +1 -1
  240. package/package.json +4 -4
  241. package/dist/gateway/static/root/assets/connectors-page-CmJV7gqj.js +0 -1
  242. package/dist/gateway/static/root/assets/gateway-realtime-store-BVriF6Zj.js +0 -1
  243. package/dist/gateway/static/root/assets/index-DBRwvWzm.css +0 -1
  244. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-D2mip-f9.js +0 -1
  245. package/dist/gateway/static/root/assets/messages-DTqbfje6.js +0 -3
  246. package/dist/gateway/static/root/assets/models-hub-cache-Ct6X5zmB.js +0 -1
  247. package/dist/gateway/static/root/assets/session-manager-COd9RECl.js +0 -16
  248. package/dist/gateway/static/root/assets/settings-advanced-gate-CDkitNHA.js +0 -1
@@ -0,0 +1,278 @@
1
+ import { McpServerSchema, init_schema } from "../../config/schema.js";
2
+ import { getWorkspacePath } from "../../config/workspace-path-helpers.js";
3
+ import { isManagedConnectorServer } from "../../connectors/materialize.js";
4
+ import { createNativeMcpCredentials } from "./credential-store.js";
5
+ import { loadMergedMcpConfig } from "./config.js";
6
+ import { discoverMcpTools } from "./tool-catalog.js";
7
+ import { cancelMcpAuthorization, getMcpAuthorization, probeMcpConnection, startMcpAuthorization, submitMcpRedirect } from "./connection-setup.js";
8
+ import { createHash, randomUUID } from "node:crypto";
9
+ //#region src/agent/mcp/connection-drafts.ts
10
+ init_schema();
11
+ const TTL_MS = 10 * 6e4;
12
+ function canonical(value) {
13
+ if (Array.isArray(value)) return value.map(canonical);
14
+ if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).filter(([, child]) => child !== void 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, child]) => [key, canonical(child)]));
15
+ return value;
16
+ }
17
+ function mcpConfigRevision(value) {
18
+ return createHash("sha256").update(JSON.stringify(canonical(value)) ?? "null").digest("hex");
19
+ }
20
+ var McpDraftError = class extends Error {
21
+ constructor(status, message) {
22
+ super(message);
23
+ this.status = status;
24
+ }
25
+ };
26
+ /** Unsaved configuration and OAuth state belong to one principal and never enter the live registry. */
27
+ var McpConnectionDrafts = class {
28
+ completed = /* @__PURE__ */ new Map();
29
+ drafts = /* @__PURE__ */ new Map();
30
+ constructor(options) {
31
+ this.options = options;
32
+ }
33
+ async create(owner, input) {
34
+ const current = this.options.readConfig();
35
+ if (!/^[a-zA-Z0-9_-]+$/.test(input.serverId) || input.sourceServerId && input.sourceServerId !== input.serverId) throw new McpDraftError(400, "Invalid or changed MCP server ID.");
36
+ const source = Object.hasOwn(current.mcp?.servers ?? {}, input.serverId) ? current.mcp?.servers?.[input.serverId] : void 0;
37
+ if (input.sourceServerId && (!source || isManagedConnectorServer(source))) throw new McpDraftError(409, "The original custom server no longer exists.");
38
+ if (input.sourceServerId && mcpConfigRevision(source) !== mcpConfigRevision(input.expectedServer)) throw new McpDraftError(409, "The original configuration changed. Reload before testing.");
39
+ this.assertAvailable(current, input.serverId, input.sourceServerId);
40
+ const parsed = McpServerSchema.safeParse(input.server);
41
+ if (!parsed.success) throw new McpDraftError(400, "Invalid MCP configuration.");
42
+ const revision = mcpConfigRevision(source);
43
+ const server = structuredClone(parsed.data);
44
+ for (const internal of [
45
+ "xopcConnector",
46
+ "xopcPlugin",
47
+ "xopcOAuthCredentialId",
48
+ "xopcConnectionCheck"
49
+ ]) delete server[internal];
50
+ const workspace = getWorkspacePath(current) || process.cwd();
51
+ const config = structuredClone(current);
52
+ config.mcp = { servers: { [input.serverId]: {
53
+ ...server,
54
+ enabled: true
55
+ } } };
56
+ const credentials = await createNativeMcpCredentials(true);
57
+ if (this.drafts.size >= 100 || [...this.drafts.values()].filter((draft) => draft.owner === owner).length >= 8) throw new McpDraftError(429, "Too many unsaved MCP connection tests.");
58
+ const id = randomUUID();
59
+ const timer = setTimeout(() => {
60
+ const draft = this.drafts.get(id);
61
+ if (draft && !draft.committing) this.dispose(draft);
62
+ }, TTL_MS);
63
+ timer.unref();
64
+ const draft = {
65
+ id,
66
+ owner,
67
+ serverId: input.serverId,
68
+ sourceServerId: input.sourceServerId,
69
+ revision,
70
+ workspace,
71
+ server,
72
+ config,
73
+ credentials,
74
+ controller: new AbortController(),
75
+ timer,
76
+ expiresAt: Date.now() + TTL_MS,
77
+ running: false,
78
+ committing: false
79
+ };
80
+ this.drafts.set(id, draft);
81
+ return {
82
+ id,
83
+ serverId: draft.serverId,
84
+ expiresAt: draft.expiresAt
85
+ };
86
+ }
87
+ async probe(owner, id) {
88
+ const draft = this.get(owner, id);
89
+ this.assertIdle(draft);
90
+ draft.authorizationId = void 0;
91
+ draft.running = true;
92
+ draft.probe = void 0;
93
+ draft.checkedAt = void 0;
94
+ try {
95
+ const result = await probeMcpConnection(draft.config, draft.workspace, draft.serverId, {
96
+ credentials: draft.credentials,
97
+ signal: draft.controller.signal
98
+ });
99
+ this.get(owner, id);
100
+ draft.probe = result;
101
+ if (result.state === "connected") draft.checkedAt = (/* @__PURE__ */ new Date()).toISOString();
102
+ return result;
103
+ } finally {
104
+ draft.running = false;
105
+ }
106
+ }
107
+ authorize(owner, id) {
108
+ const draft = this.get(owner, id);
109
+ this.assertIdle(draft);
110
+ if (draft.authorizationId) cancelMcpAuthorization(draft.authorizationId, owner);
111
+ draft.probe = void 0;
112
+ const attempt = startMcpAuthorization(draft.config, draft.workspace, draft.serverId, owner, {
113
+ credentials: draft.credentials,
114
+ authorizationScope: draft.id
115
+ });
116
+ draft.authorizationId = attempt.id;
117
+ return attempt;
118
+ }
119
+ authorization(owner, id) {
120
+ const draft = this.get(owner, id);
121
+ const result = draft.authorizationId && getMcpAuthorization(draft.authorizationId, owner, draft.config);
122
+ if (!result) throw new McpDraftError(404, "Draft authorization not found.");
123
+ if (result.state === "connected" && draft.probe?.state !== "connected") {
124
+ draft.probe = {
125
+ state: "connected",
126
+ toolCount: result.toolCount
127
+ };
128
+ draft.checkedAt = (/* @__PURE__ */ new Date()).toISOString();
129
+ }
130
+ return result;
131
+ }
132
+ redirect(owner, id, url) {
133
+ const draft = this.get(owner, id);
134
+ if (!draft.authorizationId || !submitMcpRedirect(draft.authorizationId, owner, url, draft.config)) throw new McpDraftError(400, "The callback address does not match this draft authorization.");
135
+ }
136
+ cancelAuthorization(owner, id) {
137
+ const draft = this.get(owner, id);
138
+ if (draft.committing) throw new McpDraftError(409, "This draft is being saved.");
139
+ if (draft.running) throw new McpDraftError(409, "A connection test is still running.");
140
+ if (draft.authorizationId) cancelMcpAuthorization(draft.authorizationId, owner);
141
+ draft.authorizationId = void 0;
142
+ draft.probe = void 0;
143
+ }
144
+ async tools(owner, id) {
145
+ const draft = this.get(owner, id);
146
+ this.assertIdle(draft);
147
+ if (draft.probe?.state !== "connected") throw new McpDraftError(409, "Test the connection first.");
148
+ draft.running = true;
149
+ try {
150
+ const tools = await discoverMcpTools(draft.config, draft.workspace, draft.serverId, {
151
+ credentials: draft.credentials,
152
+ signal: draft.controller.signal
153
+ });
154
+ this.get(owner, id);
155
+ return tools;
156
+ } finally {
157
+ draft.running = false;
158
+ }
159
+ }
160
+ /** Caller serializes this with other Gateway config writes. Only this entry is merged into the latest config. */
161
+ async commit(owner, id, enable = false) {
162
+ const completed = this.completed.get(id);
163
+ if (completed?.owner === owner) {
164
+ if (completed.enable !== enable) throw new McpDraftError(409, "This test has already been committed with different settings.");
165
+ return {
166
+ serverId: completed.serverId,
167
+ ...completed.reloadRequired ? { reloadRequired: true } : {}
168
+ };
169
+ }
170
+ const draft = this.get(owner, id);
171
+ this.assertIdle(draft);
172
+ if (draft.authorizationId) this.authorization(owner, id);
173
+ if (draft.probe?.state !== "connected") throw new McpDraftError(409, "A successful connection test is required before saving.");
174
+ const current = this.options.readConfig();
175
+ if (mcpConfigRevision(current.mcp?.servers?.[draft.serverId]) !== draft.revision || (getWorkspacePath(current) || process.cwd()) !== draft.workspace) throw new McpDraftError(409, "Configuration changed after the test. Reload and test again.");
176
+ this.assertAvailable(current, draft.serverId, draft.sourceServerId);
177
+ draft.committing = true;
178
+ let alias;
179
+ let durable;
180
+ let published = false;
181
+ try {
182
+ const server = structuredClone(draft.server);
183
+ if (enable) server.enabled = true;
184
+ if (server.url) {
185
+ const state = await draft.credentials.forServer(draft.serverId, server.url).load();
186
+ const candidateAlias = `mcp_draft_${randomUUID().replaceAll("-", "")}`;
187
+ durable = await createNativeMcpCredentials();
188
+ await durable.forServer(candidateAlias, server.url).save(state?.tokens ? {
189
+ ...state,
190
+ codeVerifier: void 0,
191
+ oauthState: void 0
192
+ } : { serverUrl: server.url });
193
+ alias = candidateAlias;
194
+ server.xopcOAuthCredentialId = alias;
195
+ }
196
+ server.xopcConnectionCheck = {
197
+ checkedAt: draft.checkedAt,
198
+ toolCount: draft.probe.toolCount ?? 0,
199
+ revision: mcpConfigRevision(server)
200
+ };
201
+ const latest = this.options.readConfig();
202
+ if (mcpConfigRevision(latest.mcp?.servers?.[draft.serverId]) !== draft.revision || (getWorkspacePath(latest) || process.cwd()) !== draft.workspace) throw new McpDraftError(409, "Configuration changed while preparing the save. Test again.");
203
+ this.assertAvailable(latest, draft.serverId, draft.sourceServerId);
204
+ const next = structuredClone(latest);
205
+ next.mcp = {
206
+ ...next.mcp,
207
+ servers: {
208
+ ...next.mcp?.servers,
209
+ [draft.serverId]: server
210
+ }
211
+ };
212
+ const result = await this.options.saveConfig(next, structuredClone(latest));
213
+ published = result.persisted === true || alias !== void 0 && this.options.readConfig().mcp?.servers?.[draft.serverId]?.xopcOAuthCredentialId === alias;
214
+ if (result.conflict) throw new McpDraftError(409, "Configuration changed before writing. Reload and test again.");
215
+ if (!result.saved && !result.persisted) throw new McpDraftError(500, "Could not save MCP configuration. Retry or reload the current configuration.");
216
+ const reloadRequired = !result.saved;
217
+ published = true;
218
+ const timer = setTimeout(() => this.completed.delete(id), TTL_MS);
219
+ timer.unref();
220
+ this.completed.set(id, {
221
+ owner,
222
+ enable,
223
+ serverId: draft.serverId,
224
+ reloadRequired,
225
+ timer
226
+ });
227
+ this.dispose(draft);
228
+ return {
229
+ serverId: draft.serverId,
230
+ ...reloadRequired ? { reloadRequired: true } : {}
231
+ };
232
+ } finally {
233
+ draft.committing = false;
234
+ if (alias && this.options.readConfig().mcp?.servers?.[draft.serverId]?.xopcOAuthCredentialId === alias) published = true;
235
+ if (!published && alias && durable && draft.server.url) durable.remove(alias, draft.server.url);
236
+ if (this.drafts.has(id) && draft.expiresAt <= Date.now()) this.dispose(draft);
237
+ }
238
+ }
239
+ remove(owner, id) {
240
+ const draft = this.drafts.get(id);
241
+ if (!draft || draft.owner !== owner) return;
242
+ if (draft.committing) throw new McpDraftError(409, "This draft is being saved.");
243
+ this.dispose(draft);
244
+ }
245
+ close() {
246
+ for (const draft of this.drafts.values()) this.dispose(draft);
247
+ for (const item of this.completed.values()) clearTimeout(item.timer);
248
+ this.completed.clear();
249
+ }
250
+ get(owner, id) {
251
+ const draft = this.drafts.get(id);
252
+ if (!draft || draft.owner !== owner) throw new McpDraftError(404, "MCP draft not found or expired.");
253
+ if (draft.expiresAt <= Date.now() && !draft.committing) {
254
+ this.dispose(draft);
255
+ throw new McpDraftError(404, "MCP draft expired.");
256
+ }
257
+ return draft;
258
+ }
259
+ assertIdle(draft) {
260
+ const auth = draft.authorizationId && getMcpAuthorization(draft.authorizationId, draft.owner, draft.config);
261
+ if (draft.running || draft.committing || auth && (auth.state === "starting" || auth.state === "authorizing")) throw new McpDraftError(409, "Another draft operation is still running.");
262
+ }
263
+ assertAvailable(config, id, sourceId) {
264
+ const all = loadMergedMcpConfig({
265
+ cfg: config,
266
+ workspaceDir: getWorkspacePath(config) || process.cwd()
267
+ }).config.mcpServers;
268
+ if (Object.keys(all).some((other) => other !== sourceId && other.replaceAll("-", "_") === id.replaceAll("-", "_"))) throw new McpDraftError(409, "The MCP server ID is already in use.");
269
+ }
270
+ dispose(draft) {
271
+ this.drafts.delete(draft.id);
272
+ clearTimeout(draft.timer);
273
+ draft.controller.abort();
274
+ if (draft.authorizationId) cancelMcpAuthorization(draft.authorizationId, draft.owner);
275
+ }
276
+ };
277
+ //#endregion
278
+ export { McpConnectionDrafts, McpDraftError, mcpConfigRevision };
@@ -1,10 +1,11 @@
1
1
  import type { Config } from '../../config/schema.js';
2
+ import { type McpSessionOptions } from './tool-catalog.js';
2
3
  export type McpConnectionProbe = {
3
4
  state: 'connected' | 'oauth_required' | 'token_required' | 'error';
4
5
  toolCount?: number;
5
6
  error?: string;
6
7
  };
7
- export declare function probeMcpConnection(config: Config, workspace: string, serverId: string): Promise<McpConnectionProbe>;
8
+ export declare function probeMcpConnection(config: Config, workspace: string, serverId: string, options?: McpSessionOptions): Promise<McpConnectionProbe>;
8
9
  export type McpAuthorization = {
9
10
  id: string;
10
11
  serverId: string;
@@ -15,7 +16,9 @@ export type McpAuthorization = {
15
16
  error?: string;
16
17
  };
17
18
  /** A UI bridge to native pi's login command; no host-owned OAuth client or token store. */
18
- export declare function startMcpAuthorization(config: Config, workspace: string, serverId: string, owner: string): McpAuthorization;
19
+ export declare function startMcpAuthorization(config: Config, workspace: string, serverId: string, owner: string, options?: McpSessionOptions & {
20
+ authorizationScope?: string;
21
+ }): McpAuthorization;
19
22
  export declare function getMcpAuthorization(id: string, owner: string, config: Config): McpAuthorization | undefined;
20
23
  export declare function cancelMcpAuthorization(id: string, owner: string): boolean;
21
24
  export declare function submitMcpRedirect(id: string, owner: string, redirectUrl: string, config: Config): boolean;
@@ -71,11 +71,11 @@ async function advertisesOAuth(config, workspace, serverId) {
71
71
  const legacy = await metadata(new URL("/.well-known/oauth-authorization-server", url));
72
72
  return Boolean(legacy && legacy.issuer === url.origin && typeof legacy.authorization_endpoint === "string" && typeof legacy.token_endpoint === "string");
73
73
  }
74
- async function probeMcpConnection(config, workspace, serverId) {
74
+ async function probeMcpConnection(config, workspace, serverId, options) {
75
75
  try {
76
76
  return {
77
77
  state: "connected",
78
- toolCount: (await discoverMcpTools(config, workspace, serverId)).length
78
+ toolCount: (await discoverMcpTools(config, workspace, serverId, options)).length
79
79
  };
80
80
  } catch (error) {
81
81
  if (error instanceof McpAuthenticationRequiredError) try {
@@ -117,15 +117,17 @@ function cancel(attempt) {
117
117
  }
118
118
  }
119
119
  /** A UI bridge to native pi's login command; no host-owned OAuth client or token store. */
120
- function startMcpAuthorization(config, workspace, serverId, owner) {
120
+ function startMcpAuthorization(config, workspace, serverId, owner, options) {
121
121
  const server = config.mcp?.servers?.[serverId];
122
122
  if (!server?.url || server.enabled === false || isManagedConnectorServer(server) && server.xopcConnector.enabled === false) throw new Error("An enabled HTTP MCP server is required.");
123
123
  httpUrl(server.url);
124
124
  if (server.auth || Object.keys(server.headers ?? {}).some((name) => name.toLowerCase() === "authorization")) throw new Error("This server uses configured credentials. Remove Authorization before using OAuth.");
125
- for (const attempt of attempts.values()) if (attempt.owner === owner && attempt.result.serverId === serverId) cancel(attempt);
125
+ const scope = options?.authorizationScope ?? serverId;
126
+ for (const attempt of attempts.values()) if (attempt.owner === owner && attempt.scope === scope) cancel(attempt);
126
127
  if (attempts.size >= 100) throw new Error("Too many pending sign-ins. Try again later.");
127
128
  const attempt = {
128
129
  owner,
130
+ scope,
129
131
  fingerprint: fingerprint(config, serverId),
130
132
  controller: new AbortController(),
131
133
  result: {
@@ -159,7 +161,7 @@ function startMcpAuthorization(config, workspace, serverId, owner) {
159
161
  attempt.dispose = () => signal?.removeEventListener("abort", stop);
160
162
  });
161
163
  }
162
- }).then((tools) => {
164
+ }, options).then((tools) => {
163
165
  if (!attempt.controller.signal.aborted) {
164
166
  attempt.result.state = "connected";
165
167
  attempt.result.toolCount = tools.length;
@@ -0,0 +1,6 @@
1
+ import type { McpExtensionOptions } from '@earendil-works/pi-coding-agent';
2
+ export type NativeMcpCredentials = NonNullable<McpExtensionOptions['credentials']>;
3
+ /** Use pi's own stores; never change PI_CODING_AGENT_DIR for an individual connection. */
4
+ export declare function createNativeMcpCredentials(memory?: boolean): Promise<NativeMcpCredentials>;
5
+ /** Credential identity may change on commit without changing the public tool namespace. */
6
+ export declare function routeNativeMcpCredentials(store: NativeMcpCredentials, aliases: ReadonlyMap<string, string>): NativeMcpCredentials;
@@ -0,0 +1,24 @@
1
+ //#region src/agent/mcp/credential-store.ts
2
+ /** Use pi's own stores; never change PI_CODING_AGENT_DIR for an individual connection. */
3
+ async function createNativeMcpCredentials(memory = false) {
4
+ const root = import.meta.resolve("@earendil-works/pi-coding-agent");
5
+ const { McpOAuthCredentialStore } = await import(new URL("./extensions/mcp/oauth.js", root).href);
6
+ if (!memory) return new McpOAuthCredentialStore();
7
+ const { InMemoryAuthStorageBackend } = await import(new URL("./core/auth-storage.js", root).href);
8
+ return new McpOAuthCredentialStore(new InMemoryAuthStorageBackend());
9
+ }
10
+ /** Credential identity may change on commit without changing the public tool namespace. */
11
+ function routeNativeMcpCredentials(store, aliases) {
12
+ const forServer = store.forServer.bind(store), tokens = store.tokens.bind(store), remove = store.remove.bind(store);
13
+ store.forServer = (name, url) => forServer(aliases.get(name) ?? name, url);
14
+ store.tokens = (name, url) => tokens(aliases.get(name) ?? name, url);
15
+ store.remove = (name, url) => {
16
+ const alias = aliases.get(name);
17
+ if (!alias) return remove(name, url);
18
+ forServer(alias, url).save({ serverUrl: url });
19
+ return true;
20
+ };
21
+ return store;
22
+ }
23
+ //#endregion
24
+ export { createNativeMcpCredentials, routeNativeMcpCredentials };
@@ -1,6 +1,11 @@
1
1
  import { type LoadedMcpConfig } from '@earendil-works/pi-coding-agent';
2
2
  import { type Config } from '../../config/schema.js';
3
+ import { type NativeMcpCredentials } from './credential-store.js';
3
4
  /** One process-wide pi directory: sessions share native OAuth credentials, never swap roots per turn. */
4
5
  export declare function getNativePiAgentDir(): string;
6
+ export type NativeMcpConfig = LoadedMcpConfig & {
7
+ credentials?: NativeMcpCredentials;
8
+ credentialAliases?: Record<string, string>;
9
+ };
5
10
  /** Only projects host configuration and secret references; all MCP execution belongs to pi. */
6
- export declare function prepareNativeMcpConfig(config: Config, workspaceDir: string): Promise<LoadedMcpConfig>;
11
+ export declare function prepareNativeMcpConfig(config: Config, workspaceDir: string): Promise<NativeMcpConfig>;
@@ -1,6 +1,7 @@
1
1
  import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
2
2
  import { McpServerSchema, init_schema } from "../../config/schema.js";
3
3
  import { resolveConnectorSecretReferences } from "../../connectors/secret-store.js";
4
+ import { createNativeMcpCredentials, routeNativeMcpCredentials } from "./credential-store.js";
4
5
  import { loadMergedMcpConfig } from "./config.js";
5
6
  import { join } from "node:path";
6
7
  import { mkdirSync } from "node:fs";
@@ -67,6 +68,11 @@ async function prepareNativeMcpConfig(config, workspaceDir) {
67
68
  scope: "extension"
68
69
  });
69
70
  }
71
+ const aliases = new Map(Object.entries(config.mcp?.servers ?? {}).filter(([, value]) => typeof value.xopcOAuthCredentialId === "string").map(([name, value]) => [name, value.xopcOAuthCredentialId]));
72
+ if (aliases.size) {
73
+ result.credentials = routeNativeMcpCredentials(await createNativeMcpCredentials(), aliases);
74
+ result.credentialAliases = Object.fromEntries(aliases);
75
+ }
70
76
  return result;
71
77
  }
72
78
  //#endregion
@@ -1,4 +1,5 @@
1
1
  import type { Config } from '../../config/schema.js';
2
+ import type { NativeMcpCredentials } from './credential-store.js';
2
3
  export type McpCatalogTool = {
3
4
  name: string;
4
5
  description: string;
@@ -12,7 +13,11 @@ export type McpLoginInteraction = {
12
13
  onAuthorizationUrl: (url: string) => void;
13
14
  requestRedirectUrl: (signal?: AbortSignal) => Promise<string | undefined>;
14
15
  };
16
+ export type McpSessionOptions = {
17
+ credentials?: NativeMcpCredentials;
18
+ signal?: AbortSignal;
19
+ };
15
20
  /** A short-lived native session discovers tools without making a model request. */
16
- export declare function discoverMcpTools(config: Config, workspaceDir: string, serverId: string): Promise<McpCatalogTool[]>;
21
+ export declare function discoverMcpTools(config: Config, workspaceDir: string, serverId: string, options?: McpSessionOptions): Promise<McpCatalogTool[]>;
17
22
  /** Native pi owns PKCE, registration, callbacks, token storage and refresh. */
18
- export declare function signInNativeMcp(config: Config, workspaceDir: string, serverId: string, interaction: McpLoginInteraction): Promise<McpCatalogTool[]>;
23
+ export declare function signInNativeMcp(config: Config, workspaceDir: string, serverId: string, interaction: McpLoginInteraction, options?: McpSessionOptions): Promise<McpCatalogTool[]>;
@@ -6,15 +6,19 @@ import { DefaultResourceLoader, ModelRuntime, SessionManager, SettingsManager, c
6
6
  //#region src/agent/mcp/tool-catalog.ts
7
7
  var McpAuthenticationRequiredError = class extends Error {};
8
8
  /** A short-lived native session discovers tools without making a model request. */
9
- async function discoverMcpTools(config, workspaceDir, serverId) {
10
- return runNativeMcpSession(config, workspaceDir, serverId);
9
+ async function discoverMcpTools(config, workspaceDir, serverId, options) {
10
+ return runNativeMcpSession(config, workspaceDir, serverId, void 0, options);
11
11
  }
12
12
  /** Native pi owns PKCE, registration, callbacks, token storage and refresh. */
13
- async function signInNativeMcp(config, workspaceDir, serverId, interaction) {
14
- return runNativeMcpSession(config, workspaceDir, serverId, interaction);
13
+ async function signInNativeMcp(config, workspaceDir, serverId, interaction, options) {
14
+ return runNativeMcpSession(config, workspaceDir, serverId, interaction, options);
15
15
  }
16
- async function runNativeMcpSession(config, workspaceDir, serverId, interaction) {
17
- const entry = (await prepareNativeMcpConfig(config, workspaceDir)).servers.find((server) => server.name === serverId);
16
+ async function runNativeMcpSession(config, workspaceDir, serverId, interaction, options) {
17
+ const signal = interaction?.signal ?? options?.signal;
18
+ signal?.throwIfAborted();
19
+ const loaded = await prepareNativeMcpConfig(config, workspaceDir);
20
+ signal?.throwIfAborted();
21
+ const entry = loaded.servers.find((server) => server.name === serverId);
18
22
  if (!entry) throw new Error(`MCP server "${serverId}" is not configured or has invalid configuration.`);
19
23
  if (entry.config.enabled === false) throw new Error(`MCP server "${serverId}" is disabled.`);
20
24
  const agentDir = getNativePiAgentDir();
@@ -32,6 +36,7 @@ async function runNativeMcpSession(config, workspaceDir, serverId, interaction)
32
36
  noThemes: true,
33
37
  noContextFiles: true,
34
38
  extensionFactories: [createToolSearchExtension(), createMcpExtension({
39
+ credentials: options?.credentials ?? loaded.credentials,
35
40
  loadConfig: () => ({
36
41
  servers: [entry],
37
42
  errors: [],
@@ -42,18 +47,21 @@ async function runNativeMcpSession(config, workspaceDir, serverId, interaction)
42
47
  })]
43
48
  });
44
49
  await loader.reload();
50
+ signal?.throwIfAborted();
45
51
  const provider = "url" in entry.config ? entry.config.auth?.provider : void 0;
52
+ const modelRuntime = provider ? await createEmbeddedModelRuntime(provider) : await ModelRuntime.create({
53
+ credentials: new InMemoryCredentialStore(),
54
+ modelsStore: new InMemoryModelsStore(),
55
+ modelsPath: null,
56
+ refreshOnCreate: false
57
+ });
58
+ signal?.throwIfAborted();
46
59
  const { session } = await createAgentSession({
47
60
  cwd: workspaceDir,
48
61
  agentDir,
49
62
  resourceLoader: loader,
50
63
  settingsManager,
51
- modelRuntime: provider ? await createEmbeddedModelRuntime(provider) : await ModelRuntime.create({
52
- credentials: new InMemoryCredentialStore(),
53
- modelsStore: new InMemoryModelsStore(),
54
- modelsPath: null,
55
- refreshOnCreate: false
56
- }),
64
+ modelRuntime,
57
65
  sessionManager: SessionManager.inMemory(),
58
66
  noTools: "builtin"
59
67
  });
@@ -70,6 +78,8 @@ async function runNativeMcpSession(config, workspaceDir, serverId, interaction)
70
78
  try {
71
79
  const runner = session.extensionRunner;
72
80
  if (!runner) throw new Error("Native MCP extension is unavailable.");
81
+ signal?.throwIfAborted();
82
+ signal?.addEventListener("abort", abort, { once: true });
73
83
  await session.bindExtensions({ uiContext: {
74
84
  ...runner.getUIContext(),
75
85
  notify(message) {
@@ -81,8 +91,7 @@ async function runNativeMcpSession(config, workspaceDir, serverId, interaction)
81
91
  return interaction?.requestRedirectUrl(options?.signal) ?? Promise.resolve(void 0);
82
92
  }
83
93
  } });
84
- interaction?.signal.addEventListener("abort", abort, { once: true });
85
- if (interaction?.signal.aborted) throw new Error("MCP sign-in cancelled.");
94
+ if (signal?.aborted) throw new Error("MCP sign-in cancelled.");
86
95
  let timer;
87
96
  try {
88
97
  await Promise.race([session.prompt("/mcp"), new Promise((_resolve, reject) => {
@@ -100,6 +109,7 @@ async function runNativeMcpSession(config, workspaceDir, serverId, interaction)
100
109
  if (/needs sign-in|needs-auth/.test(failure)) throw new McpAuthenticationRequiredError(failure);
101
110
  throw new Error(failure);
102
111
  }
112
+ if (signal?.aborted) throw new Error("MCP connection check cancelled.");
103
113
  const namespace = `mcp__${serverId.replace(/-/g, "_")}`;
104
114
  return session.getAllTools().filter((tool) => tool.namespace?.name === namespace).map((tool) => ({
105
115
  name: tool.name,
@@ -109,7 +119,7 @@ async function runNativeMcpSession(config, workspaceDir, serverId, interaction)
109
119
  })).sort((a, b) => a.name.localeCompare(b.name));
110
120
  } finally {
111
121
  try {
112
- interaction?.signal.removeEventListener("abort", abort);
122
+ signal?.removeEventListener("abort", abort);
113
123
  await close();
114
124
  } finally {
115
125
  session.dispose();
@@ -3,8 +3,8 @@ import { init_src } from "../../../packages/gateway-contract/src/index.js";
3
3
  import { init_session_input_repository, listTaskUpdateTriggers } from "../../storage/sqlite/session-input-repository.js";
4
4
  import { getClarificationResumeInput, init_clarification_wait_repository } from "../../storage/sqlite/clarification-wait-repository.js";
5
5
  import { getConnectionResumeInput, init_connection_wait_repository } from "../../storage/sqlite/connection-wait-repository.js";
6
- import { init_agent_session_key, resolveAgentMainConversationId } from "../../routing/agent-session-key.js";
7
6
  import { init_agent_scope, resolveDefaultAgentId } from "../agent-scope.js";
7
+ import { init_agent_session_key, resolveAgentMainConversationId } from "../../routing/agent-session-key.js";
8
8
  import { readAgentMessageContent } from "../memory/agent-message-access.js";
9
9
  import { abortEmbeddedRun } from "../embedded/runs.js";
10
10
  import { clearPendingTranscriptUserMessage, setPendingTranscriptUserMessage } from "../inbound/attachment-pipeline.js";
@@ -1,14 +1,14 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { init_attachment_ref, parseNoteAttachmentTarget } from "../notes/attachment-ref.js";
4
- import { init_agent_session_key, resolveAgentIdFromConversationId } from "../routing/agent-session-key.js";
5
4
  import { init_agent_scope, resolveAgentHomeDir, resolveDefaultAgentId } from "./agent-scope.js";
5
+ import { extractTextContent } from "./context/workspace.js";
6
+ import { init_agent_session_key, resolveAgentIdFromConversationId } from "../routing/agent-session-key.js";
6
7
  import { extractProfileAgentId, resolveEffectiveAgentConfigForSession } from "../config/agent-profile.js";
7
8
  import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
8
9
  import { init_providers, resolveModel } from "../providers/index.js";
9
10
  import { configureTracing, flushTracing } from "../observability/runtime.js";
10
11
  import { getUserTimezone } from "../user-model/repository.js";
11
- import { extractTextContent } from "./context/workspace.js";
12
12
  import { resolveAgentTurnTimeoutMs } from "./orchestration/run-agent-turn-with-timeout.js";
13
13
  import { applyConfigOverrides } from "../config/runtime-overrides.js";
14
14
  import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
@@ -1,8 +1,8 @@
1
1
  import { resolveStateDir } from "../../config/paths-state.js";
2
2
  import { createLogger } from "../../utils/logger/index.js";
3
3
  import { init_logger } from "../../utils/logger.js";
4
- import { init_paths } from "../../config/paths.js";
5
4
  import { parseFrontmatter } from "../../markdown/frontmatter.js";
5
+ import { init_paths } from "../../config/paths.js";
6
6
  import { findInstallSpec, hasBinary, installSkill } from "./installer.js";
7
7
  import { applySkillEnvOverrides, createSkillConfigManager, getSkillEnvironment, isSkillEnabled, resolveSkillConfig, validateSkillConfig } from "./config.js";
8
8
  import { parseSkillToolConditions } from "./skill-tool-gating.js";
@@ -1,5 +1,5 @@
1
- import { init_paths, resolveSkillsDir } from "../../config/paths.js";
2
1
  import { parseFrontmatter } from "../../markdown/frontmatter.js";
2
+ import { init_paths, resolveSkillsDir } from "../../config/paths.js";
3
3
  import { loadSkillsLock } from "./hub-lock.js";
4
4
  import { dirname, join, resolve, sep } from "node:path";
5
5
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
@@ -1,5 +1,5 @@
1
- import { init_paths, resolveSkillsDir } from "../../config/paths.js";
2
1
  import { parseFrontmatter } from "../../markdown/frontmatter.js";
2
+ import { init_paths, resolveSkillsDir } from "../../config/paths.js";
3
3
  import { resolveWorkspaceSkillsDir } from "./workspace-skills-dir.js";
4
4
  import { formatScanSummary, scanSkillDirectory } from "./scanner.js";
5
5
  import { fuzzyFindText, normalizeForFuzzyMatch, normalizeToLF, restoreLineEndings } from "../tools/edit-diff.js";
@@ -1,9 +1,8 @@
1
+ import type { ClarificationPresentation } from '@xopcai/gateway-contract';
1
2
  import type { AgentTool } from '@earendil-works/pi-agent-core';
2
- export type ClarifyRequestPayload = {
3
+ export type ClarifyRequestPayload = ClarificationPresentation & {
3
4
  kind?: 'approval';
4
5
  question: string;
5
- choices?: string[];
6
- suggestedAnswer?: string;
7
6
  /** Stable hash of the exact operation guarded by an approval. */
8
7
  approvalKey?: string;
9
8
  };
@@ -2,13 +2,18 @@ import { Type } from "@sinclair/typebox";
2
2
  //#region src/agent/tools/clarify-tool.ts
3
3
  const ClarifySchema = Type.Object({
4
4
  question: Type.String({ description: "The question to ask the user. Be specific and concise." }),
5
- choices: Type.Optional(Type.Array(Type.String(), {
6
- description: "Optional list of choices for multiple-choice questions. If provided, the user picks one. If omitted, the user types a free-form answer.",
5
+ interactionMode: Type.Optional(Type.Union([Type.Literal("quick"), Type.Literal("compose")], { description: "quick submits a choice immediately; compose lets the user select and add details before submitting." })),
6
+ choiceDetails: Type.Optional(Type.Array(Type.Object({
7
+ id: Type.String(),
8
+ label: Type.String(),
9
+ description: Type.Optional(Type.String())
10
+ }), {
7
11
  minItems: 2,
8
- maxItems: 10
12
+ maxItems: 10,
13
+ description: "Answer choices with stable unique IDs and optional descriptions."
9
14
  })),
10
- suggestedAnswer: Type.Optional(Type.String({ description: "Optional recommendation shown to the user. It is never selected automatically." }))
11
- });
15
+ recommendedChoiceId: Type.Optional(Type.String())
16
+ }, { additionalProperties: false });
12
17
  function waitForAbort(signal) {
13
18
  return new Promise((_, reject) => {
14
19
  if (!signal) return;
@@ -23,7 +28,7 @@ function createClarifyTool(deps) {
23
28
  return {
24
29
  name: "clarify",
25
30
  label: "❓ Clarify",
26
- description: "Ask the user a clarifying question and pause the objective until they respond.\n\nUse this when you need more information to proceed correctly, rather than guessing.\n\nWHEN TO USE:\n- Ambiguous instructions with multiple valid interpretations\n- Missing critical information (which file, which approach, etc.)\n- Confirming destructive or irreversible actions\n\nWHEN NOT TO USE:\n- When you can reasonably infer the answer from context\n- For trivial decisions that do not affect the task\n- When the user explicitly said \"just do it\" or \"your choice\"\n\nTIPS:\n- Provide choices when there are clear options (faster for the user)\n- Keep questions short and specific\n- Include a suggested answer when one option is clearly more likely",
31
+ description: "Ask the user a clarifying question and pause the objective until they respond.\n\nUse this when you need more information to proceed correctly, rather than guessing.\n\nWHEN TO USE:\n- Ambiguous instructions with multiple valid interpretations\n- Missing critical information (which file, which approach, etc.)\n- Confirming destructive or irreversible actions\n\nWHEN NOT TO USE:\n- When you can reasonably infer the answer from context\n- For trivial decisions that do not affect the task\n- When the user explicitly said \"just do it\" or \"your choice\"\n\nTIPS:\n- Provide choices when there are clear options (faster for the user)\n- Keep questions short and specific\n- Set recommendedChoiceId when one option is clearly more likely",
27
32
  parameters: ClarifySchema,
28
33
  async execute(toolCallId, params, signal) {
29
34
  const p = params;
@@ -36,9 +41,10 @@ function createClarifyTool(deps) {
36
41
  details: { answer: "" }
37
42
  };
38
43
  const payload = {
39
- question: p.question,
40
- choices: p.choices,
41
- suggestedAnswer: p.suggestedAnswer
44
+ interactionMode: p.interactionMode,
45
+ choiceDetails: p.choiceDetails,
46
+ recommendedChoiceId: p.recommendedChoiceId,
47
+ question: p.question
42
48
  };
43
49
  try {
44
50
  const result = await Promise.race([askUser(payload), waitForAbort(signal)]);