@xopcai/xopc 0.0.141 → 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 (605) 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-BRTCpm3t.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-DaMMZBAT.js → app-management-settings-panel-Cuo7SbUP.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-BXHThPyM.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-izB-4N4L.js → archive-plugin-B-Qk6cGr.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CJihXa5y.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-D3VUeG8s.js → binary-plugins-ZaOZDH2I.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-KnA0sLI3.js → block-editor-BTFhjWfg.js} +36 -36
  16. package/dist/gateway/static/root/assets/browser-settings-page-BvKLdEQt.js +8 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-api-D8rRNhc6.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-BWgqwC5h.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-CzdqX001.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-PzlO5tSM.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-DcW8Ie3r.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-06q5eCMA.js → fetch-8QNN25Sh.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-4VXUJtLz.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-2f7_vsv7.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-BpuQTufF.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-LT6qB-ua.js +1 -0
  46. package/dist/gateway/static/root/assets/logs-page-Dli2e3fS.js +7 -0
  47. package/dist/gateway/static/root/assets/{markdown-split-zS4KLNAf.js → markdown-split-Dw-yE2-y.js} +1 -1
  48. package/dist/gateway/static/root/assets/{media-plugins-_BgNJ9_7.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-B7sGQkgU.js → page-tabs-D4hkWVt_.js} +1 -1
  54. package/dist/gateway/static/root/assets/{preview-open-alternatives-D1ri4s_O.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-BClrOinh.js → save-bar-controls-B0b42kB2.js} +1 -1
  59. package/dist/gateway/static/root/assets/{schedule-field-CL7YTwLV.js → schedule-field-BtjEkczK.js} +1 -1
  60. package/dist/gateway/static/root/assets/{schema-form-ww4PiIje.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-D9gEEVm2.js → settings-collapsible-section-BTKTdTNX.js} +1 -1
  64. package/dist/gateway/static/root/assets/{settings-form-section-DGeEoBkb.js → settings-form-section-DL4P0sAj.js} +1 -1
  65. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BXUeMR37.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-CEepfbCa.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-W6MBJXrr.js → system-settings-panel-D85fBBuI.js} +1 -1
  74. package/dist/gateway/static/root/assets/{typed-models-lib-BkODXN7T.js → typed-models-lib-CwEuYrHX.js} +1 -1
  75. package/dist/gateway/static/root/assets/{use-channel-catalog-CTbwLZXc.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-ZxrKHxyb.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-B35lJzvm.js +3 -0
  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-runner.js +5 -5
  135. package/dist/src/agent/embedded/session-runner.js.map +1 -1
  136. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  137. package/dist/src/agent/embedded/xopc-auth-storage.d.ts +4 -3
  138. package/dist/src/agent/embedded/xopc-auth-storage.js +6 -6
  139. package/dist/src/agent/embedded/xopc-auth-storage.js.map +1 -1
  140. package/dist/src/agent/embedded/xopc-stream-bridge.js +1 -0
  141. package/dist/src/agent/embedded/xopc-stream-bridge.js.map +1 -1
  142. package/dist/src/agent/embedded/xopc-tools-bridge.d.ts +9 -0
  143. package/dist/src/agent/embedded/xopc-tools-bridge.js +71 -3
  144. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  145. package/dist/src/agent/goals/checklist-judge.js +3 -3
  146. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  147. package/dist/src/agent/goals/judge.js +2 -2
  148. package/dist/src/agent/goals/judge.js.map +1 -1
  149. package/dist/src/agent/goals/post-turn.js +5 -4
  150. package/dist/src/agent/goals/post-turn.js.map +1 -1
  151. package/dist/src/agent/image/understanding/pi-ai-provider.js +2 -2
  152. package/dist/src/agent/image/understanding/pi-ai-provider.js.map +1 -1
  153. package/dist/src/agent/mcp/mcp-transport.js +4 -1
  154. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  155. package/dist/src/agent/memory/compaction.js +2 -2
  156. package/dist/src/agent/memory/compaction.js.map +1 -1
  157. package/dist/src/agent/memory/context/planner.d.ts +1 -0
  158. package/dist/src/agent/memory/context/planner.js +60 -14
  159. package/dist/src/agent/memory/context/planner.js.map +1 -1
  160. package/dist/src/agent/memory/context/types.d.ts +3 -1
  161. package/dist/src/agent/memory/lifecycle.d.ts +11 -0
  162. package/dist/src/agent/memory/lifecycle.js +50 -0
  163. package/dist/src/agent/memory/lifecycle.js.map +1 -0
  164. package/dist/src/agent/memory/source-origin.d.ts +3 -0
  165. package/dist/src/agent/memory/source-origin.js +19 -0
  166. package/dist/src/agent/memory/source-origin.js.map +1 -0
  167. package/dist/src/agent/memory/understanding/service.js +5 -0
  168. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  169. package/dist/src/agent/memory/user-context-coordinator.js +7 -2
  170. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  171. package/dist/src/agent/prompt/sections/behavior.d.ts +2 -0
  172. package/dist/src/agent/prompt/sections/behavior.js +30 -1
  173. package/dist/src/agent/prompt/sections/behavior.js.map +1 -1
  174. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  175. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  176. package/dist/src/agent/prompt/service-prompt-builder.js +8 -1
  177. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  178. package/dist/src/agent/prompt/system-prompt.d.ts +2 -0
  179. package/dist/src/agent/prompt/system-prompt.js +6 -3
  180. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  181. package/dist/src/agent/service/btw-query.d.ts +4 -0
  182. package/dist/src/agent/service/btw-query.js +94 -13
  183. package/dist/src/agent/service/btw-query.js.map +1 -1
  184. package/dist/src/agent/service/process-direct-streaming.js +22 -0
  185. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  186. package/dist/src/agent/service.d.ts +2 -0
  187. package/dist/src/agent/service.js +9 -3
  188. package/dist/src/agent/service.js.map +1 -1
  189. package/dist/src/agent/session/session-inspector.js +9 -1
  190. package/dist/src/agent/session/session-inspector.js.map +1 -1
  191. package/dist/src/agent/starter-agents.js +1 -1
  192. package/dist/src/agent/starter-agents.js.map +1 -1
  193. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  194. package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
  195. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -1
  196. package/dist/src/agent/tools/composio-tool.d.ts +18 -5
  197. package/dist/src/agent/tools/composio-tool.js +252 -35
  198. package/dist/src/agent/tools/composio-tool.js.map +1 -1
  199. package/dist/src/agent/tools/factory.js +7 -3
  200. package/dist/src/agent/tools/factory.js.map +1 -1
  201. package/dist/src/agent/tools/index.d.ts +1 -1
  202. package/dist/src/agent/tools/index.js +2 -2
  203. package/dist/src/agent/tools/session-search-tool.js +2 -2
  204. package/dist/src/agent/tools/session-search-tool.js.map +1 -1
  205. package/dist/src/agent/tools/web-extract.js +2 -2
  206. package/dist/src/agent/tools/web-extract.js.map +1 -1
  207. package/dist/src/agent/tools/workflow-tool.d.ts +0 -1
  208. package/dist/src/agent/tools/workflow-tool.js +3 -16
  209. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  210. package/dist/src/agent/workflow/builtins/index.d.ts +2 -28
  211. package/dist/src/agent/workflow/builtins/index.js +226 -41
  212. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  213. package/dist/src/agent/workflow/catalog.d.ts +32 -34
  214. package/dist/src/agent/workflow/catalog.js +158 -154
  215. package/dist/src/agent/workflow/catalog.js.map +1 -1
  216. package/dist/src/agent/workflow/index.d.ts +4 -6
  217. package/dist/src/agent/workflow/index.js +2 -5
  218. package/dist/src/agent/workflow/snapshot.d.ts +2 -2
  219. package/dist/src/agent/workflow/snapshot.js +2 -2
  220. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  221. package/dist/src/agent/workflow/structured-output-tool.d.ts +2 -2
  222. package/dist/src/agent/workflow/structured-output-tool.js +2 -2
  223. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -1
  224. package/dist/src/agent/workflow/subagent-runner.js +1 -1
  225. package/dist/src/agent/workflow/types.d.ts +31 -26
  226. package/dist/src/agent-manifest/index.d.ts +1 -0
  227. package/dist/src/agent-manifest/index.js +3 -1
  228. package/dist/src/agent-manifest/index.js.map +1 -1
  229. package/dist/src/agent-manifest/preset-chain.d.ts +10 -0
  230. package/dist/src/agent-manifest/preset-chain.js +32 -0
  231. package/dist/src/agent-manifest/preset-chain.js.map +1 -0
  232. package/dist/src/agent-manifest/resolver.js +3 -10
  233. package/dist/src/agent-manifest/resolver.js.map +1 -1
  234. package/dist/src/agent-manifest/schema.d.ts +4 -4
  235. package/dist/src/ai-assist/text-assist.d.ts +2 -1
  236. package/dist/src/ai-assist/text-assist.js +10 -23
  237. package/dist/src/ai-assist/text-assist.js.map +1 -1
  238. package/dist/src/auth/credentials.js +5 -2
  239. package/dist/src/auth/credentials.js.map +1 -1
  240. package/dist/src/auth/oauth/github-copilot.d.ts +3 -4
  241. package/dist/src/auth/oauth/github-copilot.js +66 -2
  242. package/dist/src/auth/oauth/github-copilot.js.map +1 -0
  243. package/dist/src/auth/oauth/index.js +2 -2
  244. package/dist/src/automations/api/routes.js +13 -1
  245. package/dist/src/automations/api/routes.js.map +1 -1
  246. package/dist/src/automations/domain/validation.d.ts +14 -14
  247. package/dist/src/automations/draft/automation-draft-service.js +3 -3
  248. package/dist/src/automations/draft/automation-draft-service.js.map +1 -1
  249. package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -3
  250. package/dist/src/browser/providers/browser-ext-install.d.ts +11 -1
  251. package/dist/src/browser/providers/browser-ext-install.js +39 -14
  252. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  253. package/dist/src/capabilities/store-connector.d.ts +0 -1
  254. package/dist/src/capabilities/store-connector.js +3 -5
  255. package/dist/src/capabilities/store-connector.js.map +1 -1
  256. package/dist/src/chat-commands/builtins/review.js +84 -68
  257. package/dist/src/chat-commands/builtins/review.js.map +1 -1
  258. package/dist/src/chat-commands/builtins/workflow.js +9 -54
  259. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  260. package/dist/src/chat-commands/types.d.ts +4 -0
  261. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  262. package/dist/src/cli/commands/extension-create.js +2 -2
  263. package/dist/src/cli/commands/extension-create.js.map +1 -1
  264. package/dist/src/cli/commands/extension-marketplace.js +42 -36
  265. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  266. package/dist/src/cli/commands/extension-pack.d.ts +6 -0
  267. package/dist/src/cli/commands/extension-pack.js +3 -2
  268. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  269. package/dist/src/commands/agents.config.d.ts +1 -0
  270. package/dist/src/commands/agents.config.js +1 -0
  271. package/dist/src/commands/agents.config.js.map +1 -1
  272. package/dist/src/config/schema.d.ts +6 -6
  273. package/dist/src/config/schema.js +6 -22
  274. package/dist/src/config/schema.js.map +1 -1
  275. package/dist/src/config/web-patch.d.ts +1 -1
  276. package/dist/src/connectors/approval.d.ts +2 -0
  277. package/dist/src/connectors/approval.js +33 -0
  278. package/dist/src/connectors/approval.js.map +1 -0
  279. package/dist/src/connectors/auth-provider-registry.d.ts +9 -0
  280. package/dist/src/connectors/auth-provider-registry.js +17 -0
  281. package/dist/src/connectors/auth-provider-registry.js.map +1 -0
  282. package/dist/src/connectors/builtin-catalog.js +55 -116
  283. package/dist/src/connectors/builtin-catalog.js.map +1 -1
  284. package/dist/src/connectors/catalog.js +7 -2
  285. package/dist/src/connectors/catalog.js.map +1 -1
  286. package/dist/src/connectors/composio-catalog.d.ts +19 -0
  287. package/dist/src/connectors/composio-catalog.js +237 -0
  288. package/dist/src/connectors/composio-catalog.js.map +1 -0
  289. package/dist/src/connectors/composio-logo.d.ts +1 -0
  290. package/dist/src/connectors/composio-logo.js +51 -0
  291. package/dist/src/connectors/composio-logo.js.map +1 -0
  292. package/dist/src/connectors/composio-sessions.d.ts +116 -0
  293. package/dist/src/connectors/composio-sessions.js +296 -0
  294. package/dist/src/connectors/composio-sessions.js.map +1 -0
  295. package/dist/src/connectors/composio-triggers.d.ts +17 -0
  296. package/dist/src/connectors/composio-triggers.js +48 -5
  297. package/dist/src/connectors/composio-triggers.js.map +1 -1
  298. package/dist/src/connectors/composio.d.ts +31 -2
  299. package/dist/src/connectors/composio.js +374 -151
  300. package/dist/src/connectors/composio.js.map +1 -1
  301. package/dist/src/connectors/connector-memory-sync.d.ts +15 -0
  302. package/dist/src/connectors/connector-memory-sync.js +90 -0
  303. package/dist/src/connectors/connector-memory-sync.js.map +1 -0
  304. package/dist/src/connectors/install.js +35 -92
  305. package/dist/src/connectors/install.js.map +1 -1
  306. package/dist/src/connectors/instances.js +6 -2
  307. package/dist/src/connectors/instances.js.map +1 -1
  308. package/dist/src/connectors/integration-strategy.d.ts +3 -0
  309. package/dist/src/connectors/integration-strategy.js +29 -0
  310. package/dist/src/connectors/integration-strategy.js.map +1 -0
  311. package/dist/src/connectors/policy.d.ts +13 -0
  312. package/dist/src/connectors/policy.js +48 -0
  313. package/dist/src/connectors/policy.js.map +1 -0
  314. package/dist/src/connectors/providers.js +1 -1
  315. package/dist/src/connectors/runtime-adapter-registry.d.ts +25 -0
  316. package/dist/src/connectors/runtime-adapter-registry.js +154 -0
  317. package/dist/src/connectors/runtime-adapter-registry.js.map +1 -0
  318. package/dist/src/connectors/types.d.ts +113 -4
  319. package/dist/src/connectors/workflow-preflight.d.ts +20 -0
  320. package/dist/src/connectors/workflow-preflight.js +70 -0
  321. package/dist/src/connectors/workflow-preflight.js.map +1 -0
  322. package/dist/src/extensions/install-transaction.d.ts +16 -0
  323. package/dist/src/extensions/install-transaction.js +76 -0
  324. package/dist/src/extensions/install-transaction.js.map +1 -0
  325. package/dist/src/extensions/install.d.ts +2 -0
  326. package/dist/src/extensions/install.js +23 -1
  327. package/dist/src/extensions/install.js.map +1 -1
  328. package/dist/src/gateway/agents-admin.d.ts +2 -0
  329. package/dist/src/gateway/agents-admin.js +7 -0
  330. package/dist/src/gateway/agents-admin.js.map +1 -1
  331. package/dist/src/gateway/capability-presets-admin.d.ts +11 -0
  332. package/dist/src/gateway/capability-presets-admin.js +11 -4
  333. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  334. package/dist/src/gateway/chat-stream/mapper.js +17 -0
  335. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  336. package/dist/src/gateway/chat-stream/protocol.d.ts +18 -1
  337. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -3
  338. package/dist/src/gateway/hono/routes/agents.js +3 -0
  339. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  340. package/dist/src/gateway/hono/routes/capability-presets.js +19 -1
  341. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -1
  342. package/dist/src/gateway/hono/routes/connectors.js +188 -25
  343. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  344. package/dist/src/gateway/hono/routes/goals.js +22 -3
  345. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  346. package/dist/src/gateway/hono/routes/home.d.ts +60 -1
  347. package/dist/src/gateway/hono/routes/home.js +244 -18
  348. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  349. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  350. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  351. package/dist/src/gateway/hono/routes/memory.js +14 -1
  352. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  353. package/dist/src/gateway/hono/routes/models.js +1 -0
  354. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  355. package/dist/src/gateway/hono/routes/projects.js +103 -2
  356. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  357. package/dist/src/gateway/hono/routes/public-gateway.js +93 -0
  358. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  359. package/dist/src/gateway/hono/routes/voice.js +2 -2
  360. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  361. package/dist/src/gateway/hono/routes/workflows.js +137 -22
  362. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  363. package/dist/src/gateway/hono/routes/you.d.ts +23 -0
  364. package/dist/src/gateway/hono/routes/you.js +538 -0
  365. package/dist/src/gateway/hono/routes/you.js.map +1 -0
  366. package/dist/src/gateway/hono/sse.d.ts +2 -1
  367. package/dist/src/gateway/hono/sse.js +2 -1
  368. package/dist/src/gateway/hono/sse.js.map +1 -1
  369. package/dist/src/gateway/service/marketplace-service.d.ts +13 -1
  370. package/dist/src/gateway/service/marketplace-service.js +96 -40
  371. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  372. package/dist/src/gateway/service.d.ts +2 -0
  373. package/dist/src/gateway/service.js +7 -1
  374. package/dist/src/gateway/service.js.map +1 -1
  375. package/dist/src/goals/goal-contract-draft.js +2 -2
  376. package/dist/src/goals/goal-contract-draft.js.map +1 -1
  377. package/dist/src/goals/goal-evidence-review.js +2 -2
  378. package/dist/src/goals/goal-evidence-review.js.map +1 -1
  379. package/dist/src/goals/goal-service.d.ts +7 -5
  380. package/dist/src/goals/goal-service.js +25 -13
  381. package/dist/src/goals/goal-service.js.map +1 -1
  382. package/dist/src/goals/goal-store.js +46 -7
  383. package/dist/src/goals/goal-store.js.map +1 -1
  384. package/dist/src/goals/types.d.ts +24 -0
  385. package/dist/src/notes/service.js +2 -2
  386. package/dist/src/notes/service.js.map +1 -1
  387. package/dist/src/providers/constants.d.ts +2 -0
  388. package/dist/src/providers/constants.js +11 -0
  389. package/dist/src/providers/constants.js.map +1 -0
  390. package/dist/src/providers/extension-stream-bridge.js +1 -0
  391. package/dist/src/providers/extension-stream-bridge.js.map +1 -1
  392. package/dist/src/providers/index.d.ts +3 -3
  393. package/dist/src/providers/index.js +5 -4
  394. package/dist/src/providers/index.js.map +1 -1
  395. package/dist/src/providers/model-call.d.ts +17 -0
  396. package/dist/src/providers/model-call.js +60 -0
  397. package/dist/src/providers/model-call.js.map +1 -0
  398. package/dist/src/session/session-title.js +2 -2
  399. package/dist/src/session/session-title.js.map +1 -1
  400. package/dist/src/storage/sqlite/connector-repository.d.ts +49 -0
  401. package/dist/src/storage/sqlite/connector-repository.js +385 -0
  402. package/dist/src/storage/sqlite/connector-repository.js.map +1 -0
  403. package/dist/src/storage/sqlite/index.d.ts +3 -0
  404. package/dist/src/storage/sqlite/index.js +4 -1
  405. package/dist/src/storage/sqlite/migrations/030_connectors.sql +94 -0
  406. package/dist/src/storage/sqlite/migrations/031_connector_approvals.sql +24 -0
  407. package/dist/src/storage/sqlite/migrations/032_connector_webhook_deliveries.sql +15 -0
  408. package/dist/src/storage/sqlite/migrations/033_user_trust_policies.sql +6 -0
  409. package/dist/src/storage/sqlite/migrations/034_allow_global_auto_trust.sql +14 -0
  410. package/dist/src/storage/sqlite/migrations/035_user_profile_prompt_state.sql +7 -0
  411. package/dist/src/storage/sqlite/migrations/036_goal_outcome_metric.sql +12 -0
  412. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  413. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  414. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  415. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  416. package/dist/src/storage/sqlite/schema.js +1 -1
  417. package/dist/src/storage/sqlite/user-profile-setup-repository.d.ts +3 -0
  418. package/dist/src/storage/sqlite/user-profile-setup-repository.js +34 -0
  419. package/dist/src/storage/sqlite/user-profile-setup-repository.js.map +1 -0
  420. package/dist/src/storage/sqlite/user-trust-repository.d.ts +3 -0
  421. package/dist/src/storage/sqlite/user-trust-repository.js +34 -0
  422. package/dist/src/storage/sqlite/user-trust-repository.js.map +1 -0
  423. package/dist/src/tui/components/assistant-message.js +15 -0
  424. package/dist/src/tui/components/assistant-message.js.map +1 -1
  425. package/dist/src/tui/tui-agent-events.js +85 -1
  426. package/dist/src/tui/tui-agent-events.js.map +1 -1
  427. package/dist/src/tui/tui-command-formatters.js +7 -7
  428. package/dist/src/tui/tui-command-formatters.js.map +1 -1
  429. package/dist/src/tui/tui-commands.js +1 -1
  430. package/dist/src/tui/tui-startup-resources.js +1 -1
  431. package/dist/src/user-context/import.d.ts +12 -0
  432. package/dist/src/user-context/import.js +48 -0
  433. package/dist/src/user-context/import.js.map +1 -0
  434. package/dist/src/user-context/profile.d.ts +37 -0
  435. package/dist/src/user-context/profile.js +165 -0
  436. package/dist/src/user-context/profile.js.map +1 -0
  437. package/dist/src/user-context/projection.d.ts +54 -0
  438. package/dist/src/user-context/projection.js +121 -0
  439. package/dist/src/user-context/projection.js.map +1 -0
  440. package/dist/src/user-context/source-recommendations.d.ts +13 -0
  441. package/dist/src/user-context/source-recommendations.js +86 -0
  442. package/dist/src/user-context/source-recommendations.js.map +1 -0
  443. package/dist/src/user-context/trust-policy.d.ts +11 -0
  444. package/dist/src/user-context/trust-policy.js +31 -0
  445. package/dist/src/user-context/trust-policy.js.map +1 -0
  446. package/dist/src/voice/tts/summarize.js +2 -2
  447. package/dist/src/voice/tts/summarize.js.map +1 -1
  448. package/dist/src/workflows/authoring/index.d.ts +1 -0
  449. package/dist/src/workflows/authoring/index.js +2 -0
  450. package/dist/src/workflows/authoring/workflow-draft-store.d.ts +33 -0
  451. package/dist/src/workflows/authoring/workflow-draft-store.js +74 -0
  452. package/dist/src/workflows/authoring/workflow-draft-store.js.map +1 -0
  453. package/dist/src/workflows/domain/definition-utils.d.ts +6 -4
  454. package/dist/src/workflows/domain/definition-utils.js +28 -26
  455. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  456. package/dist/src/workflows/domain/definition.d.ts +79 -6
  457. package/dist/src/workflows/domain/event.d.ts +18 -2
  458. package/dist/src/workflows/domain/index.js +3 -3
  459. package/dist/src/workflows/domain/run.d.ts +16 -2
  460. package/dist/src/workflows/domain/run.js.map +1 -1
  461. package/dist/src/workflows/domain/validation.d.ts +9 -5
  462. package/dist/src/workflows/domain/validation.js +183 -40
  463. package/dist/src/workflows/domain/validation.js.map +1 -1
  464. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +2 -3
  465. package/dist/src/workflows/draft/workflow-draft-prompt.js +31 -73
  466. package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -1
  467. package/dist/src/workflows/draft/workflow-draft-service.js +6 -10
  468. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -1
  469. package/dist/src/workflows/draft/workflow-draft-validator.js +29 -37
  470. package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -1
  471. package/dist/src/workflows/draft/workflow-draft.types.d.ts +4 -4
  472. package/dist/src/workflows/engine/projector.js +43 -1
  473. package/dist/src/workflows/engine/projector.js.map +1 -1
  474. package/dist/src/workflows/engine/workflow-engine.d.ts +2 -3
  475. package/dist/src/workflows/engine/workflow-engine.js +24 -4
  476. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  477. package/dist/src/workflows/index.js +4 -7
  478. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +1 -9
  479. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -1
  480. package/dist/src/workflows/runtime/graph-workflow-runtime.d.ts +10 -0
  481. package/dist/src/workflows/runtime/graph-workflow-runtime.js +295 -0
  482. package/dist/src/workflows/runtime/graph-workflow-runtime.js.map +1 -0
  483. package/dist/src/workflows/runtime/index.d.ts +1 -2
  484. package/dist/src/workflows/runtime/index.js +2 -5
  485. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +5 -8
  486. package/dist/src/workflows/service/workflow-run-service.js +15 -1
  487. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  488. package/dist/src/workflows/service/workflow-run-service.types.d.ts +2 -1
  489. package/package.json +8 -7
  490. package/dist/gateway/static/root/assets/agents-Bd863Akz.js +0 -2
  491. package/dist/gateway/static/root/assets/apps-page-B4omjLxa.js +0 -1
  492. package/dist/gateway/static/root/assets/automation-suggestion-card-fgtj5Gek.js +0 -1
  493. package/dist/gateway/static/root/assets/automations-page-Dz2mgjIR.js +0 -4
  494. package/dist/gateway/static/root/assets/browser-settings-page-DZZz5v_i.js +0 -8
  495. package/dist/gateway/static/root/assets/capability-presets-settings-panel-sCHojZr4.js +0 -1
  496. package/dist/gateway/static/root/assets/channels-settings-UyVSnf9s.js +0 -1
  497. package/dist/gateway/static/root/assets/channels-status-swr-CB5FzcLf.js +0 -1
  498. package/dist/gateway/static/root/assets/connectors-page-BzhHiUO4.js +0 -2
  499. package/dist/gateway/static/root/assets/desktop-pet-settings-DqqUPC7G.js +0 -1
  500. package/dist/gateway/static/root/assets/dreaming-settings-BmL54kQq.js +0 -3
  501. package/dist/gateway/static/root/assets/extension-page-DT5cpace.js +0 -1
  502. package/dist/gateway/static/root/assets/extension-settings-page-CbMk4GhQ.js +0 -1
  503. package/dist/gateway/static/root/assets/gateway-settings-CdghmKHJ.js +0 -1
  504. package/dist/gateway/static/root/assets/goal-create-dialog-CAlsM9MP.js +0 -1
  505. package/dist/gateway/static/root/assets/goal-detail-page-CLPa4F2y.js +0 -4
  506. package/dist/gateway/static/root/assets/goals-page-B2VpdzfH.js +0 -2
  507. package/dist/gateway/static/root/assets/goals-settings-CW1NwxvV.js +0 -1
  508. package/dist/gateway/static/root/assets/heartbeat-settings-C86k5tff.js +0 -1
  509. package/dist/gateway/static/root/assets/index-B8s8Pq5U.css +0 -1
  510. package/dist/gateway/static/root/assets/index-ehajXmqL.js +0 -262
  511. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-8xwKEhui.js +0 -1
  512. package/dist/gateway/static/root/assets/logs-page-C_BMONOO.js +0 -7
  513. package/dist/gateway/static/root/assets/messages-B-8CqAeX.js +0 -3
  514. package/dist/gateway/static/root/assets/models-hub-panel-Do_cwNjF.js +0 -2
  515. package/dist/gateway/static/root/assets/notes-page-5IdlPHaX.js +0 -1
  516. package/dist/gateway/static/root/assets/notes-workbench-0KsRZJIZ.js +0 -2
  517. package/dist/gateway/static/root/assets/project-detail-page-Dk2zB1gy.js +0 -1
  518. package/dist/gateway/static/root/assets/projects-page-CJQntm2G.js +0 -1
  519. package/dist/gateway/static/root/assets/remote-access-hub-CHeZZg7O.js +0 -1
  520. package/dist/gateway/static/root/assets/sessions-page-9Hb_r0AG.js +0 -1
  521. package/dist/gateway/static/root/assets/settings-advanced-gate-PmzVFvAv.js +0 -1
  522. package/dist/gateway/static/root/assets/settings-page-C5G2klUB.js +0 -1
  523. package/dist/gateway/static/root/assets/setup-status-panel-oQ8OLnw3.js +0 -1
  524. package/dist/gateway/static/root/assets/share-preview-page-CXtDHMSi.js +0 -2
  525. package/dist/gateway/static/root/assets/shares-settings-BlNoairj.js +0 -1
  526. package/dist/gateway/static/root/assets/skill-reload-api-BYV5x1KO.js +0 -1
  527. package/dist/gateway/static/root/assets/skills-page-ClBcKQZP.js +0 -2
  528. package/dist/gateway/static/root/assets/toast-z0toXu32.js +0 -1
  529. package/dist/gateway/static/root/assets/user-profile-settings-panel-CeC308-E.js +0 -1
  530. package/dist/gateway/static/root/assets/voice-api-key-field-BE57S-nS.js +0 -1
  531. package/dist/gateway/static/root/assets/work-item-detail-page-Di1ww5Aa.js +0 -1
  532. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CzK84i-B.js +0 -3
  533. package/dist/gateway/static/root/assets/workflow-start-dialog-CtLTtNUB.js +0 -1
  534. package/dist/gateway/static/root/assets/workflows-page-CZFZdua9.js +0 -18
  535. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +0 -13
  536. package/dist/src/agent/workflow/builtins/audit-repo.js +0 -183
  537. package/dist/src/agent/workflow/builtins/audit-repo.js.map +0 -1
  538. package/dist/src/agent/workflow/builtins/client-proposal.d.ts +0 -12
  539. package/dist/src/agent/workflow/builtins/client-proposal.js +0 -164
  540. package/dist/src/agent/workflow/builtins/client-proposal.js.map +0 -1
  541. package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +0 -12
  542. package/dist/src/agent/workflow/builtins/competitor-scan.js +0 -164
  543. package/dist/src/agent/workflow/builtins/competitor-scan.js.map +0 -1
  544. package/dist/src/agent/workflow/builtins/content-draft.d.ts +0 -13
  545. package/dist/src/agent/workflow/builtins/content-draft.js +0 -159
  546. package/dist/src/agent/workflow/builtins/content-draft.js.map +0 -1
  547. package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +0 -11
  548. package/dist/src/agent/workflow/builtins/content-repurpose.js +0 -146
  549. package/dist/src/agent/workflow/builtins/content-repurpose.js.map +0 -1
  550. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +0 -13
  551. package/dist/src/agent/workflow/builtins/debug-incident.js +0 -177
  552. package/dist/src/agent/workflow/builtins/debug-incident.js.map +0 -1
  553. package/dist/src/agent/workflow/builtins/decision-compare.d.ts +0 -13
  554. package/dist/src/agent/workflow/builtins/decision-compare.js +0 -187
  555. package/dist/src/agent/workflow/builtins/decision-compare.js.map +0 -1
  556. package/dist/src/agent/workflow/builtins/implementation-plan.d.ts +0 -12
  557. package/dist/src/agent/workflow/builtins/implementation-plan.js +0 -185
  558. package/dist/src/agent/workflow/builtins/implementation-plan.js.map +0 -1
  559. package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +0 -11
  560. package/dist/src/agent/workflow/builtins/inbox-triage.js +0 -158
  561. package/dist/src/agent/workflow/builtins/inbox-triage.js.map +0 -1
  562. package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +0 -12
  563. package/dist/src/agent/workflow/builtins/meeting-prep.js +0 -152
  564. package/dist/src/agent/workflow/builtins/meeting-prep.js.map +0 -1
  565. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +0 -14
  566. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +0 -171
  567. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +0 -1
  568. package/dist/src/agent/workflow/builtins/offer-design.d.ts +0 -12
  569. package/dist/src/agent/workflow/builtins/offer-design.js +0 -170
  570. package/dist/src/agent/workflow/builtins/offer-design.js.map +0 -1
  571. package/dist/src/agent/workflow/builtins/pr-review.d.ts +0 -12
  572. package/dist/src/agent/workflow/builtins/pr-review.js +0 -178
  573. package/dist/src/agent/workflow/builtins/pr-review.js.map +0 -1
  574. package/dist/src/agent/workflow/builtins/release-check.d.ts +0 -11
  575. package/dist/src/agent/workflow/builtins/release-check.js +0 -174
  576. package/dist/src/agent/workflow/builtins/release-check.js.map +0 -1
  577. package/dist/src/agent/workflow/builtins/research.d.ts +0 -13
  578. package/dist/src/agent/workflow/builtins/research.js +0 -188
  579. package/dist/src/agent/workflow/builtins/research.js.map +0 -1
  580. package/dist/src/agent/workflow/builtins/weekly-review.d.ts +0 -12
  581. package/dist/src/agent/workflow/builtins/weekly-review.js +0 -139
  582. package/dist/src/agent/workflow/builtins/weekly-review.js.map +0 -1
  583. package/dist/src/agent/workflow/last-run-memory.d.ts +0 -42
  584. package/dist/src/agent/workflow/last-run-memory.js +0 -60
  585. package/dist/src/agent/workflow/last-run-memory.js.map +0 -1
  586. package/dist/src/agent/workflow/lint.d.ts +0 -38
  587. package/dist/src/agent/workflow/lint.js +0 -74
  588. package/dist/src/agent/workflow/lint.js.map +0 -1
  589. package/dist/src/agent/workflow/meta-locale.d.ts +0 -12
  590. package/dist/src/agent/workflow/meta-locale.js +0 -62
  591. package/dist/src/agent/workflow/meta-locale.js.map +0 -1
  592. package/dist/src/agent/workflow/parser.d.ts +0 -20
  593. package/dist/src/agent/workflow/parser.js +0 -152
  594. package/dist/src/agent/workflow/parser.js.map +0 -1
  595. package/dist/src/agent/workflow/runtime.d.ts +0 -34
  596. package/dist/src/agent/workflow/runtime.js +0 -402
  597. package/dist/src/agent/workflow/runtime.js.map +0 -1
  598. package/dist/src/connectors/oauth.d.ts +0 -22
  599. package/dist/src/connectors/oauth.js +0 -99
  600. package/dist/src/connectors/oauth.js.map +0 -1
  601. package/dist/src/workflows/runtime/script-runtime.d.ts +0 -3
  602. package/dist/src/workflows/runtime/script-runtime.js +0 -3
  603. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +0 -5
  604. package/dist/src/workflows/runtime/script-workflow-runtime.js +0 -15
  605. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +0 -1
@@ -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":";;;;;;AA+BA,SAAS,SAAS,OAAgB,OAA2B;AAC3D,KAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,MAAM,CAC7D,OAAM,IAAI,MAAM,GAAG,MAAM,qBAAqB;AAEhD,QAAO;;AAGT,SAAS,SAAS,OAAgB,OAAuB;AACvD,KAAI,OAAO,UAAU,YAAY,CAAC,MAAM,MAAM,CAC5C,OAAM,IAAI,MAAM,GAAG,MAAM,8BAA8B;AAEzD,QAAO,MAAM,MAAM;;AAGrB,SAAS,cAAc,OAAgB,OAAyB;AAC9D,KAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAM,SAAS,OAAO,SAAS,YAAY,CAAC,KAAK,MAAM,CAAC,CACzF,OAAM,IAAI,MAAM,GAAG,MAAM,yCAAyC;AAEpE,QAAO,MAAM,KAAK,SAAS,KAAK,MAAM,CAAC;;AAGzC,MAAM,mBAAmB;AACzB,MAAM,eAAe;AAErB,SAAS,oBAAoB,OAAwB;CACnD,MAAM,YAAY,SAAS,OAAO,yBAAyB;CAC3D,IAAI;AACJ,KAAI;AACF,QAAM,IAAI,IAAI,UAAU;SAClB;AACN,QAAM,IAAI,MAAM,8CAA8C;;CAEhE,MAAM,WAAW,IAAI,SAAS,aAAa,CAAC,QAAQ,YAAY,GAAG;AACnE,KACE,IAAI,aAAa,YACjB,IAAI,YACJ,IAAI,YACJ,aAAa,eACb,SAAS,SAAS,aAAa,IAC/B,KAAK,SAAS,CAEd,OAAM,IAAI,MAAM,yDAAyD;AAE3E,QAAO,IAAI,UAAU;;AAGvB,SAAS,gBAAgB,OAAgB,SAAwC;CAC/E,MAAM,cAAc,SAAS,OAAO,wBAAwB;AAC5D,KAAI,YAAY,cAAc,SAAS;AACrC,MAAI,QAAS,OAAM,IAAI,MAAM,wEAAwE;AACrG,QAAM,IAAI,MAAM,iEAAiE;;CAEnF,MAAM,aAAa,YAAY,eAAe,KAAA,IAC1C,EAAE,GACF,cAAc,YAAY,YAAY,mCAAmC;AAC7E,KAAI,WAAW,SAAS,EACtB,OAAM,IAAI,MAAM,qDAAqD;CAEvE,MAAM,iBAAiB,cAAc,YAAY,gBAAgB,4BAA4B;AAC7F,KAAI,CAAC,WAAW,eAAe,WAAW,EACxC,OAAM,IAAI,MAAM,6DAA6D;AAE/E,QAAO;EACL,GAAI,YAAY,SAAS,KAAA,IAAY,EAAE,GAAG,EAAE,MAAM,cAAc,YAAY,MAAM,6BAA6B,EAAE;EACjH;EACA,WAAW;EACX;EACD;;AAGH,SAAS,uBAAuB,SAAqB,UAAiF;AACpI,KAAI,QAAQ,iBAAiB,KAAA,EAAW,QAAO;CAC/C,MAAM,eAAe,SAAS,QAAQ,cAAc,yBAAyB;AAC7E,KAAI,aAAa,aAAa,MAC5B,OAAM,IAAI,MAAM,oDAAoD;CAEtE,MAAM,OAAO,SAAS,aAAa,MAAM,+BAA+B;CACxE,MAAM,UAAU,SAAS,aAAa,SAAS,kCAAkC;AACjF,KAAI,CAAC,iBAAiB,KAAK,KAAK,IAAI,CAAC,aAAa,KAAK,QAAQ,CAC7D,OAAM,IAAI,MAAM,qEAAqE;AAEvF,KAAI,SAAS,YAAY,SACvB,KAAK,UAAU,cAAc,SAAS,MAAM,gCAAgC,CAAC,KAAK,KAAK,UAAU,CAAC,SAAS,GAAG,KAAK,GAAG,UAAU,CAAC,CACjI,OAAM,IAAI,MAAM,8DAA8D;AAEhF,MAAK,MAAM,SAAS;EAAC;EAAO;EAAO;EAAO;EAAoB;EAAW;EAAY,CACnF,KAAI,SAAS,SAAU,OAAM,IAAI,MAAM,sEAAsE;AAE/G,QAAO;EAAE,UAAU;EAAO;EAAM;EAAS;;AAG3C,SAAS,sBACP,OACA,aACA,SACA,QACqB;CACrB,MAAM,WAAW,SAAS,OAAO,qBAAqB;AACtD,KAAI,SAAS,SAAS,IAAI,eAAe,KAAK,YAC5C,OAAM,IAAI,MAAM,+DAA+D;CAEjF,MAAM,UAAU,SAAS,SAAS,SAAS,oBAAoB;AAC/D,KAAI,QAAQ,SAAS,MACnB,OAAM,IAAI,MAAM,6CAA6C;CAE/D,MAAM,iBAAiB,SAAS,QAAQ,gBAAgB,+BAA+B;CACvF,MAAM,eAAe,uBAAuB,SAAS,eAAe;CACpE,MAAM,YAAY,eAAe;AACjC,KAAI,CAAC,gBAAgB,cAAc,qBAAqB,cAAc,MACpE,OAAM,IAAI,MAAM,8DAA8D;CAGhF,MAAM,WADO,SAAS,SAAS,MAAM,iBAChB,CAAC;AACtB,KAAI,aAAa,UAAU,aAAa,YAAY,aAAa,QAC/D,OAAM,IAAI,MAAM,sDAAsD;CAExE,MAAM,WAAW,SAAS,SAAS,UAAU,qBAAqB;AAClE,KAAI,CAAC;EAAC;EAAQ;EAAQ;EAAW;EAAQ;EAAc;EAAS,CAAC,SAAS,SAAS,CACjF,OAAM,IAAI,MAAM,mCAAmC,WAAW;CAEhE,MAAM,eAAe,cAAc,SAAS,cAAc,yBAAyB;CACnF,MAAM,sBAAsB,IAAI,IAAI;EAClC;EAAS;EAAa;EAAW;EAAW;EAAU;EAAe;EACrE;EAAqB;EAAmB;EACzC,CAAC;AACF,KAAI,aAAa,MAAM,eAAe,CAAC,oBAAoB,IAAI,WAAW,CAAC,CACzE,OAAM,IAAI,MAAM,yDAAyD;CAE3E,MAAM,QAAQ,SAAS,UAAU,KAAA,IAAY,EAAE,GAAG,SAAS,SAAS,OAAO,kBAAkB;CAC7F,MAAM,cAAc,gBAAgB,SAAS,aAAa,QAAQ,aAAa,CAAC;CAChF,MAAM,WAAW,eAAe,KAAA,IAAY,oBAAoB,eAAe,IAAI;CACnF,MAAM,WAAW,WAAW,IAAI,IAAI,SAAS,CAAC,WAAW,KAAA;AACzD,KAAI,YAAY,YAAY,gBAAgB,UAAU,CAAC,YAAY,eAAe,SAAS,SAAS,CAClG,OAAM,IAAI,MAAM,oEAAoE;AAGtF,QAAO;EACL,IAAI;EACJ;EACA,aAAa,SAAS,SAAS,aAAa,wBAAwB;EACpE,aAAa,SAAS,SAAS,aAAa,wBAAwB;EAC1D;EACV,MAAM;EACN,QAAQ;EACM;EACd,GAAI,MAAM,QAAQ,SAAS,KAAK,GAAG,EAAE,MAAM,cAAc,SAAS,MAAM,iBAAiB,EAAE,GAAG,EAAE;EAChG,MAAM,EAAE,MAAM,UAAU;EACjB;EACP,SAAS;GACP,MAAM;GACN,UAAU,SAAS,QAAQ,UAAU,yBAAyB;GAC9D,gBAAgB,eAAe,iBAAiB;IAAE,GAAG;IAAgB,KAAK;IAAU;GACpF,GAAI,eAAe,EAAE,cAAc,GAAG,EAAE;GACzC;EACD;EACA,YAAY;GAAE;GAAa;GAAQ;EACpC;;AAGH,SAAS,iCAAiC,QAAyB;CACjE,IAAI;AACJ,KAAI;AACF,YAAU,IAAI,OAAO,OAAO;SACtB;AACN,QAAM,IAAI,MAAM,uDAAuD;;CAEzE,MAAM,QAAQ,QAAQ,YAAY,CAAC,MAAM,cAAc;EACrD,MAAM,OAAO,UAAU,UAAU,QAAQ,OAAO,IAAI,CAAC,QAAQ,QAAQ,GAAG;AACxE,SAAO,CAAC,UAAU,gBAAgB,SAAS,yBAAyB,KAAK,SAAS,uBAAuB;GACzG;AACF,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,2DAA2D;AAE7E,KAAI;AACF,SAAO,KAAK,MAAM,MAAM,SAAS,CAAC,SAAS,OAAO,CAAC;SAC7C;AACN,QAAM,IAAI,MAAM,8CAA8C;;;AAIlE,eAAsB,oBAAoB,QAAgB,QAA+B;AACvF,QAAO,sBAAsB,0BAA0B,OAAO,EAAE,OAAO;;AAGzE,eAAsB,6BACpB,QACA,aACA,SACoC;CACpC,MAAM,eAAe,0BAA0B,OAAO;CACtD,MAAM,SAAS,MAAM,iCAAiC,cAAc,aAAa,QAAQ;CACzF,MAAM,SAAS,OAAO,cAAc;AACpC,KAAI,CAAC,UAAU,CAAC,kBAAkB,KAAK,OAAO,CAC5C,OAAM,IAAI,MAAM,+DAA+D;CAEjF,MAAM,UAAU,MAAM,gCAAgC,cAAc,OAAO,cAAc,YAAY;CACrG,MAAM,eAAe,WAAW,SAAS,CAAC,OAAO,QAAQ,CAAC,OAAO,MAAM;AACvE,KAAI,iBAAiB,OAAO,aAAa,CACvC,OAAM,IAAI,MAAM,yDAAyD;CAG3E,MAAM,aAAa,sBADM,iCAAiC,QAExC,EAChB,OAAO,MACP,OAAO,cAAc,SACrB,aACD;CACD,MAAM,gBAAgB,sBACpB,OAAO,cAAc,UACrB,OAAO,MACP,OAAO,cAAc,SACrB,aACD;AACD,KAAI,KAAK,UAAU,WAAW,QAAQ,KAAK,KAAK,UAAU,cAAc,QAAQ,CAC9E,OAAM,IAAI,MAAM,iEAAiE;AAEnF,QAAO;EACL,aAAa,OAAO;EACpB,SAAS,OAAO,cAAc;EAC9B,aAAa,WAAW,eAAe,EAAE;EACzC,iBAAiB;EACjB,eAAe,WAAW,KAAK,SAAS;EACxC;EACD;;AAGH,eAAsB,sBACpB,QACA,aACA,OACA,SACA;CACA,MAAM,OAAO,MAAM,6BAA6B,QAAQ,aAAa,QAAQ;AAC7E,KAAI,KAAK,iBAAiB,KAAK,WAAW,OAAO,SAC/C,OAAM,IAAI,MAAM,2HAA2H;AAG7I,QAAO;EAAE,UAAA,MADc,2BAA2B,QAAQ,KAAK,YAAY,MAAM;EAC9D;EAAM"}
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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"}
@@ -7,30 +7,63 @@ import { formatReviewMarkdown } from "../../review/review-types.js";
7
7
  import { randomUUID } from "node:crypto";
8
8
  //#region src/chat-commands/builtins/review.ts
9
9
  const MAX_DIFF_CHARS = 6e4;
10
- const REVIEW_JUDGE_MAX_TOKENS = 8192;
11
- async function emitToolStart(ctx, toolCallId, toolName, args) {
10
+ const REVIEW_JUDGE_MAX_TOKENS = 16384;
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
  }
27
+ async function emitReviewDelta(ctx, reviewId, delta) {
28
+ if (!delta) return;
29
+ await ctx.emitEvent?.({
30
+ type: "review_delta",
31
+ reviewId,
32
+ delta
33
+ });
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
+ }
34
67
  function truncateForPrompt(text) {
35
68
  if (text.length <= MAX_DIFF_CHARS) return {
36
69
  text,
@@ -98,13 +131,12 @@ function parseReviewJson(raw, target) {
98
131
  source: "model"
99
132
  };
100
133
  }
101
- function previewText(text, max = 500) {
102
- const trimmed = text.trim();
103
- return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;
104
- }
105
- function reviewDefaultModelRef(ctx) {
134
+ async function reviewModelRef(ctx) {
135
+ const sessionOverride = await ctx.getSessionConfigStore?.()?.get(ctx.sessionKey).then((config) => config?.modelOverride?.trim()).catch(() => void 0);
136
+ if (sessionOverride) return sessionOverride;
106
137
  try {
107
- return resolveEffectiveAgentProfileForSession(ctx.config, ctx.sessionKey).primaryModelRef;
138
+ const profile = resolveEffectiveAgentProfileForSession(ctx.config, ctx.sessionKey);
139
+ return profile.manifest.models.roles.review?.model?.trim() || profile.primaryModelRef;
108
140
  } catch {
109
141
  return;
110
142
  }
@@ -114,7 +146,9 @@ function buildReviewPrompt(params) {
114
146
  "You are a senior code reviewer. Review the provided git diff for correctness bugs only.",
115
147
  "Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.",
116
148
  "Do not mention style, broad refactors, praise, or speculative improvements.",
117
- "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:",
118
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\":\"...\"}",
119
153
  "Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.",
120
154
  params.instructions ? `Extra reviewer instructions: ${params.instructions}` : "",
@@ -136,36 +170,33 @@ async function resolveWorkspace(ctx) {
136
170
  async function buildReview(ctx, args) {
137
171
  const cwd = await resolveGitRoot(await resolveWorkspace(ctx));
138
172
  const reviewTarget = parseReviewTargetArgs(args);
139
- const prepareToolCallId = `review_prepare_${randomUUID()}`;
140
- await emitToolStart(ctx, prepareToolCallId, "review.prepare_diff", {
141
- target: args.trim() || "uncommitted",
142
- cwd
143
- });
173
+ const reviewId = `review_${randomUUID()}`;
174
+ await emitReviewStart(ctx, reviewId, args.trim() || "current workspace changes", "preparing");
144
175
  let bundle;
145
176
  try {
146
177
  bundle = await buildReviewDiffBundle(cwd, reviewTarget);
147
- 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"), {
148
- target: bundle.targetLabel,
149
- status: bundle.status,
150
- stat: bundle.stat
151
- });
152
178
  } catch (err) {
153
- 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));
154
180
  throw err;
155
181
  }
156
182
  const { text: diff, truncated } = truncateForPrompt(bundle.diff);
157
183
  const target = bundle.targetLabel;
158
184
  const instructions = reviewTarget.instructions ?? "";
159
- if (!bundle.status.trim() && !bundle.diff.trim()) return {
160
- type: "review",
161
- target,
162
- summary: "Working tree is clean.",
163
- findings: [],
164
- overallCorrectness: "patch is correct",
165
- overallExplanation: "No uncommitted changes were found to review.",
166
- generatedAt: Date.now(),
167
- source: "local"
168
- };
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
+ }
169
200
  const prompt = buildReviewPrompt({
170
201
  target,
171
202
  status: bundle.status,
@@ -174,17 +205,13 @@ async function buildReview(ctx, args) {
174
205
  truncated,
175
206
  instructions
176
207
  });
177
- const reviewerModelRef = reviewDefaultModelRef(ctx);
178
- const judgeToolCallId = `review_judge_${randomUUID()}`;
179
- await emitToolStart(ctx, judgeToolCallId, "review.model_judge", {
180
- target,
181
- diffChars: diff.length,
182
- truncated,
183
- ...reviewerModelRef ? { modelRef: reviewerModelRef } : {}
184
- });
208
+ const reviewerModelRef = await reviewModelRef(ctx);
209
+ await emitReviewStart(ctx, reviewId, target, "reviewing");
210
+ const extractReviewProgress = createReviewProgressExtractor();
185
211
  const answer = ctx.btwQuery ? await ctx.btwQuery(prompt, {
186
212
  maxTokens: REVIEW_JUDGE_MAX_TOKENS,
187
- temperature: .1,
213
+ includeSessionContext: false,
214
+ onTextDelta: (delta) => emitReviewDelta(ctx, reviewId, extractReviewProgress(delta)),
188
215
  ...reviewerModelRef ? { modelRef: reviewerModelRef } : {}
189
216
  }) : {
190
217
  text: "",
@@ -193,11 +220,7 @@ async function buildReview(ctx, args) {
193
220
  let judgeFailure = answer.error ? { reason: `Reviewer model error: ${answer.error}` } : answer.text ? void 0 : { reason: "Reviewer model returned no text." };
194
221
  if (answer?.text && !answer.error) try {
195
222
  const parsed = parseReviewJson(answer.text, target);
196
- await emitToolEnd(ctx, judgeToolCallId, "review.model_judge", parsed.summary || `${parsed.findings.length} findings`, {
197
- target,
198
- findings: parsed.findings.length,
199
- overallCorrectness: parsed.overallCorrectness
200
- });
223
+ await emitReviewEnd(ctx, reviewId, "complete");
201
224
  return parsed;
202
225
  } catch (err) {
203
226
  judgeFailure = { reason: `Reviewer model output could not be parsed: ${err instanceof Error ? err.message : String(err)}` };
@@ -213,14 +236,7 @@ async function buildReview(ctx, args) {
213
236
  generatedAt: Date.now(),
214
237
  source: "local"
215
238
  };
216
- await emitToolEnd(ctx, judgeToolCallId, "review.model_judge", fallback.summary, {
217
- target,
218
- findings: 0,
219
- overallCorrectness: fallback.overallCorrectness,
220
- fallback: true,
221
- reason,
222
- ...answer.text ? { responsePreview: previewText(answer.text) } : {}
223
- }, true);
239
+ await emitReviewEnd(ctx, reviewId, "error", reason);
224
240
  return fallback;
225
241
  }
226
242
  const reviewCommand = {
@@ -1 +1 @@
1
- {"version":3,"file":"review.js","names":[],"sources":["../../../../src/chat-commands/builtins/review.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { effectiveWorkspacePathForSession } from '../../session/session-workspace.js';\nimport { resolveEffectiveAgentProfileForSession } from '../../config/agent-profile.js';\nimport { getProjectForSession } from '../../projects/workspace.js';\nimport {\n buildReviewDiffBundle,\n parseReviewTargetArgs,\n resolveGitRoot,\n} from '../../review/review-git.js';\nimport {\n formatReviewMarkdown,\n type ReviewFinding,\n type ReviewOutput,\n type ReviewPriority,\n} from '../../review/review-types.js';\n\nconst MAX_DIFF_CHARS = 60_000;\nconst REVIEW_JUDGE_MAX_TOKENS = 8_192;\n\nasync function emitToolStart(\n ctx: CommandContext,\n toolCallId: string,\n toolName: string,\n args: Record<string, unknown>,\n): Promise<void> {\n await ctx.emitEvent?.({\n type: 'tool_execution_start',\n toolCallId,\n toolName,\n args,\n });\n}\n\nasync function emitToolEnd(\n ctx: CommandContext,\n toolCallId: string,\n toolName: string,\n resultText: string,\n details?: Record<string, unknown>,\n isError = false,\n): Promise<void> {\n await ctx.emitEvent?.({\n type: 'tool_execution_end',\n toolCallId,\n toolName,\n isError,\n result: {\n content: [{ type: 'text', text: resultText }],\n ...(details ? { details } : {}),\n },\n });\n}\n\nfunction truncateForPrompt(text: string): { text: string; truncated: boolean } {\n if (text.length <= MAX_DIFF_CHARS) return { text, truncated: false };\n return {\n text: text.slice(0, MAX_DIFF_CHARS) + '\\n\\n[diff truncated]',\n truncated: true,\n };\n}\n\nfunction extractJsonObject(raw: string): unknown {\n const fenced = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n const text = (fenced?.[1] ?? raw).trim();\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start < 0 || end <= start) throw new Error('review response did not contain JSON');\n return JSON.parse(text.slice(start, end + 1));\n}\n\nfunction priorityFrom(raw: unknown): ReviewPriority {\n const n = typeof raw === 'number' ? raw : Number.parseInt(String(raw ?? ''), 10);\n if (n === 0 || n === 1 || n === 2 || n === 3) return n;\n return 2;\n}\n\nfunction numberFrom(raw: unknown): number | undefined {\n return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;\n}\n\nfunction stringFrom(raw: unknown): string {\n return typeof raw === 'string' ? raw.trim() : '';\n}\n\nfunction parseReviewJson(raw: string, target: string): ReviewOutput {\n const parsed = extractJsonObject(raw);\n const rec = parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : {};\n const rawFindings = Array.isArray(rec.findings) ? rec.findings : [];\n const findings: ReviewFinding[] = rawFindings\n .map((item) => {\n const f = item && typeof item === 'object' && !Array.isArray(item)\n ? item as Record<string, unknown>\n : {};\n const loc = f.code_location && typeof f.code_location === 'object'\n ? f.code_location as Record<string, unknown>\n : {};\n const range = loc.line_range && typeof loc.line_range === 'object'\n ? loc.line_range as Record<string, unknown>\n : {};\n const title = stringFrom(f.title);\n const body = stringFrom(f.body);\n if (!title && !body) return undefined;\n const finding: ReviewFinding = {\n title: title || body.slice(0, 80),\n body,\n priority: priorityFrom(f.priority),\n };\n const confidenceScore = numberFrom(f.confidence_score ?? f.confidenceScore);\n const filePath = stringFrom(loc.file_path ?? f.filePath);\n const lineStart = numberFrom(range.start ?? f.lineStart);\n const lineEnd = numberFrom(range.end ?? f.lineEnd);\n if (confidenceScore !== undefined) finding.confidenceScore = confidenceScore;\n if (filePath) finding.filePath = filePath;\n if (lineStart !== undefined) finding.lineStart = lineStart;\n if (lineEnd !== undefined) finding.lineEnd = lineEnd;\n return finding;\n })\n .filter((item): item is ReviewFinding => Boolean(item));\n\n const correctness = stringFrom(rec.overall_correctness ?? rec.overallCorrectness);\n const overallCorrectness =\n correctness === 'patch is correct' || correctness === 'patch is incorrect'\n ? correctness\n : 'unknown';\n return {\n type: 'review',\n target,\n summary: stringFrom(rec.summary) || `${findings.length} finding${findings.length === 1 ? '' : 's'}`,\n findings,\n overallCorrectness,\n overallExplanation: stringFrom(rec.overall_explanation ?? rec.overallExplanation),\n overallConfidenceScore: numberFrom(rec.overall_confidence_score ?? rec.overallConfidenceScore),\n generatedAt: Date.now(),\n source: 'model',\n };\n}\n\nfunction previewText(text: string, max = 500): string {\n const trimmed = text.trim();\n return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;\n}\n\nfunction reviewDefaultModelRef(ctx: CommandContext): string | undefined {\n try {\n return resolveEffectiveAgentProfileForSession(ctx.config, ctx.sessionKey).primaryModelRef;\n } catch {\n return undefined;\n }\n}\n\nfunction buildReviewPrompt(params: {\n target: string;\n status: string;\n stat: string;\n diff: string;\n truncated: boolean;\n instructions: string;\n}): string {\n return [\n 'You are a senior code reviewer. Review the provided git diff for correctness bugs only.',\n 'Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.',\n 'Do not mention style, broad refactors, praise, or speculative improvements.',\n 'Return strict JSON only with this shape:',\n '{\"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\":\"...\"}',\n 'Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.',\n params.instructions ? `Extra reviewer instructions: ${params.instructions}` : '',\n `Target: ${params.target}`,\n params.truncated ? 'The diff was truncated; only report findings supported by visible lines.' : '',\n 'Git status:',\n params.status || '(clean)',\n 'Diff stat:',\n params.stat || '(none)',\n 'Diff:',\n params.diff || '(none)',\n ].filter(Boolean).join('\\n\\n');\n}\n\nasync function resolveWorkspace(ctx: CommandContext): Promise<string> {\n const sessionConfigStore = ctx.getSessionConfigStore?.();\n const sessionConfig = sessionConfigStore\n ? await sessionConfigStore.get(ctx.sessionKey).catch(() => null)\n : null;\n return effectiveWorkspacePathForSession(\n ctx.config,\n ctx.sessionKey,\n sessionConfig,\n getProjectForSession(ctx.sessionKey),\n );\n}\n\nasync function buildReview(ctx: CommandContext, args: string): Promise<ReviewOutput> {\n const workspace = await resolveWorkspace(ctx);\n const cwd = await resolveGitRoot(workspace);\n const reviewTarget = parseReviewTargetArgs(args);\n const prepareToolCallId = `review_prepare_${randomUUID()}`;\n await emitToolStart(ctx, prepareToolCallId, 'review.prepare_diff', {\n target: args.trim() || 'uncommitted',\n cwd,\n });\n let bundle: Awaited<ReturnType<typeof buildReviewDiffBundle>>;\n try {\n bundle = await buildReviewDiffBundle(cwd, reviewTarget);\n await emitToolEnd(\n ctx,\n prepareToolCallId,\n 'review.prepare_diff',\n [\n `Target: ${bundle.targetLabel}`,\n bundle.stat.trim() ? `Changed files:\\n${bundle.stat.trim()}` : 'No diff stat.',\n ].join('\\n\\n'),\n {\n target: bundle.targetLabel,\n status: bundle.status,\n stat: bundle.stat,\n },\n );\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n await emitToolEnd(ctx, prepareToolCallId, 'review.prepare_diff', em, { cwd }, true);\n throw err;\n }\n const { text: diff, truncated } = truncateForPrompt(bundle.diff);\n const target = bundle.targetLabel;\n const instructions = reviewTarget.instructions ?? '';\n\n if (!bundle.status.trim() && !bundle.diff.trim()) {\n return {\n type: 'review',\n target,\n summary: 'Working tree is clean.',\n findings: [],\n overallCorrectness: 'patch is correct',\n overallExplanation: 'No uncommitted changes were found to review.',\n generatedAt: Date.now(),\n source: 'local',\n };\n }\n\n const prompt = buildReviewPrompt({\n target,\n status: bundle.status,\n stat: bundle.stat,\n diff,\n truncated,\n instructions,\n });\n const reviewerModelRef = reviewDefaultModelRef(ctx);\n const judgeToolCallId = `review_judge_${randomUUID()}`;\n await emitToolStart(ctx, judgeToolCallId, 'review.model_judge', {\n target,\n diffChars: diff.length,\n truncated,\n ...(reviewerModelRef ? { modelRef: reviewerModelRef } : {}),\n });\n const answer = ctx.btwQuery\n ? await ctx.btwQuery(prompt, {\n maxTokens: REVIEW_JUDGE_MAX_TOKENS,\n temperature: 0.1,\n ...(reviewerModelRef ? { modelRef: reviewerModelRef } : {}),\n })\n : { text: '', error: 'Review model query is not available in this command context.' };\n let judgeFailure = answer.error\n ? { reason: `Reviewer model error: ${answer.error}` }\n : answer.text\n ? undefined\n : { reason: 'Reviewer model returned no text.' };\n if (answer?.text && !answer.error) {\n try {\n const parsed = parseReviewJson(answer.text, target);\n await emitToolEnd(\n ctx,\n judgeToolCallId,\n 'review.model_judge',\n parsed.summary || `${parsed.findings.length} findings`,\n {\n target,\n findings: parsed.findings.length,\n overallCorrectness: parsed.overallCorrectness,\n },\n );\n return parsed;\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n judgeFailure = {\n reason: `Reviewer model output could not be parsed: ${em}`,\n };\n }\n }\n\n const reason = judgeFailure?.reason ?? 'Reviewer model output could not be parsed.';\n const fallback: ReviewOutput = {\n type: 'review',\n target,\n summary: 'Review model did not complete; returned a local diff summary.',\n findings: [],\n overallCorrectness: 'unknown',\n overallExplanation: [\n reason,\n bundle.stat.trim() ? `Changed files:\\n${bundle.stat.trim()}` : 'No textual diff stat was available.',\n ].join('\\n\\n'),\n generatedAt: Date.now(),\n source: 'local',\n };\n await emitToolEnd(\n ctx,\n judgeToolCallId,\n 'review.model_judge',\n fallback.summary,\n {\n target,\n findings: 0,\n overallCorrectness: fallback.overallCorrectness,\n fallback: true,\n reason,\n ...(answer.text ? { responsePreview: previewText(answer.text) } : {}),\n },\n true,\n );\n return fallback;\n}\n\nconst reviewCommand: CommandDefinition = {\n id: 'coding.review',\n name: 'review',\n description: 'Review current workspace changes for correctness issues',\n category: 'tool',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/review', '/review focus on auth and persistence'],\n handler: async (ctx: CommandContext, args: string) => {\n await ctx.setTyping(true);\n const review = await buildReview(ctx, args);\n return {\n content: formatReviewMarkdown(review),\n success: true,\n metadata: { review },\n };\n },\n};\n\nexport function registerReviewCommand(): void {\n commandRegistry.register(reviewCommand);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"review.js","names":[],"sources":["../../../../src/chat-commands/builtins/review.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { effectiveWorkspacePathForSession } from '../../session/session-workspace.js';\nimport { resolveEffectiveAgentProfileForSession } from '../../config/agent-profile.js';\nimport { getProjectForSession } from '../../projects/workspace.js';\nimport {\n buildReviewDiffBundle,\n parseReviewTargetArgs,\n resolveGitRoot,\n} from '../../review/review-git.js';\nimport {\n formatReviewMarkdown,\n type ReviewFinding,\n type ReviewOutput,\n type ReviewPriority,\n} from '../../review/review-types.js';\n\nconst MAX_DIFF_CHARS = 60_000;\nconst REVIEW_JUDGE_MAX_TOKENS = 16_384;\n\nasync function emitReviewStart(\n ctx: CommandContext,\n reviewId: string,\n target: string,\n stage: 'preparing' | 'reviewing',\n): Promise<void> {\n await ctx.emitEvent?.({\n type: 'review_start',\n reviewId,\n target,\n stage,\n });\n}\n\nasync function emitReviewEnd(\n ctx: CommandContext,\n reviewId: string,\n status: 'complete' | 'error',\n message?: string,\n): Promise<void> {\n await ctx.emitEvent?.({\n type: 'review_end',\n reviewId,\n status,\n ...(message ? { message } : {}),\n });\n}\n\nasync function emitReviewDelta(\n ctx: CommandContext,\n reviewId: string,\n delta: string,\n): Promise<void> {\n if (!delta) return;\n await ctx.emitEvent?.({\n type: 'review_delta',\n reviewId,\n delta,\n });\n}\n\nfunction createReviewProgressExtractor(): (delta: string) => string {\n const open = '<review_progress>';\n const close = '</review_progress>';\n let buffer = '';\n let inside = false;\n\n return (delta) => {\n buffer += delta;\n let visible = '';\n\n while (buffer) {\n if (!inside) {\n const start = buffer.indexOf(open);\n if (start < 0) {\n buffer = buffer.slice(-Math.max(0, open.length - 1));\n break;\n }\n buffer = buffer.slice(start + open.length);\n inside = true;\n }\n\n const end = buffer.indexOf(close);\n if (end < 0) {\n const safeLength = Math.max(0, buffer.length - (close.length - 1));\n visible += buffer.slice(0, safeLength);\n buffer = buffer.slice(safeLength);\n break;\n }\n\n visible += buffer.slice(0, end);\n buffer = buffer.slice(end + close.length);\n inside = false;\n }\n\n return visible;\n };\n}\n\nfunction truncateForPrompt(text: string): { text: string; truncated: boolean } {\n if (text.length <= MAX_DIFF_CHARS) return { text, truncated: false };\n return {\n text: text.slice(0, MAX_DIFF_CHARS) + '\\n\\n[diff truncated]',\n truncated: true,\n };\n}\n\nfunction extractJsonObject(raw: string): unknown {\n const fenced = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n const text = (fenced?.[1] ?? raw).trim();\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start < 0 || end <= start) throw new Error('review response did not contain JSON');\n return JSON.parse(text.slice(start, end + 1));\n}\n\nfunction priorityFrom(raw: unknown): ReviewPriority {\n const n = typeof raw === 'number' ? raw : Number.parseInt(String(raw ?? ''), 10);\n if (n === 0 || n === 1 || n === 2 || n === 3) return n;\n return 2;\n}\n\nfunction numberFrom(raw: unknown): number | undefined {\n return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;\n}\n\nfunction stringFrom(raw: unknown): string {\n return typeof raw === 'string' ? raw.trim() : '';\n}\n\nfunction parseReviewJson(raw: string, target: string): ReviewOutput {\n const parsed = extractJsonObject(raw);\n const rec = parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : {};\n const rawFindings = Array.isArray(rec.findings) ? rec.findings : [];\n const findings: ReviewFinding[] = rawFindings\n .map((item) => {\n const f = item && typeof item === 'object' && !Array.isArray(item)\n ? item as Record<string, unknown>\n : {};\n const loc = f.code_location && typeof f.code_location === 'object'\n ? f.code_location as Record<string, unknown>\n : {};\n const range = loc.line_range && typeof loc.line_range === 'object'\n ? loc.line_range as Record<string, unknown>\n : {};\n const title = stringFrom(f.title);\n const body = stringFrom(f.body);\n if (!title && !body) return undefined;\n const finding: ReviewFinding = {\n title: title || body.slice(0, 80),\n body,\n priority: priorityFrom(f.priority),\n };\n const confidenceScore = numberFrom(f.confidence_score ?? f.confidenceScore);\n const filePath = stringFrom(loc.file_path ?? f.filePath);\n const lineStart = numberFrom(range.start ?? f.lineStart);\n const lineEnd = numberFrom(range.end ?? f.lineEnd);\n if (confidenceScore !== undefined) finding.confidenceScore = confidenceScore;\n if (filePath) finding.filePath = filePath;\n if (lineStart !== undefined) finding.lineStart = lineStart;\n if (lineEnd !== undefined) finding.lineEnd = lineEnd;\n return finding;\n })\n .filter((item): item is ReviewFinding => Boolean(item));\n\n const correctness = stringFrom(rec.overall_correctness ?? rec.overallCorrectness);\n const overallCorrectness =\n correctness === 'patch is correct' || correctness === 'patch is incorrect'\n ? correctness\n : 'unknown';\n return {\n type: 'review',\n target,\n summary: stringFrom(rec.summary) || `${findings.length} finding${findings.length === 1 ? '' : 's'}`,\n findings,\n overallCorrectness,\n overallExplanation: stringFrom(rec.overall_explanation ?? rec.overallExplanation),\n overallConfidenceScore: numberFrom(rec.overall_confidence_score ?? rec.overallConfidenceScore),\n generatedAt: Date.now(),\n source: 'model',\n };\n}\n\nasync function reviewModelRef(ctx: CommandContext): Promise<string | undefined> {\n const sessionOverride = await ctx.getSessionConfigStore?.()\n ?.get(ctx.sessionKey)\n .then((config) => config?.modelOverride?.trim())\n .catch(() => undefined);\n if (sessionOverride) return sessionOverride;\n\n try {\n const profile = resolveEffectiveAgentProfileForSession(ctx.config, ctx.sessionKey);\n return profile.manifest.models.roles.review?.model?.trim() || profile.primaryModelRef;\n } catch {\n return undefined;\n }\n}\n\nfunction buildReviewPrompt(params: {\n target: string;\n status: string;\n stat: string;\n diff: string;\n truncated: boolean;\n instructions: string;\n}): string {\n return [\n 'You are a senior code reviewer. Review the provided git diff for correctness bugs only.',\n 'Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.',\n 'Do not mention style, broad refactors, praise, or speculative improvements.',\n 'Return exactly two XML-delimited sections and nothing else.',\n '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.',\n 'Then put strict JSON inside <review_result>...</review_result> using this shape:',\n '{\"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\":\"...\"}',\n 'Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.',\n params.instructions ? `Extra reviewer instructions: ${params.instructions}` : '',\n `Target: ${params.target}`,\n params.truncated ? 'The diff was truncated; only report findings supported by visible lines.' : '',\n 'Git status:',\n params.status || '(clean)',\n 'Diff stat:',\n params.stat || '(none)',\n 'Diff:',\n params.diff || '(none)',\n ].filter(Boolean).join('\\n\\n');\n}\n\nasync function resolveWorkspace(ctx: CommandContext): Promise<string> {\n const sessionConfigStore = ctx.getSessionConfigStore?.();\n const sessionConfig = sessionConfigStore\n ? await sessionConfigStore.get(ctx.sessionKey).catch(() => null)\n : null;\n return effectiveWorkspacePathForSession(\n ctx.config,\n ctx.sessionKey,\n sessionConfig,\n getProjectForSession(ctx.sessionKey),\n );\n}\n\nasync function buildReview(ctx: CommandContext, args: string): Promise<ReviewOutput> {\n const workspace = await resolveWorkspace(ctx);\n const cwd = await resolveGitRoot(workspace);\n const reviewTarget = parseReviewTargetArgs(args);\n const reviewId = `review_${randomUUID()}`;\n await emitReviewStart(ctx, reviewId, args.trim() || 'current workspace changes', 'preparing');\n let bundle: Awaited<ReturnType<typeof buildReviewDiffBundle>>;\n try {\n bundle = await buildReviewDiffBundle(cwd, reviewTarget);\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n await emitReviewEnd(ctx, reviewId, 'error', em);\n throw err;\n }\n const { text: diff, truncated } = truncateForPrompt(bundle.diff);\n const target = bundle.targetLabel;\n const instructions = reviewTarget.instructions ?? '';\n await emitReviewStart(ctx, reviewId, target, 'preparing');\n\n if (!bundle.status.trim() && !bundle.diff.trim()) {\n const review: ReviewOutput = {\n type: 'review',\n target,\n summary: 'Working tree is clean.',\n findings: [],\n overallCorrectness: 'patch is correct',\n overallExplanation: 'No uncommitted changes were found to review.',\n generatedAt: Date.now(),\n source: 'local',\n };\n await emitReviewEnd(ctx, reviewId, 'complete');\n return review;\n }\n\n const prompt = buildReviewPrompt({\n target,\n status: bundle.status,\n stat: bundle.stat,\n diff,\n truncated,\n instructions,\n });\n const reviewerModelRef = await reviewModelRef(ctx);\n await emitReviewStart(ctx, reviewId, target, 'reviewing');\n const extractReviewProgress = createReviewProgressExtractor();\n const answer = ctx.btwQuery\n ? await ctx.btwQuery(prompt, {\n maxTokens: REVIEW_JUDGE_MAX_TOKENS,\n includeSessionContext: false,\n onTextDelta: (delta) => emitReviewDelta(ctx, reviewId, extractReviewProgress(delta)),\n ...(reviewerModelRef ? { modelRef: reviewerModelRef } : {}),\n })\n : { text: '', error: 'Review model query is not available in this command context.' };\n let judgeFailure = answer.error\n ? { reason: `Reviewer model error: ${answer.error}` }\n : answer.text\n ? undefined\n : { reason: 'Reviewer model returned no text.' };\n if (answer?.text && !answer.error) {\n try {\n const parsed = parseReviewJson(answer.text, target);\n await emitReviewEnd(ctx, reviewId, 'complete');\n return parsed;\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n judgeFailure = {\n reason: `Reviewer model output could not be parsed: ${em}`,\n };\n }\n }\n\n const reason = judgeFailure?.reason ?? 'Reviewer model output could not be parsed.';\n const fallback: ReviewOutput = {\n type: 'review',\n target,\n summary: 'Review model did not complete; returned a local diff summary.',\n findings: [],\n overallCorrectness: 'unknown',\n overallExplanation: [\n reason,\n bundle.stat.trim() ? `Changed files:\\n${bundle.stat.trim()}` : 'No textual diff stat was available.',\n ].join('\\n\\n'),\n generatedAt: Date.now(),\n source: 'local',\n };\n await emitReviewEnd(ctx, reviewId, 'error', reason);\n return fallback;\n}\n\nconst reviewCommand: CommandDefinition = {\n id: 'coding.review',\n name: 'review',\n description: 'Review current workspace changes for correctness issues',\n category: 'tool',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/review', '/review focus on auth and persistence'],\n handler: async (ctx: CommandContext, args: string) => {\n await ctx.setTyping(true);\n const review = await buildReview(ctx, args);\n return {\n content: formatReviewMarkdown(review),\n success: true,\n metadata: { review },\n };\n },\n};\n\nexport function registerReviewCommand(): void {\n commandRegistry.register(reviewCommand);\n}\n"],"mappings":";;;;;;;;AAmBA,MAAM,iBAAiB;AACvB,MAAM,0BAA0B;AAEhC,eAAe,gBACb,KACA,UACA,QACA,OACe;AACf,OAAM,IAAI,YAAY;EACpB,MAAM;EACN;EACA;EACA;EACD,CAAC;;AAGJ,eAAe,cACb,KACA,UACA,QACA,SACe;AACf,OAAM,IAAI,YAAY;EACpB,MAAM;EACN;EACA;EACA,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;EAC/B,CAAC;;AAGJ,eAAe,gBACb,KACA,UACA,OACe;AACf,KAAI,CAAC,MAAO;AACZ,OAAM,IAAI,YAAY;EACpB,MAAM;EACN;EACA;EACD,CAAC;;AAGJ,SAAS,gCAA2D;CAClE,MAAM,OAAO;CACb,MAAM,QAAQ;CACd,IAAI,SAAS;CACb,IAAI,SAAS;AAEb,SAAQ,UAAU;AAChB,YAAU;EACV,IAAI,UAAU;AAEd,SAAO,QAAQ;AACb,OAAI,CAAC,QAAQ;IACX,MAAM,QAAQ,OAAO,QAAQ,KAAK;AAClC,QAAI,QAAQ,GAAG;AACb,cAAS,OAAO,MAAM,CAAC,KAAK,IAAI,GAAG,GAAgB,CAAC;AACpD;;AAEF,aAAS,OAAO,MAAM,QAAQ,GAAY;AAC1C,aAAS;;GAGX,MAAM,MAAM,OAAO,QAAQ,MAAM;AACjC,OAAI,MAAM,GAAG;IACX,MAAM,aAAa,KAAK,IAAI,GAAG,OAAO,SAAU,GAAkB;AAClE,eAAW,OAAO,MAAM,GAAG,WAAW;AACtC,aAAS,OAAO,MAAM,WAAW;AACjC;;AAGF,cAAW,OAAO,MAAM,GAAG,IAAI;AAC/B,YAAS,OAAO,MAAM,MAAM,GAAa;AACzC,YAAS;;AAGX,SAAO;;;AAIX,SAAS,kBAAkB,MAAoD;AAC7E,KAAI,KAAK,UAAU,eAAgB,QAAO;EAAE;EAAM,WAAW;EAAO;AACpE,QAAO;EACL,MAAM,KAAK,MAAM,GAAG,eAAe,GAAG;EACtC,WAAW;EACZ;;AAGH,SAAS,kBAAkB,KAAsB;CAE/C,MAAM,QADS,IAAI,MAAM,gCACL,GAAG,MAAM,KAAK,MAAM;CACxC,MAAM,QAAQ,KAAK,QAAQ,IAAI;CAC/B,MAAM,MAAM,KAAK,YAAY,IAAI;AACjC,KAAI,QAAQ,KAAK,OAAO,MAAO,OAAM,IAAI,MAAM,uCAAuC;AACtF,QAAO,KAAK,MAAM,KAAK,MAAM,OAAO,MAAM,EAAE,CAAC;;AAG/C,SAAS,aAAa,KAA8B;CAClD,MAAM,IAAI,OAAO,QAAQ,WAAW,MAAM,OAAO,SAAS,OAAO,OAAO,GAAG,EAAE,GAAG;AAChF,KAAI,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,EAAG,QAAO;AACrD,QAAO;;AAGT,SAAS,WAAW,KAAkC;AACpD,QAAO,OAAO,QAAQ,YAAY,OAAO,SAAS,IAAI,GAAG,MAAM,KAAA;;AAGjE,SAAS,WAAW,KAAsB;AACxC,QAAO,OAAO,QAAQ,WAAW,IAAI,MAAM,GAAG;;AAGhD,SAAS,gBAAgB,KAAa,QAA8B;CAClE,MAAM,SAAS,kBAAkB,IAAI;CACrC,MAAM,MAAM,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,OAAO,GACtE,SACA,EAAE;CAEN,MAAM,YADc,MAAM,QAAQ,IAAI,SAAS,GAAG,IAAI,WAAW,EAAE,EAEhE,KAAK,SAAS;EACb,MAAM,IAAI,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,KAAK,GAC9D,OACA,EAAE;EACN,MAAM,MAAM,EAAE,iBAAiB,OAAO,EAAE,kBAAkB,WACtD,EAAE,gBACF,EAAE;EACN,MAAM,QAAQ,IAAI,cAAc,OAAO,IAAI,eAAe,WACtD,IAAI,aACJ,EAAE;EACN,MAAM,QAAQ,WAAW,EAAE,MAAM;EACjC,MAAM,OAAO,WAAW,EAAE,KAAK;AAC/B,MAAI,CAAC,SAAS,CAAC,KAAM,QAAO,KAAA;EAC5B,MAAM,UAAyB;GAC7B,OAAO,SAAS,KAAK,MAAM,GAAG,GAAG;GACjC;GACA,UAAU,aAAa,EAAE,SAAS;GACnC;EACD,MAAM,kBAAkB,WAAW,EAAE,oBAAoB,EAAE,gBAAgB;EAC3E,MAAM,WAAW,WAAW,IAAI,aAAa,EAAE,SAAS;EACxD,MAAM,YAAY,WAAW,MAAM,SAAS,EAAE,UAAU;EACxD,MAAM,UAAU,WAAW,MAAM,OAAO,EAAE,QAAQ;AAClD,MAAI,oBAAoB,KAAA,EAAW,SAAQ,kBAAkB;AAC7D,MAAI,SAAU,SAAQ,WAAW;AACjC,MAAI,cAAc,KAAA,EAAW,SAAQ,YAAY;AACjD,MAAI,YAAY,KAAA,EAAW,SAAQ,UAAU;AAC7C,SAAO;GACP,CACD,QAAQ,SAAgC,QAAQ,KAAK,CAAC;CAEzD,MAAM,cAAc,WAAW,IAAI,uBAAuB,IAAI,mBAAmB;CACjF,MAAM,qBACJ,gBAAgB,sBAAsB,gBAAgB,uBAClD,cACA;AACN,QAAO;EACL,MAAM;EACN;EACA,SAAS,WAAW,IAAI,QAAQ,IAAI,GAAG,SAAS,OAAO,UAAU,SAAS,WAAW,IAAI,KAAK;EAC9F;EACA;EACA,oBAAoB,WAAW,IAAI,uBAAuB,IAAI,mBAAmB;EACjF,wBAAwB,WAAW,IAAI,4BAA4B,IAAI,uBAAuB;EAC9F,aAAa,KAAK,KAAK;EACvB,QAAQ;EACT;;AAGH,eAAe,eAAe,KAAkD;CAC9E,MAAM,kBAAkB,MAAM,IAAI,yBAAyB,EACvD,IAAI,IAAI,WAAW,CACpB,MAAM,WAAW,QAAQ,eAAe,MAAM,CAAC,CAC/C,YAAY,KAAA,EAAU;AACzB,KAAI,gBAAiB,QAAO;AAE5B,KAAI;EACF,MAAM,UAAU,uCAAuC,IAAI,QAAQ,IAAI,WAAW;AAClF,SAAO,QAAQ,SAAS,OAAO,MAAM,QAAQ,OAAO,MAAM,IAAI,QAAQ;SAChE;AACN;;;AAIJ,SAAS,kBAAkB,QAOhB;AACT,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,eAAe,gCAAgC,OAAO,iBAAiB;EAC9E,WAAW,OAAO;EAClB,OAAO,YAAY,6EAA6E;EAChG;EACA,OAAO,UAAU;EACjB;EACA,OAAO,QAAQ;EACf;EACA,OAAO,QAAQ;EAChB,CAAC,OAAO,QAAQ,CAAC,KAAK,OAAO;;AAGhC,eAAe,iBAAiB,KAAsC;CACpE,MAAM,qBAAqB,IAAI,yBAAyB;CACxD,MAAM,gBAAgB,qBAClB,MAAM,mBAAmB,IAAI,IAAI,WAAW,CAAC,YAAY,KAAK,GAC9D;AACJ,QAAO,iCACL,IAAI,QACJ,IAAI,YACJ,eACA,qBAAqB,IAAI,WAAW,CACrC;;AAGH,eAAe,YAAY,KAAqB,MAAqC;CAEnF,MAAM,MAAM,MAAM,eAAe,MADT,iBAAiB,IAAI,CACF;CAC3C,MAAM,eAAe,sBAAsB,KAAK;CAChD,MAAM,WAAW,UAAU,YAAY;AACvC,OAAM,gBAAgB,KAAK,UAAU,KAAK,MAAM,IAAI,6BAA6B,YAAY;CAC7F,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,sBAAsB,KAAK,aAAa;UAChD,KAAK;AAEZ,QAAM,cAAc,KAAK,UAAU,SADxB,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CACZ;AAC/C,QAAM;;CAER,MAAM,EAAE,MAAM,MAAM,cAAc,kBAAkB,OAAO,KAAK;CAChE,MAAM,SAAS,OAAO;CACtB,MAAM,eAAe,aAAa,gBAAgB;AAClD,OAAM,gBAAgB,KAAK,UAAU,QAAQ,YAAY;AAEzD,KAAI,CAAC,OAAO,OAAO,MAAM,IAAI,CAAC,OAAO,KAAK,MAAM,EAAE;EAChD,MAAM,SAAuB;GAC3B,MAAM;GACN;GACA,SAAS;GACT,UAAU,EAAE;GACZ,oBAAoB;GACpB,oBAAoB;GACpB,aAAa,KAAK,KAAK;GACvB,QAAQ;GACT;AACD,QAAM,cAAc,KAAK,UAAU,WAAW;AAC9C,SAAO;;CAGT,MAAM,SAAS,kBAAkB;EAC/B;EACA,QAAQ,OAAO;EACf,MAAM,OAAO;EACb;EACA;EACA;EACD,CAAC;CACF,MAAM,mBAAmB,MAAM,eAAe,IAAI;AAClD,OAAM,gBAAgB,KAAK,UAAU,QAAQ,YAAY;CACzD,MAAM,wBAAwB,+BAA+B;CAC7D,MAAM,SAAS,IAAI,WACf,MAAM,IAAI,SAAS,QAAQ;EAC3B,WAAW;EACX,uBAAuB;EACvB,cAAc,UAAU,gBAAgB,KAAK,UAAU,sBAAsB,MAAM,CAAC;EACpF,GAAI,mBAAmB,EAAE,UAAU,kBAAkB,GAAG,EAAE;EACzD,CAAC,GACF;EAAE,MAAM;EAAI,OAAO;EAAgE;CACvF,IAAI,eAAe,OAAO,QACtB,EAAE,QAAQ,yBAAyB,OAAO,SAAS,GACnD,OAAO,OACL,KAAA,IACA,EAAE,QAAQ,oCAAoC;AACpD,KAAI,QAAQ,QAAQ,CAAC,OAAO,MAC1B,KAAI;EACF,MAAM,SAAS,gBAAgB,OAAO,MAAM,OAAO;AACnD,QAAM,cAAc,KAAK,UAAU,WAAW;AAC9C,SAAO;UACA,KAAK;AAEZ,iBAAe,EACb,QAAQ,8CAFC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,IAG1D;;CAIL,MAAM,SAAS,cAAc,UAAU;CACvC,MAAM,WAAyB;EAC7B,MAAM;EACN;EACA,SAAS;EACT,UAAU,EAAE;EACZ,oBAAoB;EACpB,oBAAoB,CAClB,QACA,OAAO,KAAK,MAAM,GAAG,mBAAmB,OAAO,KAAK,MAAM,KAAK,sCAChE,CAAC,KAAK,OAAO;EACd,aAAa,KAAK,KAAK;EACvB,QAAQ;EACT;AACD,OAAM,cAAc,KAAK,UAAU,SAAS,OAAO;AACnD,QAAO;;AAGT,MAAM,gBAAmC;CACvC,IAAI;CACJ,MAAM;CACN,aAAa;CACb,UAAU;CACV,OAAO;EAAC;EAAU;EAAW;EAAQ;CACrC,aAAa;CACb,UAAU,CAAC,WAAW,wCAAwC;CAC9D,SAAS,OAAO,KAAqB,SAAiB;AACpD,QAAM,IAAI,UAAU,KAAK;EACzB,MAAM,SAAS,MAAM,YAAY,KAAK,KAAK;AAC3C,SAAO;GACL,SAAS,qBAAqB,OAAO;GACrC,SAAS;GACT,UAAU,EAAE,QAAQ;GACrB;;CAEJ;AAED,SAAgB,wBAA8B;AAC5C,iBAAgB,SAAS,cAAc"}