@xopcai/xopc 0.0.142 → 0.0.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (543) hide show
  1. package/README.md +1 -1
  2. package/dist/browser-ext/manifest.json +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/activity-center-store-jITiX2vJ.js +1 -0
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BawPxiu5.js → agent-avatar-dicebear-DiME9u_P.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-DzBXhZXO.js +2 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-81xd1p9R.js → app-management-settings-panel-Cuo7SbUP.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-DYeQsYU8.js → appearance-settings-DUfdNQqk.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-CKuKK5AU.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-D_oa7oti.js → archive-plugin-B-Qk6cGr.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-Cd-bwI2N.js → attachment-load-Di6EEbQX.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-DGxvRxtO.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-D-FF_WKV.js +4 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-O8svLKWw.js → binary-plugins-ZaOZDH2I.js} +1 -1
  15. package/dist/gateway/static/root/assets/block-editor-BTFhjWfg.js +184 -0
  16. package/dist/gateway/static/root/assets/browser-settings-page-BvKLdEQt.js +8 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-api-dJy1Eqgx.js → capability-presets-api-BU-pVZiZ.js} +1 -1
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DgyeEwzh.js +2 -0
  19. package/dist/gateway/static/root/assets/{channel-recipient-api-Bfuhp2ty.js → channel-recipient-api-DuulnhIj.js} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-BbVsdD_I.js +1 -0
  21. package/dist/gateway/static/root/assets/channels-status-swr-B5lVrUsN.js +1 -0
  22. package/dist/gateway/static/root/assets/check-BODqo66o.js +1 -0
  23. package/dist/gateway/static/root/assets/chunk-QUQL4437-DXsxWP7r.js +4 -0
  24. package/dist/gateway/static/root/assets/circle-alert-RzVebuX2.js +1 -0
  25. package/dist/gateway/static/root/assets/connectors-page-B8QqVy3I.js +2 -0
  26. package/dist/gateway/static/root/assets/{desktop-pet-DFMfIb5F.js → desktop-pet---yzVxVR.js} +1 -1
  27. package/dist/gateway/static/root/assets/desktop-pet-settings-Dc3gqBJE.js +1 -0
  28. package/dist/gateway/static/root/assets/{directory-picker-path-field-BrYt1gAr.js → directory-picker-path-field-DCmOGLtK.js} +1 -1
  29. package/dist/gateway/static/root/assets/dreaming-settings-BgT5KZVe.js +3 -0
  30. package/dist/gateway/static/root/assets/{extension-debug-page-Bh630pLD.js → extension-debug-page-ByaKTTq4.js} +1 -1
  31. package/dist/gateway/static/root/assets/extension-page-BmRzHAZr.js +1 -0
  32. package/dist/gateway/static/root/assets/extension-settings-page-JUtwIhbF.js +1 -0
  33. package/dist/gateway/static/root/assets/{fetch-B1WtuprY.js → fetch-8QNN25Sh.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-De2N821l.js → gateway-config-api-CxicF50_.js} +1 -1
  35. package/dist/gateway/static/root/assets/gateway-settings-Bz2I_EO5.js +1 -0
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-nEujFSDj.js → gateway-startup-retry-5YBnS9Fj.js} +1 -1
  37. package/dist/gateway/static/root/assets/goal-create-dialog-VcoyuZGN.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-Cilkap2G.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-DUy3eEse.js → goals-config-api-CwcHRdC0.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-C6eoni4z.js +2 -0
  41. package/dist/gateway/static/root/assets/goals-settings-o4i-qAOS.js +1 -0
  42. package/dist/gateway/static/root/assets/heartbeat-settings-DQQkETX8.js +1 -0
  43. package/dist/gateway/static/root/assets/index-BKRqeRHm.js +257 -0
  44. package/dist/gateway/static/root/assets/index-CphxClbs.css +1 -0
  45. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CVIwwM15.js → keyboard-shortcuts-settings-LT6qB-ua.js} +1 -1
  46. package/dist/gateway/static/root/assets/logs-page-Dli2e3fS.js +7 -0
  47. package/dist/gateway/static/root/assets/{markdown-split-B_6us9j7.js → markdown-split-Dw-yE2-y.js} +1 -1
  48. package/dist/gateway/static/root/assets/{media-plugins-D_fryIyj.js → media-plugins-D9NNNUgE.js} +1 -1
  49. package/dist/gateway/static/root/assets/messages-CzKxM6I4.js +5 -0
  50. package/dist/gateway/static/root/assets/models-hub-panel-DVn2Q1Ik.js +2 -0
  51. package/dist/gateway/static/root/assets/notes-page-CRgbJGgk.js +1 -0
  52. package/dist/gateway/static/root/assets/notes-workbench-BxZRHLWx.js +2 -0
  53. package/dist/gateway/static/root/assets/{page-tabs-D_8jGlqx.js → page-tabs-D4hkWVt_.js} +1 -1
  54. package/dist/gateway/static/root/assets/{preview-open-alternatives-BBLMK8Mp.js → preview-open-alternatives-CIckv0uy.js} +1 -1
  55. package/dist/gateway/static/root/assets/project-detail-page-Doz53xLn.js +1 -0
  56. package/dist/gateway/static/root/assets/projects-page-DoMtcRLg.js +1 -0
  57. package/dist/gateway/static/root/assets/remote-access-hub-BeHVEgrm.js +1 -0
  58. package/dist/gateway/static/root/assets/{save-bar-controls-DVS3FR5r.js → save-bar-controls-B0b42kB2.js} +1 -1
  59. package/dist/gateway/static/root/assets/{schedule-field-D6vKd6-T.js → schedule-field-BtjEkczK.js} +1 -1
  60. package/dist/gateway/static/root/assets/{schema-form-BPy4lbIh.js → schema-form-Bf0bk3i6.js} +1 -1
  61. package/dist/gateway/static/root/assets/sessions-page-Bk4bQsBe.js +1 -0
  62. package/dist/gateway/static/root/assets/settings-advanced-gate-DdFyaRMm.js +1 -0
  63. package/dist/gateway/static/root/assets/{settings-collapsible-section-WzdikxPt.js → settings-collapsible-section-BTKTdTNX.js} +1 -1
  64. package/dist/gateway/static/root/assets/{settings-form-section-CvfzhBV-.js → settings-form-section-DL4P0sAj.js} +1 -1
  65. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BxR-Ulhi.js → settings-loading-skeleton-BV6KFNj4.js} +1 -1
  66. package/dist/gateway/static/root/assets/settings-page-B_4DsX5W.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-page-layout-CKefvbYi.js → settings-page-layout-CyGlrInB.js} +1 -1
  68. package/dist/gateway/static/root/assets/setup-status-panel-DJ1_MLgX.js +1 -0
  69. package/dist/gateway/static/root/assets/share-preview-page-BQBV7YrV.js +2 -0
  70. package/dist/gateway/static/root/assets/shares-settings-0VuFLBeU.js +1 -0
  71. package/dist/gateway/static/root/assets/skill-reload-api-DO87Ckeo.js +1 -0
  72. package/dist/gateway/static/root/assets/skills-page-D3VdtxAn.js +2 -0
  73. package/dist/gateway/static/root/assets/{system-settings-panel-BokgAgf7.js → system-settings-panel-D85fBBuI.js} +1 -1
  74. package/dist/gateway/static/root/assets/{typed-models-lib-BwHlNL3L.js → typed-models-lib-CwEuYrHX.js} +1 -1
  75. package/dist/gateway/static/root/assets/{use-channel-catalog-DR11ap3A.js → use-channel-catalog-COXIfXcl.js} +1 -1
  76. package/dist/gateway/static/root/assets/user-context-page-m9JVQ73F.js +1 -0
  77. package/dist/gateway/static/root/assets/user-profile-fields-editor-DtQiuY7E.js +1 -0
  78. package/dist/gateway/static/root/assets/user-profile-settings-panel-CWM0fEpb.js +1 -0
  79. package/dist/gateway/static/root/assets/{utils-BKUWB-TT.js → utils--BO6xT3u.js} +1 -1
  80. package/dist/gateway/static/root/assets/voice-api-key-field-LoT3wgZ9.js +1 -0
  81. package/dist/gateway/static/root/assets/with-selector-aYPsXwdl.js +1 -0
  82. package/dist/gateway/static/root/assets/work-item-detail-page-DSTMz_mO.js +1 -0
  83. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CL_rnAUB.js → workflow-run-setup-panel-B35lJzvm.js} +2 -2
  84. package/dist/gateway/static/root/assets/workflows-page-BfSm9oR8.js +11 -0
  85. package/dist/gateway/static/root/assets/workflows-page-DLioOiRN.css +1 -0
  86. package/dist/gateway/static/root/connector-icons/README.md +11 -0
  87. package/dist/gateway/static/root/connector-icons/airtable.svg +13 -0
  88. package/dist/gateway/static/root/connector-icons/asana.svg +15 -0
  89. package/dist/gateway/static/root/connector-icons/brave-search.svg +1 -0
  90. package/dist/gateway/static/root/connector-icons/clickup.svg +19 -0
  91. package/dist/gateway/static/root/connector-icons/composio.svg +266 -0
  92. package/dist/gateway/static/root/connector-icons/discord.svg +15 -0
  93. package/dist/gateway/static/root/connector-icons/dropbox.svg +152 -0
  94. package/dist/gateway/static/root/connector-icons/excel.svg +56 -0
  95. package/dist/gateway/static/root/connector-icons/fetch.svg +6 -0
  96. package/dist/gateway/static/root/connector-icons/figma.svg +178 -0
  97. package/dist/gateway/static/root/connector-icons/filesystem.svg +6 -0
  98. package/dist/gateway/static/root/connector-icons/github.svg +10 -0
  99. package/dist/gateway/static/root/connector-icons/gmail.svg +3 -0
  100. package/dist/gateway/static/root/connector-icons/google-calendar.svg +3 -0
  101. package/dist/gateway/static/root/connector-icons/google-docs.svg +25 -0
  102. package/dist/gateway/static/root/connector-icons/google-drive.svg +25 -0
  103. package/dist/gateway/static/root/connector-icons/google-sheets.svg +1 -0
  104. package/dist/gateway/static/root/connector-icons/hubspot.svg +142 -0
  105. package/dist/gateway/static/root/connector-icons/jira.svg +15 -0
  106. package/dist/gateway/static/root/connector-icons/linear.svg +5 -0
  107. package/dist/gateway/static/root/connector-icons/memory.svg +5 -0
  108. package/dist/gateway/static/root/connector-icons/microsoft-teams.svg +33 -0
  109. package/dist/gateway/static/root/connector-icons/notion.svg +5 -0
  110. package/dist/gateway/static/root/connector-icons/one-drive.svg +13 -0
  111. package/dist/gateway/static/root/connector-icons/outlook.svg +76 -0
  112. package/dist/gateway/static/root/connector-icons/playwright.svg +9 -0
  113. package/dist/gateway/static/root/connector-icons/salesforce.svg +17 -0
  114. package/dist/gateway/static/root/connector-icons/sequential-thinking.svg +8 -0
  115. package/dist/gateway/static/root/connector-icons/shopify.svg +5 -0
  116. package/dist/gateway/static/root/connector-icons/slack.svg +9 -0
  117. package/dist/gateway/static/root/connector-icons/spotify.svg +43 -0
  118. package/dist/gateway/static/root/connector-icons/stripe.svg +11 -0
  119. package/dist/gateway/static/root/connector-icons/telegram.svg +130 -0
  120. package/dist/gateway/static/root/connector-icons/time.svg +6 -0
  121. package/dist/gateway/static/root/connector-icons/todoist.svg +277 -0
  122. package/dist/gateway/static/root/connector-icons/trello.svg +19 -0
  123. package/dist/gateway/static/root/connector-icons/twitter.svg +128 -0
  124. package/dist/gateway/static/root/connector-icons/whatsapp.svg +61 -0
  125. package/dist/gateway/static/root/connector-icons/youtube.svg +11 -0
  126. package/dist/gateway/static/root/index.html +9 -6
  127. package/dist/package.js +1 -1
  128. package/dist/src/agent/agent-manager.d.ts +2 -0
  129. package/dist/src/agent/agent-manager.js +8 -0
  130. package/dist/src/agent/agent-manager.js.map +1 -1
  131. package/dist/src/agent/background-review/prompts.d.ts +1 -1
  132. package/dist/src/agent/background-review/prompts.js +3 -2
  133. package/dist/src/agent/background-review/prompts.js.map +1 -1
  134. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  135. package/dist/src/agent/embedded/xopc-tools-bridge.d.ts +9 -0
  136. package/dist/src/agent/embedded/xopc-tools-bridge.js +71 -3
  137. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  138. package/dist/src/agent/goals/post-turn.js +5 -4
  139. package/dist/src/agent/goals/post-turn.js.map +1 -1
  140. package/dist/src/agent/mcp/mcp-transport.js +4 -1
  141. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  142. package/dist/src/agent/memory/context/planner.d.ts +1 -0
  143. package/dist/src/agent/memory/context/planner.js +60 -14
  144. package/dist/src/agent/memory/context/planner.js.map +1 -1
  145. package/dist/src/agent/memory/context/types.d.ts +3 -1
  146. package/dist/src/agent/memory/lifecycle.d.ts +11 -0
  147. package/dist/src/agent/memory/lifecycle.js +50 -0
  148. package/dist/src/agent/memory/lifecycle.js.map +1 -0
  149. package/dist/src/agent/memory/source-origin.d.ts +3 -0
  150. package/dist/src/agent/memory/source-origin.js +19 -0
  151. package/dist/src/agent/memory/source-origin.js.map +1 -0
  152. package/dist/src/agent/memory/understanding/service.js +5 -0
  153. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  154. package/dist/src/agent/memory/user-context-coordinator.js +7 -2
  155. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  156. package/dist/src/agent/prompt/sections/behavior.d.ts +2 -0
  157. package/dist/src/agent/prompt/sections/behavior.js +30 -1
  158. package/dist/src/agent/prompt/sections/behavior.js.map +1 -1
  159. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  160. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  161. package/dist/src/agent/prompt/service-prompt-builder.js +8 -1
  162. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  163. package/dist/src/agent/prompt/system-prompt.d.ts +2 -0
  164. package/dist/src/agent/prompt/system-prompt.js +6 -3
  165. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  166. package/dist/src/agent/service/process-direct-streaming.js +22 -0
  167. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  168. package/dist/src/agent/service.d.ts +2 -0
  169. package/dist/src/agent/service.js +9 -3
  170. package/dist/src/agent/service.js.map +1 -1
  171. package/dist/src/agent/starter-agents.js +1 -1
  172. package/dist/src/agent/starter-agents.js.map +1 -1
  173. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  174. package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
  175. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -1
  176. package/dist/src/agent/tools/composio-tool.d.ts +18 -5
  177. package/dist/src/agent/tools/composio-tool.js +252 -35
  178. package/dist/src/agent/tools/composio-tool.js.map +1 -1
  179. package/dist/src/agent/tools/factory.js +7 -3
  180. package/dist/src/agent/tools/factory.js.map +1 -1
  181. package/dist/src/agent/tools/index.d.ts +1 -1
  182. package/dist/src/agent/tools/index.js +2 -2
  183. package/dist/src/agent/tools/workflow-tool.d.ts +0 -1
  184. package/dist/src/agent/tools/workflow-tool.js +3 -16
  185. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  186. package/dist/src/agent/workflow/builtins/index.d.ts +2 -28
  187. package/dist/src/agent/workflow/builtins/index.js +226 -41
  188. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  189. package/dist/src/agent/workflow/catalog.d.ts +32 -34
  190. package/dist/src/agent/workflow/catalog.js +158 -154
  191. package/dist/src/agent/workflow/catalog.js.map +1 -1
  192. package/dist/src/agent/workflow/index.d.ts +4 -6
  193. package/dist/src/agent/workflow/index.js +2 -5
  194. package/dist/src/agent/workflow/snapshot.d.ts +2 -2
  195. package/dist/src/agent/workflow/snapshot.js +2 -2
  196. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  197. package/dist/src/agent/workflow/structured-output-tool.d.ts +2 -2
  198. package/dist/src/agent/workflow/structured-output-tool.js +2 -2
  199. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -1
  200. package/dist/src/agent/workflow/subagent-runner.js +1 -1
  201. package/dist/src/agent/workflow/types.d.ts +31 -26
  202. package/dist/src/agent-manifest/index.d.ts +1 -0
  203. package/dist/src/agent-manifest/index.js +3 -1
  204. package/dist/src/agent-manifest/index.js.map +1 -1
  205. package/dist/src/agent-manifest/preset-chain.d.ts +10 -0
  206. package/dist/src/agent-manifest/preset-chain.js +32 -0
  207. package/dist/src/agent-manifest/preset-chain.js.map +1 -0
  208. package/dist/src/agent-manifest/resolver.js +3 -10
  209. package/dist/src/agent-manifest/resolver.js.map +1 -1
  210. package/dist/src/agent-manifest/schema.d.ts +4 -4
  211. package/dist/src/automations/api/routes.js +13 -1
  212. package/dist/src/automations/api/routes.js.map +1 -1
  213. package/dist/src/automations/domain/validation.d.ts +14 -14
  214. package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -3
  215. package/dist/src/browser/providers/browser-ext-install.d.ts +11 -1
  216. package/dist/src/browser/providers/browser-ext-install.js +39 -14
  217. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  218. package/dist/src/capabilities/store-connector.d.ts +0 -1
  219. package/dist/src/capabilities/store-connector.js +3 -5
  220. package/dist/src/capabilities/store-connector.js.map +1 -1
  221. package/dist/src/chat-commands/builtins/review.js +72 -73
  222. package/dist/src/chat-commands/builtins/review.js.map +1 -1
  223. package/dist/src/chat-commands/builtins/workflow.js +9 -54
  224. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  225. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  226. package/dist/src/cli/commands/extension-create.js +2 -2
  227. package/dist/src/cli/commands/extension-create.js.map +1 -1
  228. package/dist/src/cli/commands/extension-marketplace.js +42 -36
  229. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  230. package/dist/src/cli/commands/extension-pack.d.ts +6 -0
  231. package/dist/src/cli/commands/extension-pack.js +3 -2
  232. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  233. package/dist/src/commands/agents.config.d.ts +1 -0
  234. package/dist/src/commands/agents.config.js +1 -0
  235. package/dist/src/commands/agents.config.js.map +1 -1
  236. package/dist/src/config/schema.d.ts +6 -6
  237. package/dist/src/config/schema.js +6 -22
  238. package/dist/src/config/schema.js.map +1 -1
  239. package/dist/src/config/web-patch.d.ts +1 -1
  240. package/dist/src/connectors/approval.d.ts +2 -0
  241. package/dist/src/connectors/approval.js +33 -0
  242. package/dist/src/connectors/approval.js.map +1 -0
  243. package/dist/src/connectors/auth-provider-registry.d.ts +9 -0
  244. package/dist/src/connectors/auth-provider-registry.js +17 -0
  245. package/dist/src/connectors/auth-provider-registry.js.map +1 -0
  246. package/dist/src/connectors/builtin-catalog.js +55 -116
  247. package/dist/src/connectors/builtin-catalog.js.map +1 -1
  248. package/dist/src/connectors/catalog.js +7 -2
  249. package/dist/src/connectors/catalog.js.map +1 -1
  250. package/dist/src/connectors/composio-catalog.d.ts +19 -0
  251. package/dist/src/connectors/composio-catalog.js +237 -0
  252. package/dist/src/connectors/composio-catalog.js.map +1 -0
  253. package/dist/src/connectors/composio-logo.d.ts +1 -0
  254. package/dist/src/connectors/composio-logo.js +51 -0
  255. package/dist/src/connectors/composio-logo.js.map +1 -0
  256. package/dist/src/connectors/composio-sessions.d.ts +116 -0
  257. package/dist/src/connectors/composio-sessions.js +296 -0
  258. package/dist/src/connectors/composio-sessions.js.map +1 -0
  259. package/dist/src/connectors/composio-triggers.d.ts +17 -0
  260. package/dist/src/connectors/composio-triggers.js +48 -5
  261. package/dist/src/connectors/composio-triggers.js.map +1 -1
  262. package/dist/src/connectors/composio.d.ts +31 -2
  263. package/dist/src/connectors/composio.js +374 -151
  264. package/dist/src/connectors/composio.js.map +1 -1
  265. package/dist/src/connectors/connector-memory-sync.d.ts +15 -0
  266. package/dist/src/connectors/connector-memory-sync.js +90 -0
  267. package/dist/src/connectors/connector-memory-sync.js.map +1 -0
  268. package/dist/src/connectors/install.js +35 -92
  269. package/dist/src/connectors/install.js.map +1 -1
  270. package/dist/src/connectors/instances.js +6 -2
  271. package/dist/src/connectors/instances.js.map +1 -1
  272. package/dist/src/connectors/integration-strategy.d.ts +3 -0
  273. package/dist/src/connectors/integration-strategy.js +29 -0
  274. package/dist/src/connectors/integration-strategy.js.map +1 -0
  275. package/dist/src/connectors/policy.d.ts +13 -0
  276. package/dist/src/connectors/policy.js +48 -0
  277. package/dist/src/connectors/policy.js.map +1 -0
  278. package/dist/src/connectors/providers.js +1 -1
  279. package/dist/src/connectors/runtime-adapter-registry.d.ts +25 -0
  280. package/dist/src/connectors/runtime-adapter-registry.js +154 -0
  281. package/dist/src/connectors/runtime-adapter-registry.js.map +1 -0
  282. package/dist/src/connectors/types.d.ts +113 -4
  283. package/dist/src/connectors/workflow-preflight.d.ts +20 -0
  284. package/dist/src/connectors/workflow-preflight.js +70 -0
  285. package/dist/src/connectors/workflow-preflight.js.map +1 -0
  286. package/dist/src/extensions/install-transaction.d.ts +16 -0
  287. package/dist/src/extensions/install-transaction.js +76 -0
  288. package/dist/src/extensions/install-transaction.js.map +1 -0
  289. package/dist/src/extensions/install.d.ts +2 -0
  290. package/dist/src/extensions/install.js +23 -1
  291. package/dist/src/extensions/install.js.map +1 -1
  292. package/dist/src/gateway/agents-admin.d.ts +2 -0
  293. package/dist/src/gateway/agents-admin.js +7 -0
  294. package/dist/src/gateway/agents-admin.js.map +1 -1
  295. package/dist/src/gateway/capability-presets-admin.d.ts +11 -0
  296. package/dist/src/gateway/capability-presets-admin.js +11 -4
  297. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  298. package/dist/src/gateway/chat-stream/mapper.js +17 -0
  299. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  300. package/dist/src/gateway/chat-stream/protocol.d.ts +18 -1
  301. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -3
  302. package/dist/src/gateway/hono/routes/agents.js +3 -0
  303. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  304. package/dist/src/gateway/hono/routes/capability-presets.js +19 -1
  305. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -1
  306. package/dist/src/gateway/hono/routes/connectors.js +188 -25
  307. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  308. package/dist/src/gateway/hono/routes/goals.js +22 -3
  309. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  310. package/dist/src/gateway/hono/routes/home.d.ts +60 -1
  311. package/dist/src/gateway/hono/routes/home.js +244 -18
  312. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  313. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  314. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  315. package/dist/src/gateway/hono/routes/memory.js +14 -1
  316. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  317. package/dist/src/gateway/hono/routes/projects.js +103 -2
  318. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  319. package/dist/src/gateway/hono/routes/public-gateway.js +93 -0
  320. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  321. package/dist/src/gateway/hono/routes/workflows.js +137 -22
  322. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  323. package/dist/src/gateway/hono/routes/you.d.ts +23 -0
  324. package/dist/src/gateway/hono/routes/you.js +538 -0
  325. package/dist/src/gateway/hono/routes/you.js.map +1 -0
  326. package/dist/src/gateway/hono/sse.d.ts +2 -1
  327. package/dist/src/gateway/hono/sse.js +2 -1
  328. package/dist/src/gateway/hono/sse.js.map +1 -1
  329. package/dist/src/gateway/service/marketplace-service.d.ts +13 -1
  330. package/dist/src/gateway/service/marketplace-service.js +96 -40
  331. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  332. package/dist/src/gateway/service.d.ts +2 -0
  333. package/dist/src/gateway/service.js +7 -1
  334. package/dist/src/gateway/service.js.map +1 -1
  335. package/dist/src/goals/goal-service.d.ts +7 -5
  336. package/dist/src/goals/goal-service.js +25 -13
  337. package/dist/src/goals/goal-service.js.map +1 -1
  338. package/dist/src/goals/goal-store.js +46 -7
  339. package/dist/src/goals/goal-store.js.map +1 -1
  340. package/dist/src/goals/types.d.ts +24 -0
  341. package/dist/src/storage/sqlite/connector-repository.d.ts +49 -0
  342. package/dist/src/storage/sqlite/connector-repository.js +385 -0
  343. package/dist/src/storage/sqlite/connector-repository.js.map +1 -0
  344. package/dist/src/storage/sqlite/index.d.ts +3 -0
  345. package/dist/src/storage/sqlite/index.js +4 -1
  346. package/dist/src/storage/sqlite/migrations/030_connectors.sql +94 -0
  347. package/dist/src/storage/sqlite/migrations/031_connector_approvals.sql +24 -0
  348. package/dist/src/storage/sqlite/migrations/032_connector_webhook_deliveries.sql +15 -0
  349. package/dist/src/storage/sqlite/migrations/033_user_trust_policies.sql +6 -0
  350. package/dist/src/storage/sqlite/migrations/034_allow_global_auto_trust.sql +14 -0
  351. package/dist/src/storage/sqlite/migrations/035_user_profile_prompt_state.sql +7 -0
  352. package/dist/src/storage/sqlite/migrations/036_goal_outcome_metric.sql +12 -0
  353. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  354. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  355. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  356. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  357. package/dist/src/storage/sqlite/schema.js +1 -1
  358. package/dist/src/storage/sqlite/user-profile-setup-repository.d.ts +3 -0
  359. package/dist/src/storage/sqlite/user-profile-setup-repository.js +34 -0
  360. package/dist/src/storage/sqlite/user-profile-setup-repository.js.map +1 -0
  361. package/dist/src/storage/sqlite/user-trust-repository.d.ts +3 -0
  362. package/dist/src/storage/sqlite/user-trust-repository.js +34 -0
  363. package/dist/src/storage/sqlite/user-trust-repository.js.map +1 -0
  364. package/dist/src/tui/components/assistant-message.js +15 -0
  365. package/dist/src/tui/components/assistant-message.js.map +1 -1
  366. package/dist/src/tui/tui-agent-events.js +85 -1
  367. package/dist/src/tui/tui-agent-events.js.map +1 -1
  368. package/dist/src/tui/tui-command-formatters.js +7 -7
  369. package/dist/src/tui/tui-command-formatters.js.map +1 -1
  370. package/dist/src/tui/tui-commands.js +1 -1
  371. package/dist/src/tui/tui-startup-resources.js +1 -1
  372. package/dist/src/user-context/import.d.ts +12 -0
  373. package/dist/src/user-context/import.js +48 -0
  374. package/dist/src/user-context/import.js.map +1 -0
  375. package/dist/src/user-context/profile.d.ts +37 -0
  376. package/dist/src/user-context/profile.js +165 -0
  377. package/dist/src/user-context/profile.js.map +1 -0
  378. package/dist/src/user-context/projection.d.ts +54 -0
  379. package/dist/src/user-context/projection.js +121 -0
  380. package/dist/src/user-context/projection.js.map +1 -0
  381. package/dist/src/user-context/source-recommendations.d.ts +13 -0
  382. package/dist/src/user-context/source-recommendations.js +86 -0
  383. package/dist/src/user-context/source-recommendations.js.map +1 -0
  384. package/dist/src/user-context/trust-policy.d.ts +11 -0
  385. package/dist/src/user-context/trust-policy.js +31 -0
  386. package/dist/src/user-context/trust-policy.js.map +1 -0
  387. package/dist/src/workflows/authoring/index.d.ts +1 -0
  388. package/dist/src/workflows/authoring/index.js +2 -0
  389. package/dist/src/workflows/authoring/workflow-draft-store.d.ts +33 -0
  390. package/dist/src/workflows/authoring/workflow-draft-store.js +74 -0
  391. package/dist/src/workflows/authoring/workflow-draft-store.js.map +1 -0
  392. package/dist/src/workflows/domain/definition-utils.d.ts +6 -4
  393. package/dist/src/workflows/domain/definition-utils.js +28 -26
  394. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  395. package/dist/src/workflows/domain/definition.d.ts +79 -6
  396. package/dist/src/workflows/domain/event.d.ts +18 -2
  397. package/dist/src/workflows/domain/index.js +3 -3
  398. package/dist/src/workflows/domain/run.d.ts +16 -2
  399. package/dist/src/workflows/domain/run.js.map +1 -1
  400. package/dist/src/workflows/domain/validation.d.ts +9 -5
  401. package/dist/src/workflows/domain/validation.js +183 -40
  402. package/dist/src/workflows/domain/validation.js.map +1 -1
  403. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +2 -3
  404. package/dist/src/workflows/draft/workflow-draft-prompt.js +31 -73
  405. package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -1
  406. package/dist/src/workflows/draft/workflow-draft-service.js +4 -8
  407. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -1
  408. package/dist/src/workflows/draft/workflow-draft-validator.js +29 -37
  409. package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -1
  410. package/dist/src/workflows/draft/workflow-draft.types.d.ts +4 -4
  411. package/dist/src/workflows/engine/projector.js +43 -1
  412. package/dist/src/workflows/engine/projector.js.map +1 -1
  413. package/dist/src/workflows/engine/workflow-engine.d.ts +2 -3
  414. package/dist/src/workflows/engine/workflow-engine.js +24 -4
  415. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  416. package/dist/src/workflows/index.js +4 -7
  417. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +1 -9
  418. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -1
  419. package/dist/src/workflows/runtime/graph-workflow-runtime.d.ts +10 -0
  420. package/dist/src/workflows/runtime/graph-workflow-runtime.js +295 -0
  421. package/dist/src/workflows/runtime/graph-workflow-runtime.js.map +1 -0
  422. package/dist/src/workflows/runtime/index.d.ts +1 -2
  423. package/dist/src/workflows/runtime/index.js +2 -5
  424. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +5 -8
  425. package/dist/src/workflows/service/workflow-run-service.js +15 -1
  426. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  427. package/dist/src/workflows/service/workflow-run-service.types.d.ts +2 -1
  428. package/package.json +4 -3
  429. package/dist/gateway/static/root/assets/agents-CyvCIHnB.js +0 -2
  430. package/dist/gateway/static/root/assets/apps-page-DK_Vx6nl.js +0 -1
  431. package/dist/gateway/static/root/assets/automation-suggestion-card-B1LV3YYv.js +0 -1
  432. package/dist/gateway/static/root/assets/automations-page-fzrovqhv.js +0 -4
  433. package/dist/gateway/static/root/assets/block-editor-Dhj5f4Bx.js +0 -184
  434. package/dist/gateway/static/root/assets/browser-settings-page-BDn-n-UB.js +0 -8
  435. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Co5ipo_Q.js +0 -1
  436. package/dist/gateway/static/root/assets/channels-settings-BWlpaxg9.js +0 -1
  437. package/dist/gateway/static/root/assets/channels-status-swr-D_jkIZLV.js +0 -1
  438. package/dist/gateway/static/root/assets/connectors-page-BcekbW4q.js +0 -2
  439. package/dist/gateway/static/root/assets/desktop-pet-settings-BJCUuL8Y.js +0 -1
  440. package/dist/gateway/static/root/assets/dreaming-settings-BN1Z2mIo.js +0 -3
  441. package/dist/gateway/static/root/assets/extension-page-B-1KxvVy.js +0 -1
  442. package/dist/gateway/static/root/assets/extension-settings-page-BF9NACI3.js +0 -1
  443. package/dist/gateway/static/root/assets/gateway-settings-DN9sNREz.js +0 -1
  444. package/dist/gateway/static/root/assets/goal-create-dialog-BpoQW8cD.js +0 -1
  445. package/dist/gateway/static/root/assets/goal-detail-page-CBRSPd0b.js +0 -4
  446. package/dist/gateway/static/root/assets/goals-page-BCcBi407.js +0 -2
  447. package/dist/gateway/static/root/assets/goals-settings-pkTXzXkh.js +0 -1
  448. package/dist/gateway/static/root/assets/heartbeat-settings-ezsufgLQ.js +0 -1
  449. package/dist/gateway/static/root/assets/index-B8s8Pq5U.css +0 -1
  450. package/dist/gateway/static/root/assets/index-DcUaXYeb.js +0 -262
  451. package/dist/gateway/static/root/assets/logs-page-DQtTRXtj.js +0 -7
  452. package/dist/gateway/static/root/assets/messages-BXNELNBa.js +0 -3
  453. package/dist/gateway/static/root/assets/models-hub-panel-BP2M9n6Q.js +0 -2
  454. package/dist/gateway/static/root/assets/notes-page-CspveYaO.js +0 -1
  455. package/dist/gateway/static/root/assets/notes-workbench-BHwzJ0OC.js +0 -2
  456. package/dist/gateway/static/root/assets/project-detail-page-Dy3rsobs.js +0 -1
  457. package/dist/gateway/static/root/assets/projects-page-CWKpPE0L.js +0 -1
  458. package/dist/gateway/static/root/assets/remote-access-hub-CqNRyXEo.js +0 -1
  459. package/dist/gateway/static/root/assets/sessions-page-MEME7ivF.js +0 -1
  460. package/dist/gateway/static/root/assets/settings-advanced-gate-JVd0qaSF.js +0 -1
  461. package/dist/gateway/static/root/assets/settings-page-DYEbB1EV.js +0 -1
  462. package/dist/gateway/static/root/assets/setup-status-panel-dWN8BJ3z.js +0 -1
  463. package/dist/gateway/static/root/assets/share-preview-page-D8foINzP.js +0 -2
  464. package/dist/gateway/static/root/assets/shares-settings-Tgbv1s7G.js +0 -1
  465. package/dist/gateway/static/root/assets/skill-reload-api-D_YK0b_Z.js +0 -1
  466. package/dist/gateway/static/root/assets/skills-page-DGytfoZK.js +0 -2
  467. package/dist/gateway/static/root/assets/toast-z0toXu32.js +0 -1
  468. package/dist/gateway/static/root/assets/user-profile-settings-panel-8YtygcJp.js +0 -1
  469. package/dist/gateway/static/root/assets/voice-api-key-field-BVH71EFf.js +0 -1
  470. package/dist/gateway/static/root/assets/work-item-detail-page-JeTE7XNM.js +0 -1
  471. package/dist/gateway/static/root/assets/workflow-start-dialog-_u8Uc1ze.js +0 -1
  472. package/dist/gateway/static/root/assets/workflows-page-ixgk_y1l.js +0 -18
  473. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +0 -13
  474. package/dist/src/agent/workflow/builtins/audit-repo.js +0 -183
  475. package/dist/src/agent/workflow/builtins/audit-repo.js.map +0 -1
  476. package/dist/src/agent/workflow/builtins/client-proposal.d.ts +0 -12
  477. package/dist/src/agent/workflow/builtins/client-proposal.js +0 -164
  478. package/dist/src/agent/workflow/builtins/client-proposal.js.map +0 -1
  479. package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +0 -12
  480. package/dist/src/agent/workflow/builtins/competitor-scan.js +0 -164
  481. package/dist/src/agent/workflow/builtins/competitor-scan.js.map +0 -1
  482. package/dist/src/agent/workflow/builtins/content-draft.d.ts +0 -13
  483. package/dist/src/agent/workflow/builtins/content-draft.js +0 -159
  484. package/dist/src/agent/workflow/builtins/content-draft.js.map +0 -1
  485. package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +0 -11
  486. package/dist/src/agent/workflow/builtins/content-repurpose.js +0 -146
  487. package/dist/src/agent/workflow/builtins/content-repurpose.js.map +0 -1
  488. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +0 -13
  489. package/dist/src/agent/workflow/builtins/debug-incident.js +0 -177
  490. package/dist/src/agent/workflow/builtins/debug-incident.js.map +0 -1
  491. package/dist/src/agent/workflow/builtins/decision-compare.d.ts +0 -13
  492. package/dist/src/agent/workflow/builtins/decision-compare.js +0 -187
  493. package/dist/src/agent/workflow/builtins/decision-compare.js.map +0 -1
  494. package/dist/src/agent/workflow/builtins/implementation-plan.d.ts +0 -12
  495. package/dist/src/agent/workflow/builtins/implementation-plan.js +0 -185
  496. package/dist/src/agent/workflow/builtins/implementation-plan.js.map +0 -1
  497. package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +0 -11
  498. package/dist/src/agent/workflow/builtins/inbox-triage.js +0 -158
  499. package/dist/src/agent/workflow/builtins/inbox-triage.js.map +0 -1
  500. package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +0 -12
  501. package/dist/src/agent/workflow/builtins/meeting-prep.js +0 -152
  502. package/dist/src/agent/workflow/builtins/meeting-prep.js.map +0 -1
  503. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +0 -14
  504. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +0 -171
  505. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +0 -1
  506. package/dist/src/agent/workflow/builtins/offer-design.d.ts +0 -12
  507. package/dist/src/agent/workflow/builtins/offer-design.js +0 -170
  508. package/dist/src/agent/workflow/builtins/offer-design.js.map +0 -1
  509. package/dist/src/agent/workflow/builtins/pr-review.d.ts +0 -12
  510. package/dist/src/agent/workflow/builtins/pr-review.js +0 -178
  511. package/dist/src/agent/workflow/builtins/pr-review.js.map +0 -1
  512. package/dist/src/agent/workflow/builtins/release-check.d.ts +0 -11
  513. package/dist/src/agent/workflow/builtins/release-check.js +0 -174
  514. package/dist/src/agent/workflow/builtins/release-check.js.map +0 -1
  515. package/dist/src/agent/workflow/builtins/research.d.ts +0 -13
  516. package/dist/src/agent/workflow/builtins/research.js +0 -188
  517. package/dist/src/agent/workflow/builtins/research.js.map +0 -1
  518. package/dist/src/agent/workflow/builtins/weekly-review.d.ts +0 -12
  519. package/dist/src/agent/workflow/builtins/weekly-review.js +0 -139
  520. package/dist/src/agent/workflow/builtins/weekly-review.js.map +0 -1
  521. package/dist/src/agent/workflow/last-run-memory.d.ts +0 -42
  522. package/dist/src/agent/workflow/last-run-memory.js +0 -60
  523. package/dist/src/agent/workflow/last-run-memory.js.map +0 -1
  524. package/dist/src/agent/workflow/lint.d.ts +0 -38
  525. package/dist/src/agent/workflow/lint.js +0 -74
  526. package/dist/src/agent/workflow/lint.js.map +0 -1
  527. package/dist/src/agent/workflow/meta-locale.d.ts +0 -12
  528. package/dist/src/agent/workflow/meta-locale.js +0 -62
  529. package/dist/src/agent/workflow/meta-locale.js.map +0 -1
  530. package/dist/src/agent/workflow/parser.d.ts +0 -20
  531. package/dist/src/agent/workflow/parser.js +0 -152
  532. package/dist/src/agent/workflow/parser.js.map +0 -1
  533. package/dist/src/agent/workflow/runtime.d.ts +0 -34
  534. package/dist/src/agent/workflow/runtime.js +0 -402
  535. package/dist/src/agent/workflow/runtime.js.map +0 -1
  536. package/dist/src/connectors/oauth.d.ts +0 -22
  537. package/dist/src/connectors/oauth.js +0 -99
  538. package/dist/src/connectors/oauth.js.map +0 -1
  539. package/dist/src/workflows/runtime/script-runtime.d.ts +0 -3
  540. package/dist/src/workflows/runtime/script-runtime.js +0 -3
  541. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +0 -5
  542. package/dist/src/workflows/runtime/script-workflow-runtime.js +0 -15
  543. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +0 -1
