@xopcai/xopc 0.0.142 → 0.0.143

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 (543) hide show
  1. package/README.md +1 -1
  2. package/dist/browser-ext/manifest.json +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/activity-center-store-jITiX2vJ.js +1 -0
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BawPxiu5.js → agent-avatar-dicebear-DiME9u_P.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-DzBXhZXO.js +2 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-81xd1p9R.js → app-management-settings-panel-Cuo7SbUP.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-DYeQsYU8.js → appearance-settings-DUfdNQqk.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-CKuKK5AU.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-D_oa7oti.js → archive-plugin-B-Qk6cGr.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-Cd-bwI2N.js → attachment-load-Di6EEbQX.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-DGxvRxtO.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-D-FF_WKV.js +4 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-O8svLKWw.js → binary-plugins-ZaOZDH2I.js} +1 -1
  15. package/dist/gateway/static/root/assets/block-editor-BTFhjWfg.js +184 -0
  16. package/dist/gateway/static/root/assets/browser-settings-page-BvKLdEQt.js +8 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-api-dJy1Eqgx.js → capability-presets-api-BU-pVZiZ.js} +1 -1
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DgyeEwzh.js +2 -0
  19. package/dist/gateway/static/root/assets/{channel-recipient-api-Bfuhp2ty.js → channel-recipient-api-DuulnhIj.js} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-BbVsdD_I.js +1 -0
  21. package/dist/gateway/static/root/assets/channels-status-swr-B5lVrUsN.js +1 -0
  22. package/dist/gateway/static/root/assets/check-BODqo66o.js +1 -0
  23. package/dist/gateway/static/root/assets/chunk-QUQL4437-DXsxWP7r.js +4 -0
  24. package/dist/gateway/static/root/assets/circle-alert-RzVebuX2.js +1 -0
  25. package/dist/gateway/static/root/assets/connectors-page-B8QqVy3I.js +2 -0
  26. package/dist/gateway/static/root/assets/{desktop-pet-DFMfIb5F.js → desktop-pet---yzVxVR.js} +1 -1
  27. package/dist/gateway/static/root/assets/desktop-pet-settings-Dc3gqBJE.js +1 -0
  28. package/dist/gateway/static/root/assets/{directory-picker-path-field-BrYt1gAr.js → directory-picker-path-field-DCmOGLtK.js} +1 -1
  29. package/dist/gateway/static/root/assets/dreaming-settings-BgT5KZVe.js +3 -0
  30. package/dist/gateway/static/root/assets/{extension-debug-page-Bh630pLD.js → extension-debug-page-ByaKTTq4.js} +1 -1
  31. package/dist/gateway/static/root/assets/extension-page-BmRzHAZr.js +1 -0
  32. package/dist/gateway/static/root/assets/extension-settings-page-JUtwIhbF.js +1 -0
  33. package/dist/gateway/static/root/assets/{fetch-B1WtuprY.js → fetch-8QNN25Sh.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-De2N821l.js → gateway-config-api-CxicF50_.js} +1 -1
  35. package/dist/gateway/static/root/assets/gateway-settings-Bz2I_EO5.js +1 -0
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-nEujFSDj.js → gateway-startup-retry-5YBnS9Fj.js} +1 -1
  37. package/dist/gateway/static/root/assets/goal-create-dialog-VcoyuZGN.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-Cilkap2G.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-DUy3eEse.js → goals-config-api-CwcHRdC0.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-C6eoni4z.js +2 -0
  41. package/dist/gateway/static/root/assets/goals-settings-o4i-qAOS.js +1 -0
  42. package/dist/gateway/static/root/assets/heartbeat-settings-DQQkETX8.js +1 -0
  43. package/dist/gateway/static/root/assets/index-BKRqeRHm.js +257 -0
  44. package/dist/gateway/static/root/assets/index-CphxClbs.css +1 -0
  45. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CVIwwM15.js → keyboard-shortcuts-settings-LT6qB-ua.js} +1 -1
  46. package/dist/gateway/static/root/assets/logs-page-Dli2e3fS.js +7 -0
  47. package/dist/gateway/static/root/assets/{markdown-split-B_6us9j7.js → markdown-split-Dw-yE2-y.js} +1 -1
  48. package/dist/gateway/static/root/assets/{media-plugins-D_fryIyj.js → media-plugins-D9NNNUgE.js} +1 -1
  49. package/dist/gateway/static/root/assets/messages-CzKxM6I4.js +5 -0
  50. package/dist/gateway/static/root/assets/models-hub-panel-DVn2Q1Ik.js +2 -0
  51. package/dist/gateway/static/root/assets/notes-page-CRgbJGgk.js +1 -0
  52. package/dist/gateway/static/root/assets/notes-workbench-BxZRHLWx.js +2 -0
  53. package/dist/gateway/static/root/assets/{page-tabs-D_8jGlqx.js → page-tabs-D4hkWVt_.js} +1 -1
  54. package/dist/gateway/static/root/assets/{preview-open-alternatives-BBLMK8Mp.js → preview-open-alternatives-CIckv0uy.js} +1 -1
  55. package/dist/gateway/static/root/assets/project-detail-page-Doz53xLn.js +1 -0
  56. package/dist/gateway/static/root/assets/projects-page-DoMtcRLg.js +1 -0
  57. package/dist/gateway/static/root/assets/remote-access-hub-BeHVEgrm.js +1 -0
  58. package/dist/gateway/static/root/assets/{save-bar-controls-DVS3FR5r.js → save-bar-controls-B0b42kB2.js} +1 -1
  59. package/dist/gateway/static/root/assets/{schedule-field-D6vKd6-T.js → schedule-field-BtjEkczK.js} +1 -1
  60. package/dist/gateway/static/root/assets/{schema-form-BPy4lbIh.js → schema-form-Bf0bk3i6.js} +1 -1
  61. package/dist/gateway/static/root/assets/sessions-page-Bk4bQsBe.js +1 -0
  62. package/dist/gateway/static/root/assets/settings-advanced-gate-DdFyaRMm.js +1 -0
  63. package/dist/gateway/static/root/assets/{settings-collapsible-section-WzdikxPt.js → settings-collapsible-section-BTKTdTNX.js} +1 -1
  64. package/dist/gateway/static/root/assets/{settings-form-section-CvfzhBV-.js → settings-form-section-DL4P0sAj.js} +1 -1
  65. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BxR-Ulhi.js → settings-loading-skeleton-BV6KFNj4.js} +1 -1
  66. package/dist/gateway/static/root/assets/settings-page-B_4DsX5W.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-page-layout-CKefvbYi.js → settings-page-layout-CyGlrInB.js} +1 -1
  68. package/dist/gateway/static/root/assets/setup-status-panel-DJ1_MLgX.js +1 -0
  69. package/dist/gateway/static/root/assets/share-preview-page-BQBV7YrV.js +2 -0
  70. package/dist/gateway/static/root/assets/shares-settings-0VuFLBeU.js +1 -0
  71. package/dist/gateway/static/root/assets/skill-reload-api-DO87Ckeo.js +1 -0
  72. package/dist/gateway/static/root/assets/skills-page-D3VdtxAn.js +2 -0
  73. package/dist/gateway/static/root/assets/{system-settings-panel-BokgAgf7.js → system-settings-panel-D85fBBuI.js} +1 -1
  74. package/dist/gateway/static/root/assets/{typed-models-lib-BwHlNL3L.js → typed-models-lib-CwEuYrHX.js} +1 -1
  75. package/dist/gateway/static/root/assets/{use-channel-catalog-DR11ap3A.js → use-channel-catalog-COXIfXcl.js} +1 -1
  76. package/dist/gateway/static/root/assets/user-context-page-m9JVQ73F.js +1 -0
  77. package/dist/gateway/static/root/assets/user-profile-fields-editor-DtQiuY7E.js +1 -0
  78. package/dist/gateway/static/root/assets/user-profile-settings-panel-CWM0fEpb.js +1 -0
  79. package/dist/gateway/static/root/assets/{utils-BKUWB-TT.js → utils--BO6xT3u.js} +1 -1
  80. package/dist/gateway/static/root/assets/voice-api-key-field-LoT3wgZ9.js +1 -0
  81. package/dist/gateway/static/root/assets/with-selector-aYPsXwdl.js +1 -0
  82. package/dist/gateway/static/root/assets/work-item-detail-page-DSTMz_mO.js +1 -0
  83. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CL_rnAUB.js → workflow-run-setup-panel-B35lJzvm.js} +2 -2
  84. package/dist/gateway/static/root/assets/workflows-page-BfSm9oR8.js +11 -0
  85. package/dist/gateway/static/root/assets/workflows-page-DLioOiRN.css +1 -0
  86. package/dist/gateway/static/root/connector-icons/README.md +11 -0
  87. package/dist/gateway/static/root/connector-icons/airtable.svg +13 -0
  88. package/dist/gateway/static/root/connector-icons/asana.svg +15 -0
  89. package/dist/gateway/static/root/connector-icons/brave-search.svg +1 -0
  90. package/dist/gateway/static/root/connector-icons/clickup.svg +19 -0
  91. package/dist/gateway/static/root/connector-icons/composio.svg +266 -0
  92. package/dist/gateway/static/root/connector-icons/discord.svg +15 -0
  93. package/dist/gateway/static/root/connector-icons/dropbox.svg +152 -0
  94. package/dist/gateway/static/root/connector-icons/excel.svg +56 -0
  95. package/dist/gateway/static/root/connector-icons/fetch.svg +6 -0
  96. package/dist/gateway/static/root/connector-icons/figma.svg +178 -0
  97. package/dist/gateway/static/root/connector-icons/filesystem.svg +6 -0
  98. package/dist/gateway/static/root/connector-icons/github.svg +10 -0
  99. package/dist/gateway/static/root/connector-icons/gmail.svg +3 -0
  100. package/dist/gateway/static/root/connector-icons/google-calendar.svg +3 -0
  101. package/dist/gateway/static/root/connector-icons/google-docs.svg +25 -0
  102. package/dist/gateway/static/root/connector-icons/google-drive.svg +25 -0
  103. package/dist/gateway/static/root/connector-icons/google-sheets.svg +1 -0
  104. package/dist/gateway/static/root/connector-icons/hubspot.svg +142 -0
  105. package/dist/gateway/static/root/connector-icons/jira.svg +15 -0
  106. package/dist/gateway/static/root/connector-icons/linear.svg +5 -0
  107. package/dist/gateway/static/root/connector-icons/memory.svg +5 -0
  108. package/dist/gateway/static/root/connector-icons/microsoft-teams.svg +33 -0
  109. package/dist/gateway/static/root/connector-icons/notion.svg +5 -0
  110. package/dist/gateway/static/root/connector-icons/one-drive.svg +13 -0
  111. package/dist/gateway/static/root/connector-icons/outlook.svg +76 -0
  112. package/dist/gateway/static/root/connector-icons/playwright.svg +9 -0
  113. package/dist/gateway/static/root/connector-icons/salesforce.svg +17 -0
  114. package/dist/gateway/static/root/connector-icons/sequential-thinking.svg +8 -0
  115. package/dist/gateway/static/root/connector-icons/shopify.svg +5 -0
  116. package/dist/gateway/static/root/connector-icons/slack.svg +9 -0
  117. package/dist/gateway/static/root/connector-icons/spotify.svg +43 -0
  118. package/dist/gateway/static/root/connector-icons/stripe.svg +11 -0
  119. package/dist/gateway/static/root/connector-icons/telegram.svg +130 -0
  120. package/dist/gateway/static/root/connector-icons/time.svg +6 -0
  121. package/dist/gateway/static/root/connector-icons/todoist.svg +277 -0
  122. package/dist/gateway/static/root/connector-icons/trello.svg +19 -0
  123. package/dist/gateway/static/root/connector-icons/twitter.svg +128 -0
  124. package/dist/gateway/static/root/connector-icons/whatsapp.svg +61 -0
  125. package/dist/gateway/static/root/connector-icons/youtube.svg +11 -0
  126. package/dist/gateway/static/root/index.html +9 -6
  127. package/dist/package.js +1 -1
  128. package/dist/src/agent/agent-manager.d.ts +2 -0
  129. package/dist/src/agent/agent-manager.js +8 -0
  130. package/dist/src/agent/agent-manager.js.map +1 -1
  131. package/dist/src/agent/background-review/prompts.d.ts +1 -1
  132. package/dist/src/agent/background-review/prompts.js +3 -2
  133. package/dist/src/agent/background-review/prompts.js.map +1 -1
  134. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  135. package/dist/src/agent/embedded/xopc-tools-bridge.d.ts +9 -0
  136. package/dist/src/agent/embedded/xopc-tools-bridge.js +71 -3
  137. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  138. package/dist/src/agent/goals/post-turn.js +5 -4
  139. package/dist/src/agent/goals/post-turn.js.map +1 -1
  140. package/dist/src/agent/mcp/mcp-transport.js +4 -1
  141. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  142. package/dist/src/agent/memory/context/planner.d.ts +1 -0
  143. package/dist/src/agent/memory/context/planner.js +60 -14
  144. package/dist/src/agent/memory/context/planner.js.map +1 -1
  145. package/dist/src/agent/memory/context/types.d.ts +3 -1
  146. package/dist/src/agent/memory/lifecycle.d.ts +11 -0
  147. package/dist/src/agent/memory/lifecycle.js +50 -0
  148. package/dist/src/agent/memory/lifecycle.js.map +1 -0
  149. package/dist/src/agent/memory/source-origin.d.ts +3 -0
  150. package/dist/src/agent/memory/source-origin.js +19 -0
  151. package/dist/src/agent/memory/source-origin.js.map +1 -0
  152. package/dist/src/agent/memory/understanding/service.js +5 -0
  153. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  154. package/dist/src/agent/memory/user-context-coordinator.js +7 -2
  155. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  156. package/dist/src/agent/prompt/sections/behavior.d.ts +2 -0
  157. package/dist/src/agent/prompt/sections/behavior.js +30 -1
  158. package/dist/src/agent/prompt/sections/behavior.js.map +1 -1
  159. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  160. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  161. package/dist/src/agent/prompt/service-prompt-builder.js +8 -1
  162. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  163. package/dist/src/agent/prompt/system-prompt.d.ts +2 -0
  164. package/dist/src/agent/prompt/system-prompt.js +6 -3
  165. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  166. package/dist/src/agent/service/process-direct-streaming.js +22 -0
  167. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  168. package/dist/src/agent/service.d.ts +2 -0
  169. package/dist/src/agent/service.js +9 -3
  170. package/dist/src/agent/service.js.map +1 -1
  171. package/dist/src/agent/starter-agents.js +1 -1
  172. package/dist/src/agent/starter-agents.js.map +1 -1
  173. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  174. package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
  175. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -1
  176. package/dist/src/agent/tools/composio-tool.d.ts +18 -5
  177. package/dist/src/agent/tools/composio-tool.js +252 -35
  178. package/dist/src/agent/tools/composio-tool.js.map +1 -1
  179. package/dist/src/agent/tools/factory.js +7 -3
  180. package/dist/src/agent/tools/factory.js.map +1 -1
  181. package/dist/src/agent/tools/index.d.ts +1 -1
  182. package/dist/src/agent/tools/index.js +2 -2
  183. package/dist/src/agent/tools/workflow-tool.d.ts +0 -1
  184. package/dist/src/agent/tools/workflow-tool.js +3 -16
  185. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  186. package/dist/src/agent/workflow/builtins/index.d.ts +2 -28
  187. package/dist/src/agent/workflow/builtins/index.js +226 -41
  188. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  189. package/dist/src/agent/workflow/catalog.d.ts +32 -34
  190. package/dist/src/agent/workflow/catalog.js +158 -154
  191. package/dist/src/agent/workflow/catalog.js.map +1 -1
  192. package/dist/src/agent/workflow/index.d.ts +4 -6
  193. package/dist/src/agent/workflow/index.js +2 -5
  194. package/dist/src/agent/workflow/snapshot.d.ts +2 -2
  195. package/dist/src/agent/workflow/snapshot.js +2 -2
  196. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  197. package/dist/src/agent/workflow/structured-output-tool.d.ts +2 -2
  198. package/dist/src/agent/workflow/structured-output-tool.js +2 -2
  199. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -1
  200. package/dist/src/agent/workflow/subagent-runner.js +1 -1
  201. package/dist/src/agent/workflow/types.d.ts +31 -26
  202. package/dist/src/agent-manifest/index.d.ts +1 -0
  203. package/dist/src/agent-manifest/index.js +3 -1
  204. package/dist/src/agent-manifest/index.js.map +1 -1
  205. package/dist/src/agent-manifest/preset-chain.d.ts +10 -0
  206. package/dist/src/agent-manifest/preset-chain.js +32 -0
  207. package/dist/src/agent-manifest/preset-chain.js.map +1 -0
  208. package/dist/src/agent-manifest/resolver.js +3 -10
  209. package/dist/src/agent-manifest/resolver.js.map +1 -1
  210. package/dist/src/agent-manifest/schema.d.ts +4 -4
  211. package/dist/src/automations/api/routes.js +13 -1
  212. package/dist/src/automations/api/routes.js.map +1 -1
  213. package/dist/src/automations/domain/validation.d.ts +14 -14
  214. package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -3
  215. package/dist/src/browser/providers/browser-ext-install.d.ts +11 -1
  216. package/dist/src/browser/providers/browser-ext-install.js +39 -14
  217. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  218. package/dist/src/capabilities/store-connector.d.ts +0 -1
  219. package/dist/src/capabilities/store-connector.js +3 -5
  220. package/dist/src/capabilities/store-connector.js.map +1 -1
  221. package/dist/src/chat-commands/builtins/review.js +72 -73
  222. package/dist/src/chat-commands/builtins/review.js.map +1 -1
  223. package/dist/src/chat-commands/builtins/workflow.js +9 -54
  224. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  225. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  226. package/dist/src/cli/commands/extension-create.js +2 -2
  227. package/dist/src/cli/commands/extension-create.js.map +1 -1
  228. package/dist/src/cli/commands/extension-marketplace.js +42 -36
  229. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  230. package/dist/src/cli/commands/extension-pack.d.ts +6 -0
  231. package/dist/src/cli/commands/extension-pack.js +3 -2
  232. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  233. package/dist/src/commands/agents.config.d.ts +1 -0
  234. package/dist/src/commands/agents.config.js +1 -0
  235. package/dist/src/commands/agents.config.js.map +1 -1
  236. package/dist/src/config/schema.d.ts +6 -6
  237. package/dist/src/config/schema.js +6 -22
  238. package/dist/src/config/schema.js.map +1 -1
  239. package/dist/src/config/web-patch.d.ts +1 -1
  240. package/dist/src/connectors/approval.d.ts +2 -0
  241. package/dist/src/connectors/approval.js +33 -0
  242. package/dist/src/connectors/approval.js.map +1 -0
  243. package/dist/src/connectors/auth-provider-registry.d.ts +9 -0
  244. package/dist/src/connectors/auth-provider-registry.js +17 -0
  245. package/dist/src/connectors/auth-provider-registry.js.map +1 -0
  246. package/dist/src/connectors/builtin-catalog.js +55 -116
  247. package/dist/src/connectors/builtin-catalog.js.map +1 -1
  248. package/dist/src/connectors/catalog.js +7 -2
  249. package/dist/src/connectors/catalog.js.map +1 -1
  250. package/dist/src/connectors/composio-catalog.d.ts +19 -0
  251. package/dist/src/connectors/composio-catalog.js +237 -0
  252. package/dist/src/connectors/composio-catalog.js.map +1 -0
  253. package/dist/src/connectors/composio-logo.d.ts +1 -0
  254. package/dist/src/connectors/composio-logo.js +51 -0
  255. package/dist/src/connectors/composio-logo.js.map +1 -0
  256. package/dist/src/connectors/composio-sessions.d.ts +116 -0
  257. package/dist/src/connectors/composio-sessions.js +296 -0
  258. package/dist/src/connectors/composio-sessions.js.map +1 -0
  259. package/dist/src/connectors/composio-triggers.d.ts +17 -0
  260. package/dist/src/connectors/composio-triggers.js +48 -5
  261. package/dist/src/connectors/composio-triggers.js.map +1 -1
  262. package/dist/src/connectors/composio.d.ts +31 -2
  263. package/dist/src/connectors/composio.js +374 -151
  264. package/dist/src/connectors/composio.js.map +1 -1
  265. package/dist/src/connectors/connector-memory-sync.d.ts +15 -0
  266. package/dist/src/connectors/connector-memory-sync.js +90 -0
  267. package/dist/src/connectors/connector-memory-sync.js.map +1 -0
  268. package/dist/src/connectors/install.js +35 -92
  269. package/dist/src/connectors/install.js.map +1 -1
  270. package/dist/src/connectors/instances.js +6 -2
  271. package/dist/src/connectors/instances.js.map +1 -1
  272. package/dist/src/connectors/integration-strategy.d.ts +3 -0
  273. package/dist/src/connectors/integration-strategy.js +29 -0
  274. package/dist/src/connectors/integration-strategy.js.map +1 -0
  275. package/dist/src/connectors/policy.d.ts +13 -0
  276. package/dist/src/connectors/policy.js +48 -0
  277. package/dist/src/connectors/policy.js.map +1 -0
  278. package/dist/src/connectors/providers.js +1 -1
  279. package/dist/src/connectors/runtime-adapter-registry.d.ts +25 -0
  280. package/dist/src/connectors/runtime-adapter-registry.js +154 -0
  281. package/dist/src/connectors/runtime-adapter-registry.js.map +1 -0
  282. package/dist/src/connectors/types.d.ts +113 -4
  283. package/dist/src/connectors/workflow-preflight.d.ts +20 -0
  284. package/dist/src/connectors/workflow-preflight.js +70 -0
  285. package/dist/src/connectors/workflow-preflight.js.map +1 -0
  286. package/dist/src/extensions/install-transaction.d.ts +16 -0
  287. package/dist/src/extensions/install-transaction.js +76 -0
  288. package/dist/src/extensions/install-transaction.js.map +1 -0
  289. package/dist/src/extensions/install.d.ts +2 -0
  290. package/dist/src/extensions/install.js +23 -1
  291. package/dist/src/extensions/install.js.map +1 -1
  292. package/dist/src/gateway/agents-admin.d.ts +2 -0
  293. package/dist/src/gateway/agents-admin.js +7 -0
  294. package/dist/src/gateway/agents-admin.js.map +1 -1
  295. package/dist/src/gateway/capability-presets-admin.d.ts +11 -0
  296. package/dist/src/gateway/capability-presets-admin.js +11 -4
  297. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  298. package/dist/src/gateway/chat-stream/mapper.js +17 -0
  299. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  300. package/dist/src/gateway/chat-stream/protocol.d.ts +18 -1
  301. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -3
  302. package/dist/src/gateway/hono/routes/agents.js +3 -0
  303. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  304. package/dist/src/gateway/hono/routes/capability-presets.js +19 -1
  305. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -1
  306. package/dist/src/gateway/hono/routes/connectors.js +188 -25
  307. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  308. package/dist/src/gateway/hono/routes/goals.js +22 -3
  309. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  310. package/dist/src/gateway/hono/routes/home.d.ts +60 -1
  311. package/dist/src/gateway/hono/routes/home.js +244 -18
  312. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  313. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  314. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  315. package/dist/src/gateway/hono/routes/memory.js +14 -1
  316. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  317. package/dist/src/gateway/hono/routes/projects.js +103 -2
  318. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  319. package/dist/src/gateway/hono/routes/public-gateway.js +93 -0
  320. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  321. package/dist/src/gateway/hono/routes/workflows.js +137 -22
  322. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  323. package/dist/src/gateway/hono/routes/you.d.ts +23 -0
  324. package/dist/src/gateway/hono/routes/you.js +538 -0
  325. package/dist/src/gateway/hono/routes/you.js.map +1 -0
  326. package/dist/src/gateway/hono/sse.d.ts +2 -1
  327. package/dist/src/gateway/hono/sse.js +2 -1
  328. package/dist/src/gateway/hono/sse.js.map +1 -1
  329. package/dist/src/gateway/service/marketplace-service.d.ts +13 -1
  330. package/dist/src/gateway/service/marketplace-service.js +96 -40
  331. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  332. package/dist/src/gateway/service.d.ts +2 -0
  333. package/dist/src/gateway/service.js +7 -1
  334. package/dist/src/gateway/service.js.map +1 -1
  335. package/dist/src/goals/goal-service.d.ts +7 -5
  336. package/dist/src/goals/goal-service.js +25 -13
  337. package/dist/src/goals/goal-service.js.map +1 -1
  338. package/dist/src/goals/goal-store.js +46 -7
  339. package/dist/src/goals/goal-store.js.map +1 -1
  340. package/dist/src/goals/types.d.ts +24 -0
  341. package/dist/src/storage/sqlite/connector-repository.d.ts +49 -0
  342. package/dist/src/storage/sqlite/connector-repository.js +385 -0
  343. package/dist/src/storage/sqlite/connector-repository.js.map +1 -0
  344. package/dist/src/storage/sqlite/index.d.ts +3 -0
  345. package/dist/src/storage/sqlite/index.js +4 -1
  346. package/dist/src/storage/sqlite/migrations/030_connectors.sql +94 -0
  347. package/dist/src/storage/sqlite/migrations/031_connector_approvals.sql +24 -0
  348. package/dist/src/storage/sqlite/migrations/032_connector_webhook_deliveries.sql +15 -0
  349. package/dist/src/storage/sqlite/migrations/033_user_trust_policies.sql +6 -0
  350. package/dist/src/storage/sqlite/migrations/034_allow_global_auto_trust.sql +14 -0
  351. package/dist/src/storage/sqlite/migrations/035_user_profile_prompt_state.sql +7 -0
  352. package/dist/src/storage/sqlite/migrations/036_goal_outcome_metric.sql +12 -0
  353. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  354. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  355. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  356. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  357. package/dist/src/storage/sqlite/schema.js +1 -1
  358. package/dist/src/storage/sqlite/user-profile-setup-repository.d.ts +3 -0
  359. package/dist/src/storage/sqlite/user-profile-setup-repository.js +34 -0
  360. package/dist/src/storage/sqlite/user-profile-setup-repository.js.map +1 -0
  361. package/dist/src/storage/sqlite/user-trust-repository.d.ts +3 -0
  362. package/dist/src/storage/sqlite/user-trust-repository.js +34 -0
  363. package/dist/src/storage/sqlite/user-trust-repository.js.map +1 -0
  364. package/dist/src/tui/components/assistant-message.js +15 -0
  365. package/dist/src/tui/components/assistant-message.js.map +1 -1
  366. package/dist/src/tui/tui-agent-events.js +85 -1
  367. package/dist/src/tui/tui-agent-events.js.map +1 -1
  368. package/dist/src/tui/tui-command-formatters.js +7 -7
  369. package/dist/src/tui/tui-command-formatters.js.map +1 -1
  370. package/dist/src/tui/tui-commands.js +1 -1
  371. package/dist/src/tui/tui-startup-resources.js +1 -1
  372. package/dist/src/user-context/import.d.ts +12 -0
  373. package/dist/src/user-context/import.js +48 -0
  374. package/dist/src/user-context/import.js.map +1 -0
  375. package/dist/src/user-context/profile.d.ts +37 -0
  376. package/dist/src/user-context/profile.js +165 -0
  377. package/dist/src/user-context/profile.js.map +1 -0
  378. package/dist/src/user-context/projection.d.ts +54 -0
  379. package/dist/src/user-context/projection.js +121 -0
  380. package/dist/src/user-context/projection.js.map +1 -0
  381. package/dist/src/user-context/source-recommendations.d.ts +13 -0
  382. package/dist/src/user-context/source-recommendations.js +86 -0
  383. package/dist/src/user-context/source-recommendations.js.map +1 -0
  384. package/dist/src/user-context/trust-policy.d.ts +11 -0
  385. package/dist/src/user-context/trust-policy.js +31 -0
  386. package/dist/src/user-context/trust-policy.js.map +1 -0
  387. package/dist/src/workflows/authoring/index.d.ts +1 -0
  388. package/dist/src/workflows/authoring/index.js +2 -0
  389. package/dist/src/workflows/authoring/workflow-draft-store.d.ts +33 -0
  390. package/dist/src/workflows/authoring/workflow-draft-store.js +74 -0
  391. package/dist/src/workflows/authoring/workflow-draft-store.js.map +1 -0
  392. package/dist/src/workflows/domain/definition-utils.d.ts +6 -4
  393. package/dist/src/workflows/domain/definition-utils.js +28 -26
  394. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  395. package/dist/src/workflows/domain/definition.d.ts +79 -6
  396. package/dist/src/workflows/domain/event.d.ts +18 -2
  397. package/dist/src/workflows/domain/index.js +3 -3
  398. package/dist/src/workflows/domain/run.d.ts +16 -2
  399. package/dist/src/workflows/domain/run.js.map +1 -1
  400. package/dist/src/workflows/domain/validation.d.ts +9 -5
  401. package/dist/src/workflows/domain/validation.js +183 -40
  402. package/dist/src/workflows/domain/validation.js.map +1 -1
  403. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +2 -3
  404. package/dist/src/workflows/draft/workflow-draft-prompt.js +31 -73
  405. package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -1
  406. package/dist/src/workflows/draft/workflow-draft-service.js +4 -8
  407. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -1
  408. package/dist/src/workflows/draft/workflow-draft-validator.js +29 -37
  409. package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -1
  410. package/dist/src/workflows/draft/workflow-draft.types.d.ts +4 -4
  411. package/dist/src/workflows/engine/projector.js +43 -1
  412. package/dist/src/workflows/engine/projector.js.map +1 -1
  413. package/dist/src/workflows/engine/workflow-engine.d.ts +2 -3
  414. package/dist/src/workflows/engine/workflow-engine.js +24 -4
  415. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  416. package/dist/src/workflows/index.js +4 -7
  417. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +1 -9
  418. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -1
  419. package/dist/src/workflows/runtime/graph-workflow-runtime.d.ts +10 -0
  420. package/dist/src/workflows/runtime/graph-workflow-runtime.js +295 -0
  421. package/dist/src/workflows/runtime/graph-workflow-runtime.js.map +1 -0
  422. package/dist/src/workflows/runtime/index.d.ts +1 -2
  423. package/dist/src/workflows/runtime/index.js +2 -5
  424. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +5 -8
  425. package/dist/src/workflows/service/workflow-run-service.js +15 -1
  426. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  427. package/dist/src/workflows/service/workflow-run-service.types.d.ts +2 -1
  428. package/package.json +4 -3
  429. package/dist/gateway/static/root/assets/agents-CyvCIHnB.js +0 -2
  430. package/dist/gateway/static/root/assets/apps-page-DK_Vx6nl.js +0 -1
  431. package/dist/gateway/static/root/assets/automation-suggestion-card-B1LV3YYv.js +0 -1
  432. package/dist/gateway/static/root/assets/automations-page-fzrovqhv.js +0 -4
  433. package/dist/gateway/static/root/assets/block-editor-Dhj5f4Bx.js +0 -184
  434. package/dist/gateway/static/root/assets/browser-settings-page-BDn-n-UB.js +0 -8
  435. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Co5ipo_Q.js +0 -1
  436. package/dist/gateway/static/root/assets/channels-settings-BWlpaxg9.js +0 -1
  437. package/dist/gateway/static/root/assets/channels-status-swr-D_jkIZLV.js +0 -1
  438. package/dist/gateway/static/root/assets/connectors-page-BcekbW4q.js +0 -2
  439. package/dist/gateway/static/root/assets/desktop-pet-settings-BJCUuL8Y.js +0 -1
  440. package/dist/gateway/static/root/assets/dreaming-settings-BN1Z2mIo.js +0 -3
  441. package/dist/gateway/static/root/assets/extension-page-B-1KxvVy.js +0 -1
  442. package/dist/gateway/static/root/assets/extension-settings-page-BF9NACI3.js +0 -1
  443. package/dist/gateway/static/root/assets/gateway-settings-DN9sNREz.js +0 -1
  444. package/dist/gateway/static/root/assets/goal-create-dialog-BpoQW8cD.js +0 -1
  445. package/dist/gateway/static/root/assets/goal-detail-page-CBRSPd0b.js +0 -4
  446. package/dist/gateway/static/root/assets/goals-page-BCcBi407.js +0 -2
  447. package/dist/gateway/static/root/assets/goals-settings-pkTXzXkh.js +0 -1
  448. package/dist/gateway/static/root/assets/heartbeat-settings-ezsufgLQ.js +0 -1
  449. package/dist/gateway/static/root/assets/index-B8s8Pq5U.css +0 -1
  450. package/dist/gateway/static/root/assets/index-DcUaXYeb.js +0 -262
  451. package/dist/gateway/static/root/assets/logs-page-DQtTRXtj.js +0 -7
  452. package/dist/gateway/static/root/assets/messages-BXNELNBa.js +0 -3
  453. package/dist/gateway/static/root/assets/models-hub-panel-BP2M9n6Q.js +0 -2
  454. package/dist/gateway/static/root/assets/notes-page-CspveYaO.js +0 -1
  455. package/dist/gateway/static/root/assets/notes-workbench-BHwzJ0OC.js +0 -2
  456. package/dist/gateway/static/root/assets/project-detail-page-Dy3rsobs.js +0 -1
  457. package/dist/gateway/static/root/assets/projects-page-CWKpPE0L.js +0 -1
  458. package/dist/gateway/static/root/assets/remote-access-hub-CqNRyXEo.js +0 -1
  459. package/dist/gateway/static/root/assets/sessions-page-MEME7ivF.js +0 -1
  460. package/dist/gateway/static/root/assets/settings-advanced-gate-JVd0qaSF.js +0 -1
  461. package/dist/gateway/static/root/assets/settings-page-DYEbB1EV.js +0 -1
  462. package/dist/gateway/static/root/assets/setup-status-panel-dWN8BJ3z.js +0 -1
  463. package/dist/gateway/static/root/assets/share-preview-page-D8foINzP.js +0 -2
  464. package/dist/gateway/static/root/assets/shares-settings-Tgbv1s7G.js +0 -1
  465. package/dist/gateway/static/root/assets/skill-reload-api-D_YK0b_Z.js +0 -1
  466. package/dist/gateway/static/root/assets/skills-page-DGytfoZK.js +0 -2
  467. package/dist/gateway/static/root/assets/toast-z0toXu32.js +0 -1
  468. package/dist/gateway/static/root/assets/user-profile-settings-panel-8YtygcJp.js +0 -1
  469. package/dist/gateway/static/root/assets/voice-api-key-field-BVH71EFf.js +0 -1
  470. package/dist/gateway/static/root/assets/work-item-detail-page-JeTE7XNM.js +0 -1
  471. package/dist/gateway/static/root/assets/workflow-start-dialog-_u8Uc1ze.js +0 -1
  472. package/dist/gateway/static/root/assets/workflows-page-ixgk_y1l.js +0 -18
  473. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +0 -13
  474. package/dist/src/agent/workflow/builtins/audit-repo.js +0 -183
  475. package/dist/src/agent/workflow/builtins/audit-repo.js.map +0 -1
  476. package/dist/src/agent/workflow/builtins/client-proposal.d.ts +0 -12
  477. package/dist/src/agent/workflow/builtins/client-proposal.js +0 -164
  478. package/dist/src/agent/workflow/builtins/client-proposal.js.map +0 -1
  479. package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +0 -12
  480. package/dist/src/agent/workflow/builtins/competitor-scan.js +0 -164
  481. package/dist/src/agent/workflow/builtins/competitor-scan.js.map +0 -1
  482. package/dist/src/agent/workflow/builtins/content-draft.d.ts +0 -13
  483. package/dist/src/agent/workflow/builtins/content-draft.js +0 -159
  484. package/dist/src/agent/workflow/builtins/content-draft.js.map +0 -1
  485. package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +0 -11
  486. package/dist/src/agent/workflow/builtins/content-repurpose.js +0 -146
  487. package/dist/src/agent/workflow/builtins/content-repurpose.js.map +0 -1
  488. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +0 -13
  489. package/dist/src/agent/workflow/builtins/debug-incident.js +0 -177
  490. package/dist/src/agent/workflow/builtins/debug-incident.js.map +0 -1
  491. package/dist/src/agent/workflow/builtins/decision-compare.d.ts +0 -13
  492. package/dist/src/agent/workflow/builtins/decision-compare.js +0 -187
  493. package/dist/src/agent/workflow/builtins/decision-compare.js.map +0 -1
  494. package/dist/src/agent/workflow/builtins/implementation-plan.d.ts +0 -12
  495. package/dist/src/agent/workflow/builtins/implementation-plan.js +0 -185
  496. package/dist/src/agent/workflow/builtins/implementation-plan.js.map +0 -1
  497. package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +0 -11
  498. package/dist/src/agent/workflow/builtins/inbox-triage.js +0 -158
  499. package/dist/src/agent/workflow/builtins/inbox-triage.js.map +0 -1
  500. package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +0 -12
  501. package/dist/src/agent/workflow/builtins/meeting-prep.js +0 -152
  502. package/dist/src/agent/workflow/builtins/meeting-prep.js.map +0 -1
  503. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +0 -14
  504. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +0 -171
  505. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +0 -1
  506. package/dist/src/agent/workflow/builtins/offer-design.d.ts +0 -12
  507. package/dist/src/agent/workflow/builtins/offer-design.js +0 -170
  508. package/dist/src/agent/workflow/builtins/offer-design.js.map +0 -1
  509. package/dist/src/agent/workflow/builtins/pr-review.d.ts +0 -12
  510. package/dist/src/agent/workflow/builtins/pr-review.js +0 -178
  511. package/dist/src/agent/workflow/builtins/pr-review.js.map +0 -1
  512. package/dist/src/agent/workflow/builtins/release-check.d.ts +0 -11
  513. package/dist/src/agent/workflow/builtins/release-check.js +0 -174
  514. package/dist/src/agent/workflow/builtins/release-check.js.map +0 -1
  515. package/dist/src/agent/workflow/builtins/research.d.ts +0 -13
  516. package/dist/src/agent/workflow/builtins/research.js +0 -188
  517. package/dist/src/agent/workflow/builtins/research.js.map +0 -1
  518. package/dist/src/agent/workflow/builtins/weekly-review.d.ts +0 -12
  519. package/dist/src/agent/workflow/builtins/weekly-review.js +0 -139
  520. package/dist/src/agent/workflow/builtins/weekly-review.js.map +0 -1
  521. package/dist/src/agent/workflow/last-run-memory.d.ts +0 -42
  522. package/dist/src/agent/workflow/last-run-memory.js +0 -60
  523. package/dist/src/agent/workflow/last-run-memory.js.map +0 -1
  524. package/dist/src/agent/workflow/lint.d.ts +0 -38
  525. package/dist/src/agent/workflow/lint.js +0 -74
  526. package/dist/src/agent/workflow/lint.js.map +0 -1
  527. package/dist/src/agent/workflow/meta-locale.d.ts +0 -12
  528. package/dist/src/agent/workflow/meta-locale.js +0 -62
  529. package/dist/src/agent/workflow/meta-locale.js.map +0 -1
  530. package/dist/src/agent/workflow/parser.d.ts +0 -20
  531. package/dist/src/agent/workflow/parser.js +0 -152
  532. package/dist/src/agent/workflow/parser.js.map +0 -1
  533. package/dist/src/agent/workflow/runtime.d.ts +0 -34
  534. package/dist/src/agent/workflow/runtime.js +0 -402
  535. package/dist/src/agent/workflow/runtime.js.map +0 -1
  536. package/dist/src/connectors/oauth.d.ts +0 -22
  537. package/dist/src/connectors/oauth.js +0 -99
  538. package/dist/src/connectors/oauth.js.map +0 -1
  539. package/dist/src/workflows/runtime/script-runtime.d.ts +0 -3
  540. package/dist/src/workflows/runtime/script-runtime.js +0 -3
  541. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +0 -5
  542. package/dist/src/workflows/runtime/script-workflow-runtime.js +0 -15
  543. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +0 -1