@@ -25,6 +25,8 @@ export interface ListedExtension {
25
25
  origin: 'workspace' | 'global' | 'bundled';
26
26
  }
27
27
  export declare function peekExtensionManifestFromStoreZip(buffer: Buffer): Record<string, unknown> | undefined;
28
+ /** Read package.json from the same root as the shallowest extension manifest. */
29
+ export declare function peekExtensionPackageJsonFromStoreZip(buffer: Buffer): Record<string, unknown> | undefined;
28
30
  /** Read `id` from the shallowest xopc.extension.json in a store zip (for --force / preflight). */
29
31
  export declare function peekExtensionIdFromStoreZip(buffer: Buffer): string | undefined;
30
32
  /**
@@ -141,6 +141,28 @@ function readShallowestExtensionManifestFromZip(buffer) {
141
141
  function peekExtensionManifestFromStoreZip(buffer) {
142
142
  return readShallowestExtensionManifestFromZip(buffer);
143
143
  }
144
+ /** Read package.json from the same root as the shallowest extension manifest. */
145
+ function peekExtensionPackageJsonFromStoreZip(buffer) {
146
+ if (buffer.length > 10485760) return void 0;
147
+ let zip;
148
+ try {
149
+ zip = new AdmZip(buffer);
150
+ } catch {
151
+ return;
152
+ }
153
+ const entries = zip.getEntries().filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName)).filter((e) => isSafeZipPath(e.entryName));
154
+ const manifestPaths = entries.map((e) => e.entryName.replace(/\\/g, "/")).filter((name) => /(^|\/)xopc\.extension\.json$/i.test(name)).filter((name) => name.split("/").filter(Boolean).length <= 2).sort((a, b) => a.length - b.length);
155
+ if (manifestPaths.length === 0) return void 0;
156
+ const packagePath = `${inferExtensionStripPrefix(manifestPaths[0])}package.json`;
157
+ const entry = entries.find((candidate) => candidate.entryName.replace(/\\/g, "/") === packagePath);
158
+ if (!entry) return void 0;
159
+ try {
160
+ const parsed = JSON.parse(entry.getData().toString("utf8"));
161
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : void 0;
162
+ } catch {
163
+ return;
164
+ }
165
+ }
144
166
  /** Read `id` from the shallowest xopc.extension.json in a store zip (for --force / preflight). */
145
167
  function peekExtensionIdFromStoreZip(buffer) {
146
168
  const m = readShallowestExtensionManifestFromZip(buffer);
@@ -510,6 +532,6 @@ function readManifest(extensionDir) {
510
532
  }
511
533
  }
512
534
  //#endregion
513
- export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, peekExtensionManifestFromStoreZip, removeExtension, resolveExtensionsDir };
535
+ export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, peekExtensionManifestFromStoreZip, peekExtensionPackageJsonFromStoreZip, removeExtension, resolveExtensionsDir };
514
536
 
515
537
  //# sourceMappingURL=install.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","names":["resolveGlobalExtensionsDir"],"sources":["../../../src/extensions/install.ts"],"sourcesContent":["/**\n * Extension Installation Module\n * Supports installing from npm packages, local directories, and xopc-store zips\n * Supports three-tier storage: workspace, global, bundled\n */\n\nimport { execSync } from 'child_process';\nimport AdmZip from 'adm-zip';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n cpSync,\n rmSync,\n readdirSync,\n mkdtempSync,\n writeFileSync,\n} from 'fs';\nimport { dirname, join, isAbsolute, resolve, sep } from 'path';\nimport { tmpdir } from 'os';\nimport {\n resolveExtensionsDir as resolveGlobalExtensionsDir,\n resolveBundledExtensionsDir,\n} from '../config/paths.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport { createLogger } from '../utils/logger.js';\nimport { checkEngineCompatibility } from './engine-check.js';\nimport { collectExtensionPackageDependencyIssues } from './package-contract.js';\nimport { MAX_EXTENSION_STORE_ZIP_BYTES } from './store-zip-limits.js';\n\nconst log = createLogger('ExtensionInstall');\n\nconst NPM_INSTALL_ENV = process.env.XOPC_EXTENSION_NPM_INSTALL?.trim().toLowerCase();\n\nfunction extractExecSyncOutput(error: unknown): string {\n if (!error || typeof error !== 'object') return '';\n const o = error as { stderr?: Buffer | string; stdout?: Buffer | string; message?: string };\n const read = (x?: Buffer | string | null) => {\n if (x == null) return '';\n return Buffer.isBuffer(x) ? x.toString('utf8') : x;\n };\n const stderr = read(o.stderr).trim();\n const stdout = read(o.stdout).trim();\n if (stderr) return stderr;\n if (stdout) return stdout;\n return typeof o.message === 'string' ? o.message.trim() : '';\n}\n\nfunction truncateOutput(text: string, max = 4500): string {\n const t = text.trim();\n if (t.length <= max) return t;\n return `…${t.slice(-max)}`;\n}\n\n/**\n * Install production `node_modules` for an unpacked extension (package.json dependencies).\n * Uses pnpm when `pnpm-lock.yaml` is present, otherwise npm. Set `XOPC_EXTENSION_NPM_INSTALL=skip`\n * to skip (extensions must ship runnable code or you install deps manually).\n */\nfunction installExtensionProdDependencies(extensionDir: string): { ok: true } | { ok: false; error: string } {\n if (NPM_INSTALL_ENV === 'skip' || NPM_INSTALL_ENV === '0' || NPM_INSTALL_ENV === 'false') {\n log.warn(\n { extensionDir, XOPC_EXTENSION_NPM_INSTALL: process.env.XOPC_EXTENSION_NPM_INSTALL },\n 'Skipping extension dependency install (XOPC_EXTENSION_NPM_INSTALL)',\n );\n return { ok: true };\n }\n\n const execOpts = {\n cwd: extensionDir,\n timeout: 300_000,\n encoding: 'utf-8' as const,\n stdio: ['ignore', 'pipe', 'pipe'] as ('ignore' | 'pipe')[],\n maxBuffer: 20 * 1024 * 1024,\n env: process.env,\n ...(process.platform === 'win32'\n ? { shell: (process.env.ComSpec && process.env.ComSpec.trim()) || 'cmd.exe' }\n : {}),\n };\n\n const run = (label: string, command: string): { ok: true } | { ok: false; error: string } => {\n try {\n execSync(command, execOpts);\n return { ok: true };\n } catch (err) {\n const out = truncateOutput(extractExecSyncOutput(err));\n const hint =\n label === 'npm'\n ? ' Check that Node.js/npm is on PATH, the registry is reachable, and peer/engine rules allow install.'\n : ' Check that pnpm is on PATH or remove pnpm-lock.yaml to use npm instead.';\n return {\n ok: false,\n error: `${label} install failed.${hint}${out ? `\\n\\n${out}` : ''}`,\n };\n }\n };\n\n const usePnpm = existsSync(join(extensionDir, 'pnpm-lock.yaml'));\n if (usePnpm) {\n const pnpm = run('pnpm', 'pnpm install --prod --no-frozen-lockfile');\n if (pnpm.ok) return pnpm;\n const npmFallback = run('npm', 'npm install --omit=dev --no-audit --no-fund');\n if (npmFallback.ok) {\n log.warn({ extensionDir }, 'pnpm failed; extension dependencies installed with npm instead');\n return { ok: true };\n }\n return npmFallback;\n }\n\n return run('npm', 'npm install --omit=dev --no-audit --no-fund');\n}\n\nexport interface InstallOptions {\n source: 'npm' | 'local';\n targetDir: string;\n timeoutMs?: number;\n global?: boolean;\n}\n\nexport interface InstallResult {\n ok: boolean;\n extensionId?: string;\n targetDir?: string;\n origin?: 'workspace' | 'global';\n error?: string;\n}\n\nexport interface ListedExtension {\n id: string;\n name?: string;\n version?: string;\n kind?: string;\n path: string;\n origin: 'workspace' | 'global' | 'bundled';\n}\n\ninterface ExtensionManifest {\n id: string;\n name?: string;\n version?: string;\n main?: string;\n engines?: {\n xopc?: string;\n extensionApi?: string;\n extensionUiApi?: string;\n };\n}\n\nfunction isSafeZipPath(name: string): boolean {\n if (!name) return false;\n const normalized = name.replace(/\\\\/g, '/');\n if (normalized.includes('..')) return false;\n if (normalized.startsWith('/') || /^\\w:/.test(normalized)) return false;\n for (const p of normalized.split('/')) {\n if (p === '..') return false;\n }\n return true;\n}\n\nfunction isIgnorableZipEntry(name: string): boolean {\n const n = name.replace(/\\\\/g, '/');\n if (n.startsWith('__MACOSX/')) return true;\n const segments = n.split('/').filter(Boolean);\n for (const s of segments) {\n if (s === '.DS_Store' || s === 'Thumbs.db' || s === 'desktop.ini') return true;\n if (s.startsWith('._')) return true;\n }\n return false;\n}\n\nfunction inferExtensionStripPrefix(primaryManifestPath: string): string {\n const norm = primaryManifestPath.replace(/\\\\/g, '/');\n const lower = norm.toLowerCase();\n const suff = 'xopc.extension.json';\n if (lower === suff) return '';\n if (!lower.endsWith(suff)) return '';\n return norm.slice(0, norm.length - suff.length);\n}\n\nfunction readShallowestExtensionManifestFromZip(buffer: Buffer): Record<string, unknown> | undefined {\n if (buffer.length > MAX_EXTENSION_STORE_ZIP_BYTES) return undefined;\n let zip: AdmZip;\n try {\n zip = new AdmZip(buffer);\n } catch {\n return undefined;\n }\n const entries = zip\n .getEntries()\n .filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName));\n const safeEntries = entries.filter((e) => isSafeZipPath(e.entryName));\n const names = safeEntries.map((e) => e.entryName.replace(/\\\\/g, '/'));\n const manifestPaths = names.filter((n) => /(^|\\/)xopc\\.extension\\.json$/i.test(n));\n const shallow = manifestPaths.filter((n) => n.split('/').filter(Boolean).length <= 2);\n if (shallow.length === 0) return undefined;\n shallow.sort((a, b) => a.length - b.length);\n const path = shallow[0];\n const entry = safeEntries.find((e) => e.entryName.replace(/\\\\/g, '/') === path);\n if (!entry) return undefined;\n try {\n const raw = entry.getData().toString('utf8');\n const parsed = JSON.parse(raw) as unknown;\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function peekExtensionManifestFromStoreZip(buffer: Buffer): Record<string, unknown> | undefined {\n return readShallowestExtensionManifestFromZip(buffer);\n}\n\n/** Read `id` from the shallowest xopc.extension.json in a store zip (for --force / preflight). */\nexport function peekExtensionIdFromStoreZip(buffer: Buffer): string | undefined {\n const m = readShallowestExtensionManifestFromZip(buffer) as { id?: string } | undefined;\n const id = typeof m?.id === 'string' ? m.id.trim() : '';\n if (!id || id.includes('/') || id.includes('\\\\')) return undefined;\n return id;\n}\n\n/**\n * Install an extension from an xopc-store zip buffer (layout: manifest at archive root\n * or under a single top-level folder).\n */\nexport async function installExtensionFromStoreZip(\n buffer: Buffer,\n extensionsDir: string,\n): Promise<InstallResult> {\n if (buffer.length > MAX_EXTENSION_STORE_ZIP_BYTES) {\n return {\n ok: false,\n error: `Extension zip exceeds maximum size (${MAX_EXTENSION_STORE_ZIP_BYTES} bytes)`,\n };\n }\n\n const zip = new AdmZip(buffer);\n const entries = zip\n .getEntries()\n .filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName));\n const safeEntries = entries.filter((e) => isSafeZipPath(e.entryName));\n if (safeEntries.length === 0) {\n return { ok: false, error: 'Zip is empty or invalid' };\n }\n\n const names = safeEntries.map((e) => e.entryName.replace(/\\\\/g, '/'));\n const manifestPaths = names.filter((n) => /(^|\\/)xopc\\.extension\\.json$/i.test(n));\n if (manifestPaths.length === 0) {\n return { ok: false, error: 'Zip must contain xopc.extension.json' };\n }\n const shallow = manifestPaths.filter((n) => n.split('/').filter(Boolean).length <= 2);\n if (shallow.length === 0) {\n return {\n ok: false,\n error:\n 'xopc.extension.json is nested too deeply; use a zip with manifest at archive root or one folder (e.g. my-ext/xopc.extension.json)',\n };\n }\n shallow.sort((a, b) => a.length - b.length);\n const stripPrefix = inferExtensionStripPrefix(shallow[0]);\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n const outside = names.filter((n) => !n.startsWith(prefixNorm) && !isIgnorableZipEntry(n));\n if (outside.length > 0) {\n return {\n ok: false,\n error: `Invalid zip: expected all files under \"${prefixNorm.replace(/\\/$/, '')}/\", but found \"${outside[0]}\".`,\n };\n }\n }\n\n const tmpRoot = mkdtempSync(join(tmpdir(), 'xopc-ext-zip-'));\n const destResolved = resolve(tmpRoot);\n try {\n for (const e of safeEntries) {\n const norm = e.entryName.replace(/\\\\/g, '/');\n let rel: string;\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n if (!norm.startsWith(prefixNorm)) {\n return {\n ok: false,\n error: `Zip entry outside extension prefix \"${prefixNorm.replace(/\\/$/, '')}\": ${norm}`,\n };\n }\n rel = norm.slice(prefixNorm.length).replace(/^\\//, '');\n } else {\n rel = norm;\n }\n if (!rel || rel.includes('..')) {\n return { ok: false, error: `Refusing unsafe zip entry path: ${e.entryName}` };\n }\n const targetPath = join(tmpRoot, rel);\n const resolvedTarget = resolve(targetPath);\n if (!resolvedTarget.startsWith(destResolved + sep) && resolvedTarget !== destResolved) {\n return {\n ok: false,\n error: `Refusing unsafe zip path (possible traversal): ${e.entryName}`,\n };\n }\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, e.getData());\n }\n\n if (!existsSync(join(tmpRoot, 'xopc.extension.json'))) {\n return { ok: false, error: 'Extracted content is missing xopc.extension.json' };\n }\n\n return await installFromDirectory(tmpRoot, extensionsDir);\n } finally {\n try {\n rmSync(tmpRoot, { recursive: true, force: true });\n } catch {\n // ignore\n }\n }\n}\n\n/**\n * Resolve target extensions directory based on options\n */\nexport function resolveExtensionsDir(\n workspaceDir: string,\n global = false,\n): string {\n if (global) {\n const globalDir = resolveGlobalExtensionsDir();\n mkdirSync(globalDir, { recursive: true });\n return globalDir;\n }\n return join(workspaceDir, '.extensions');\n}\n\n/**\n * Install extension from npm package\n */\nexport async function installFromNpm(\n packageSpec: string,\n extensionsDir: string,\n timeoutMs = 120000,\n): Promise<InstallResult> {\n const tmpDir = join(tmpdir(), `xopc-install-${Date.now()}`);\n\n try {\n console.log(`📦 Downloading ${packageSpec} from npm...`);\n\n // Create temp directory\n mkdirSync(tmpDir, { recursive: true });\n\n // Use npm pack to download package\n const result = execSync(`npm pack ${packageSpec} --pack-destination ${tmpDir}`, {\n timeout: timeoutMs,\n encoding: 'utf-8',\n stdio: 'pipe',\n });\n\n const packedFile = result.trim().split('\\n').pop()?.trim();\n if (!packedFile) {\n return { ok: false, error: 'Failed to download package from npm' };\n }\n\n const archivePath = join(tmpDir, packedFile);\n\n // Extract tarball\n console.log(`📂 Extracting ${packedFile}...`);\n execSync(`tar -xzf ${archivePath} -C ${tmpDir}`, {\n timeout: 30000,\n stdio: 'pipe',\n });\n\n // npm pack extracts to 'package' directory\n const extractDir = join(tmpDir, 'package');\n\n // Validate and install\n return await installFromDirectory(extractDir, extensionsDir);\n } catch (error) {\n return {\n ok: false,\n error: `Failed to install from npm: ${error instanceof Error ? error.message : String(error)}`,\n };\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Install extension from local directory\n */\nexport async function installFromLocal(\n localPath: string,\n extensionsDir: string,\n): Promise<InstallResult> {\n // Resolve to absolute path\n const sourceDir = isAbsolute(localPath) ? localPath : resolve(process.cwd(), localPath);\n\n if (!existsSync(sourceDir)) {\n return { ok: false, error: `Directory not found: ${sourceDir}` };\n }\n\n console.log(`📂 Installing from local directory: ${sourceDir}...`);\n\n return await installFromDirectory(sourceDir, extensionsDir);\n}\n\n/**\n * Install extension from extracted directory\n */\nasync function installFromDirectory(\n sourceDir: string,\n extensionsDir: string,\n): Promise<InstallResult> {\n // Validate manifest\n const manifestPath = join(sourceDir, 'xopc.extension.json');\n const packagePath = join(sourceDir, 'package.json');\n\n let manifest: ExtensionManifest | null = null;\n let packageJson: { name?: string; version?: string; dependencies?: Record<string, string> } | null =\n null;\n\n // Try to load xopc.extension.json first\n if (existsSync(manifestPath)) {\n try {\n manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as ExtensionManifest;\n } catch {\n return { ok: false, error: 'Invalid xopc.extension.json manifest file' };\n }\n }\n\n // Also try package.json for metadata\n if (existsSync(packagePath)) {\n try {\n packageJson = JSON.parse(readFileSync(packagePath, 'utf-8')) as typeof packageJson;\n } catch {\n // Ignore package.json parse errors\n }\n }\n\n if (packageJson) {\n const packageIssues = collectExtensionPackageDependencyIssues(\n packageJson as Record<string, unknown>,\n { strictRuntimeSdkDeps: true },\n );\n if (packageIssues.length > 0) {\n return {\n ok: false,\n error: `Extension package is not installable as an independent package:\\n${packageIssues\n .map((issue) => `- ${issue.message}`)\n .join('\\n')}`,\n };\n }\n }\n\n // Determine extension ID\n const extensionId = manifest?.id || packageJson?.name;\n if (!extensionId) {\n return {\n ok: false,\n error: 'Extension must have an id in xopc.extension.json or name in package.json',\n };\n }\n\n // Validate extension ID (no path separators)\n if (extensionId.includes('/') || extensionId.includes('\\\\')) {\n return { ok: false, error: 'Extension ID cannot contain path separators' };\n }\n\n // Check if already exists\n const targetDir = join(extensionsDir, extensionId);\n if (existsSync(targetDir)) {\n return { ok: false, error: `Extension already exists at ${targetDir}. Use update instead.` };\n }\n\n if (!manifest) {\n return { ok: false, error: 'Extension must include xopc.extension.json' };\n }\n\n if (!manifest.engines?.xopc) {\n return { ok: false, error: 'Extension manifest must declare engines.xopc' };\n }\n const engineCheck = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);\n if (engineCheck.parseWarning) {\n return {\n ok: false,\n error: engineCheck.reason ?? `Could not parse engines.xopc ${manifest.engines.xopc}`,\n };\n }\n if (!engineCheck.compatible) {\n return {\n ok: false,\n error: engineCheck.reason ?? `xopc ${PACKAGE_VERSION} does not satisfy engines.xopc ${manifest.engines.xopc}`,\n };\n }\n\n if (!manifest.main) {\n return { ok: false, error: 'Extension manifest must declare main' };\n }\n\n if (!/\\.(mjs|cjs|js)$/i.test(manifest.main)) {\n return {\n ok: false,\n error: `Extension main must point at built JavaScript (.js/.mjs/.cjs), got: ${manifest.main}`,\n };\n }\n\n // Validate main entry exists\n const mainFile = manifest.main;\n const mainPath = join(sourceDir, mainFile);\n if (!existsSync(mainPath)) {\n return { ok: false, error: `Main entry not found: ${mainFile}` };\n }\n\n console.log(`📋 Extension: ${manifest?.name || extensionId} (${extensionId})`);\n if (manifest?.version || packageJson?.version) {\n console.log(`🔖 Version: ${manifest?.version || packageJson?.version}`);\n }\n\n // Create target directory\n mkdirSync(targetDir, { recursive: true });\n\n // Copy files\n console.log(`📂 Copying files to ${targetDir}...`);\n cpSync(sourceDir, targetDir, { recursive: true, force: true });\n\n // Install dependencies if package.json exists and has dependencies\n if (packageJson?.dependencies && Object.keys(packageJson.dependencies).length > 0) {\n console.log(`📦 Installing dependencies...`);\n const depResult = installExtensionProdDependencies(targetDir);\n if (depResult.ok === false) {\n rmSync(targetDir, { recursive: true, force: true });\n return { ok: false, error: depResult.error };\n }\n }\n\n const origin = extensionsDir.includes('.xopc/extensions') ? 'global' : 'workspace';\n\n console.log(`✅ Extension ${extensionId} installed successfully!`);\n console.log(`\\nTo enable the extension, add to your config:`);\n console.log(` extensions:`);\n console.log(` enabled: [${extensionId}]`);\n console.log(` ${extensionId}:`);\n console.log(` # your extension options here\\n`);\n\n return { ok: true, extensionId, targetDir, origin };\n}\n\n/**\n * Remove installed extension from all tiers\n */\nexport function removeExtension(\n extensionId: string,\n workspaceDir: string,\n): { ok: boolean; removedFrom?: string; error?: string } {\n // Try workspace first\n const workspaceDir_ = join(workspaceDir, '.extensions');\n const workspaceExtension = join(workspaceDir_, extensionId);\n\n if (existsSync(workspaceExtension)) {\n try {\n rmSync(workspaceExtension, { recursive: true, force: true });\n return { ok: true, removedFrom: 'workspace' };\n } catch (error) {\n return {\n ok: false,\n error: `Failed to remove from workspace: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n\n // Try global\n const globalDir = resolveGlobalExtensionsDir();\n const globalExtension = join(globalDir, extensionId);\n\n if (existsSync(globalExtension)) {\n try {\n rmSync(globalExtension, { recursive: true, force: true });\n return { ok: true, removedFrom: 'global' };\n } catch (error) {\n return {\n ok: false,\n error: `Failed to remove from global: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n\n return { ok: false, error: `Extension not found: ${extensionId}` };\n}\n\n/**\n * List installed extensions from all tiers\n */\nexport function listAllExtensions(workspaceDir: string): ListedExtension[] {\n const extensions: ListedExtension[] = [];\n const seen = new Set<string>();\n\n // Priority 1: Workspace (highest)\n const workspaceExtensionsDir = join(workspaceDir, '.extensions');\n if (existsSync(workspaceExtensionsDir)) {\n for (const entry of readdirSync(workspaceExtensionsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n\n const extensionDir = join(workspaceExtensionsDir, entry.name);\n const manifest = readManifest(extensionDir);\n\n if (manifest) {\n seen.add(entry.name);\n extensions.push({\n id: entry.name,\n name: manifest.name,\n version: manifest.version,\n path: extensionDir,\n origin: 'workspace',\n });\n }\n }\n }\n\n // Priority 2: Global\n const globalDir = resolveGlobalExtensionsDir();\n if (existsSync(globalDir)) {\n for (const entry of readdirSync(globalDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n if (seen.has(entry.name)) continue; // Skip if already in workspace\n\n const extensionDir = join(globalDir, entry.name);\n const manifest = readManifest(extensionDir);\n\n if (manifest) {\n seen.add(entry.name);\n extensions.push({\n id: entry.name,\n name: manifest.name,\n version: manifest.version,\n path: extensionDir,\n origin: 'global',\n });\n }\n }\n }\n\n // Priority 3: Bundled (lowest)\n const bundledDir = resolveBundledExtensionsDir();\n if (bundledDir && existsSync(bundledDir)) {\n for (const entry of readdirSync(bundledDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n if (seen.has(entry.name)) continue;\n\n const extensionDir = join(bundledDir, entry.name);\n const manifest = readManifest(extensionDir);\n\n if (manifest) {\n extensions.push({\n id: entry.name,\n name: manifest.name,\n version: manifest.version,\n path: extensionDir,\n origin: 'bundled',\n });\n }\n }\n }\n\n return extensions;\n}\n\nfunction readManifest(extensionDir: string): ExtensionManifest | null {\n const manifestPath = join(extensionDir, 'xopc.extension.json');\n\n if (!existsSync(manifestPath)) {\n // Try package.json\n const packagePath = join(extensionDir, 'package.json');\n if (existsSync(packagePath)) {\n try {\n const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));\n return {\n id: pkg.name,\n name: pkg.xopc?.extension?.name || pkg.name,\n version: pkg.version,\n };\n } catch {\n return null;\n }\n }\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(manifestPath, 'utf-8')) as ExtensionManifest;\n } catch {\n return null;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"install.js","names":["resolveGlobalExtensionsDir"],"sources":["../../../src/extensions/install.ts"],"sourcesContent":["/**\n * Extension Installation Module\n * Supports installing from npm packages, local directories, and xopc-store zips\n * Supports three-tier storage: workspace, global, bundled\n */\n\nimport { execSync } from 'child_process';\nimport AdmZip from 'adm-zip';\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n cpSync,\n rmSync,\n readdirSync,\n mkdtempSync,\n writeFileSync,\n} from 'fs';\nimport { dirname, join, isAbsolute, resolve, sep } from 'path';\nimport { tmpdir } from 'os';\nimport {\n resolveExtensionsDir as resolveGlobalExtensionsDir,\n resolveBundledExtensionsDir,\n} from '../config/paths.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport { createLogger } from '../utils/logger.js';\nimport { checkEngineCompatibility } from './engine-check.js';\nimport { collectExtensionPackageDependencyIssues } from './package-contract.js';\nimport { MAX_EXTENSION_STORE_ZIP_BYTES } from './store-zip-limits.js';\n\nconst log = createLogger('ExtensionInstall');\n\nconst NPM_INSTALL_ENV = process.env.XOPC_EXTENSION_NPM_INSTALL?.trim().toLowerCase();\n\nfunction extractExecSyncOutput(error: unknown): string {\n if (!error || typeof error !== 'object') return '';\n const o = error as { stderr?: Buffer | string; stdout?: Buffer | string; message?: string };\n const read = (x?: Buffer | string | null) => {\n if (x == null) return '';\n return Buffer.isBuffer(x) ? x.toString('utf8') : x;\n };\n const stderr = read(o.stderr).trim();\n const stdout = read(o.stdout).trim();\n if (stderr) return stderr;\n if (stdout) return stdout;\n return typeof o.message === 'string' ? o.message.trim() : '';\n}\n\nfunction truncateOutput(text: string, max = 4500): string {\n const t = text.trim();\n if (t.length <= max) return t;\n return `…${t.slice(-max)}`;\n}\n\n/**\n * Install production `node_modules` for an unpacked extension (package.json dependencies).\n * Uses pnpm when `pnpm-lock.yaml` is present, otherwise npm. Set `XOPC_EXTENSION_NPM_INSTALL=skip`\n * to skip (extensions must ship runnable code or you install deps manually).\n */\nfunction installExtensionProdDependencies(extensionDir: string): { ok: true } | { ok: false; error: string } {\n if (NPM_INSTALL_ENV === 'skip' || NPM_INSTALL_ENV === '0' || NPM_INSTALL_ENV === 'false') {\n log.warn(\n { extensionDir, XOPC_EXTENSION_NPM_INSTALL: process.env.XOPC_EXTENSION_NPM_INSTALL },\n 'Skipping extension dependency install (XOPC_EXTENSION_NPM_INSTALL)',\n );\n return { ok: true };\n }\n\n const execOpts = {\n cwd: extensionDir,\n timeout: 300_000,\n encoding: 'utf-8' as const,\n stdio: ['ignore', 'pipe', 'pipe'] as ('ignore' | 'pipe')[],\n maxBuffer: 20 * 1024 * 1024,\n env: process.env,\n ...(process.platform === 'win32'\n ? { shell: (process.env.ComSpec && process.env.ComSpec.trim()) || 'cmd.exe' }\n : {}),\n };\n\n const run = (label: string, command: string): { ok: true } | { ok: false; error: string } => {\n try {\n execSync(command, execOpts);\n return { ok: true };\n } catch (err) {\n const out = truncateOutput(extractExecSyncOutput(err));\n const hint =\n label === 'npm'\n ? ' Check that Node.js/npm is on PATH, the registry is reachable, and peer/engine rules allow install.'\n : ' Check that pnpm is on PATH or remove pnpm-lock.yaml to use npm instead.';\n return {\n ok: false,\n error: `${label} install failed.${hint}${out ? `\\n\\n${out}` : ''}`,\n };\n }\n };\n\n const usePnpm = existsSync(join(extensionDir, 'pnpm-lock.yaml'));\n if (usePnpm) {\n const pnpm = run('pnpm', 'pnpm install --prod --no-frozen-lockfile');\n if (pnpm.ok) return pnpm;\n const npmFallback = run('npm', 'npm install --omit=dev --no-audit --no-fund');\n if (npmFallback.ok) {\n log.warn({ extensionDir }, 'pnpm failed; extension dependencies installed with npm instead');\n return { ok: true };\n }\n return npmFallback;\n }\n\n return run('npm', 'npm install --omit=dev --no-audit --no-fund');\n}\n\nexport interface InstallOptions {\n source: 'npm' | 'local';\n targetDir: string;\n timeoutMs?: number;\n global?: boolean;\n}\n\nexport interface InstallResult {\n ok: boolean;\n extensionId?: string;\n targetDir?: string;\n origin?: 'workspace' | 'global';\n error?: string;\n}\n\nexport interface ListedExtension {\n id: string;\n name?: string;\n version?: string;\n kind?: string;\n path: string;\n origin: 'workspace' | 'global' | 'bundled';\n}\n\ninterface ExtensionManifest {\n id: string;\n name?: string;\n version?: string;\n main?: string;\n engines?: {\n xopc?: string;\n extensionApi?: string;\n extensionUiApi?: string;\n };\n}\n\nfunction isSafeZipPath(name: string): boolean {\n if (!name) return false;\n const normalized = name.replace(/\\\\/g, '/');\n if (normalized.includes('..')) return false;\n if (normalized.startsWith('/') || /^\\w:/.test(normalized)) return false;\n for (const p of normalized.split('/')) {\n if (p === '..') return false;\n }\n return true;\n}\n\nfunction isIgnorableZipEntry(name: string): boolean {\n const n = name.replace(/\\\\/g, '/');\n if (n.startsWith('__MACOSX/')) return true;\n const segments = n.split('/').filter(Boolean);\n for (const s of segments) {\n if (s === '.DS_Store' || s === 'Thumbs.db' || s === 'desktop.ini') return true;\n if (s.startsWith('._')) return true;\n }\n return false;\n}\n\nfunction inferExtensionStripPrefix(primaryManifestPath: string): string {\n const norm = primaryManifestPath.replace(/\\\\/g, '/');\n const lower = norm.toLowerCase();\n const suff = 'xopc.extension.json';\n if (lower === suff) return '';\n if (!lower.endsWith(suff)) return '';\n return norm.slice(0, norm.length - suff.length);\n}\n\nfunction readShallowestExtensionManifestFromZip(buffer: Buffer): Record<string, unknown> | undefined {\n if (buffer.length > MAX_EXTENSION_STORE_ZIP_BYTES) return undefined;\n let zip: AdmZip;\n try {\n zip = new AdmZip(buffer);\n } catch {\n return undefined;\n }\n const entries = zip\n .getEntries()\n .filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName));\n const safeEntries = entries.filter((e) => isSafeZipPath(e.entryName));\n const names = safeEntries.map((e) => e.entryName.replace(/\\\\/g, '/'));\n const manifestPaths = names.filter((n) => /(^|\\/)xopc\\.extension\\.json$/i.test(n));\n const shallow = manifestPaths.filter((n) => n.split('/').filter(Boolean).length <= 2);\n if (shallow.length === 0) return undefined;\n shallow.sort((a, b) => a.length - b.length);\n const path = shallow[0];\n const entry = safeEntries.find((e) => e.entryName.replace(/\\\\/g, '/') === path);\n if (!entry) return undefined;\n try {\n const raw = entry.getData().toString('utf8');\n const parsed = JSON.parse(raw) as unknown;\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function peekExtensionManifestFromStoreZip(buffer: Buffer): Record<string, unknown> | undefined {\n return readShallowestExtensionManifestFromZip(buffer);\n}\n\n/** Read package.json from the same root as the shallowest extension manifest. */\nexport function peekExtensionPackageJsonFromStoreZip(\n buffer: Buffer,\n): Record<string, unknown> | undefined {\n if (buffer.length > MAX_EXTENSION_STORE_ZIP_BYTES) return undefined;\n let zip: AdmZip;\n try {\n zip = new AdmZip(buffer);\n } catch {\n return undefined;\n }\n const entries = zip\n .getEntries()\n .filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName))\n .filter((e) => isSafeZipPath(e.entryName));\n const manifestPaths = entries\n .map((e) => e.entryName.replace(/\\\\/g, '/'))\n .filter((name) => /(^|\\/)xopc\\.extension\\.json$/i.test(name))\n .filter((name) => name.split('/').filter(Boolean).length <= 2)\n .sort((a, b) => a.length - b.length);\n if (manifestPaths.length === 0) return undefined;\n\n const prefix = inferExtensionStripPrefix(manifestPaths[0]);\n const packagePath = `${prefix}package.json`;\n const entry = entries.find((candidate) => candidate.entryName.replace(/\\\\/g, '/') === packagePath);\n if (!entry) return undefined;\n try {\n const parsed = JSON.parse(entry.getData().toString('utf8')) as unknown;\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Read `id` from the shallowest xopc.extension.json in a store zip (for --force / preflight). */\nexport function peekExtensionIdFromStoreZip(buffer: Buffer): string | undefined {\n const m = readShallowestExtensionManifestFromZip(buffer) as { id?: string } | undefined;\n const id = typeof m?.id === 'string' ? m.id.trim() : '';\n if (!id || id.includes('/') || id.includes('\\\\')) return undefined;\n return id;\n}\n\n/**\n * Install an extension from an xopc-store zip buffer (layout: manifest at archive root\n * or under a single top-level folder).\n */\nexport async function installExtensionFromStoreZip(\n buffer: Buffer,\n extensionsDir: string,\n): Promise<InstallResult> {\n if (buffer.length > MAX_EXTENSION_STORE_ZIP_BYTES) {\n return {\n ok: false,\n error: `Extension zip exceeds maximum size (${MAX_EXTENSION_STORE_ZIP_BYTES} bytes)`,\n };\n }\n\n const zip = new AdmZip(buffer);\n const entries = zip\n .getEntries()\n .filter((e) => !e.isDirectory && e.entryName && !isIgnorableZipEntry(e.entryName));\n const safeEntries = entries.filter((e) => isSafeZipPath(e.entryName));\n if (safeEntries.length === 0) {\n return { ok: false, error: 'Zip is empty or invalid' };\n }\n\n const names = safeEntries.map((e) => e.entryName.replace(/\\\\/g, '/'));\n const manifestPaths = names.filter((n) => /(^|\\/)xopc\\.extension\\.json$/i.test(n));\n if (manifestPaths.length === 0) {\n return { ok: false, error: 'Zip must contain xopc.extension.json' };\n }\n const shallow = manifestPaths.filter((n) => n.split('/').filter(Boolean).length <= 2);\n if (shallow.length === 0) {\n return {\n ok: false,\n error:\n 'xopc.extension.json is nested too deeply; use a zip with manifest at archive root or one folder (e.g. my-ext/xopc.extension.json)',\n };\n }\n shallow.sort((a, b) => a.length - b.length);\n const stripPrefix = inferExtensionStripPrefix(shallow[0]);\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n const outside = names.filter((n) => !n.startsWith(prefixNorm) && !isIgnorableZipEntry(n));\n if (outside.length > 0) {\n return {\n ok: false,\n error: `Invalid zip: expected all files under \"${prefixNorm.replace(/\\/$/, '')}/\", but found \"${outside[0]}\".`,\n };\n }\n }\n\n const tmpRoot = mkdtempSync(join(tmpdir(), 'xopc-ext-zip-'));\n const destResolved = resolve(tmpRoot);\n try {\n for (const e of safeEntries) {\n const norm = e.entryName.replace(/\\\\/g, '/');\n let rel: string;\n if (stripPrefix) {\n const prefixNorm = stripPrefix.replace(/\\\\/g, '/');\n if (!norm.startsWith(prefixNorm)) {\n return {\n ok: false,\n error: `Zip entry outside extension prefix \"${prefixNorm.replace(/\\/$/, '')}\": ${norm}`,\n };\n }\n rel = norm.slice(prefixNorm.length).replace(/^\\//, '');\n } else {\n rel = norm;\n }\n if (!rel || rel.includes('..')) {\n return { ok: false, error: `Refusing unsafe zip entry path: ${e.entryName}` };\n }\n const targetPath = join(tmpRoot, rel);\n const resolvedTarget = resolve(targetPath);\n if (!resolvedTarget.startsWith(destResolved + sep) && resolvedTarget !== destResolved) {\n return {\n ok: false,\n error: `Refusing unsafe zip path (possible traversal): ${e.entryName}`,\n };\n }\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, e.getData());\n }\n\n if (!existsSync(join(tmpRoot, 'xopc.extension.json'))) {\n return { ok: false, error: 'Extracted content is missing xopc.extension.json' };\n }\n\n return await installFromDirectory(tmpRoot, extensionsDir);\n } finally {\n try {\n rmSync(tmpRoot, { recursive: true, force: true });\n } catch {\n // ignore\n }\n }\n}\n\n/**\n * Resolve target extensions directory based on options\n */\nexport function resolveExtensionsDir(\n workspaceDir: string,\n global = false,\n): string {\n if (global) {\n const globalDir = resolveGlobalExtensionsDir();\n mkdirSync(globalDir, { recursive: true });\n return globalDir;\n }\n return join(workspaceDir, '.extensions');\n}\n\n/**\n * Install extension from npm package\n */\nexport async function installFromNpm(\n packageSpec: string,\n extensionsDir: string,\n timeoutMs = 120000,\n): Promise<InstallResult> {\n const tmpDir = join(tmpdir(), `xopc-install-${Date.now()}`);\n\n try {\n console.log(`📦 Downloading ${packageSpec} from npm...`);\n\n // Create temp directory\n mkdirSync(tmpDir, { recursive: true });\n\n // Use npm pack to download package\n const result = execSync(`npm pack ${packageSpec} --pack-destination ${tmpDir}`, {\n timeout: timeoutMs,\n encoding: 'utf-8',\n stdio: 'pipe',\n });\n\n const packedFile = result.trim().split('\\n').pop()?.trim();\n if (!packedFile) {\n return { ok: false, error: 'Failed to download package from npm' };\n }\n\n const archivePath = join(tmpDir, packedFile);\n\n // Extract tarball\n console.log(`📂 Extracting ${packedFile}...`);\n execSync(`tar -xzf ${archivePath} -C ${tmpDir}`, {\n timeout: 30000,\n stdio: 'pipe',\n });\n\n // npm pack extracts to 'package' directory\n const extractDir = join(tmpDir, 'package');\n\n // Validate and install\n return await installFromDirectory(extractDir, extensionsDir);\n } catch (error) {\n return {\n ok: false,\n error: `Failed to install from npm: ${error instanceof Error ? error.message : String(error)}`,\n };\n } finally {\n // Cleanup temp directory\n try {\n rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Install extension from local directory\n */\nexport async function installFromLocal(\n localPath: string,\n extensionsDir: string,\n): Promise<InstallResult> {\n // Resolve to absolute path\n const sourceDir = isAbsolute(localPath) ? localPath : resolve(process.cwd(), localPath);\n\n if (!existsSync(sourceDir)) {\n return { ok: false, error: `Directory not found: ${sourceDir}` };\n }\n\n console.log(`📂 Installing from local directory: ${sourceDir}...`);\n\n return await installFromDirectory(sourceDir, extensionsDir);\n}\n\n/**\n * Install extension from extracted directory\n */\nasync function installFromDirectory(\n sourceDir: string,\n extensionsDir: string,\n): Promise<InstallResult> {\n // Validate manifest\n const manifestPath = join(sourceDir, 'xopc.extension.json');\n const packagePath = join(sourceDir, 'package.json');\n\n let manifest: ExtensionManifest | null = null;\n let packageJson: { name?: string; version?: string; dependencies?: Record<string, string> } | null =\n null;\n\n // Try to load xopc.extension.json first\n if (existsSync(manifestPath)) {\n try {\n manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as ExtensionManifest;\n } catch {\n return { ok: false, error: 'Invalid xopc.extension.json manifest file' };\n }\n }\n\n // Also try package.json for metadata\n if (existsSync(packagePath)) {\n try {\n packageJson = JSON.parse(readFileSync(packagePath, 'utf-8')) as typeof packageJson;\n } catch {\n // Ignore package.json parse errors\n }\n }\n\n if (packageJson) {\n const packageIssues = collectExtensionPackageDependencyIssues(\n packageJson as Record<string, unknown>,\n { strictRuntimeSdkDeps: true },\n );\n if (packageIssues.length > 0) {\n return {\n ok: false,\n error: `Extension package is not installable as an independent package:\\n${packageIssues\n .map((issue) => `- ${issue.message}`)\n .join('\\n')}`,\n };\n }\n }\n\n // Determine extension ID\n const extensionId = manifest?.id || packageJson?.name;\n if (!extensionId) {\n return {\n ok: false,\n error: 'Extension must have an id in xopc.extension.json or name in package.json',\n };\n }\n\n // Validate extension ID (no path separators)\n if (extensionId.includes('/') || extensionId.includes('\\\\')) {\n return { ok: false, error: 'Extension ID cannot contain path separators' };\n }\n\n // Check if already exists\n const targetDir = join(extensionsDir, extensionId);\n if (existsSync(targetDir)) {\n return { ok: false, error: `Extension already exists at ${targetDir}. Use update instead.` };\n }\n\n if (!manifest) {\n return { ok: false, error: 'Extension must include xopc.extension.json' };\n }\n\n if (!manifest.engines?.xopc) {\n return { ok: false, error: 'Extension manifest must declare engines.xopc' };\n }\n const engineCheck = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);\n if (engineCheck.parseWarning) {\n return {\n ok: false,\n error: engineCheck.reason ?? `Could not parse engines.xopc ${manifest.engines.xopc}`,\n };\n }\n if (!engineCheck.compatible) {\n return {\n ok: false,\n error: engineCheck.reason ?? `xopc ${PACKAGE_VERSION} does not satisfy engines.xopc ${manifest.engines.xopc}`,\n };\n }\n\n if (!manifest.main) {\n return { ok: false, error: 'Extension manifest must declare main' };\n }\n\n if (!/\\.(mjs|cjs|js)$/i.test(manifest.main)) {\n return {\n ok: false,\n error: `Extension main must point at built JavaScript (.js/.mjs/.cjs), got: ${manifest.main}`,\n };\n }\n\n // Validate main entry exists\n const mainFile = manifest.main;\n const mainPath = join(sourceDir, mainFile);\n if (!existsSync(mainPath)) {\n return { ok: false, error: `Main entry not found: ${mainFile}` };\n }\n\n console.log(`📋 Extension: ${manifest?.name || extensionId} (${extensionId})`);\n if (manifest?.version || packageJson?.version) {\n console.log(`🔖 Version: ${manifest?.version || packageJson?.version}`);\n }\n\n // Create target directory\n mkdirSync(targetDir, { recursive: true });\n\n // Copy files\n console.log(`📂 Copying files to ${targetDir}...`);\n cpSync(sourceDir, targetDir, { recursive: true, force: true });\n\n // Install dependencies if package.json exists and has dependencies\n if (packageJson?.dependencies && Object.keys(packageJson.dependencies).length > 0) {\n console.log(`📦 Installing dependencies...`);\n const depResult = installExtensionProdDependencies(targetDir);\n if (depResult.ok === false) {\n rmSync(targetDir, { recursive: true, force: true });\n return { ok: false, error: depResult.error };\n }\n }\n\n const origin = extensionsDir.includes('.xopc/extensions') ? 'global' : 'workspace';\n\n console.log(`✅ Extension ${extensionId} installed successfully!`);\n console.log(`\\nTo enable the extension, add to your config:`);\n console.log(` extensions:`);\n console.log(` enabled: [${extensionId}]`);\n console.log(` ${extensionId}:`);\n console.log(` # your extension options here\\n`);\n\n return { ok: true, extensionId, targetDir, origin };\n}\n\n/**\n * Remove installed extension from all tiers\n */\nexport function removeExtension(\n extensionId: string,\n workspaceDir: string,\n): { ok: boolean; removedFrom?: string; error?: string } {\n // Try workspace first\n const workspaceDir_ = join(workspaceDir, '.extensions');\n const workspaceExtension = join(workspaceDir_, extensionId);\n\n if (existsSync(workspaceExtension)) {\n try {\n rmSync(workspaceExtension, { recursive: true, force: true });\n return { ok: true, removedFrom: 'workspace' };\n } catch (error) {\n return {\n ok: false,\n error: `Failed to remove from workspace: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n\n // Try global\n const globalDir = resolveGlobalExtensionsDir();\n const globalExtension = join(globalDir, extensionId);\n\n if (existsSync(globalExtension)) {\n try {\n rmSync(globalExtension, { recursive: true, force: true });\n return { ok: true, removedFrom: 'global' };\n } catch (error) {\n return {\n ok: false,\n error: `Failed to remove from global: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n\n return { ok: false, error: `Extension not found: ${extensionId}` };\n}\n\n/**\n * List installed extensions from all tiers\n */\nexport function listAllExtensions(workspaceDir: string): ListedExtension[] {\n const extensions: ListedExtension[] = [];\n const seen = new Set<string>();\n\n // Priority 1: Workspace (highest)\n const workspaceExtensionsDir = join(workspaceDir, '.extensions');\n if (existsSync(workspaceExtensionsDir)) {\n for (const entry of readdirSync(workspaceExtensionsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n\n const extensionDir = join(workspaceExtensionsDir, entry.name);\n const manifest = readManifest(extensionDir);\n\n if (manifest) {\n seen.add(entry.name);\n extensions.push({\n id: entry.name,\n name: manifest.name,\n version: manifest.version,\n path: extensionDir,\n origin: 'workspace',\n });\n }\n }\n }\n\n // Priority 2: Global\n const globalDir = resolveGlobalExtensionsDir();\n if (existsSync(globalDir)) {\n for (const entry of readdirSync(globalDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n if (seen.has(entry.name)) continue; // Skip if already in workspace\n\n const extensionDir = join(globalDir, entry.name);\n const manifest = readManifest(extensionDir);\n\n if (manifest) {\n seen.add(entry.name);\n extensions.push({\n id: entry.name,\n name: manifest.name,\n version: manifest.version,\n path: extensionDir,\n origin: 'global',\n });\n }\n }\n }\n\n // Priority 3: Bundled (lowest)\n const bundledDir = resolveBundledExtensionsDir();\n if (bundledDir && existsSync(bundledDir)) {\n for (const entry of readdirSync(bundledDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n if (seen.has(entry.name)) continue;\n\n const extensionDir = join(bundledDir, entry.name);\n const manifest = readManifest(extensionDir);\n\n if (manifest) {\n extensions.push({\n id: entry.name,\n name: manifest.name,\n version: manifest.version,\n path: extensionDir,\n origin: 'bundled',\n });\n }\n }\n }\n\n return extensions;\n}\n\nfunction readManifest(extensionDir: string): ExtensionManifest | null {\n const manifestPath = join(extensionDir, 'xopc.extension.json');\n\n if (!existsSync(manifestPath)) {\n // Try package.json\n const packagePath = join(extensionDir, 'package.json');\n if (existsSync(packagePath)) {\n try {\n const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));\n return {\n id: pkg.name,\n name: pkg.xopc?.extension?.name || pkg.name,\n version: pkg.version,\n };\n } catch {\n return null;\n }\n }\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(manifestPath, 'utf-8')) as ExtensionManifest;\n } catch {\n return null;\n }\n}\n"],"mappings":"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"}