@@ -283,26 +283,46 @@ function spawnDetached(command, args) {
283
283
  detached: true
284
284
  }).unref();
285
285
  }
286
- function openChromeExtensionsPage() {
287
- const chromeUrl = "chrome://extensions";
286
+ function windowsExtensionManagerCandidates(env) {
287
+ const programFiles = [
288
+ env.PROGRAMFILES,
289
+ env["PROGRAMFILES(X86)"],
290
+ env.LOCALAPPDATA
291
+ ].filter((path) => Boolean(path?.trim()));
292
+ const candidates = [];
293
+ for (const root of programFiles) candidates.push({
294
+ browser: "chrome",
295
+ executablePath: join(root, "Google", "Chrome", "Application", "chrome.exe"),
296
+ url: "chrome://extensions/"
297
+ });
298
+ for (const root of programFiles) candidates.push({
299
+ browser: "edge",
300
+ executablePath: join(root, "Microsoft", "Edge", "Application", "msedge.exe"),
301
+ url: "edge://extensions/"
302
+ });
303
+ return candidates;
304
+ }
305
+ function resolveWindowsExtensionManager(env = process.env) {
306
+ return windowsExtensionManagerCandidates(env).find(({ executablePath }) => existsSync(executablePath)) ?? null;
307
+ }
308
+ function openBrowserExtensionManager() {
309
+ const chromeUrl = "chrome://extensions/";
288
310
  if (process.platform === "darwin") {
289
311
  spawnDetached("open", [
290
312
  "-a",
291
313
  "Google Chrome",
292
314
  chromeUrl
293
315
  ]);
294
- return;
316
+ return "chrome";
295
317
  }
296
318
  if (process.platform === "win32") {
297
- spawnDetached("cmd", [
298
- "/c",
299
- "start",
300
- "chrome",
301
- chromeUrl
302
- ]);
303
- return;
319
+ const target = resolveWindowsExtensionManager();
320
+ if (!target) throw new Error("No compatible browser found. Install Google Chrome or Microsoft Edge, then try again.");
321
+ spawnDetached(target.executablePath, [target.url]);
322
+ return target.browser;
304
323
  }
305
324
  spawnDetached("xdg-open", [chromeUrl]);
325
+ return "chrome";
306
326
  }
307
327
  function revealFolderInFileManager(dir) {
308
328
  if (process.platform === "darwin") {
@@ -316,16 +336,21 @@ function revealFolderInFileManager(dir) {
316
336
  spawnDetached("xdg-open", [dir]);
317
337
  }
318
338
  /**
319
- * Open chrome://extensions and/or reveal the installed extension folder on the gateway host.
339
+ * Open the compatible browser's extension manager and/or reveal the installed extension folder
340
+ * on the gateway host.
320
341
  */
321
342
  async function openBrowserExtensionInstallUi(opts) {
322
343
  const dir = (await browserExtDoctor({ cacheDir: opts.cacheDir })).extensionDir;
323
344
  if (!dir) throw new Error("Extension not installed. Run xopc browser extension install first.");
324
- if (opts.action === "chrome" || opts.action === "both") openChromeExtensionsPage();
345
+ let browser;
346
+ if (opts.action === "chrome" || opts.action === "both") browser = openBrowserExtensionManager();
325
347
  if (opts.action === "folder" || opts.action === "both") revealFolderInFileManager(dir);
326
- return { extensionDir: dir };
348
+ return {
349
+ extensionDir: dir,
350
+ browser
351
+ };
327
352
  }
328
353
  //#endregion
329
- export { BROWSER_EXT_REQUIRED_FILES, browserExtDoctor, computeNeedsRefresh, ensureBrowserExtensionArtifacts, ensureBrowserExtensionOnStartup, openBrowserExtensionInstallUi, readInstalledExtensionDir, resolveBundledBrowserExtDir, resolveInstalledExtensionPath, validateBrowserExtLayout };
354
+ export { BROWSER_EXT_REQUIRED_FILES, browserExtDoctor, computeNeedsRefresh, ensureBrowserExtensionArtifacts, ensureBrowserExtensionOnStartup, openBrowserExtensionInstallUi, readInstalledExtensionDir, resolveBundledBrowserExtDir, resolveInstalledExtensionPath, resolveWindowsExtensionManager, validateBrowserExtLayout };
330
355
 
331
356
  //# sourceMappingURL=browser-ext-install.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser-ext-install.js","names":[],"sources":["../../../../src/browser/providers/browser-ext-install.ts"],"sourcesContent":["/**\n * Install bundled Chrome extension artifacts into {resolveBinDir()}/browser-ext/.\n * Fixed path — gateway upgrades overwrite in place so Chrome sideload paths stay stable.\n */\n\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { readFile, readdir, rm } from 'node:fs/promises';\nimport { spawn } from 'node:child_process';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { resolveBinDir } from '../../config/paths.js';\nimport { resolvePackageRoot } from '../../infra/update-check.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { assertCacheDir } from '../cache-dir-policy.js';\n\nconst log = createLogger('BrowserExtInstall');\n\nconst META_FILENAME = '.meta.json';\nconst STAGING_MAX_AGE_MS = 60 * 60 * 1000;\nconst INSTALLED_ARTIFACT_NAMES = ['manifest.json', 'popup.html', 'dist', 'icons'] as const;\n\nexport const BROWSER_EXT_REQUIRED_FILES = [\n 'manifest.json',\n 'popup.html',\n 'dist/background.js',\n 'dist/content.js',\n 'dist/popup.js',\n] as const;\n\nexport type BrowserExtBundledFrom = 'npm-dist' | 'git-dev' | 'electron-asar' | 'env-override';\n\nexport interface BrowserExtInstallMeta {\n xopcVersion: string;\n manifestVersion: string;\n source: 'bundled';\n bundledFrom: BrowserExtBundledFrom;\n installedAt: string;\n installPath: string;\n}\n\nexport interface BrowserExtDoctor {\n bundledAvailable: boolean;\n installed: boolean;\n xopcVersion: string;\n installedVersion?: string;\n manifestVersion?: string;\n extensionDir?: string;\n cacheDir: string;\n needsRefresh: boolean;\n needsChromeReload?: boolean;\n bundledFrom?: BrowserExtBundledFrom;\n runtimeExtensionVersion?: string;\n}\n\nexport interface EnsureBrowserExtResult {\n extensionDir: string;\n xopcVersion: string;\n copied: boolean;\n}\n\nfunction moduleDir(): string {\n return dirname(fileURLToPath(import.meta.url));\n}\n\n/** Validate a directory contains a loadable extension tree. */\nexport function validateBrowserExtLayout(dir: string): boolean {\n return BROWSER_EXT_REQUIRED_FILES.every((rel) => existsSync(join(dir, rel)));\n}\n\nfunction readManifestVersion(dir: string): string | undefined {\n try {\n const raw = readFileSync(join(dir, 'manifest.json'), 'utf8');\n const parsed = JSON.parse(raw) as { version?: unknown };\n return typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function readMeta(metaPath: string): Promise<BrowserExtInstallMeta | null> {\n try {\n const raw = await readFile(metaPath, 'utf8');\n const parsed = JSON.parse(raw) as BrowserExtInstallMeta;\n if (parsed && typeof parsed === 'object' && typeof parsed.xopcVersion === 'string') {\n return parsed;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction browserExtRoot(cacheDir: string): string {\n return join(cacheDir, 'browser-ext');\n}\n\nfunction resolveMetaPath(cacheDir: string): string {\n return join(browserExtRoot(cacheDir), META_FILENAME);\n}\n\n/** Resolve the installed extension directory (fixed `browser-ext/` root). */\nexport function resolveInstalledExtensionPath(\n cacheDir: string,\n _meta: BrowserExtInstallMeta | null,\n): string | null {\n const root = browserExtRoot(cacheDir);\n if (validateBrowserExtLayout(root)) {\n return root;\n }\n\n return null;\n}\n\nfunction walkAncestorsForGitDevBundled(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 12; i++) {\n const candidate = join(dir, 'packages/browser-ext');\n if (validateBrowserExtLayout(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/**\n * Resolve the bundled extension source directory (read-only).\n */\nexport async function resolveBundledBrowserExtDir(): Promise<{\n dir: string;\n bundledFrom: BrowserExtBundledFrom;\n} | null> {\n const envOverride = process.env.XOPC_BROWSER_EXT_BUNDLED_ROOT?.trim();\n if (envOverride && validateBrowserExtLayout(envOverride)) {\n return { dir: envOverride, bundledFrom: 'env-override' };\n }\n\n const fromModule = join(moduleDir(), '../../../browser-ext');\n if (validateBrowserExtLayout(fromModule)) {\n const root = await resolvePackageRoot();\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: fromModule, bundledFrom };\n }\n\n const gitDev = walkAncestorsForGitDevBundled(moduleDir());\n if (gitDev) {\n return { dir: gitDev, bundledFrom: 'git-dev' };\n }\n\n const root = await resolvePackageRoot();\n if (root) {\n const distBundled = join(root, 'dist/browser-ext');\n if (validateBrowserExtLayout(distBundled)) {\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: distBundled, bundledFrom };\n }\n }\n\n return null;\n}\n\nexport function computeNeedsRefresh(params: {\n force?: boolean;\n bundledManifestVersion: string;\n installedPath: string | null;\n meta: BrowserExtInstallMeta | null;\n}): boolean {\n if (params.force) return true;\n if (!params.installedPath || !validateBrowserExtLayout(params.installedPath)) return true;\n\n const installedManifest = readManifestVersion(params.installedPath);\n if (!installedManifest || installedManifest !== params.bundledManifestVersion) return true;\n\n if (!params.meta || params.meta.xopcVersion !== PACKAGE_VERSION) return true;\n\n return false;\n}\n\nasync function cleanupStaleStaging(root: string): Promise<void> {\n if (!existsSync(root)) return;\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return;\n }\n const now = Date.now();\n for (const name of entries) {\n if (!name.startsWith('.staging-')) continue;\n const full = join(root, name);\n try {\n const st = statSync(full);\n if (now - st.mtimeMs > STAGING_MAX_AGE_MS) {\n await rm(full, { recursive: true, force: true });\n }\n } catch {\n /* */\n }\n }\n}\n\nfunction removeInstalledArtifacts(root: string): void {\n for (const name of INSTALLED_ARTIFACT_NAMES) {\n const full = join(root, name);\n if (existsSync(full)) {\n rmSync(full, { recursive: true, force: true });\n }\n }\n}\n\nfunction promoteStagingToRoot(stagingDir: string, root: string): void {\n removeInstalledArtifacts(root);\n for (const name of readdirSync(stagingDir)) {\n renameSync(join(stagingDir, name), join(root, name));\n }\n rmSync(stagingDir, { recursive: true, force: true });\n if (!validateBrowserExtLayout(root)) {\n throw new Error('Bundled browser extension copy failed validation');\n }\n}\n\n/** Copy one bundled file (read/write works when src is inside Electron app.asar). */\nfunction copyBundledFile(src: string, dest: string): void {\n mkdirSync(dirname(dest), { recursive: true });\n writeFileSync(dest, readFileSync(src));\n}\n\nconst BROWSER_EXT_DIST_FILES = ['background.js', 'content.js', 'popup.js'] as const;\nconst BROWSER_EXT_ICON_FILES = ['icon-16.png', 'icon-32.png', 'icon-48.png', 'icon-128.png'] as const;\n\nfunction copyBundledTree(src: string, dest: string): void {\n mkdirSync(dest, { recursive: true });\n for (const name of ['manifest.json', 'popup.html']) {\n copyBundledFile(join(src, name), join(dest, name));\n }\n for (const file of BROWSER_EXT_DIST_FILES) {\n copyBundledFile(join(src, 'dist', file), join(dest, 'dist', file));\n }\n for (const icon of BROWSER_EXT_ICON_FILES) {\n const iconSrc = join(src, 'icons', icon);\n if (existsSync(iconSrc)) {\n copyBundledFile(iconSrc, join(dest, 'icons', icon));\n }\n }\n if (!validateBrowserExtLayout(dest)) {\n throw new Error('Bundled browser extension copy failed validation');\n }\n}\n\nexport async function browserExtDoctor(opts?: {\n cacheDir?: string;\n runtimeExtensionVersion?: string;\n}): Promise<BrowserExtDoctor> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n const bundledManifestVersion = bundled ? readManifestVersion(bundled.dir) : undefined;\n const meta = await readMeta(resolveMetaPath(cacheDir));\n const installedPath = resolveInstalledExtensionPath(cacheDir, meta);\n\n const needsRefresh = bundled\n ? computeNeedsRefresh({\n force: false,\n bundledManifestVersion: bundledManifestVersion ?? PACKAGE_VERSION,\n installedPath,\n meta,\n })\n : false;\n\n const installed = Boolean(installedPath) && !needsRefresh;\n const manifestVersion = installedPath ? readManifestVersion(installedPath) : undefined;\n\n let needsChromeReload: boolean | undefined;\n const runtimeVer = opts?.runtimeExtensionVersion?.trim();\n if (runtimeVer && manifestVersion && runtimeVer !== manifestVersion) {\n needsChromeReload = true;\n }\n\n return {\n bundledAvailable: Boolean(bundled),\n installed,\n xopcVersion: PACKAGE_VERSION,\n installedVersion: meta?.xopcVersion,\n manifestVersion,\n extensionDir: installedPath ?? undefined,\n cacheDir,\n needsRefresh,\n needsChromeReload,\n bundledFrom: bundled?.bundledFrom,\n runtimeExtensionVersion: runtimeVer,\n };\n}\n\nexport async function ensureBrowserExtensionArtifacts(opts?: {\n force?: boolean;\n cacheDir?: string;\n}): Promise<EnsureBrowserExtResult> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n if (!bundled) {\n throw new Error(\n 'Bundled browser extension not found. Reinstall xopc or run from a built checkout (pnpm run build).',\n );\n }\n\n const bundledManifestVersion = readManifestVersion(bundled.dir) ?? PACKAGE_VERSION;\n const root = browserExtRoot(cacheDir);\n mkdirSync(root, { recursive: true });\n await cleanupStaleStaging(root);\n\n const meta = await readMeta(resolveMetaPath(cacheDir));\n const installedPath = resolveInstalledExtensionPath(cacheDir, meta);\n const needsRefresh = computeNeedsRefresh({\n force: opts?.force,\n bundledManifestVersion,\n installedPath,\n meta,\n });\n\n const extensionDir = root;\n\n if (!needsRefresh && installedPath) {\n return {\n extensionDir: installedPath,\n xopcVersion: PACKAGE_VERSION,\n copied: false,\n };\n }\n\n const stagingDir = join(root, `.staging-${process.pid}`);\n\n if (existsSync(stagingDir)) {\n rmSync(stagingDir, { recursive: true, force: true });\n }\n copyBundledTree(bundled.dir, stagingDir);\n promoteStagingToRoot(stagingDir, root);\n\n const nextMeta: BrowserExtInstallMeta = {\n xopcVersion: PACKAGE_VERSION,\n manifestVersion: bundledManifestVersion,\n source: 'bundled',\n bundledFrom: bundled.bundledFrom,\n installedAt: new Date().toISOString(),\n installPath: extensionDir,\n };\n await writeTextAtomic(resolveMetaPath(cacheDir), JSON.stringify(nextMeta, null, 2));\n\n log.info(\n { extensionDir, xopcVersion: PACKAGE_VERSION, bundledFrom: bundled.bundledFrom },\n 'Browser extension artifacts installed',\n );\n\n return {\n extensionDir,\n xopcVersion: PACKAGE_VERSION,\n copied: true,\n };\n}\n\n/** Gateway startup hook: ensure extension artifacts for the fixed extension backend. */\nexport async function ensureBrowserExtensionOnStartup(_config: unknown): Promise<void> {\n await ensureBrowserExtensionArtifacts();\n}\n\nexport async function readInstalledExtensionDir(cacheDir?: string): Promise<string | null> {\n const dir = cacheDir?.trim() ? assertCacheDir(cacheDir) : resolveBinDir();\n const resolved = dir || resolveBinDir();\n const meta = await readMeta(resolveMetaPath(resolved));\n return resolveInstalledExtensionPath(resolved, meta);\n}\n\nexport type BrowserExtensionOpenAction = 'chrome' | 'folder' | 'both';\n\nfunction spawnDetached(command: string, args: readonly string[]): void {\n spawn(command, [...args], { stdio: 'ignore', detached: true }).unref();\n}\n\nfunction openChromeExtensionsPage(): void {\n const chromeUrl = 'chrome://extensions';\n if (process.platform === 'darwin') {\n spawnDetached('open', ['-a', 'Google Chrome', chromeUrl]);\n return;\n }\n if (process.platform === 'win32') {\n spawnDetached('cmd', ['/c', 'start', 'chrome', chromeUrl]);\n return;\n }\n spawnDetached('xdg-open', [chromeUrl]);\n}\n\nfunction revealFolderInFileManager(dir: string): void {\n if (process.platform === 'darwin') {\n spawnDetached('open', [dir]);\n return;\n }\n if (process.platform === 'win32') {\n spawnDetached('explorer', [dir]);\n return;\n }\n spawnDetached('xdg-open', [dir]);\n}\n\n/**\n * Open chrome://extensions and/or reveal the installed extension folder on the gateway host.\n */\nexport async function openBrowserExtensionInstallUi(opts: {\n action: BrowserExtensionOpenAction;\n cacheDir?: string;\n}): Promise<{ extensionDir: string }> {\n const doctor = await browserExtDoctor({ cacheDir: opts.cacheDir });\n const dir = doctor.extensionDir;\n if (!dir) {\n throw new Error('Extension not installed. Run xopc browser extension install first.');\n }\n\n if (opts.action === 'chrome' || opts.action === 'both') {\n openChromeExtensionsPage();\n }\n if (opts.action === 'folder' || opts.action === 'both') {\n revealFolderInFileManager(dir);\n }\n\n return { extensionDir: dir };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"browser-ext-install.js","names":[],"sources":["../../../../src/browser/providers/browser-ext-install.ts"],"sourcesContent":["/**\n * Install bundled Chrome extension artifacts into {resolveBinDir()}/browser-ext/.\n * Fixed path — gateway upgrades overwrite in place so Chrome sideload paths stay stable.\n */\n\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from 'node:fs';\nimport { readFile, readdir, rm } from 'node:fs/promises';\nimport { spawn } from 'node:child_process';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { resolveBinDir } from '../../config/paths.js';\nimport { resolvePackageRoot } from '../../infra/update-check.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { assertCacheDir } from '../cache-dir-policy.js';\n\nconst log = createLogger('BrowserExtInstall');\n\nconst META_FILENAME = '.meta.json';\nconst STAGING_MAX_AGE_MS = 60 * 60 * 1000;\nconst INSTALLED_ARTIFACT_NAMES = ['manifest.json', 'popup.html', 'dist', 'icons'] as const;\n\nexport const BROWSER_EXT_REQUIRED_FILES = [\n 'manifest.json',\n 'popup.html',\n 'dist/background.js',\n 'dist/content.js',\n 'dist/popup.js',\n] as const;\n\nexport type BrowserExtBundledFrom = 'npm-dist' | 'git-dev' | 'electron-asar' | 'env-override';\n\nexport interface BrowserExtInstallMeta {\n xopcVersion: string;\n manifestVersion: string;\n source: 'bundled';\n bundledFrom: BrowserExtBundledFrom;\n installedAt: string;\n installPath: string;\n}\n\nexport interface BrowserExtDoctor {\n bundledAvailable: boolean;\n installed: boolean;\n xopcVersion: string;\n installedVersion?: string;\n manifestVersion?: string;\n extensionDir?: string;\n cacheDir: string;\n needsRefresh: boolean;\n needsChromeReload?: boolean;\n bundledFrom?: BrowserExtBundledFrom;\n runtimeExtensionVersion?: string;\n}\n\nexport interface EnsureBrowserExtResult {\n extensionDir: string;\n xopcVersion: string;\n copied: boolean;\n}\n\nfunction moduleDir(): string {\n return dirname(fileURLToPath(import.meta.url));\n}\n\n/** Validate a directory contains a loadable extension tree. */\nexport function validateBrowserExtLayout(dir: string): boolean {\n return BROWSER_EXT_REQUIRED_FILES.every((rel) => existsSync(join(dir, rel)));\n}\n\nfunction readManifestVersion(dir: string): string | undefined {\n try {\n const raw = readFileSync(join(dir, 'manifest.json'), 'utf8');\n const parsed = JSON.parse(raw) as { version?: unknown };\n return typeof parsed.version === 'string' ? parsed.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function readMeta(metaPath: string): Promise<BrowserExtInstallMeta | null> {\n try {\n const raw = await readFile(metaPath, 'utf8');\n const parsed = JSON.parse(raw) as BrowserExtInstallMeta;\n if (parsed && typeof parsed === 'object' && typeof parsed.xopcVersion === 'string') {\n return parsed;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nfunction browserExtRoot(cacheDir: string): string {\n return join(cacheDir, 'browser-ext');\n}\n\nfunction resolveMetaPath(cacheDir: string): string {\n return join(browserExtRoot(cacheDir), META_FILENAME);\n}\n\n/** Resolve the installed extension directory (fixed `browser-ext/` root). */\nexport function resolveInstalledExtensionPath(\n cacheDir: string,\n _meta: BrowserExtInstallMeta | null,\n): string | null {\n const root = browserExtRoot(cacheDir);\n if (validateBrowserExtLayout(root)) {\n return root;\n }\n\n return null;\n}\n\nfunction walkAncestorsForGitDevBundled(start: string): string | null {\n let dir = start;\n for (let i = 0; i < 12; i++) {\n const candidate = join(dir, 'packages/browser-ext');\n if (validateBrowserExtLayout(candidate)) {\n return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/**\n * Resolve the bundled extension source directory (read-only).\n */\nexport async function resolveBundledBrowserExtDir(): Promise<{\n dir: string;\n bundledFrom: BrowserExtBundledFrom;\n} | null> {\n const envOverride = process.env.XOPC_BROWSER_EXT_BUNDLED_ROOT?.trim();\n if (envOverride && validateBrowserExtLayout(envOverride)) {\n return { dir: envOverride, bundledFrom: 'env-override' };\n }\n\n const fromModule = join(moduleDir(), '../../../browser-ext');\n if (validateBrowserExtLayout(fromModule)) {\n const root = await resolvePackageRoot();\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: fromModule, bundledFrom };\n }\n\n const gitDev = walkAncestorsForGitDevBundled(moduleDir());\n if (gitDev) {\n return { dir: gitDev, bundledFrom: 'git-dev' };\n }\n\n const root = await resolvePackageRoot();\n if (root) {\n const distBundled = join(root, 'dist/browser-ext');\n if (validateBrowserExtLayout(distBundled)) {\n const bundledFrom: BrowserExtBundledFrom =\n process.versions.electron && root.includes('app.asar') ? 'electron-asar' : 'npm-dist';\n return { dir: distBundled, bundledFrom };\n }\n }\n\n return null;\n}\n\nexport function computeNeedsRefresh(params: {\n force?: boolean;\n bundledManifestVersion: string;\n installedPath: string | null;\n meta: BrowserExtInstallMeta | null;\n}): boolean {\n if (params.force) return true;\n if (!params.installedPath || !validateBrowserExtLayout(params.installedPath)) return true;\n\n const installedManifest = readManifestVersion(params.installedPath);\n if (!installedManifest || installedManifest !== params.bundledManifestVersion) return true;\n\n if (!params.meta || params.meta.xopcVersion !== PACKAGE_VERSION) return true;\n\n return false;\n}\n\nasync function cleanupStaleStaging(root: string): Promise<void> {\n if (!existsSync(root)) return;\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return;\n }\n const now = Date.now();\n for (const name of entries) {\n if (!name.startsWith('.staging-')) continue;\n const full = join(root, name);\n try {\n const st = statSync(full);\n if (now - st.mtimeMs > STAGING_MAX_AGE_MS) {\n await rm(full, { recursive: true, force: true });\n }\n } catch {\n /* */\n }\n }\n}\n\nfunction removeInstalledArtifacts(root: string): void {\n for (const name of INSTALLED_ARTIFACT_NAMES) {\n const full = join(root, name);\n if (existsSync(full)) {\n rmSync(full, { recursive: true, force: true });\n }\n }\n}\n\nfunction promoteStagingToRoot(stagingDir: string, root: string): void {\n removeInstalledArtifacts(root);\n for (const name of readdirSync(stagingDir)) {\n renameSync(join(stagingDir, name), join(root, name));\n }\n rmSync(stagingDir, { recursive: true, force: true });\n if (!validateBrowserExtLayout(root)) {\n throw new Error('Bundled browser extension copy failed validation');\n }\n}\n\n/** Copy one bundled file (read/write works when src is inside Electron app.asar). */\nfunction copyBundledFile(src: string, dest: string): void {\n mkdirSync(dirname(dest), { recursive: true });\n writeFileSync(dest, readFileSync(src));\n}\n\nconst BROWSER_EXT_DIST_FILES = ['background.js', 'content.js', 'popup.js'] as const;\nconst BROWSER_EXT_ICON_FILES = ['icon-16.png', 'icon-32.png', 'icon-48.png', 'icon-128.png'] as const;\n\nfunction copyBundledTree(src: string, dest: string): void {\n mkdirSync(dest, { recursive: true });\n for (const name of ['manifest.json', 'popup.html']) {\n copyBundledFile(join(src, name), join(dest, name));\n }\n for (const file of BROWSER_EXT_DIST_FILES) {\n copyBundledFile(join(src, 'dist', file), join(dest, 'dist', file));\n }\n for (const icon of BROWSER_EXT_ICON_FILES) {\n const iconSrc = join(src, 'icons', icon);\n if (existsSync(iconSrc)) {\n copyBundledFile(iconSrc, join(dest, 'icons', icon));\n }\n }\n if (!validateBrowserExtLayout(dest)) {\n throw new Error('Bundled browser extension copy failed validation');\n }\n}\n\nexport async function browserExtDoctor(opts?: {\n cacheDir?: string;\n runtimeExtensionVersion?: string;\n}): Promise<BrowserExtDoctor> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n const bundledManifestVersion = bundled ? readManifestVersion(bundled.dir) : undefined;\n const meta = await readMeta(resolveMetaPath(cacheDir));\n const installedPath = resolveInstalledExtensionPath(cacheDir, meta);\n\n const needsRefresh = bundled\n ? computeNeedsRefresh({\n force: false,\n bundledManifestVersion: bundledManifestVersion ?? PACKAGE_VERSION,\n installedPath,\n meta,\n })\n : false;\n\n const installed = Boolean(installedPath) && !needsRefresh;\n const manifestVersion = installedPath ? readManifestVersion(installedPath) : undefined;\n\n let needsChromeReload: boolean | undefined;\n const runtimeVer = opts?.runtimeExtensionVersion?.trim();\n if (runtimeVer && manifestVersion && runtimeVer !== manifestVersion) {\n needsChromeReload = true;\n }\n\n return {\n bundledAvailable: Boolean(bundled),\n installed,\n xopcVersion: PACKAGE_VERSION,\n installedVersion: meta?.xopcVersion,\n manifestVersion,\n extensionDir: installedPath ?? undefined,\n cacheDir,\n needsRefresh,\n needsChromeReload,\n bundledFrom: bundled?.bundledFrom,\n runtimeExtensionVersion: runtimeVer,\n };\n}\n\nexport async function ensureBrowserExtensionArtifacts(opts?: {\n force?: boolean;\n cacheDir?: string;\n}): Promise<EnsureBrowserExtResult> {\n const resolvedCache = opts?.cacheDir?.trim()\n ? assertCacheDir(opts.cacheDir)\n : resolveBinDir();\n const cacheDir = resolvedCache || resolveBinDir();\n\n const bundled = await resolveBundledBrowserExtDir();\n if (!bundled) {\n throw new Error(\n 'Bundled browser extension not found. Reinstall xopc or run from a built checkout (pnpm run build).',\n );\n }\n\n const bundledManifestVersion = readManifestVersion(bundled.dir) ?? PACKAGE_VERSION;\n const root = browserExtRoot(cacheDir);\n mkdirSync(root, { recursive: true });\n await cleanupStaleStaging(root);\n\n const meta = await readMeta(resolveMetaPath(cacheDir));\n const installedPath = resolveInstalledExtensionPath(cacheDir, meta);\n const needsRefresh = computeNeedsRefresh({\n force: opts?.force,\n bundledManifestVersion,\n installedPath,\n meta,\n });\n\n const extensionDir = root;\n\n if (!needsRefresh && installedPath) {\n return {\n extensionDir: installedPath,\n xopcVersion: PACKAGE_VERSION,\n copied: false,\n };\n }\n\n const stagingDir = join(root, `.staging-${process.pid}`);\n\n if (existsSync(stagingDir)) {\n rmSync(stagingDir, { recursive: true, force: true });\n }\n copyBundledTree(bundled.dir, stagingDir);\n promoteStagingToRoot(stagingDir, root);\n\n const nextMeta: BrowserExtInstallMeta = {\n xopcVersion: PACKAGE_VERSION,\n manifestVersion: bundledManifestVersion,\n source: 'bundled',\n bundledFrom: bundled.bundledFrom,\n installedAt: new Date().toISOString(),\n installPath: extensionDir,\n };\n await writeTextAtomic(resolveMetaPath(cacheDir), JSON.stringify(nextMeta, null, 2));\n\n log.info(\n { extensionDir, xopcVersion: PACKAGE_VERSION, bundledFrom: bundled.bundledFrom },\n 'Browser extension artifacts installed',\n );\n\n return {\n extensionDir,\n xopcVersion: PACKAGE_VERSION,\n copied: true,\n };\n}\n\n/** Gateway startup hook: ensure extension artifacts for the fixed extension backend. */\nexport async function ensureBrowserExtensionOnStartup(_config: unknown): Promise<void> {\n await ensureBrowserExtensionArtifacts();\n}\n\nexport async function readInstalledExtensionDir(cacheDir?: string): Promise<string | null> {\n const dir = cacheDir?.trim() ? assertCacheDir(cacheDir) : resolveBinDir();\n const resolved = dir || resolveBinDir();\n const meta = await readMeta(resolveMetaPath(resolved));\n return resolveInstalledExtensionPath(resolved, meta);\n}\n\nexport type BrowserExtensionOpenAction = 'chrome' | 'folder' | 'both';\n\ntype ExtensionManagerBrowser = 'chrome' | 'edge';\n\ninterface ExtensionManagerTarget {\n browser: ExtensionManagerBrowser;\n executablePath: string;\n url: string;\n}\n\nfunction spawnDetached(command: string, args: readonly string[]): void {\n spawn(command, [...args], { stdio: 'ignore', detached: true }).unref();\n}\n\nfunction windowsExtensionManagerCandidates(env: NodeJS.ProcessEnv): ExtensionManagerTarget[] {\n const programFiles = [env.PROGRAMFILES, env['PROGRAMFILES(X86)'], env.LOCALAPPDATA].filter(\n (path): path is string => Boolean(path?.trim()),\n );\n const candidates: ExtensionManagerTarget[] = [];\n\n for (const root of programFiles) {\n candidates.push({\n browser: 'chrome',\n executablePath: join(root, 'Google', 'Chrome', 'Application', 'chrome.exe'),\n url: 'chrome://extensions/',\n });\n }\n for (const root of programFiles) {\n candidates.push({\n browser: 'edge',\n executablePath: join(root, 'Microsoft', 'Edge', 'Application', 'msedge.exe'),\n url: 'edge://extensions/',\n });\n }\n\n return candidates;\n}\n\nexport function resolveWindowsExtensionManager(\n env: NodeJS.ProcessEnv = process.env,\n): ExtensionManagerTarget | null {\n return windowsExtensionManagerCandidates(env).find(({ executablePath }) => existsSync(executablePath)) ?? null;\n}\n\nfunction openBrowserExtensionManager(): ExtensionManagerBrowser | undefined {\n const chromeUrl = 'chrome://extensions/';\n if (process.platform === 'darwin') {\n spawnDetached('open', ['-a', 'Google Chrome', chromeUrl]);\n return 'chrome';\n }\n if (process.platform === 'win32') {\n const target = resolveWindowsExtensionManager();\n if (!target) {\n throw new Error(\n 'No compatible browser found. Install Google Chrome or Microsoft Edge, then try again.',\n );\n }\n spawnDetached(target.executablePath, [target.url]);\n return target.browser;\n }\n spawnDetached('xdg-open', [chromeUrl]);\n return 'chrome';\n}\n\nfunction revealFolderInFileManager(dir: string): void {\n if (process.platform === 'darwin') {\n spawnDetached('open', [dir]);\n return;\n }\n if (process.platform === 'win32') {\n spawnDetached('explorer', [dir]);\n return;\n }\n spawnDetached('xdg-open', [dir]);\n}\n\n/**\n * Open the compatible browser's extension manager and/or reveal the installed extension folder\n * on the gateway host.\n */\nexport async function openBrowserExtensionInstallUi(opts: {\n action: BrowserExtensionOpenAction;\n cacheDir?: string;\n}): Promise<{ extensionDir: string; browser?: ExtensionManagerBrowser }> {\n const doctor = await browserExtDoctor({ cacheDir: opts.cacheDir });\n const dir = doctor.extensionDir;\n if (!dir) {\n throw new Error('Extension not installed. Run xopc browser extension install first.');\n }\n\n let browser: ExtensionManagerBrowser | undefined;\n if (opts.action === 'chrome' || opts.action === 'both') {\n browser = openBrowserExtensionManager();\n }\n if (opts.action === 'folder' || opts.action === 'both') {\n revealFolderInFileManager(dir);\n }\n\n return { extensionDir: dir, browser };\n}\n"],"mappings":"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"}
@@ -7,7 +7,6 @@ export type StoreConnectorInstallPlan = {
7
7
  definition: ConnectorDefinition;
8
8
  permissions: ConnectorPermissions;
9
9
  requiresRestart: false;
10
- requiresOAuth: boolean;
11
10
  };
12
11
  export declare function listStoreConnectors(config: Config, params: SkillsStoreListParams): Promise<import("../agent/skills/skills-marketplace.js").SkillsStoreListResponse>;
13
12
  export declare function getStoreConnectorInstallPlan(config: Config, packageName: string, version?: string): Promise<StoreConnectorInstallPlan>;
@@ -79,7 +79,8 @@ function readConnectorManifest(value, packageName, version, sha256) {
79
79
  const transport = serverTemplate.transport;
80
80
  if (!localPackage && transport !== "streamable-http" && transport !== "sse") throw new Error("Store connectors must use streamable-http or sse transport.");
81
81
  const authMode = asRecord(manifest.auth, "Connector auth").mode;
82
- if (authMode !== "none" && authMode !== "apiKey" && authMode !== "oauth") throw new Error("Connector auth mode must be none, apiKey, or oauth.");
82
+ if (authMode !== "none" && authMode !== "apiKey") throw new Error("Store connectors support only none or apiKey authentication.");
83
+ const normalizedAuth = { mode: authMode };
83
84
  const category = asString(manifest.category, "Connector category");
84
85
  if (![
85
86
  "code",
@@ -97,7 +98,6 @@ function readConnectorManifest(value, packageName, version, sha256) {
97
98
  "context",
98
99
  "events",
99
100
  "auth.apiKey",
100
- "auth.oauth",
101
101
  "runtime.mcp.stdio",
102
102
  "runtime.mcp.sse",
103
103
  "runtime.mcp.streamableHttp"
@@ -118,7 +118,7 @@ function readConnectorManifest(value, packageName, version, sha256) {
118
118
  source: "store",
119
119
  capabilities,
120
120
  ...Array.isArray(manifest.tags) ? { tags: asStringArray(manifest.tags, "Connector tags") } : {},
121
- auth: { mode: authMode },
121
+ auth: normalizedAuth,
122
122
  setup,
123
123
  runtime: {
124
124
  type: "mcp",
@@ -173,13 +173,11 @@ async function getStoreConnectorInstallPlan(config, packageName, version) {
173
173
  version: detail.latestVersion.version,
174
174
  permissions: definition.permissions ?? {},
175
175
  requiresRestart: false,
176
- requiresOAuth: definition.auth.mode === "oauth",
177
176
  definition
178
177
  };
179
178
  }
180
179
  async function installStoreConnector(config, packageName, input, version) {
181
180
  const plan = await getStoreConnectorInstallPlan(config, packageName, version);
182
- if (plan.requiresOAuth && plan.definition.id !== "github") throw new Error("OAuth installation for store connectors is not available yet. Use an API-key connector or the built-in GitHub connector.");
183
181
  return {
184
182
  instance: await installConnectorDefinition(config, plan.definition, input),
185
183
  plan
@@ -1 +1 @@
1
- {"version":3,"file":"store-connector.js","names":[],"sources":["../../../src/capabilities/store-connector.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { isIP } from 'node:net';\n\nimport AdmZip from 'adm-zip';\n\nimport type { Config } from '../config/schema.js';\nimport { installConnectorDefinition } from '../connectors/install.js';\nimport type {\n ConnectorDefinition,\n ConnectorInstallInput,\n ConnectorPermissions,\n} from '../connectors/types.js';\nimport {\n downloadConnectorStoreZipBuffer,\n fetchStoreConnectorPackageDetail,\n listConnectorPackages,\n resolveSkillsStoreBaseUrl,\n type SkillsStoreListParams,\n} from '../agent/skills/marketplace/adapters/store/store-api-client.js';\n\ntype JsonRecord = Record<string, unknown>;\n\nexport type StoreConnectorInstallPlan = {\n packageName: string;\n version: string;\n definition: ConnectorDefinition;\n permissions: ConnectorPermissions;\n requiresRestart: false;\n requiresOAuth: boolean;\n};\n\nfunction asRecord(value: unknown, label: string): JsonRecord {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} must be an object.`);\n }\n return value as JsonRecord;\n}\n\nfunction asString(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value.trim()) {\n throw new Error(`${label} must be a non-empty string.`);\n }\n return value.trim();\n}\n\nfunction asStringArray(value: unknown, label: string): string[] {\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || !item.trim())) {\n throw new Error(`${label} must be an array of non-empty strings.`);\n }\n return value.map((item) => item.trim());\n}\n\nconst NPM_PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/;\nconst EXACT_SEMVER = /^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/;\n\nfunction assertSafeRemoteUrl(value: unknown): string {\n const urlString = asString(value, 'Connector MCP endpoint');\n let url: URL;\n try {\n url = new URL(urlString);\n } catch {\n throw new Error('Connector MCP endpoint must be a valid URL.');\n }\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n if (\n url.protocol !== 'https:' ||\n url.username ||\n url.password ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n isIP(hostname)\n ) {\n throw new Error('Store connectors must use a public HTTPS MCP endpoint.');\n }\n return url.toString();\n}\n\nfunction readPermissions(value: unknown, isLocal: boolean): ConnectorPermissions {\n const permissions = asRecord(value, 'Connector permissions');\n if (permissions.localExec !== isLocal) {\n if (isLocal) throw new Error('Local Store connectors must explicitly allow local command execution.');\n throw new Error('Store connectors must explicitly deny local command execution.');\n }\n const filesystem = permissions.filesystem === undefined\n ? []\n : asStringArray(permissions.filesystem, 'Connector filesystem permissions');\n if (filesystem.length > 0) {\n throw new Error('Store connectors cannot request filesystem access.');\n }\n const networkDomains = asStringArray(permissions.networkDomains, 'Connector network domains');\n if (!isLocal && networkDomains.length === 0) {\n throw new Error('Store connectors must declare at least one network domain.');\n }\n return {\n ...(permissions.data === undefined ? {} : { data: asStringArray(permissions.data, 'Connector data permissions') }),\n networkDomains,\n localExec: isLocal,\n filesystem,\n };\n}\n\nfunction readPinnedLocalRuntime(runtime: JsonRecord, template: JsonRecord): { registry: 'npm'; name: string; version: string } | null {\n if (runtime.localPackage === undefined) return null;\n const localPackage = asRecord(runtime.localPackage, 'Connector localPackage');\n if (localPackage.registry !== 'npm') {\n throw new Error('Local Store connectors must use the npm registry.');\n }\n const name = asString(localPackage.name, 'Connector local package name');\n const version = asString(localPackage.version, 'Connector local package version');\n if (!NPM_PACKAGE_NAME.test(name) || !EXACT_SEMVER.test(version)) {\n throw new Error('Local Store connectors must use a valid exact npm package version.');\n }\n if (template.command !== 'npx' ||\n JSON.stringify(asStringArray(template.args, 'Connector local MCP arguments')) !== JSON.stringify(['--yes', `${name}@${version}`])) {\n throw new Error('Local Store connectors must use the pinned npx launch form.');\n }\n for (const field of ['url', 'env', 'cwd', 'workingDirectory', 'headers', 'transport']) {\n if (field in template) throw new Error('Local Store connectors cannot define additional MCP process fields.');\n }\n return { registry: 'npm', name, version };\n}\n\nfunction readConnectorManifest(\n value: unknown,\n packageName: string,\n version: string,\n sha256: string,\n): ConnectorDefinition {\n const manifest = asRecord(value, 'Connector manifest');\n if (asString(manifest.id, 'Connector id') !== packageName) {\n throw new Error('Connector manifest id does not match the store package name.');\n }\n const runtime = asRecord(manifest.runtime, 'Connector runtime');\n if (runtime.type !== 'mcp') {\n throw new Error('Store connectors must use the MCP runtime.');\n }\n const serverTemplate = asRecord(runtime.serverTemplate, 'Connector MCP serverTemplate');\n const localPackage = readPinnedLocalRuntime(runtime, serverTemplate);\n const transport = serverTemplate.transport;\n if (!localPackage && transport !== 'streamable-http' && transport !== 'sse') {\n throw new Error('Store connectors must use streamable-http or sse transport.');\n }\n const auth = asRecord(manifest.auth, 'Connector auth');\n const authMode = auth.mode;\n if (authMode !== 'none' && authMode !== 'apiKey' && authMode !== 'oauth') {\n throw new Error('Connector auth mode must be none, apiKey, or oauth.');\n }\n const category = asString(manifest.category, 'Connector category');\n if (!['code', 'docs', 'browser', 'data', 'automation', 'custom'].includes(category)) {\n throw new Error(`Unsupported connector category: ${category}`);\n }\n const capabilities = asStringArray(manifest.capabilities, 'Connector capabilities');\n const allowedCapabilities = new Set([\n 'tools', 'resources', 'prompts', 'context', 'events', 'auth.apiKey', 'auth.oauth',\n 'runtime.mcp.stdio', 'runtime.mcp.sse', 'runtime.mcp.streamableHttp',\n ]);\n if (capabilities.some((capability) => !allowedCapabilities.has(capability))) {\n throw new Error('Connector manifest contains an unsupported capability.');\n }\n const setup = manifest.setup === undefined ? {} : asRecord(manifest.setup, 'Connector setup');\n const permissions = readPermissions(manifest.permissions, Boolean(localPackage));\n const endpoint = localPackage ? undefined : assertSafeRemoteUrl(serverTemplate.url);\n const hostname = endpoint ? new URL(endpoint).hostname : undefined;\n if (hostname && permissions.networkDomains?.length && !permissions.networkDomains.includes(hostname)) {\n throw new Error('Connector network permissions must include the MCP endpoint host.');\n }\n\n return {\n id: packageName,\n version,\n displayName: asString(manifest.displayName, 'Connector displayName'),\n description: asString(manifest.description, 'Connector description'),\n category: category as ConnectorDefinition['category'],\n kind: 'mcp',\n source: 'store',\n capabilities: capabilities as ConnectorDefinition['capabilities'],\n ...(Array.isArray(manifest.tags) ? { tags: asStringArray(manifest.tags, 'Connector tags') } : {}),\n auth: { mode: authMode },\n setup: setup as ConnectorDefinition['setup'],\n runtime: {\n type: 'mcp',\n serverId: asString(runtime.serverId, 'Connector MCP serverId'),\n serverTemplate: localPackage ? serverTemplate : { ...serverTemplate, url: endpoint },\n ...(localPackage ? { localPackage } : {}),\n },\n permissions,\n provenance: { packageName, sha256 },\n };\n}\n\nfunction readConnectorManifestFromArchive(buffer: Buffer): unknown {\n let archive: AdmZip;\n try {\n archive = new AdmZip(buffer);\n } catch {\n throw new Error('Store connector artifact is not a valid zip archive.');\n }\n const entry = archive.getEntries().find((candidate) => {\n const path = candidate.entryName.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n return !candidate.isDirectory && (path === 'xopc.connector.json' || path.endsWith('/xopc.connector.json'));\n });\n if (!entry) {\n throw new Error('Store connector artifact is missing xopc.connector.json.');\n }\n try {\n return JSON.parse(entry.getData().toString('utf8'));\n } catch {\n throw new Error('Store connector manifest is not valid JSON.');\n }\n}\n\nexport async function listStoreConnectors(config: Config, params: SkillsStoreListParams) {\n return listConnectorPackages(resolveSkillsStoreBaseUrl(config), params);\n}\n\nexport async function getStoreConnectorInstallPlan(\n config: Config,\n packageName: string,\n version?: string,\n): Promise<StoreConnectorInstallPlan> {\n const storeBaseUrl = resolveSkillsStoreBaseUrl(config);\n const detail = await fetchStoreConnectorPackageDetail(storeBaseUrl, packageName, version);\n const sha256 = detail.latestVersion.sha256;\n if (!sha256 || !/^[a-f0-9]{64}$/i.test(sha256)) {\n throw new Error('Store connector version is missing a valid SHA-256 checksum.');\n }\n const archive = await downloadConnectorStoreZipBuffer(storeBaseUrl, detail.latestVersion.downloadUrl);\n const actualSha256 = createHash('sha256').update(archive).digest('hex');\n if (actualSha256 !== sha256.toLowerCase()) {\n throw new Error('Store connector artifact checksum verification failed.');\n }\n const artifactManifest = readConnectorManifestFromArchive(archive);\n const definition = readConnectorManifest(\n artifactManifest,\n detail.name,\n detail.latestVersion.version,\n actualSha256,\n );\n const storeManifest = readConnectorManifest(\n detail.latestVersion.manifest,\n detail.name,\n detail.latestVersion.version,\n actualSha256,\n );\n if (JSON.stringify(definition.runtime) !== JSON.stringify(storeManifest.runtime)) {\n throw new Error('Store connector metadata does not match its verified artifact.');\n }\n return {\n packageName: detail.name,\n version: detail.latestVersion.version,\n permissions: definition.permissions ?? {},\n requiresRestart: false,\n requiresOAuth: definition.auth.mode === 'oauth',\n definition,\n };\n}\n\nexport async function installStoreConnector(\n config: Config,\n packageName: string,\n input: ConnectorInstallInput,\n version?: string,\n) {\n const plan = await getStoreConnectorInstallPlan(config, packageName, version);\n if (plan.requiresOAuth && plan.definition.id !== 'github') {\n throw new Error('OAuth installation for store connectors is not available yet. Use an API-key connector or the built-in GitHub connector.');\n }\n const instance = await installConnectorDefinition(config, plan.definition, input);\n return { instance, plan };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"store-connector.js","names":[],"sources":["../../../src/capabilities/store-connector.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { isIP } from 'node:net';\n\nimport AdmZip from 'adm-zip';\n\nimport type { Config } from '../config/schema.js';\nimport { installConnectorDefinition } from '../connectors/install.js';\nimport type {\n ConnectorDefinition,\n ConnectorInstallInput,\n ConnectorPermissions,\n} from '../connectors/types.js';\nimport {\n downloadConnectorStoreZipBuffer,\n fetchStoreConnectorPackageDetail,\n listConnectorPackages,\n resolveSkillsStoreBaseUrl,\n type SkillsStoreListParams,\n} from '../agent/skills/marketplace/adapters/store/store-api-client.js';\n\ntype JsonRecord = Record<string, unknown>;\n\nexport type StoreConnectorInstallPlan = {\n packageName: string;\n version: string;\n definition: ConnectorDefinition;\n permissions: ConnectorPermissions;\n requiresRestart: false;\n};\n\nfunction asRecord(value: unknown, label: string): JsonRecord {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} must be an object.`);\n }\n return value as JsonRecord;\n}\n\nfunction asString(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value.trim()) {\n throw new Error(`${label} must be a non-empty string.`);\n }\n return value.trim();\n}\n\nfunction asStringArray(value: unknown, label: string): string[] {\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || !item.trim())) {\n throw new Error(`${label} must be an array of non-empty strings.`);\n }\n return value.map((item) => item.trim());\n}\n\nconst NPM_PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/;\nconst EXACT_SEMVER = /^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/;\n\nfunction assertSafeRemoteUrl(value: unknown): string {\n const urlString = asString(value, 'Connector MCP endpoint');\n let url: URL;\n try {\n url = new URL(urlString);\n } catch {\n throw new Error('Connector MCP endpoint must be a valid URL.');\n }\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n if (\n url.protocol !== 'https:' ||\n url.username ||\n url.password ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n isIP(hostname)\n ) {\n throw new Error('Store connectors must use a public HTTPS MCP endpoint.');\n }\n return url.toString();\n}\n\nfunction readPermissions(value: unknown, isLocal: boolean): ConnectorPermissions {\n const permissions = asRecord(value, 'Connector permissions');\n if (permissions.localExec !== isLocal) {\n if (isLocal) throw new Error('Local Store connectors must explicitly allow local command execution.');\n throw new Error('Store connectors must explicitly deny local command execution.');\n }\n const filesystem = permissions.filesystem === undefined\n ? []\n : asStringArray(permissions.filesystem, 'Connector filesystem permissions');\n if (filesystem.length > 0) {\n throw new Error('Store connectors cannot request filesystem access.');\n }\n const networkDomains = asStringArray(permissions.networkDomains, 'Connector network domains');\n if (!isLocal && networkDomains.length === 0) {\n throw new Error('Store connectors must declare at least one network domain.');\n }\n return {\n ...(permissions.data === undefined ? {} : { data: asStringArray(permissions.data, 'Connector data permissions') }),\n networkDomains,\n localExec: isLocal,\n filesystem,\n };\n}\n\nfunction readPinnedLocalRuntime(runtime: JsonRecord, template: JsonRecord): { registry: 'npm'; name: string; version: string } | null {\n if (runtime.localPackage === undefined) return null;\n const localPackage = asRecord(runtime.localPackage, 'Connector localPackage');\n if (localPackage.registry !== 'npm') {\n throw new Error('Local Store connectors must use the npm registry.');\n }\n const name = asString(localPackage.name, 'Connector local package name');\n const version = asString(localPackage.version, 'Connector local package version');\n if (!NPM_PACKAGE_NAME.test(name) || !EXACT_SEMVER.test(version)) {\n throw new Error('Local Store connectors must use a valid exact npm package version.');\n }\n if (template.command !== 'npx' ||\n JSON.stringify(asStringArray(template.args, 'Connector local MCP arguments')) !== JSON.stringify(['--yes', `${name}@${version}`])) {\n throw new Error('Local Store connectors must use the pinned npx launch form.');\n }\n for (const field of ['url', 'env', 'cwd', 'workingDirectory', 'headers', 'transport']) {\n if (field in template) throw new Error('Local Store connectors cannot define additional MCP process fields.');\n }\n return { registry: 'npm', name, version };\n}\n\nfunction readConnectorManifest(\n value: unknown,\n packageName: string,\n version: string,\n sha256: string,\n): ConnectorDefinition {\n const manifest = asRecord(value, 'Connector manifest');\n if (asString(manifest.id, 'Connector id') !== packageName) {\n throw new Error('Connector manifest id does not match the store package name.');\n }\n const runtime = asRecord(manifest.runtime, 'Connector runtime');\n if (runtime.type !== 'mcp') {\n throw new Error('Store connectors must use the MCP runtime.');\n }\n const serverTemplate = asRecord(runtime.serverTemplate, 'Connector MCP serverTemplate');\n const localPackage = readPinnedLocalRuntime(runtime, serverTemplate);\n const transport = serverTemplate.transport;\n if (!localPackage && transport !== 'streamable-http' && transport !== 'sse') {\n throw new Error('Store connectors must use streamable-http or sse transport.');\n }\n const auth = asRecord(manifest.auth, 'Connector auth');\n const authMode = auth.mode;\n if (authMode !== 'none' && authMode !== 'apiKey') {\n throw new Error('Store connectors support only none or apiKey authentication.');\n }\n const normalizedAuth: ConnectorDefinition['auth'] = { mode: authMode };\n const category = asString(manifest.category, 'Connector category');\n if (!['code', 'docs', 'browser', 'data', 'automation', 'custom'].includes(category)) {\n throw new Error(`Unsupported connector category: ${category}`);\n }\n const capabilities = asStringArray(manifest.capabilities, 'Connector capabilities');\n const allowedCapabilities = new Set([\n 'tools', 'resources', 'prompts', 'context', 'events', 'auth.apiKey',\n 'runtime.mcp.stdio', 'runtime.mcp.sse', 'runtime.mcp.streamableHttp',\n ]);\n if (capabilities.some((capability) => !allowedCapabilities.has(capability))) {\n throw new Error('Connector manifest contains an unsupported capability.');\n }\n const setup = manifest.setup === undefined ? {} : asRecord(manifest.setup, 'Connector setup');\n const permissions = readPermissions(manifest.permissions, Boolean(localPackage));\n const endpoint = localPackage ? undefined : assertSafeRemoteUrl(serverTemplate.url);\n const hostname = endpoint ? new URL(endpoint).hostname : undefined;\n if (hostname && permissions.networkDomains?.length && !permissions.networkDomains.includes(hostname)) {\n throw new Error('Connector network permissions must include the MCP endpoint host.');\n }\n\n return {\n id: packageName,\n version,\n displayName: asString(manifest.displayName, 'Connector displayName'),\n description: asString(manifest.description, 'Connector description'),\n category: category as ConnectorDefinition['category'],\n kind: 'mcp',\n source: 'store',\n capabilities: capabilities as ConnectorDefinition['capabilities'],\n ...(Array.isArray(manifest.tags) ? { tags: asStringArray(manifest.tags, 'Connector tags') } : {}),\n auth: normalizedAuth,\n setup: setup as ConnectorDefinition['setup'],\n runtime: {\n type: 'mcp',\n serverId: asString(runtime.serverId, 'Connector MCP serverId'),\n serverTemplate: localPackage ? serverTemplate : { ...serverTemplate, url: endpoint },\n ...(localPackage ? { localPackage } : {}),\n },\n permissions,\n provenance: { packageName, sha256 },\n };\n}\n\nfunction readConnectorManifestFromArchive(buffer: Buffer): unknown {\n let archive: AdmZip;\n try {\n archive = new AdmZip(buffer);\n } catch {\n throw new Error('Store connector artifact is not a valid zip archive.');\n }\n const entry = archive.getEntries().find((candidate) => {\n const path = candidate.entryName.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n return !candidate.isDirectory && (path === 'xopc.connector.json' || path.endsWith('/xopc.connector.json'));\n });\n if (!entry) {\n throw new Error('Store connector artifact is missing xopc.connector.json.');\n }\n try {\n return JSON.parse(entry.getData().toString('utf8'));\n } catch {\n throw new Error('Store connector manifest is not valid JSON.');\n }\n}\n\nexport async function listStoreConnectors(config: Config, params: SkillsStoreListParams) {\n return listConnectorPackages(resolveSkillsStoreBaseUrl(config), params);\n}\n\nexport async function getStoreConnectorInstallPlan(\n config: Config,\n packageName: string,\n version?: string,\n): Promise<StoreConnectorInstallPlan> {\n const storeBaseUrl = resolveSkillsStoreBaseUrl(config);\n const detail = await fetchStoreConnectorPackageDetail(storeBaseUrl, packageName, version);\n const sha256 = detail.latestVersion.sha256;\n if (!sha256 || !/^[a-f0-9]{64}$/i.test(sha256)) {\n throw new Error('Store connector version is missing a valid SHA-256 checksum.');\n }\n const archive = await downloadConnectorStoreZipBuffer(storeBaseUrl, detail.latestVersion.downloadUrl);\n const actualSha256 = createHash('sha256').update(archive).digest('hex');\n if (actualSha256 !== sha256.toLowerCase()) {\n throw new Error('Store connector artifact checksum verification failed.');\n }\n const artifactManifest = readConnectorManifestFromArchive(archive);\n const definition = readConnectorManifest(\n artifactManifest,\n detail.name,\n detail.latestVersion.version,\n actualSha256,\n );\n const storeManifest = readConnectorManifest(\n detail.latestVersion.manifest,\n detail.name,\n detail.latestVersion.version,\n actualSha256,\n );\n if (JSON.stringify(definition.runtime) !== JSON.stringify(storeManifest.runtime)) {\n throw new Error('Store connector metadata does not match its verified artifact.');\n }\n return {\n packageName: detail.name,\n version: detail.latestVersion.version,\n permissions: definition.permissions ?? {},\n requiresRestart: false,\n definition,\n };\n}\n\nexport async function installStoreConnector(\n config: Config,\n packageName: string,\n input: ConnectorInstallInput,\n version?: string,\n) {\n const plan = await getStoreConnectorInstallPlan(config, packageName, version);\n const instance = await installConnectorDefinition(config, plan.definition, input);\n return { instance, plan };\n}\n"],"mappings":"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"}
@@ -8,42 +8,62 @@ import { randomUUID } from "node:crypto";
8
8
  //#region src/chat-commands/builtins/review.ts
9
9
  const MAX_DIFF_CHARS = 6e4;
10
10
  const REVIEW_JUDGE_MAX_TOKENS = 16384;
11
- async function emitToolStart(ctx, toolCallId, toolName, args) {
11
+ async function emitReviewStart(ctx, reviewId, target, stage) {
12
12
  await ctx.emitEvent?.({
13
- type: "tool_execution_start",
14
- toolCallId,
15
- toolName,
16
- args
13
+ type: "review_start",
14
+ reviewId,
15
+ target,
16
+ stage
17
17
  });
18
18
  }
19
- async function emitToolEnd(ctx, toolCallId, toolName, resultText, details, isError = false) {
19
+ async function emitReviewEnd(ctx, reviewId, status, message) {
20
20
  await ctx.emitEvent?.({
21
- type: "tool_execution_end",
22
- toolCallId,
23
- toolName,
24
- isError,
25
- result: {
26
- content: [{
27
- type: "text",
28
- text: resultText
29
- }],
30
- ...details ? { details } : {}
31
- }
21
+ type: "review_end",
22
+ reviewId,
23
+ status,
24
+ ...message ? { message } : {}
32
25
  });
33
26
  }
34
- async function emitToolTextDelta(ctx, toolCallId, toolName, delta) {
27
+ async function emitReviewDelta(ctx, reviewId, delta) {
35
28
  if (!delta) return;
36
29
  await ctx.emitEvent?.({
37
- type: "tool_execution_update",
38
- toolCallId,
39
- toolName,
40
- args: {},
41
- partialResult: { content: [{
42
- type: "text",
43
- text: delta
44
- }] }
30
+ type: "review_delta",
31
+ reviewId,
32
+ delta
45
33
  });
46
34
  }
35
+ function createReviewProgressExtractor() {
36
+ const open = "<review_progress>";
37
+ const close = "</review_progress>";
38
+ let buffer = "";
39
+ let inside = false;
40
+ return (delta) => {
41
+ buffer += delta;
42
+ let visible = "";
43
+ while (buffer) {
44
+ if (!inside) {
45
+ const start = buffer.indexOf(open);
46
+ if (start < 0) {
47
+ buffer = buffer.slice(-Math.max(0, 16));
48
+ break;
49
+ }
50
+ buffer = buffer.slice(start + 17);
51
+ inside = true;
52
+ }
53
+ const end = buffer.indexOf(close);
54
+ if (end < 0) {
55
+ const safeLength = Math.max(0, buffer.length - 17);
56
+ visible += buffer.slice(0, safeLength);
57
+ buffer = buffer.slice(safeLength);
58
+ break;
59
+ }
60
+ visible += buffer.slice(0, end);
61
+ buffer = buffer.slice(end + 18);
62
+ inside = false;
63
+ }
64
+ return visible;
65
+ };
66
+ }
47
67
  function truncateForPrompt(text) {
48
68
  if (text.length <= MAX_DIFF_CHARS) return {
49
69
  text,
@@ -111,10 +131,6 @@ function parseReviewJson(raw, target) {
111
131
  source: "model"
112
132
  };
113
133
  }
114
- function previewText(text, max = 500) {
115
- const trimmed = text.trim();
116
- return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;
117
- }
118
134
  async function reviewModelRef(ctx) {
119
135
  const sessionOverride = await ctx.getSessionConfigStore?.()?.get(ctx.sessionKey).then((config) => config?.modelOverride?.trim()).catch(() => void 0);
120
136
  if (sessionOverride) return sessionOverride;
@@ -130,7 +146,9 @@ function buildReviewPrompt(params) {
130
146
  "You are a senior code reviewer. Review the provided git diff for correctness bugs only.",
131
147
  "Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.",
132
148
  "Do not mention style, broad refactors, praise, or speculative improvements.",
133
- "Return strict JSON only with this shape:",
149
+ "Return exactly two XML-delimited sections and nothing else.",
150
+ "First write a concise, user-facing Markdown review draft inside <review_progress>...</review_progress>. State the scope and concrete evidence only; do not reveal hidden chain-of-thought.",
151
+ "Then put strict JSON inside <review_result>...</review_result> using this shape:",
134
152
  "{\"findings\":[{\"title\":\"...\",\"body\":\"...\",\"priority\":1,\"confidence_score\":0.9,\"code_location\":{\"file_path\":\"path\",\"line_range\":{\"start\":12,\"end\":12}}}],\"overall_correctness\":\"patch is correct\",\"overall_explanation\":\"...\",\"overall_confidence_score\":0.8,\"summary\":\"...\"}",
135
153
  "Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.",
136
154
  params.instructions ? `Extra reviewer instructions: ${params.instructions}` : "",
@@ -152,36 +170,33 @@ async function resolveWorkspace(ctx) {
152
170
  async function buildReview(ctx, args) {
153
171
  const cwd = await resolveGitRoot(await resolveWorkspace(ctx));
154
172
  const reviewTarget = parseReviewTargetArgs(args);
155
- const prepareToolCallId = `review_prepare_${randomUUID()}`;
156
- await emitToolStart(ctx, prepareToolCallId, "review.prepare_diff", {
157
- target: args.trim() || "uncommitted",
158
- cwd
159
- });
173
+ const reviewId = `review_${randomUUID()}`;
174
+ await emitReviewStart(ctx, reviewId, args.trim() || "current workspace changes", "preparing");
160
175
  let bundle;
161
176
  try {
162
177
  bundle = await buildReviewDiffBundle(cwd, reviewTarget);
163
- await emitToolEnd(ctx, prepareToolCallId, "review.prepare_diff", [`Target: ${bundle.targetLabel}`, bundle.stat.trim() ? `Changed files:\n${bundle.stat.trim()}` : "No diff stat."].join("\n\n"), {
164
- target: bundle.targetLabel,
165
- status: bundle.status,
166
- stat: bundle.stat
167
- });
168
178
  } catch (err) {
169
- await emitToolEnd(ctx, prepareToolCallId, "review.prepare_diff", err instanceof Error ? err.message : String(err), { cwd }, true);
179
+ await emitReviewEnd(ctx, reviewId, "error", err instanceof Error ? err.message : String(err));
170
180
  throw err;
171
181
  }
172
182
  const { text: diff, truncated } = truncateForPrompt(bundle.diff);
173
183
  const target = bundle.targetLabel;
174
184
  const instructions = reviewTarget.instructions ?? "";
175
- if (!bundle.status.trim() && !bundle.diff.trim()) return {
176
- type: "review",
177
- target,
178
- summary: "Working tree is clean.",
179
- findings: [],
180
- overallCorrectness: "patch is correct",
181
- overallExplanation: "No uncommitted changes were found to review.",
182
- generatedAt: Date.now(),
183
- source: "local"
184
- };
185
+ await emitReviewStart(ctx, reviewId, target, "preparing");
186
+ if (!bundle.status.trim() && !bundle.diff.trim()) {
187
+ const review = {
188
+ type: "review",
189
+ target,
190
+ summary: "Working tree is clean.",
191
+ findings: [],
192
+ overallCorrectness: "patch is correct",
193
+ overallExplanation: "No uncommitted changes were found to review.",
194
+ generatedAt: Date.now(),
195
+ source: "local"
196
+ };
197
+ await emitReviewEnd(ctx, reviewId, "complete");
198
+ return review;
199
+ }
185
200
  const prompt = buildReviewPrompt({
186
201
  target,
187
202
  status: bundle.status,
@@ -191,17 +206,12 @@ async function buildReview(ctx, args) {
191
206
  instructions
192
207
  });
193
208
  const reviewerModelRef = await reviewModelRef(ctx);
194
- const judgeToolCallId = `review_judge_${randomUUID()}`;
195
- await emitToolStart(ctx, judgeToolCallId, "review.model_judge", {
196
- target,
197
- diffChars: diff.length,
198
- truncated,
199
- ...reviewerModelRef ? { modelRef: reviewerModelRef } : {}
200
- });
209
+ await emitReviewStart(ctx, reviewId, target, "reviewing");
210
+ const extractReviewProgress = createReviewProgressExtractor();
201
211
  const answer = ctx.btwQuery ? await ctx.btwQuery(prompt, {
202
212
  maxTokens: REVIEW_JUDGE_MAX_TOKENS,
203
213
  includeSessionContext: false,
204
- onTextDelta: (delta) => emitToolTextDelta(ctx, judgeToolCallId, "review.model_judge", delta),
214
+ onTextDelta: (delta) => emitReviewDelta(ctx, reviewId, extractReviewProgress(delta)),
205
215
  ...reviewerModelRef ? { modelRef: reviewerModelRef } : {}
206
216
  }) : {
207
217
  text: "",
@@ -210,11 +220,7 @@ async function buildReview(ctx, args) {
210
220
  let judgeFailure = answer.error ? { reason: `Reviewer model error: ${answer.error}` } : answer.text ? void 0 : { reason: "Reviewer model returned no text." };
211
221
  if (answer?.text && !answer.error) try {
212
222
  const parsed = parseReviewJson(answer.text, target);
213
- await emitToolEnd(ctx, judgeToolCallId, "review.model_judge", parsed.summary || `${parsed.findings.length} findings`, {
214
- target,
215
- findings: parsed.findings.length,
216
- overallCorrectness: parsed.overallCorrectness
217
- });
223
+ await emitReviewEnd(ctx, reviewId, "complete");
218
224
  return parsed;
219
225
  } catch (err) {
220
226
  judgeFailure = { reason: `Reviewer model output could not be parsed: ${err instanceof Error ? err.message : String(err)}` };
@@ -230,14 +236,7 @@ async function buildReview(ctx, args) {
230
236
  generatedAt: Date.now(),
231
237
  source: "local"
232
238
  };
233
- await emitToolEnd(ctx, judgeToolCallId, "review.model_judge", fallback.summary, {
234
- target,
235
- findings: 0,
236
- overallCorrectness: fallback.overallCorrectness,
237
- fallback: true,
238
- reason,
239
- ...answer.text ? { responsePreview: previewText(answer.text) } : {}
240
- }, true);
239
+ await emitReviewEnd(ctx, reviewId, "error", reason);
241
240
  return fallback;
242
241
  }
243
242
  const reviewCommand = {