@@ -66,6 +66,8 @@ export type CreateAgentBody = {
66
66
  id?: string;
67
67
  workspace: string;
68
68
  models?: AgentModelsConfig;
69
+ /** Reusable capability plans applied after the global baseline. */
70
+ extends?: string[];
69
71
  /** Initial `agents.list[].skills` for the new entry. */
70
72
  skills?: string[];
71
73
  /** Initial `agents.list[].tools` for the new entry. */
@@ -191,6 +191,12 @@ function prepareCreateAgent(cfg, body) {
191
191
  }
192
192
  const wsAbs = resolveUserPath(workspace);
193
193
  const rawModels = body.models ?? cloneSourceEntry?.models;
194
+ const inheritedPresetIds = body.extends ?? cloneSourceEntry?.extends ?? [];
195
+ for (const presetId of inheritedPresetIds) if (!cfg.agents.capabilityPresets[presetId]) return {
196
+ ok: false,
197
+ error: `capability preset "${presetId}" not found`,
198
+ status: 400
199
+ };
194
200
  const effectiveModels = rawModels?.roles ? {
195
201
  defaultRole: rawModels.defaultRole ?? Object.keys(rawModels.roles)[0] ?? "deep",
196
202
  roles: rawModels.roles
@@ -206,6 +212,7 @@ function prepareCreateAgent(cfg, body) {
206
212
  nextConfig: applyAgentConfig(cfg, {
207
213
  agentId,
208
214
  workspace: wsAbs,
215
+ extends: [...inheritedPresetIds],
209
216
  ...effectiveModels ? { models: effectiveModels } : {},
210
217
  ...body.skills !== void 0 ? { skills: body.skills.map((s) => String(s).trim()).filter(Boolean) } : cloneSourceEntry?.skills.mode === "allowlist" && body.cloneFrom ? { skills: [...cloneSourceEntry.skills.allow ?? []] } : {},
211
218
  ...body.tools !== void 0 ? { tools: body.tools } : cloneSourceEntry?.tools && body.cloneFrom ? { tools: cloneSourceEntry.tools } : {}
@@ -1 +1 @@
1
- {"version":3,"file":"agents-admin.js","names":["pathResolve"],"sources":["../../../src/gateway/agents-admin.ts"],"sourcesContent":["/**\n * Gateway REST helpers for multi-agent management.\n */\n\nimport { cp, mkdir, readdir, readFile, realpath, stat, unlink, writeFile } from 'node:fs/promises';\nimport { dirname, join, resolve as pathResolve } from 'node:path';\n\nimport {\n listAgentEntries,\n normalizeAgentId,\n resolveAgentDir,\n resolveAgentProfileDir,\n resolveAgentWorkspaceDir,\n resolveDefaultAgentId,\n resolveUserPath,\n validateAgentIdForNewAgent,\n} from '../agent/agent-scope.js';\nimport {\n AGENT_PROFILE_MARKDOWN_SYSTEM_FILES,\n REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET,\n} from '../agent/context/workspace.js';\nimport { seedAgentProfileMarkdownFiles } from '../agent/context/workspace-seed.js';\nimport {\n resolveEffectiveAgentManifest,\n type ResolveManifestResult,\n} from '../agent-manifest/resolver.js';\nimport {\n applyAgentConfig,\n findAgentEntryIndex,\n getAgentDeleteBlocker,\n pruneAgentConfig,\n removeAgentDirsFromDisk,\n} from '../commands/agents.config.js';\nimport type { AgentModelsConfig, Config } from '../config/schema.js';\nimport { resolveUserProfilePath, WORKSPACE_FILES } from '../config/paths.js';\nimport { resolveEffectiveAgentProfile } from '../config/agent-profile.js';\nimport type { AgentTypedModel } from '../config/schema.js';\nimport { resolveEffectiveTypedModels } from '../config/agent-typed-models.js';\nimport { GATEWAY_BUILTIN_TOOL_IDS } from './agent-builtin-tools.js';\nimport { isPathUnderWorkspace, resolveWorkspaceSafePath } from './workspace-editor-path.js';\n\nconst EDITABLE_PROFILE_MARKDOWN_NAMES = new Set<string>([...AGENT_PROFILE_MARKDOWN_SYSTEM_FILES]);\n\nexport type GatewayAgentTypedModelsInfo = {\n defaultRole: string;\n preset: AgentTypedModel[];\n entry?: AgentTypedModel[];\n effective: AgentTypedModel[];\n};\n\nexport type GatewayAgentRow = {\n id: string;\n name?: string;\n description?: string;\n language?: string;\n role?: string;\n responsibilities?: {\n primary: string[];\n secondary?: string[];\n };\n /** Value from `IDENTITY.md` **Avatar:** line when present (may be URL, `xopc:…`, etc.). */\n avatar?: string;\n workspace: string;\n /** Absolute directory for profile Markdown (`SOUL.md`, …) and gateway avatars: `agents/<id>/profile/`. */\n profileDir: string;\n model?: { primary?: string; fallbacks?: string[] };\n typedModels: GatewayAgentTypedModelsInfo;\n extends: string[];\n isDefault: boolean;\n skills: {\n preset: string[];\n entry?: string[];\n effectiveAllowlist?: string[];\n };\n tools: {\n presetDenied: string[];\n entryDisable: string[];\n effectiveDisable: string[];\n };\n};\n\nexport type GatewayAgentsListResponse = {\n defaultId: string;\n agents: GatewayAgentRow[];\n builtinToolIds: string[];\n};\n\nexport type GatewayAgentEffectiveManifestResponse = ResolveManifestResult;\n\nfunction collectAgentIdsForList(cfg: Config): string[] {\n const entries = listAgentEntries(cfg).filter((e) => e.enabled !== false);\n const defaultId = resolveDefaultAgentId(cfg);\n if (entries.length === 0) {\n return [defaultId];\n }\n const ids = new Set<string>();\n for (const e of entries) {\n ids.add(normalizeAgentId(e.id));\n }\n ids.add(defaultId);\n return [...ids];\n}\n\nfunction rolesToTypedModels(\n roles: Record<string, { model: string; fallbacks?: string[]; description?: string }> | undefined,\n): AgentTypedModel[] {\n return Object.entries(roles ?? {})\n .map(([id, role]) => ({ id, ...role }))\n .sort((a, b) => a.id.localeCompare(b.id));\n}\n\n/** Extract `**Avatar:**` value from profile IDENTITY.md (same line shape as the gateway console parser). */\nexport function extractAvatarFromIdentityMarkdown(content: string): string | undefined {\n return parseIdentityMarkdown(content).avatar || undefined;\n}\n\nexport function parseIdentityMarkdown(content: string): {\n name?: string;\n description?: string;\n language?: string;\n avatar?: string;\n} {\n const out: { name?: string; description?: string; language?: string; avatar?: string } = {};\n for (const line of content.split('\\n')) {\n const match = line.match(/^[-*]\\s+\\*\\*(Name|Description|Language|Avatar):\\*\\*\\s*(.*)/i);\n if (match) {\n const key = match[1]?.toLowerCase();\n const v = match[2]?.trim() ?? '';\n if (!v || /^_\\(.*\\)_$/.test(v)) continue;\n if (key === 'name') out.name = v;\n if (key === 'description') out.description = v;\n if (key === 'language') out.language = v;\n if (key === 'avatar') out.avatar = v;\n }\n }\n return out;\n}\n\nexport async function listGatewayAgents(\n cfg: Config,\n _options: { locale?: string } = {},\n): Promise<GatewayAgentsListResponse> {\n const defaultId = resolveDefaultAgentId(cfg);\n const agents: GatewayAgentRow[] = [];\n const presetSkills: string[] | undefined = undefined;\n const presetDenied: string[] = [];\n const presetTypedModels: ReturnType<typeof rolesToTypedModels> = [];\n for (const id of collectAgentIdsForList(cfg)) {\n const profile = resolveEffectiveAgentProfile(cfg, id);\n const entry = listAgentEntries(cfg).find((e) => normalizeAgentId(e.id) === id);\n const model =\n profile.primaryModelRef || profile.fallbacks.length > 0\n ? {\n ...(profile.primaryModelRef ? { primary: profile.primaryModelRef } : {}),\n ...(profile.fallbacks.length > 0 ? { fallbacks: profile.fallbacks } : {}),\n }\n : undefined;\n const entrySkills = entry?.skills.mode === 'allowlist' ? entry.skills.allow ?? [] : undefined;\n const entryDisable = Object.entries(entry?.tools.builtin ?? {})\n .filter(([, policy]) => policy.mode === 'deny')\n .map(([name]) => name);\n const entryTypedModels = rolesToTypedModels(entry?.models?.roles);\n const effectiveTypedModels = [...resolveEffectiveTypedModels(cfg, id).values()].sort((a, b) =>\n a.id.localeCompare(b.id),\n );\n let identity: ReturnType<typeof parseIdentityMarkdown> = {};\n try {\n const identityPath = join(resolveAgentProfileDir(cfg, id), WORKSPACE_FILES.IDENTITY);\n const content = await readFile(identityPath, 'utf-8');\n identity = parseIdentityMarkdown(content);\n } catch {\n /* missing IDENTITY.md or unreadable */\n }\n agents.push({\n id,\n ...(identity.name ? { name: identity.name } : {}),\n ...(identity.description ? { description: identity.description } : {}),\n ...(identity.language ? { language: identity.language } : {}),\n ...(profile.manifest.identity.role ? { role: profile.manifest.identity.role } : {}),\n responsibilities: {\n primary: [...profile.manifest.responsibilities.primary],\n ...(profile.manifest.responsibilities.secondary\n ? { secondary: [...profile.manifest.responsibilities.secondary] }\n : {}),\n },\n ...(identity.avatar ? { avatar: identity.avatar } : {}),\n workspace: profile.resolvedWorkspacePath,\n profileDir: resolveAgentProfileDir(cfg, id),\n ...(model ? { model } : {}),\n typedModels: {\n defaultRole: profile.manifest.models.defaultRole,\n preset: [...presetTypedModels],\n ...(entryTypedModels.length > 0 ? { entry: entryTypedModels } : {}),\n effective: effectiveTypedModels,\n },\n extends: [...(entry?.extends ?? [])],\n isDefault: id === defaultId,\n skills: {\n preset: presetSkills ? [...presetSkills] : [],\n ...(entrySkills !== undefined ? { entry: [...entrySkills] } : {}),\n ...(profile.skillsAllowlist !== undefined\n ? { effectiveAllowlist: [...profile.skillsAllowlist] }\n : {}),\n },\n tools: {\n presetDenied: [...presetDenied],\n entryDisable: [...entryDisable],\n effectiveDisable: [...profile.tools.denied].sort((a, b) => a.localeCompare(b)),\n },\n });\n }\n agents.sort((a, b) => a.id.localeCompare(b.id));\n return { defaultId, agents, builtinToolIds: [...GATEWAY_BUILTIN_TOOL_IDS] };\n}\n\nexport function getGatewayAgentEffectiveManifest(\n cfg: Config,\n agentIdRaw: string,\n): AgentAdminResult<GatewayAgentEffectiveManifestResponse> {\n const agentId = normalizeAgentId(agentIdRaw);\n const entry = listAgentEntries(cfg).find((e) => normalizeAgentId(e.id) === agentId);\n if (!entry) {\n return { ok: false, error: `agent \"${agentId}\" not found`, status: 404 };\n }\n try {\n return {\n ok: true,\n data: resolveEffectiveAgentManifest({\n agent: entry,\n presets: cfg.agents.capabilityPresets,\n defaultPresetId: cfg.agents.defaultPreset,\n }),\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n status: 400,\n };\n }\n}\n\nexport type CreateAgentBody = {\n /** Optional id seed; normalized agent id defaults from `profileFiles[\"IDENTITY.md\"]` name when omitted. */\n id?: string;\n workspace: string;\n models?: AgentModelsConfig;\n /** Initial `agents.list[].skills` for the new entry. */\n skills?: string[];\n /** Initial `agents.list[].tools` for the new entry. */\n tools?: NonNullable<Config['agents']['list']>[number]['tools'];\n /** Profile markdown files to write after seeding (e.g. `IDENTITY.md`, `SOUL.md`). */\n profileFiles?: Record<string, string>;\n /** Clone from an existing agent id — copies config entry fields and profile directory. */\n cloneFrom?: string;\n};\n\nexport type AgentAdminHttpStatus = 400 | 404 | 409;\n\nexport type AgentAdminResult<T> =\n | { ok: true; data: T }\n | { ok: false; error: string; status?: AgentAdminHttpStatus };\n\nexport function prepareCreateAgent(\n cfg: Config,\n body: CreateAgentBody,\n): AgentAdminResult<{ nextConfig: Config; agentId: string; workspace: string }> {\n const workspace = body.workspace?.trim() ?? '';\n if (!workspace) {\n return { ok: false, error: 'workspace is required', status: 400 };\n }\n if (body.profileFiles !== undefined) {\n if (typeof body.profileFiles !== 'object' || body.profileFiles === null || Array.isArray(body.profileFiles)) {\n return { ok: false, error: 'profileFiles must be an object', status: 400 };\n }\n for (const [name, content] of Object.entries(body.profileFiles)) {\n const bad = assertAllowedFile(name);\n if (bad) {\n return bad;\n }\n if (typeof content !== 'string') {\n return { ok: false, error: `profileFiles[\"${name}\"] must be a string`, status: 400 };\n }\n }\n }\n if (!body.cloneFrom && typeof body.profileFiles?.[WORKSPACE_FILES.IDENTITY] !== 'string') {\n return { ok: false, error: `profileFiles[\"${WORKSPACE_FILES.IDENTITY}\"] is required`, status: 400 };\n }\n\n const identity = body.profileFiles?.[WORKSPACE_FILES.IDENTITY]\n ? parseIdentityMarkdown(body.profileFiles[WORKSPACE_FILES.IDENTITY])\n : {};\n const nameSeed = identity.name ?? body.id ?? '';\n const idRes = validateAgentIdForNewAgent(body.id, nameSeed);\n if (idRes.ok === false) {\n return { ok: false, error: idRes.error, status: 400 };\n }\n const agentId = idRes.agentId;\n if (findAgentEntryIndex(listAgentEntries(cfg), agentId) >= 0) {\n return { ok: false, error: `agent \"${agentId}\" already exists`, status: 409 };\n }\n\n // Resolve fields from cloneFrom source when present\n let cloneSourceEntry: ReturnType<typeof listAgentEntries>[number] | undefined;\n if (body.cloneFrom) {\n const srcId = normalizeAgentId(body.cloneFrom);\n cloneSourceEntry = listAgentEntries(cfg).find((e) => normalizeAgentId(e.id) === srcId);\n if (!cloneSourceEntry && srcId !== resolveDefaultAgentId(cfg)) {\n return { ok: false, error: `source agent \"${srcId}\" not found`, status: 404 };\n }\n }\n\n const wsAbs = resolveUserPath(workspace);\n\n const rawModels = body.models ?? cloneSourceEntry?.models;\n const effectiveModels =\n rawModels?.roles\n ? {\n defaultRole: rawModels.defaultRole ?? Object.keys(rawModels.roles)[0] ?? 'deep',\n roles: rawModels.roles,\n }\n : undefined;\n if (effectiveModels && !effectiveModels.roles[effectiveModels.defaultRole]) {\n return { ok: false, error: 'models.defaultRole must reference models.roles', status: 400 };\n }\n\n let next = applyAgentConfig(cfg, {\n agentId,\n workspace: wsAbs,\n ...(effectiveModels ? { models: effectiveModels } : {}),\n ...(body.skills !== undefined\n ? { skills: body.skills.map((s) => String(s).trim()).filter(Boolean) }\n : cloneSourceEntry?.skills.mode === 'allowlist' && body.cloneFrom\n ? { skills: [...(cloneSourceEntry.skills.allow ?? [])] }\n : {}),\n ...(body.tools !== undefined ? { tools: body.tools } : cloneSourceEntry?.tools && body.cloneFrom ? { tools: cloneSourceEntry.tools } : {}),\n });\n\n return { ok: true, data: { nextConfig: next, agentId, workspace: wsAbs } };\n}\n\nexport async function finalizeCreateAgentDirs(\n cfg: Config,\n agentId: string,\n opts?: { profileFiles?: Record<string, string>; cloneFrom?: string },\n): Promise<AgentAdminResult<void>> {\n const wsPath = resolveAgentWorkspaceDir(cfg, agentId);\n const profilePath = resolveAgentProfileDir(cfg, agentId);\n const adPath = resolveAgentDir(cfg, agentId);\n await mkdir(wsPath, { recursive: true });\n await mkdir(profilePath, { recursive: true });\n await mkdir(adPath, { recursive: true });\n const id = normalizeAgentId(agentId);\n const displayName = opts?.profileFiles?.[WORKSPACE_FILES.IDENTITY]\n ? (parseIdentityMarkdown(opts.profileFiles[WORKSPACE_FILES.IDENTITY]).name ?? id)\n : id;\n\n // When cloning, copy the entire source profile directory instead of seeding\n if (opts?.cloneFrom) {\n const srcProfilePath = resolveAgentProfileDir(cfg, normalizeAgentId(opts.cloneFrom));\n try {\n const srcStat = await stat(srcProfilePath);\n if (srcStat.isDirectory()) {\n const srcFiles = await readdir(srcProfilePath);\n for (const fileName of srcFiles) {\n const srcFile = join(srcProfilePath, fileName);\n const dstFile = join(profilePath, fileName);\n try {\n const fileStat = await stat(srcFile);\n if (fileStat.isFile()) {\n await cp(srcFile, dstFile);\n }\n } catch {\n /* skip unreadable files */\n }\n }\n }\n } catch {\n // Source profile dir doesn't exist — fall through to normal seed\n seedAgentProfileMarkdownFiles(profilePath, wsPath, { displayName });\n }\n } else {\n seedAgentProfileMarkdownFiles(profilePath, wsPath, { displayName });\n }\n\n const profileFiles = opts?.profileFiles;\n if (profileFiles && Object.keys(profileFiles).length > 0) {\n for (const [name, content] of Object.entries(profileFiles)) {\n const written = await writeAgentProfileFile(cfg, agentId, name, content);\n if (written.ok === false) {\n return written;\n }\n }\n }\n\n return { ok: true, data: undefined };\n}\n\nexport type UpdateAgentBody = {\n workspace?: string;\n extends?: string[];\n models?: {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; fallbacks?: string[]; description?: string }>;\n } | null;\n setDefault?: boolean;\n /** Replace `agents.list[].skills`; `null` resets to all skills. */\n skills?: string[] | null;\n /** Replace `agents.list[].tools`; `null` resets to no explicit policies. */\n tools?: NonNullable<Config['agents']['list']>[number]['tools'] | null;\n /** Replace `agents.list[].memory`; every agent manifest owns its memory policy. */\n memory?: NonNullable<Config['agents']['list']>[number]['memory'];\n};\n\nexport function prepareUpdateAgent(\n cfg: Config,\n agentIdRaw: string,\n body: UpdateAgentBody,\n): AgentAdminResult<{ nextConfig: Config }> {\n const agentId = normalizeAgentId(agentIdRaw);\n let list = [...listAgentEntries(cfg)];\n let idx = findAgentEntryIndex(list, agentId);\n if (idx < 0 && agentId === resolveDefaultAgentId(cfg)) {\n list = [...list, {\n id: agentId,\n enabled: true as const,\n identity: { name: agentId, role: 'Agent', language: 'en', tone: 'direct' },\n responsibilities: { primary: ['Help the user complete tasks'] },\n workspace: { root: `~/.xopc/workspace/${agentId}` },\n tools: { builtin: {} },\n skills: { mode: 'all' },\n memory: { mode: 'confirmWrite', sources: ['session', 'curated'], writePolicy: { curated: 'confirm' } },\n workflows: {},\n boundaries: { requiresConfirmation: [], forbidden: [], escalation: [] },\n }];\n idx = list.length - 1;\n }\n if (idx < 0) {\n return { ok: false, error: `agent \"${agentId}\" not found`, status: 404 };\n }\n\n type Entry = (typeof list)[number];\n const entry: Entry = { ...list[idx] };\n\n if (body.workspace !== undefined) {\n const w = body.workspace.trim();\n if (w) {\n entry.workspace = { root: resolveUserPath(w) };\n }\n }\n if (body.extends !== undefined) {\n const nextExtends = Array.from(new Set(body.extends.map((id) => normalizeAgentId(id)).filter(Boolean)));\n for (const presetId of nextExtends) {\n if (!cfg.agents.capabilityPresets[presetId]) {\n return { ok: false, error: `capability preset \"${presetId}\" not found`, status: 400 };\n }\n }\n if (nextExtends.length > 0) {\n entry.extends = nextExtends;\n } else {\n delete entry.extends;\n }\n }\n if (body.models !== undefined) {\n if (body.models === null) {\n delete entry.models;\n } else {\n if (body.models.defaultRole !== undefined) {\n if (body.models.defaultRole === null || !body.models.defaultRole.trim()) {\n return { ok: false, error: 'models.defaultRole must be a non-empty string', status: 400 };\n }\n entry.models = {\n defaultRole: body.models.defaultRole.trim(),\n roles: entry.models?.roles ?? {},\n ...(entry.models?.policy ? { policy: entry.models.policy } : {}),\n };\n }\n if (Object.hasOwn(body.models, 'roles')) {\n if (body.models.roles !== undefined) {\n const roles = Object.fromEntries(\n Object.entries(body.models.roles)\n .map(([id, row]) => ({\n id: id.trim(),\n model: row.model.trim(),\n fallbacks: (row.fallbacks ?? []).map((ref) => ref.trim()).filter(Boolean),\n description: row.description?.trim(),\n }))\n .filter((row) => row.id && row.model)\n .map((row) => [\n row.id,\n {\n model: row.model,\n ...(row.fallbacks.length > 0 ? { fallbacks: row.fallbacks } : {}),\n ...(row.description ? { description: row.description } : {}),\n },\n ]),\n );\n entry.models = {\n defaultRole: entry.models?.defaultRole ?? Object.keys(roles)[0] ?? 'deep',\n roles,\n ...(entry.models?.policy ? { policy: entry.models.policy } : {}),\n };\n }\n }\n const roles = entry.models?.roles ?? {};\n const defaultRole = entry.models?.defaultRole ?? Object.keys(roles)[0];\n if (!defaultRole || !roles[defaultRole]) {\n return { ok: false, error: 'models.defaultRole must reference models.roles', status: 400 };\n }\n entry.models = { ...entry.models, defaultRole };\n }\n }\n\n if (body.skills !== undefined) {\n if (body.skills === null) {\n entry.skills = { mode: 'all' };\n } else {\n const next = body.skills.map((s) => String(s).trim()).filter(Boolean);\n if (next.length === 0) {\n entry.skills = { mode: 'allowlist', allow: [] };\n } else {\n entry.skills = { mode: 'allowlist', allow: next };\n }\n }\n }\n\n if (body.tools !== undefined) {\n if (body.tools === null) {\n entry.tools = { builtin: {} };\n } else {\n entry.tools = body.tools;\n }\n }\n\n if (body.memory !== undefined) {\n entry.memory = body.memory;\n }\n\n list[idx] = entry;\n let next: Config = {\n ...cfg,\n agents: {\n ...cfg.agents,\n list,\n },\n };\n\n if (body.setDefault === true) {\n next = {\n ...next,\n agents: {\n ...next.agents,\n default: agentId,\n },\n };\n }\n return { ok: true, data: { nextConfig: next } };\n}\n\nexport function prepareDeleteAgent(\n cfg: Config,\n agentIdRaw: string,\n): AgentAdminResult<{ nextConfig: Config; agentId: string }> {\n const agentId = normalizeAgentId(agentIdRaw);\n const blocker = getAgentDeleteBlocker(cfg, agentId);\n if (blocker) {\n return { ok: false, error: blocker, status: 400 };\n }\n if (findAgentEntryIndex(listAgentEntries(cfg), agentId) < 0) {\n return { ok: false, error: `agent \"${agentId}\" not found`, status: 404 };\n }\n const { config: pruned } = pruneAgentConfig(cfg, agentId);\n return { ok: true, data: { nextConfig: pruned, agentId } };\n}\n\nexport async function runAfterDeletePurge(cfg: Config, agentId: string): Promise<void> {\n await removeAgentDirsFromDisk(cfg, agentId);\n}\n\nexport type AgentFileEntry = {\n name: string;\n missing: boolean;\n size?: number;\n updatedAtMs?: number;\n};\n\nasync function profileMarkdownRootReal(cfg: Config, agentId: string): Promise<string> {\n const dir = resolveAgentProfileDir(cfg, agentId);\n await mkdir(dir, { recursive: true });\n try {\n return await realpath(dir);\n } catch {\n return pathResolve(dir);\n }\n}\n\nfunction assertAllowedFile(name: string): AgentAdminResult<never> | null {\n if (!name || name.includes('/') || name.includes('\\\\') || !EDITABLE_PROFILE_MARKDOWN_NAMES.has(name)) {\n return { ok: false, error: `unsupported file \"${name}\"`, status: 400 };\n }\n return null;\n}\n\nexport async function listAgentProfileFiles(\n cfg: Config,\n agentId: string,\n): Promise<AgentAdminResult<{ agentId: string; profileDir: string; files: AgentFileEntry[] }>> {\n const id = normalizeAgentId(agentId);\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n const root = await profileMarkdownRootReal(cfg, id);\n const names = [...EDITABLE_PROFILE_MARKDOWN_NAMES];\n const files: AgentFileEntry[] = [];\n for (const name of names.sort((a, b) => a.localeCompare(b))) {\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n continue;\n }\n try {\n const st = await stat(abs);\n if (!st.isFile()) {\n continue;\n }\n files.push({\n name,\n missing: false,\n size: st.size,\n updatedAtMs: st.mtimeMs,\n });\n } catch {\n if (!REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET.has(name)) {\n continue;\n }\n files.push({ name, missing: true });\n }\n }\n files.sort((a, b) => a.name.localeCompare(b.name));\n return { ok: true, data: { agentId: id, profileDir: root, files } };\n}\n\nexport async function readAgentProfileFile(\n cfg: Config,\n agentId: string,\n name: string,\n): Promise<AgentAdminResult<{ agentId: string; content: string; path: string }>> {\n const bad = assertAllowedFile(name);\n if (bad) {\n return bad;\n }\n const id = normalizeAgentId(agentId);\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n const root = await profileMarkdownRootReal(cfg, id);\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n return { ok: false, error: 'invalid path', status: 400 };\n }\n try {\n const content = await readFile(abs, 'utf-8');\n return { ok: true, data: { agentId: id, content, path: abs } };\n } catch {\n return { ok: false, error: 'file not found', status: 404 };\n }\n}\n\nexport async function writeAgentProfileFile(\n cfg: Config,\n agentId: string,\n name: string,\n content: string,\n): Promise<AgentAdminResult<{ agentId: string; path: string }>> {\n const bad = assertAllowedFile(name);\n if (bad) {\n return bad;\n }\n const id = normalizeAgentId(agentId);\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n const root = await profileMarkdownRootReal(cfg, id);\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n return { ok: false, error: 'invalid path', status: 400 };\n }\n const rootReal = await profileMarkdownRootReal(cfg, id);\n if (!isPathUnderWorkspace(rootReal, abs)) {\n return { ok: false, error: 'path escapes profile markdown root', status: 400 };\n }\n await writeFile(abs, content, 'utf-8');\n return { ok: true, data: { agentId: id, path: abs } };\n}\n\nexport async function readUserProfileFile(): Promise<AgentAdminResult<{ content: string; path: string }>> {\n const path = resolveUserProfilePath();\n try {\n const content = await readFile(path, 'utf-8');\n return { ok: true, data: { content, path } };\n } catch {\n return { ok: true, data: { content: '', path } };\n }\n}\n\nexport async function writeUserProfileFile(\n content: string,\n): Promise<AgentAdminResult<{ path: string }>> {\n const path = resolveUserProfilePath();\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, 'utf-8');\n return { ok: true, data: { path } };\n}\n\n// ---------------------------------------------------------------------------\n// Binary agent avatar (profile markdown root dir, not a SOUL/IDENTITY markdown file)\n// ---------------------------------------------------------------------------\n\nconst AGENT_AVATAR_MAX_BYTES = 512 * 1024;\nconst AGENT_AVATAR_BASENAME = 'agent-avatar';\n\nconst AGENT_AVATAR_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp'] as const;\n\nfunction agentAvatarFilenames(): string[] {\n return AGENT_AVATAR_EXTENSIONS.map((ext) => `${AGENT_AVATAR_BASENAME}${ext}`);\n}\n\nfunction mimeToExt(mime: string): '.png' | '.jpg' | '.jpeg' | '.webp' | null {\n const m = mime.toLowerCase().trim();\n if (m === 'image/png') return '.png';\n if (m === 'image/jpeg' || m === 'image/jpg') return '.jpg';\n if (m === 'image/webp') return '.webp';\n return null;\n}\n\nfunction detectImageMimeFromBytes(buf: Uint8Array): 'image/png' | 'image/jpeg' | 'image/webp' | null {\n if (buf.length >= 8 && buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47) {\n return 'image/png';\n }\n if (buf.length >= 3 && buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff) {\n return 'image/jpeg';\n }\n if (\n buf.length >= 12 &&\n buf[0] === 0x52 &&\n buf[1] === 0x49 &&\n buf[2] === 0x46 &&\n buf[3] === 0x46 &&\n buf[8] === 0x57 &&\n buf[9] === 0x45 &&\n buf[10] === 0x42 &&\n buf[11] === 0x50\n ) {\n return 'image/webp';\n }\n return null;\n}\n\nfunction assertAgentExistsForAvatar(cfg: Config, id: string): AgentAdminResult<never> | null {\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n return null;\n}\n\nexport async function readAgentAvatarFile(\n cfg: Config,\n agentId: string,\n): Promise<AgentAdminResult<{ agentId: string; buffer: Buffer; contentType: string; path: string }>> {\n const missingAgent = assertAgentExistsForAvatar(cfg, agentId);\n if (missingAgent) {\n return missingAgent;\n }\n const id = normalizeAgentId(agentId);\n const root = await profileMarkdownRootReal(cfg, id);\n for (const name of agentAvatarFilenames()) {\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n continue;\n }\n try {\n const st = await stat(abs);\n if (!st.isFile() || st.size <= 0 || st.size > AGENT_AVATAR_MAX_BYTES) {\n continue;\n }\n const buffer = await readFile(abs);\n const detected = detectImageMimeFromBytes(buffer);\n if (!detected) {\n continue;\n }\n return { ok: true, data: { agentId: id, buffer, contentType: detected, path: abs } };\n } catch {\n /* try next */\n }\n }\n return { ok: false, error: 'avatar not found', status: 404 };\n}\n\nexport async function writeAgentAvatarFromBase64(\n cfg: Config,\n agentId: string,\n base64: string,\n mimeType: string,\n): Promise<AgentAdminResult<{ agentId: string; path: string }>> {\n const missingAgent = assertAgentExistsForAvatar(cfg, agentId);\n if (missingAgent) {\n return missingAgent;\n }\n const id = normalizeAgentId(agentId);\n const ext = mimeToExt(mimeType);\n if (!ext) {\n return { ok: false, error: 'unsupported mimeType (use image/png, image/jpeg, or image/webp)', status: 400 };\n }\n let raw: Buffer;\n try {\n raw = Buffer.from(base64, 'base64');\n } catch {\n return { ok: false, error: 'invalid base64', status: 400 };\n }\n if (raw.length === 0 || raw.length > AGENT_AVATAR_MAX_BYTES) {\n return { ok: false, error: `avatar must be non-empty and at most ${AGENT_AVATAR_MAX_BYTES} bytes`, status: 400 };\n }\n const detected = detectImageMimeFromBytes(raw);\n if (!detected || !extMatchesDetectedMime(ext, detected)) {\n return { ok: false, error: 'file content does not match declared image type', status: 400 };\n }\n\n const root = await profileMarkdownRootReal(cfg, id);\n const rootReal = await profileMarkdownRootReal(cfg, id);\n const targetName = `${AGENT_AVATAR_BASENAME}${ext}`;\n const abs = resolveWorkspaceSafePath(root, targetName);\n if (!abs || !isPathUnderWorkspace(rootReal, abs)) {\n return { ok: false, error: 'invalid path', status: 400 };\n }\n for (const name of agentAvatarFilenames()) {\n if (name === targetName) {\n continue;\n }\n const other = resolveWorkspaceSafePath(root, name);\n if (other && isPathUnderWorkspace(rootReal, other)) {\n try {\n await unlink(other);\n } catch {\n /* absent */\n }\n }\n }\n await writeFile(abs, raw);\n return { ok: true, data: { agentId: id, path: abs } };\n}\n\nfunction mimeToExtToMime(ext: '.png' | '.jpg' | '.jpeg' | '.webp'): 'image/png' | 'image/jpeg' | 'image/webp' {\n if (ext === '.png') return 'image/png';\n if (ext === '.webp') return 'image/webp';\n return 'image/jpeg';\n}\n\nfunction extMatchesDetectedMime(\n ext: '.png' | '.jpg' | '.jpeg' | '.webp',\n detected: 'image/png' | 'image/jpeg' | 'image/webp',\n): boolean {\n return detected === mimeToExtToMime(ext);\n}\n\n/** Remove any `agent-avatar.*` in the agent profile markdown root. Idempotent: ok even when no file existed. */\nexport async function deleteAgentAvatarFile(cfg: Config, agentId: string): Promise<AgentAdminResult<{ agentId: string }>> {\n const missingAgent = assertAgentExistsForAvatar(cfg, agentId);\n if (missingAgent) {\n return missingAgent;\n }\n const id = normalizeAgentId(agentId);\n const root = await profileMarkdownRootReal(cfg, id);\n const rootReal = await profileMarkdownRootReal(cfg, id);\n for (const name of agentAvatarFilenames()) {\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs || !isPathUnderWorkspace(rootReal, abs)) {\n continue;\n }\n try {\n await unlink(abs);\n } catch {\n /* absent */\n }\n }\n return { ok: true, data: { agentId: id } };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agents-admin.js","names":["pathResolve"],"sources":["../../../src/gateway/agents-admin.ts"],"sourcesContent":["/**\n * Gateway REST helpers for multi-agent management.\n */\n\nimport { cp, mkdir, readdir, readFile, realpath, stat, unlink, writeFile } from 'node:fs/promises';\nimport { dirname, join, resolve as pathResolve } from 'node:path';\n\nimport {\n listAgentEntries,\n normalizeAgentId,\n resolveAgentDir,\n resolveAgentProfileDir,\n resolveAgentWorkspaceDir,\n resolveDefaultAgentId,\n resolveUserPath,\n validateAgentIdForNewAgent,\n} from '../agent/agent-scope.js';\nimport {\n AGENT_PROFILE_MARKDOWN_SYSTEM_FILES,\n REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET,\n} from '../agent/context/workspace.js';\nimport { seedAgentProfileMarkdownFiles } from '../agent/context/workspace-seed.js';\nimport {\n resolveEffectiveAgentManifest,\n type ResolveManifestResult,\n} from '../agent-manifest/resolver.js';\nimport {\n applyAgentConfig,\n findAgentEntryIndex,\n getAgentDeleteBlocker,\n pruneAgentConfig,\n removeAgentDirsFromDisk,\n} from '../commands/agents.config.js';\nimport type { AgentModelsConfig, Config } from '../config/schema.js';\nimport { resolveUserProfilePath, WORKSPACE_FILES } from '../config/paths.js';\nimport { resolveEffectiveAgentProfile } from '../config/agent-profile.js';\nimport type { AgentTypedModel } from '../config/schema.js';\nimport { resolveEffectiveTypedModels } from '../config/agent-typed-models.js';\nimport { GATEWAY_BUILTIN_TOOL_IDS } from './agent-builtin-tools.js';\nimport { isPathUnderWorkspace, resolveWorkspaceSafePath } from './workspace-editor-path.js';\n\nconst EDITABLE_PROFILE_MARKDOWN_NAMES = new Set<string>([...AGENT_PROFILE_MARKDOWN_SYSTEM_FILES]);\n\nexport type GatewayAgentTypedModelsInfo = {\n defaultRole: string;\n preset: AgentTypedModel[];\n entry?: AgentTypedModel[];\n effective: AgentTypedModel[];\n};\n\nexport type GatewayAgentRow = {\n id: string;\n name?: string;\n description?: string;\n language?: string;\n role?: string;\n responsibilities?: {\n primary: string[];\n secondary?: string[];\n };\n /** Value from `IDENTITY.md` **Avatar:** line when present (may be URL, `xopc:…`, etc.). */\n avatar?: string;\n workspace: string;\n /** Absolute directory for profile Markdown (`SOUL.md`, …) and gateway avatars: `agents/<id>/profile/`. */\n profileDir: string;\n model?: { primary?: string; fallbacks?: string[] };\n typedModels: GatewayAgentTypedModelsInfo;\n extends: string[];\n isDefault: boolean;\n skills: {\n preset: string[];\n entry?: string[];\n effectiveAllowlist?: string[];\n };\n tools: {\n presetDenied: string[];\n entryDisable: string[];\n effectiveDisable: string[];\n };\n};\n\nexport type GatewayAgentsListResponse = {\n defaultId: string;\n agents: GatewayAgentRow[];\n builtinToolIds: string[];\n};\n\nexport type GatewayAgentEffectiveManifestResponse = ResolveManifestResult;\n\nfunction collectAgentIdsForList(cfg: Config): string[] {\n const entries = listAgentEntries(cfg).filter((e) => e.enabled !== false);\n const defaultId = resolveDefaultAgentId(cfg);\n if (entries.length === 0) {\n return [defaultId];\n }\n const ids = new Set<string>();\n for (const e of entries) {\n ids.add(normalizeAgentId(e.id));\n }\n ids.add(defaultId);\n return [...ids];\n}\n\nfunction rolesToTypedModels(\n roles: Record<string, { model: string; fallbacks?: string[]; description?: string }> | undefined,\n): AgentTypedModel[] {\n return Object.entries(roles ?? {})\n .map(([id, role]) => ({ id, ...role }))\n .sort((a, b) => a.id.localeCompare(b.id));\n}\n\n/** Extract `**Avatar:**` value from profile IDENTITY.md (same line shape as the gateway console parser). */\nexport function extractAvatarFromIdentityMarkdown(content: string): string | undefined {\n return parseIdentityMarkdown(content).avatar || undefined;\n}\n\nexport function parseIdentityMarkdown(content: string): {\n name?: string;\n description?: string;\n language?: string;\n avatar?: string;\n} {\n const out: { name?: string; description?: string; language?: string; avatar?: string } = {};\n for (const line of content.split('\\n')) {\n const match = line.match(/^[-*]\\s+\\*\\*(Name|Description|Language|Avatar):\\*\\*\\s*(.*)/i);\n if (match) {\n const key = match[1]?.toLowerCase();\n const v = match[2]?.trim() ?? '';\n if (!v || /^_\\(.*\\)_$/.test(v)) continue;\n if (key === 'name') out.name = v;\n if (key === 'description') out.description = v;\n if (key === 'language') out.language = v;\n if (key === 'avatar') out.avatar = v;\n }\n }\n return out;\n}\n\nexport async function listGatewayAgents(\n cfg: Config,\n _options: { locale?: string } = {},\n): Promise<GatewayAgentsListResponse> {\n const defaultId = resolveDefaultAgentId(cfg);\n const agents: GatewayAgentRow[] = [];\n const presetSkills: string[] | undefined = undefined;\n const presetDenied: string[] = [];\n const presetTypedModels: ReturnType<typeof rolesToTypedModels> = [];\n for (const id of collectAgentIdsForList(cfg)) {\n const profile = resolveEffectiveAgentProfile(cfg, id);\n const entry = listAgentEntries(cfg).find((e) => normalizeAgentId(e.id) === id);\n const model =\n profile.primaryModelRef || profile.fallbacks.length > 0\n ? {\n ...(profile.primaryModelRef ? { primary: profile.primaryModelRef } : {}),\n ...(profile.fallbacks.length > 0 ? { fallbacks: profile.fallbacks } : {}),\n }\n : undefined;\n const entrySkills = entry?.skills.mode === 'allowlist' ? entry.skills.allow ?? [] : undefined;\n const entryDisable = Object.entries(entry?.tools.builtin ?? {})\n .filter(([, policy]) => policy.mode === 'deny')\n .map(([name]) => name);\n const entryTypedModels = rolesToTypedModels(entry?.models?.roles);\n const effectiveTypedModels = [...resolveEffectiveTypedModels(cfg, id).values()].sort((a, b) =>\n a.id.localeCompare(b.id),\n );\n let identity: ReturnType<typeof parseIdentityMarkdown> = {};\n try {\n const identityPath = join(resolveAgentProfileDir(cfg, id), WORKSPACE_FILES.IDENTITY);\n const content = await readFile(identityPath, 'utf-8');\n identity = parseIdentityMarkdown(content);\n } catch {\n /* missing IDENTITY.md or unreadable */\n }\n agents.push({\n id,\n ...(identity.name ? { name: identity.name } : {}),\n ...(identity.description ? { description: identity.description } : {}),\n ...(identity.language ? { language: identity.language } : {}),\n ...(profile.manifest.identity.role ? { role: profile.manifest.identity.role } : {}),\n responsibilities: {\n primary: [...profile.manifest.responsibilities.primary],\n ...(profile.manifest.responsibilities.secondary\n ? { secondary: [...profile.manifest.responsibilities.secondary] }\n : {}),\n },\n ...(identity.avatar ? { avatar: identity.avatar } : {}),\n workspace: profile.resolvedWorkspacePath,\n profileDir: resolveAgentProfileDir(cfg, id),\n ...(model ? { model } : {}),\n typedModels: {\n defaultRole: profile.manifest.models.defaultRole,\n preset: [...presetTypedModels],\n ...(entryTypedModels.length > 0 ? { entry: entryTypedModels } : {}),\n effective: effectiveTypedModels,\n },\n extends: [...(entry?.extends ?? [])],\n isDefault: id === defaultId,\n skills: {\n preset: presetSkills ? [...presetSkills] : [],\n ...(entrySkills !== undefined ? { entry: [...entrySkills] } : {}),\n ...(profile.skillsAllowlist !== undefined\n ? { effectiveAllowlist: [...profile.skillsAllowlist] }\n : {}),\n },\n tools: {\n presetDenied: [...presetDenied],\n entryDisable: [...entryDisable],\n effectiveDisable: [...profile.tools.denied].sort((a, b) => a.localeCompare(b)),\n },\n });\n }\n agents.sort((a, b) => a.id.localeCompare(b.id));\n return { defaultId, agents, builtinToolIds: [...GATEWAY_BUILTIN_TOOL_IDS] };\n}\n\nexport function getGatewayAgentEffectiveManifest(\n cfg: Config,\n agentIdRaw: string,\n): AgentAdminResult<GatewayAgentEffectiveManifestResponse> {\n const agentId = normalizeAgentId(agentIdRaw);\n const entry = listAgentEntries(cfg).find((e) => normalizeAgentId(e.id) === agentId);\n if (!entry) {\n return { ok: false, error: `agent \"${agentId}\" not found`, status: 404 };\n }\n try {\n return {\n ok: true,\n data: resolveEffectiveAgentManifest({\n agent: entry,\n presets: cfg.agents.capabilityPresets,\n defaultPresetId: cfg.agents.defaultPreset,\n }),\n };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n status: 400,\n };\n }\n}\n\nexport type CreateAgentBody = {\n /** Optional id seed; normalized agent id defaults from `profileFiles[\"IDENTITY.md\"]` name when omitted. */\n id?: string;\n workspace: string;\n models?: AgentModelsConfig;\n /** Reusable capability plans applied after the global baseline. */\n extends?: string[];\n /** Initial `agents.list[].skills` for the new entry. */\n skills?: string[];\n /** Initial `agents.list[].tools` for the new entry. */\n tools?: NonNullable<Config['agents']['list']>[number]['tools'];\n /** Profile markdown files to write after seeding (e.g. `IDENTITY.md`, `SOUL.md`). */\n profileFiles?: Record<string, string>;\n /** Clone from an existing agent id — copies config entry fields and profile directory. */\n cloneFrom?: string;\n};\n\nexport type AgentAdminHttpStatus = 400 | 404 | 409;\n\nexport type AgentAdminResult<T> =\n | { ok: true; data: T }\n | { ok: false; error: string; status?: AgentAdminHttpStatus };\n\nexport function prepareCreateAgent(\n cfg: Config,\n body: CreateAgentBody,\n): AgentAdminResult<{ nextConfig: Config; agentId: string; workspace: string }> {\n const workspace = body.workspace?.trim() ?? '';\n if (!workspace) {\n return { ok: false, error: 'workspace is required', status: 400 };\n }\n if (body.profileFiles !== undefined) {\n if (typeof body.profileFiles !== 'object' || body.profileFiles === null || Array.isArray(body.profileFiles)) {\n return { ok: false, error: 'profileFiles must be an object', status: 400 };\n }\n for (const [name, content] of Object.entries(body.profileFiles)) {\n const bad = assertAllowedFile(name);\n if (bad) {\n return bad;\n }\n if (typeof content !== 'string') {\n return { ok: false, error: `profileFiles[\"${name}\"] must be a string`, status: 400 };\n }\n }\n }\n if (!body.cloneFrom && typeof body.profileFiles?.[WORKSPACE_FILES.IDENTITY] !== 'string') {\n return { ok: false, error: `profileFiles[\"${WORKSPACE_FILES.IDENTITY}\"] is required`, status: 400 };\n }\n\n const identity = body.profileFiles?.[WORKSPACE_FILES.IDENTITY]\n ? parseIdentityMarkdown(body.profileFiles[WORKSPACE_FILES.IDENTITY])\n : {};\n const nameSeed = identity.name ?? body.id ?? '';\n const idRes = validateAgentIdForNewAgent(body.id, nameSeed);\n if (idRes.ok === false) {\n return { ok: false, error: idRes.error, status: 400 };\n }\n const agentId = idRes.agentId;\n if (findAgentEntryIndex(listAgentEntries(cfg), agentId) >= 0) {\n return { ok: false, error: `agent \"${agentId}\" already exists`, status: 409 };\n }\n\n // Resolve fields from cloneFrom source when present\n let cloneSourceEntry: ReturnType<typeof listAgentEntries>[number] | undefined;\n if (body.cloneFrom) {\n const srcId = normalizeAgentId(body.cloneFrom);\n cloneSourceEntry = listAgentEntries(cfg).find((e) => normalizeAgentId(e.id) === srcId);\n if (!cloneSourceEntry && srcId !== resolveDefaultAgentId(cfg)) {\n return { ok: false, error: `source agent \"${srcId}\" not found`, status: 404 };\n }\n }\n\n const wsAbs = resolveUserPath(workspace);\n\n const rawModels = body.models ?? cloneSourceEntry?.models;\n const inheritedPresetIds = body.extends ?? cloneSourceEntry?.extends ?? [];\n for (const presetId of inheritedPresetIds) {\n if (!cfg.agents.capabilityPresets[presetId]) {\n return { ok: false, error: `capability preset \"${presetId}\" not found`, status: 400 };\n }\n }\n const effectiveModels =\n rawModels?.roles\n ? {\n defaultRole: rawModels.defaultRole ?? Object.keys(rawModels.roles)[0] ?? 'deep',\n roles: rawModels.roles,\n }\n : undefined;\n if (effectiveModels && !effectiveModels.roles[effectiveModels.defaultRole]) {\n return { ok: false, error: 'models.defaultRole must reference models.roles', status: 400 };\n }\n\n let next = applyAgentConfig(cfg, {\n agentId,\n workspace: wsAbs,\n extends: [...inheritedPresetIds],\n ...(effectiveModels ? { models: effectiveModels } : {}),\n ...(body.skills !== undefined\n ? { skills: body.skills.map((s) => String(s).trim()).filter(Boolean) }\n : cloneSourceEntry?.skills.mode === 'allowlist' && body.cloneFrom\n ? { skills: [...(cloneSourceEntry.skills.allow ?? [])] }\n : {}),\n ...(body.tools !== undefined ? { tools: body.tools } : cloneSourceEntry?.tools && body.cloneFrom ? { tools: cloneSourceEntry.tools } : {}),\n });\n\n return { ok: true, data: { nextConfig: next, agentId, workspace: wsAbs } };\n}\n\nexport async function finalizeCreateAgentDirs(\n cfg: Config,\n agentId: string,\n opts?: { profileFiles?: Record<string, string>; cloneFrom?: string },\n): Promise<AgentAdminResult<void>> {\n const wsPath = resolveAgentWorkspaceDir(cfg, agentId);\n const profilePath = resolveAgentProfileDir(cfg, agentId);\n const adPath = resolveAgentDir(cfg, agentId);\n await mkdir(wsPath, { recursive: true });\n await mkdir(profilePath, { recursive: true });\n await mkdir(adPath, { recursive: true });\n const id = normalizeAgentId(agentId);\n const displayName = opts?.profileFiles?.[WORKSPACE_FILES.IDENTITY]\n ? (parseIdentityMarkdown(opts.profileFiles[WORKSPACE_FILES.IDENTITY]).name ?? id)\n : id;\n\n // When cloning, copy the entire source profile directory instead of seeding\n if (opts?.cloneFrom) {\n const srcProfilePath = resolveAgentProfileDir(cfg, normalizeAgentId(opts.cloneFrom));\n try {\n const srcStat = await stat(srcProfilePath);\n if (srcStat.isDirectory()) {\n const srcFiles = await readdir(srcProfilePath);\n for (const fileName of srcFiles) {\n const srcFile = join(srcProfilePath, fileName);\n const dstFile = join(profilePath, fileName);\n try {\n const fileStat = await stat(srcFile);\n if (fileStat.isFile()) {\n await cp(srcFile, dstFile);\n }\n } catch {\n /* skip unreadable files */\n }\n }\n }\n } catch {\n // Source profile dir doesn't exist — fall through to normal seed\n seedAgentProfileMarkdownFiles(profilePath, wsPath, { displayName });\n }\n } else {\n seedAgentProfileMarkdownFiles(profilePath, wsPath, { displayName });\n }\n\n const profileFiles = opts?.profileFiles;\n if (profileFiles && Object.keys(profileFiles).length > 0) {\n for (const [name, content] of Object.entries(profileFiles)) {\n const written = await writeAgentProfileFile(cfg, agentId, name, content);\n if (written.ok === false) {\n return written;\n }\n }\n }\n\n return { ok: true, data: undefined };\n}\n\nexport type UpdateAgentBody = {\n workspace?: string;\n extends?: string[];\n models?: {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; fallbacks?: string[]; description?: string }>;\n } | null;\n setDefault?: boolean;\n /** Replace `agents.list[].skills`; `null` resets to all skills. */\n skills?: string[] | null;\n /** Replace `agents.list[].tools`; `null` resets to no explicit policies. */\n tools?: NonNullable<Config['agents']['list']>[number]['tools'] | null;\n /** Replace `agents.list[].memory`; every agent manifest owns its memory policy. */\n memory?: NonNullable<Config['agents']['list']>[number]['memory'];\n};\n\nexport function prepareUpdateAgent(\n cfg: Config,\n agentIdRaw: string,\n body: UpdateAgentBody,\n): AgentAdminResult<{ nextConfig: Config }> {\n const agentId = normalizeAgentId(agentIdRaw);\n let list = [...listAgentEntries(cfg)];\n let idx = findAgentEntryIndex(list, agentId);\n if (idx < 0 && agentId === resolveDefaultAgentId(cfg)) {\n list = [...list, {\n id: agentId,\n enabled: true as const,\n identity: { name: agentId, role: 'Agent', language: 'en', tone: 'direct' },\n responsibilities: { primary: ['Help the user complete tasks'] },\n workspace: { root: `~/.xopc/workspace/${agentId}` },\n tools: { builtin: {} },\n skills: { mode: 'all' },\n memory: { mode: 'confirmWrite', sources: ['session', 'curated'], writePolicy: { curated: 'confirm' } },\n workflows: {},\n boundaries: { requiresConfirmation: [], forbidden: [], escalation: [] },\n }];\n idx = list.length - 1;\n }\n if (idx < 0) {\n return { ok: false, error: `agent \"${agentId}\" not found`, status: 404 };\n }\n\n type Entry = (typeof list)[number];\n const entry: Entry = { ...list[idx] };\n\n if (body.workspace !== undefined) {\n const w = body.workspace.trim();\n if (w) {\n entry.workspace = { root: resolveUserPath(w) };\n }\n }\n if (body.extends !== undefined) {\n const nextExtends = Array.from(new Set(body.extends.map((id) => normalizeAgentId(id)).filter(Boolean)));\n for (const presetId of nextExtends) {\n if (!cfg.agents.capabilityPresets[presetId]) {\n return { ok: false, error: `capability preset \"${presetId}\" not found`, status: 400 };\n }\n }\n if (nextExtends.length > 0) {\n entry.extends = nextExtends;\n } else {\n delete entry.extends;\n }\n }\n if (body.models !== undefined) {\n if (body.models === null) {\n delete entry.models;\n } else {\n if (body.models.defaultRole !== undefined) {\n if (body.models.defaultRole === null || !body.models.defaultRole.trim()) {\n return { ok: false, error: 'models.defaultRole must be a non-empty string', status: 400 };\n }\n entry.models = {\n defaultRole: body.models.defaultRole.trim(),\n roles: entry.models?.roles ?? {},\n ...(entry.models?.policy ? { policy: entry.models.policy } : {}),\n };\n }\n if (Object.hasOwn(body.models, 'roles')) {\n if (body.models.roles !== undefined) {\n const roles = Object.fromEntries(\n Object.entries(body.models.roles)\n .map(([id, row]) => ({\n id: id.trim(),\n model: row.model.trim(),\n fallbacks: (row.fallbacks ?? []).map((ref) => ref.trim()).filter(Boolean),\n description: row.description?.trim(),\n }))\n .filter((row) => row.id && row.model)\n .map((row) => [\n row.id,\n {\n model: row.model,\n ...(row.fallbacks.length > 0 ? { fallbacks: row.fallbacks } : {}),\n ...(row.description ? { description: row.description } : {}),\n },\n ]),\n );\n entry.models = {\n defaultRole: entry.models?.defaultRole ?? Object.keys(roles)[0] ?? 'deep',\n roles,\n ...(entry.models?.policy ? { policy: entry.models.policy } : {}),\n };\n }\n }\n const roles = entry.models?.roles ?? {};\n const defaultRole = entry.models?.defaultRole ?? Object.keys(roles)[0];\n if (!defaultRole || !roles[defaultRole]) {\n return { ok: false, error: 'models.defaultRole must reference models.roles', status: 400 };\n }\n entry.models = { ...entry.models, defaultRole };\n }\n }\n\n if (body.skills !== undefined) {\n if (body.skills === null) {\n entry.skills = { mode: 'all' };\n } else {\n const next = body.skills.map((s) => String(s).trim()).filter(Boolean);\n if (next.length === 0) {\n entry.skills = { mode: 'allowlist', allow: [] };\n } else {\n entry.skills = { mode: 'allowlist', allow: next };\n }\n }\n }\n\n if (body.tools !== undefined) {\n if (body.tools === null) {\n entry.tools = { builtin: {} };\n } else {\n entry.tools = body.tools;\n }\n }\n\n if (body.memory !== undefined) {\n entry.memory = body.memory;\n }\n\n list[idx] = entry;\n let next: Config = {\n ...cfg,\n agents: {\n ...cfg.agents,\n list,\n },\n };\n\n if (body.setDefault === true) {\n next = {\n ...next,\n agents: {\n ...next.agents,\n default: agentId,\n },\n };\n }\n return { ok: true, data: { nextConfig: next } };\n}\n\nexport function prepareDeleteAgent(\n cfg: Config,\n agentIdRaw: string,\n): AgentAdminResult<{ nextConfig: Config; agentId: string }> {\n const agentId = normalizeAgentId(agentIdRaw);\n const blocker = getAgentDeleteBlocker(cfg, agentId);\n if (blocker) {\n return { ok: false, error: blocker, status: 400 };\n }\n if (findAgentEntryIndex(listAgentEntries(cfg), agentId) < 0) {\n return { ok: false, error: `agent \"${agentId}\" not found`, status: 404 };\n }\n const { config: pruned } = pruneAgentConfig(cfg, agentId);\n return { ok: true, data: { nextConfig: pruned, agentId } };\n}\n\nexport async function runAfterDeletePurge(cfg: Config, agentId: string): Promise<void> {\n await removeAgentDirsFromDisk(cfg, agentId);\n}\n\nexport type AgentFileEntry = {\n name: string;\n missing: boolean;\n size?: number;\n updatedAtMs?: number;\n};\n\nasync function profileMarkdownRootReal(cfg: Config, agentId: string): Promise<string> {\n const dir = resolveAgentProfileDir(cfg, agentId);\n await mkdir(dir, { recursive: true });\n try {\n return await realpath(dir);\n } catch {\n return pathResolve(dir);\n }\n}\n\nfunction assertAllowedFile(name: string): AgentAdminResult<never> | null {\n if (!name || name.includes('/') || name.includes('\\\\') || !EDITABLE_PROFILE_MARKDOWN_NAMES.has(name)) {\n return { ok: false, error: `unsupported file \"${name}\"`, status: 400 };\n }\n return null;\n}\n\nexport async function listAgentProfileFiles(\n cfg: Config,\n agentId: string,\n): Promise<AgentAdminResult<{ agentId: string; profileDir: string; files: AgentFileEntry[] }>> {\n const id = normalizeAgentId(agentId);\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n const root = await profileMarkdownRootReal(cfg, id);\n const names = [...EDITABLE_PROFILE_MARKDOWN_NAMES];\n const files: AgentFileEntry[] = [];\n for (const name of names.sort((a, b) => a.localeCompare(b))) {\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n continue;\n }\n try {\n const st = await stat(abs);\n if (!st.isFile()) {\n continue;\n }\n files.push({\n name,\n missing: false,\n size: st.size,\n updatedAtMs: st.mtimeMs,\n });\n } catch {\n if (!REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET.has(name)) {\n continue;\n }\n files.push({ name, missing: true });\n }\n }\n files.sort((a, b) => a.name.localeCompare(b.name));\n return { ok: true, data: { agentId: id, profileDir: root, files } };\n}\n\nexport async function readAgentProfileFile(\n cfg: Config,\n agentId: string,\n name: string,\n): Promise<AgentAdminResult<{ agentId: string; content: string; path: string }>> {\n const bad = assertAllowedFile(name);\n if (bad) {\n return bad;\n }\n const id = normalizeAgentId(agentId);\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n const root = await profileMarkdownRootReal(cfg, id);\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n return { ok: false, error: 'invalid path', status: 400 };\n }\n try {\n const content = await readFile(abs, 'utf-8');\n return { ok: true, data: { agentId: id, content, path: abs } };\n } catch {\n return { ok: false, error: 'file not found', status: 404 };\n }\n}\n\nexport async function writeAgentProfileFile(\n cfg: Config,\n agentId: string,\n name: string,\n content: string,\n): Promise<AgentAdminResult<{ agentId: string; path: string }>> {\n const bad = assertAllowedFile(name);\n if (bad) {\n return bad;\n }\n const id = normalizeAgentId(agentId);\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n const root = await profileMarkdownRootReal(cfg, id);\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n return { ok: false, error: 'invalid path', status: 400 };\n }\n const rootReal = await profileMarkdownRootReal(cfg, id);\n if (!isPathUnderWorkspace(rootReal, abs)) {\n return { ok: false, error: 'path escapes profile markdown root', status: 400 };\n }\n await writeFile(abs, content, 'utf-8');\n return { ok: true, data: { agentId: id, path: abs } };\n}\n\nexport async function readUserProfileFile(): Promise<AgentAdminResult<{ content: string; path: string }>> {\n const path = resolveUserProfilePath();\n try {\n const content = await readFile(path, 'utf-8');\n return { ok: true, data: { content, path } };\n } catch {\n return { ok: true, data: { content: '', path } };\n }\n}\n\nexport async function writeUserProfileFile(\n content: string,\n): Promise<AgentAdminResult<{ path: string }>> {\n const path = resolveUserProfilePath();\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, 'utf-8');\n return { ok: true, data: { path } };\n}\n\n// ---------------------------------------------------------------------------\n// Binary agent avatar (profile markdown root dir, not a SOUL/IDENTITY markdown file)\n// ---------------------------------------------------------------------------\n\nconst AGENT_AVATAR_MAX_BYTES = 512 * 1024;\nconst AGENT_AVATAR_BASENAME = 'agent-avatar';\n\nconst AGENT_AVATAR_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp'] as const;\n\nfunction agentAvatarFilenames(): string[] {\n return AGENT_AVATAR_EXTENSIONS.map((ext) => `${AGENT_AVATAR_BASENAME}${ext}`);\n}\n\nfunction mimeToExt(mime: string): '.png' | '.jpg' | '.jpeg' | '.webp' | null {\n const m = mime.toLowerCase().trim();\n if (m === 'image/png') return '.png';\n if (m === 'image/jpeg' || m === 'image/jpg') return '.jpg';\n if (m === 'image/webp') return '.webp';\n return null;\n}\n\nfunction detectImageMimeFromBytes(buf: Uint8Array): 'image/png' | 'image/jpeg' | 'image/webp' | null {\n if (buf.length >= 8 && buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4e && buf[3] === 0x47) {\n return 'image/png';\n }\n if (buf.length >= 3 && buf[0] === 0xff && buf[1] === 0xd8 && buf[2] === 0xff) {\n return 'image/jpeg';\n }\n if (\n buf.length >= 12 &&\n buf[0] === 0x52 &&\n buf[1] === 0x49 &&\n buf[2] === 0x46 &&\n buf[3] === 0x46 &&\n buf[8] === 0x57 &&\n buf[9] === 0x45 &&\n buf[10] === 0x42 &&\n buf[11] === 0x50\n ) {\n return 'image/webp';\n }\n return null;\n}\n\nfunction assertAgentExistsForAvatar(cfg: Config, id: string): AgentAdminResult<never> | null {\n if (collectAgentIdsForList(cfg).every((x) => x !== id)) {\n return { ok: false, error: `agent \"${id}\" not found`, status: 404 };\n }\n return null;\n}\n\nexport async function readAgentAvatarFile(\n cfg: Config,\n agentId: string,\n): Promise<AgentAdminResult<{ agentId: string; buffer: Buffer; contentType: string; path: string }>> {\n const missingAgent = assertAgentExistsForAvatar(cfg, agentId);\n if (missingAgent) {\n return missingAgent;\n }\n const id = normalizeAgentId(agentId);\n const root = await profileMarkdownRootReal(cfg, id);\n for (const name of agentAvatarFilenames()) {\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs) {\n continue;\n }\n try {\n const st = await stat(abs);\n if (!st.isFile() || st.size <= 0 || st.size > AGENT_AVATAR_MAX_BYTES) {\n continue;\n }\n const buffer = await readFile(abs);\n const detected = detectImageMimeFromBytes(buffer);\n if (!detected) {\n continue;\n }\n return { ok: true, data: { agentId: id, buffer, contentType: detected, path: abs } };\n } catch {\n /* try next */\n }\n }\n return { ok: false, error: 'avatar not found', status: 404 };\n}\n\nexport async function writeAgentAvatarFromBase64(\n cfg: Config,\n agentId: string,\n base64: string,\n mimeType: string,\n): Promise<AgentAdminResult<{ agentId: string; path: string }>> {\n const missingAgent = assertAgentExistsForAvatar(cfg, agentId);\n if (missingAgent) {\n return missingAgent;\n }\n const id = normalizeAgentId(agentId);\n const ext = mimeToExt(mimeType);\n if (!ext) {\n return { ok: false, error: 'unsupported mimeType (use image/png, image/jpeg, or image/webp)', status: 400 };\n }\n let raw: Buffer;\n try {\n raw = Buffer.from(base64, 'base64');\n } catch {\n return { ok: false, error: 'invalid base64', status: 400 };\n }\n if (raw.length === 0 || raw.length > AGENT_AVATAR_MAX_BYTES) {\n return { ok: false, error: `avatar must be non-empty and at most ${AGENT_AVATAR_MAX_BYTES} bytes`, status: 400 };\n }\n const detected = detectImageMimeFromBytes(raw);\n if (!detected || !extMatchesDetectedMime(ext, detected)) {\n return { ok: false, error: 'file content does not match declared image type', status: 400 };\n }\n\n const root = await profileMarkdownRootReal(cfg, id);\n const rootReal = await profileMarkdownRootReal(cfg, id);\n const targetName = `${AGENT_AVATAR_BASENAME}${ext}`;\n const abs = resolveWorkspaceSafePath(root, targetName);\n if (!abs || !isPathUnderWorkspace(rootReal, abs)) {\n return { ok: false, error: 'invalid path', status: 400 };\n }\n for (const name of agentAvatarFilenames()) {\n if (name === targetName) {\n continue;\n }\n const other = resolveWorkspaceSafePath(root, name);\n if (other && isPathUnderWorkspace(rootReal, other)) {\n try {\n await unlink(other);\n } catch {\n /* absent */\n }\n }\n }\n await writeFile(abs, raw);\n return { ok: true, data: { agentId: id, path: abs } };\n}\n\nfunction mimeToExtToMime(ext: '.png' | '.jpg' | '.jpeg' | '.webp'): 'image/png' | 'image/jpeg' | 'image/webp' {\n if (ext === '.png') return 'image/png';\n if (ext === '.webp') return 'image/webp';\n return 'image/jpeg';\n}\n\nfunction extMatchesDetectedMime(\n ext: '.png' | '.jpg' | '.jpeg' | '.webp',\n detected: 'image/png' | 'image/jpeg' | 'image/webp',\n): boolean {\n return detected === mimeToExtToMime(ext);\n}\n\n/** Remove any `agent-avatar.*` in the agent profile markdown root. Idempotent: ok even when no file existed. */\nexport async function deleteAgentAvatarFile(cfg: Config, agentId: string): Promise<AgentAdminResult<{ agentId: string }>> {\n const missingAgent = assertAgentExistsForAvatar(cfg, agentId);\n if (missingAgent) {\n return missingAgent;\n }\n const id = normalizeAgentId(agentId);\n const root = await profileMarkdownRootReal(cfg, id);\n const rootReal = await profileMarkdownRootReal(cfg, id);\n for (const name of agentAvatarFilenames()) {\n const abs = resolveWorkspaceSafePath(root, name);\n if (!abs || !isPathUnderWorkspace(rootReal, abs)) {\n continue;\n }\n try {\n await unlink(abs);\n } catch {\n /* absent */\n }\n }\n return { ok: true, data: { agentId: id } };\n}\n"],"mappings":"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"}
@@ -11,6 +11,7 @@ export type CapabilityPresetAdminResult<T> = {
11
11
  export type CapabilityPresetAgentUsage = {
12
12
  agentId: string;
13
13
  agentName?: string;
14
+ direct: boolean;
14
15
  };
15
16
  export type CapabilityPresetRow = CapabilityPreset & {
16
17
  usage: CapabilityPresetAgentUsage[];
@@ -29,6 +30,16 @@ export type CreateCapabilityPresetBody = {
29
30
  id?: string;
30
31
  name?: string;
31
32
  description?: string;
33
+ version?: number;
34
+ extends?: CapabilityPreset['extends'];
35
+ models?: CapabilityPreset['models'];
36
+ tools?: CapabilityPreset['tools'];
37
+ skills?: CapabilityPreset['skills'];
38
+ memory?: CapabilityPreset['memory'];
39
+ workflows?: CapabilityPreset['workflows'];
40
+ boundaries?: CapabilityPreset['boundaries'];
41
+ runtime?: CapabilityPreset['runtime'];
42
+ locks?: CapabilityPreset['locks'];
32
43
  };
33
44
  export type UpdateCapabilityPresetBody = {
34
45
  name?: string;
@@ -1,7 +1,9 @@
1
1
  import { CapabilityPresetSchema, init_schema } from "../agent-manifest/schema.js";
2
+ import { init_preset_chain, linearizePresetIds } from "../agent-manifest/preset-chain.js";
2
3
  import { GATEWAY_BUILTIN_TOOL_IDS } from "./agent-builtin-tools.js";
3
4
  //#region src/gateway/capability-presets-admin.ts
4
5
  init_schema();
6
+ init_preset_chain();
5
7
  function presetMap(cfg) {
6
8
  return cfg.agents.capabilityPresets ?? {};
7
9
  }
@@ -10,9 +12,12 @@ function normalizePresetId(id) {
10
12
  }
11
13
  function agentUsage(cfg, presetId) {
12
14
  const defaultPresetId = cfg.agents.defaultPreset || "default";
13
- return cfg.agents.list.filter((agent) => presetId === defaultPresetId || (agent.extends ?? []).includes(presetId)).map((agent) => ({
15
+ return cfg.agents.list.filter((agent) => {
16
+ return linearizePresetIds([...cfg.agents.capabilityPresets[defaultPresetId] ? [defaultPresetId] : [], ...(agent.extends ?? []).filter((id) => id !== defaultPresetId)], cfg.agents.capabilityPresets).includes(presetId);
17
+ }).map((agent) => ({
14
18
  agentId: agent.id,
15
- ...agent.identity.name ? { agentName: agent.identity.name } : {}
19
+ ...agent.identity.name ? { agentName: agent.identity.name } : {},
20
+ direct: presetId === defaultPresetId || (agent.extends ?? []).includes(presetId)
16
21
  })).sort((a, b) => a.agentId.localeCompare(b.agentId));
17
22
  }
18
23
  function validatePresetReferences(presets) {
@@ -112,10 +117,12 @@ function prepareCreateCapabilityPreset(cfg, body) {
112
117
  const id = normalizePresetId(body.id ?? "");
113
118
  const name = body.name?.trim() || id;
114
119
  const description = body.description?.trim();
120
+ const { id: _id, name: _name, description: _description, ...policy } = body;
115
121
  const parsed = CapabilityPresetSchema.safeParse({
122
+ ...policy,
116
123
  id,
117
124
  name,
118
- version: 1,
125
+ version: body.version ?? 1,
119
126
  ...description ? { description } : {}
120
127
  });
121
128
  if (!parsed.success) return {
@@ -167,7 +174,7 @@ function prepareUpdateCapabilityPreset(cfg, presetIdRaw, body) {
167
174
  }
168
175
  if (body.description !== void 0) if (body.description === null || !body.description.trim()) delete nextPreset.description;
169
176
  else nextPreset.description = body.description.trim();
170
- if (body.version !== void 0) nextPreset.version = body.version;
177
+ nextPreset.version = body.version ?? current.version + 1;
171
178
  for (const key of [
172
179
  "extends",
173
180
  "models",