@xopcai/xopc 0.0.105 → 0.0.107

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 (430) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/dashscope/xopc.extension.json +7 -2
  3. package/dist/extensions/fal/xopc.extension.json +7 -2
  4. package/dist/extensions/feishu/src/adapters/gateway-setup.js +22 -26
  5. package/dist/extensions/feishu/src/adapters/gateway-setup.js.map +1 -1
  6. package/dist/extensions/feishu/src/directory/directory-adapter.js +1 -1
  7. package/dist/extensions/feishu/src/directory/directory-adapter.js.map +1 -1
  8. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  9. package/dist/extensions/feishu/src/outbound/outbound-adapter.js +4 -3
  10. package/dist/extensions/feishu/src/outbound/outbound-adapter.js.map +1 -1
  11. package/dist/extensions/feishu/src/plugin.d.ts +6 -3
  12. package/dist/extensions/feishu/src/plugin.js +59 -40
  13. package/dist/extensions/feishu/src/plugin.js.map +1 -1
  14. package/dist/extensions/feishu/src/streaming/streaming-adapter.js +20 -16
  15. package/dist/extensions/feishu/src/streaming/streaming-adapter.js.map +1 -1
  16. package/dist/extensions/feishu/src/transport/socket-mode/monitor.js +1 -1
  17. package/dist/extensions/feishu/src/transport/webhook/monitor.js +1 -1
  18. package/dist/extensions/feishu/src/workflow-progress.d.ts +1 -1
  19. package/dist/extensions/feishu/src/workflow-progress.js +3 -3
  20. package/dist/extensions/feishu/src/workflow-progress.js.map +1 -1
  21. package/dist/extensions/feishu/xopc.extension.json +458 -26
  22. package/dist/extensions/google/xopc.extension.json +7 -2
  23. package/dist/extensions/minimax/xopc.extension.json +8 -2
  24. package/dist/extensions/openai/xopc.extension.json +7 -2
  25. package/dist/extensions/telegram/src/adapters/gateway-setup.js +8 -6
  26. package/dist/extensions/telegram/src/adapters/gateway-setup.js.map +1 -1
  27. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  28. package/dist/extensions/telegram/src/command-handler.d.ts +1 -1
  29. package/dist/extensions/telegram/src/command-handler.js +11 -9
  30. package/dist/extensions/telegram/src/command-handler.js.map +1 -1
  31. package/dist/extensions/telegram/src/inbound-processor.js +2 -3
  32. package/dist/extensions/telegram/src/inbound-processor.js.map +1 -1
  33. package/dist/extensions/telegram/src/plugin.d.ts +1 -0
  34. package/dist/extensions/telegram/src/plugin.js +7 -7
  35. package/dist/extensions/telegram/src/plugin.js.map +1 -1
  36. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  37. package/dist/extensions/telegram/src/update-offset-store.js +1 -1
  38. package/dist/extensions/telegram/src/workflow-progress.d.ts +1 -1
  39. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  40. package/dist/extensions/telegram/src/workflow-progress.js.map +1 -1
  41. package/dist/extensions/telegram/xopc.extension.json +10 -2
  42. package/dist/extensions/weixin/src/api/api.js +2 -2
  43. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  44. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  45. package/dist/extensions/weixin/src/cli/gateway-qr-login.d.ts +4 -0
  46. package/dist/extensions/weixin/src/cli/gateway-qr-login.js +34 -5
  47. package/dist/extensions/weixin/src/cli/gateway-qr-login.js.map +1 -1
  48. package/dist/extensions/weixin/src/cli/qr-login.js +4 -3
  49. package/dist/extensions/weixin/src/cli/qr-login.js.map +1 -1
  50. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  51. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  52. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  53. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  54. package/dist/extensions/weixin/src/plugin.d.ts +1 -0
  55. package/dist/extensions/weixin/src/plugin.js +8 -7
  56. package/dist/extensions/weixin/src/plugin.js.map +1 -1
  57. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  58. package/dist/extensions/weixin/src/workflow-progress.d.ts +1 -1
  59. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  60. package/dist/extensions/weixin/src/workflow-progress.js.map +1 -1
  61. package/dist/extensions/weixin/xopc.extension.json +57 -14
  62. package/dist/gateway/static/root/apple-touch-icon.png +0 -0
  63. package/dist/gateway/static/root/assets/agents-BXg2_mE4.js +78 -0
  64. package/dist/gateway/static/root/assets/apps-page-CJqQ-7Ss.js +1 -0
  65. package/dist/gateway/static/root/assets/channels-settings-DvMZ6NAd.js +1 -0
  66. package/dist/gateway/static/root/assets/cron-page-BPBlvSl5.js +1 -0
  67. package/dist/gateway/static/root/assets/{dist-DJDkNhu5.js → dist-CZh0c-s8.js} +1 -1
  68. package/dist/gateway/static/root/assets/{extension-debug-page-DI1XJTJi.js → extension-debug-page-DyJQR0SR.js} +1 -1
  69. package/dist/gateway/static/root/assets/{extension-page-SuafGTT_.js → extension-page-CDTuUr9B.js} +1 -1
  70. package/dist/gateway/static/root/assets/{extension-settings-page-cKmGax9v.js → extension-settings-page-DszZ8zHD.js} +1 -1
  71. package/dist/gateway/static/root/assets/{fetch-CkvRO30i.js → fetch-CFdKBnE6.js} +1 -1
  72. package/dist/gateway/static/root/assets/{gateway-startup-retry-BkKyRDrF.js → gateway-startup-retry-DdngdObI.js} +1 -1
  73. package/dist/gateway/static/root/assets/{heartbeat-config-api-CRiDcxtt.js → heartbeat-config-api-U10wnPdc.js} +1 -1
  74. package/dist/gateway/static/root/assets/index-DBc-bVOQ.js +4845 -0
  75. package/dist/gateway/static/root/assets/index-DI5_GsZt.css +1 -0
  76. package/dist/gateway/static/root/assets/{logs-page-DM8o5-Bm.js → logs-page-B6js8Bfi.js} +2 -2
  77. package/dist/gateway/static/root/assets/{note-detail-page-j53jtvq9.js → note-detail-page-DFzAXR35.js} +4 -4
  78. package/dist/gateway/static/root/assets/{note-time-Ck2H2Qpw.js → note-time-DOiSU-10.js} +1 -1
  79. package/dist/gateway/static/root/assets/notes-page-DAuZJMT8.js +1 -0
  80. package/dist/gateway/static/root/assets/{schema-form-BvmGNxiJ.js → schema-form-zM36dvbY.js} +1 -1
  81. package/dist/gateway/static/root/assets/sessions-page-CAsV03BY.js +1 -0
  82. package/dist/gateway/static/root/assets/{settings-advanced-gate-DRdayl8P.js → settings-advanced-gate-BCvObK1y.js} +1 -1
  83. package/dist/gateway/static/root/assets/{settings-form-section-BlIYg2gZ.js → settings-form-section-Bvl-RInc.js} +1 -1
  84. package/dist/gateway/static/root/assets/settings-page-DuCJDd74.js +3 -0
  85. package/dist/gateway/static/root/assets/{share-preview-page-BlT6Akvk.js → share-preview-page-rpL4DDTO.js} +1 -1
  86. package/dist/gateway/static/root/assets/skills-page--BioR9J4.js +2 -0
  87. package/dist/gateway/static/root/assets/{theme-store-DYgVdRB4.js → theme-store-BZozwAeK.js} +1 -1
  88. package/dist/gateway/static/root/assets/url-DQRqHuL-.js +3 -0
  89. package/dist/gateway/static/root/assets/voice-api-key-field-D2RJaoj_.js +1 -0
  90. package/dist/gateway/static/root/assets/{workflow-page.utils-_sjXCMvi.js → workflow-page.utils-BxacHYen.js} +1 -1
  91. package/dist/gateway/static/root/assets/workflows-page-B1B-est-.js +18 -0
  92. package/dist/gateway/static/root/favicon-16.png +0 -0
  93. package/dist/gateway/static/root/favicon-32.png +0 -0
  94. package/dist/gateway/static/root/favicon.ico +0 -0
  95. package/dist/gateway/static/root/favicon.svg +18 -0
  96. package/dist/gateway/static/root/index.html +11 -10
  97. package/dist/package.js +1 -1
  98. package/dist/src/agent/agent-manager.js +7 -7
  99. package/dist/src/agent/agent-scope.js +1 -1
  100. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  101. package/dist/src/agent/context/workspace-seed.js +2 -2
  102. package/dist/src/agent/context/workspace-state.js +1 -1
  103. package/dist/src/agent/goals/goal-run-store.js +4 -4
  104. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  105. package/dist/src/agent/goals/post-turn.js +2 -2
  106. package/dist/src/agent/image/load-image-media.js +2 -2
  107. package/dist/src/agent/ipc/bus.js +1 -1
  108. package/dist/src/agent/ipc/inbox.js +2 -2
  109. package/dist/src/agent/ipc/socket.js +1 -1
  110. package/dist/src/agent/mcp/bundle-mcp-config.js +16 -8
  111. package/dist/src/agent/mcp/bundle-mcp-config.js.map +1 -1
  112. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  113. package/dist/src/agent/mcp/bundle-mcp-policy.js +2 -2
  114. package/dist/src/agent/mcp/bundle-mcp-policy.js.map +1 -1
  115. package/dist/src/agent/mcp/bundle-mcp-runtime.js +2 -2
  116. package/dist/src/agent/mcp/mcp-http.js +1 -1
  117. package/dist/src/agent/mcp/mcp-http.js.map +1 -1
  118. package/dist/src/agent/mcp/mcp-transport-config.js +3 -7
  119. package/dist/src/agent/mcp/mcp-transport-config.js.map +1 -1
  120. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  121. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  122. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  123. package/dist/src/agent/memory/dreaming/events.js +1 -1
  124. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  125. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  126. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  127. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  128. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  129. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  130. package/dist/src/agent/memory/memory-flush.js +1 -1
  131. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  132. package/dist/src/agent/models/manager.js +1 -1
  133. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  134. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  135. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  136. package/dist/src/agent/sandbox/path-policy.js +2 -2
  137. package/dist/src/agent/service.js +4 -4
  138. package/dist/src/agent/session/session-inspector.js +1 -1
  139. package/dist/src/agent/skills/config.js +1 -1
  140. package/dist/src/agent/skills/hub-hash.js +2 -2
  141. package/dist/src/agent/skills/hub-lock.js +1 -1
  142. package/dist/src/agent/skills/hub-pull.js +2 -2
  143. package/dist/src/agent/skills/index.js +1 -1
  144. package/dist/src/agent/skills/managed-store.js +1 -1
  145. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +4 -0
  146. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +4 -2
  147. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
  148. package/dist/src/agent/skills/scanner.js +1 -1
  149. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  150. package/dist/src/agent/skills/skill-manager.js +1 -1
  151. package/dist/src/agent/starter-agents.d.ts +19 -0
  152. package/dist/src/agent/starter-agents.js +190 -0
  153. package/dist/src/agent/starter-agents.js.map +1 -0
  154. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  155. package/dist/src/agent/tools/factory.js +1 -1
  156. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  157. package/dist/src/agent/tools/send-media.js +1 -1
  158. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  159. package/dist/src/agent/tools/workflow-tool.js +1 -1
  160. package/dist/src/agent/tools/write.js +1 -1
  161. package/dist/src/agent/workflow/catalog.js +1 -1
  162. package/dist/src/agent/workflow/index.js +2 -1
  163. package/dist/src/agent/workflow/runtime.d.ts +2 -2
  164. package/dist/src/agent/workflow/runtime.js +50 -29
  165. package/dist/src/agent/workflow/runtime.js.map +1 -1
  166. package/dist/src/agent/workflow/snapshot-empty.d.ts +2 -0
  167. package/dist/src/agent/workflow/snapshot-empty.js +19 -0
  168. package/dist/src/agent/workflow/snapshot-empty.js.map +1 -0
  169. package/dist/src/agent/workflow/snapshot.js +1 -1
  170. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  171. package/dist/src/agent/workflow/types.d.ts +11 -0
  172. package/dist/src/auth/credentials.js +3 -3
  173. package/dist/src/auth/profiles/store.js +2 -2
  174. package/dist/src/auth/sync-provider-auth.js +1 -1
  175. package/dist/src/browser/cache-dir-policy.js +1 -1
  176. package/dist/src/browser/cdp-local-launcher.js +2 -2
  177. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  178. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  179. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  180. package/dist/src/browser/stealth.js +1 -1
  181. package/dist/src/channels/catalog/channel-catalog-service.js +13 -0
  182. package/dist/src/channels/catalog/channel-catalog-service.js.map +1 -1
  183. package/dist/src/channels/outbound/persist-store.js +1 -1
  184. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  185. package/dist/src/channels/pairing/pairing-store.js +2 -2
  186. package/dist/src/channels/plugins/types.adapters.d.ts +2 -0
  187. package/dist/src/chat-commands/agent-edit.js +2 -2
  188. package/dist/src/chat-commands/builtins/config.js +2 -2
  189. package/dist/src/chat-commands/context.js +1 -1
  190. package/dist/src/cli/commands/config.js +1 -1
  191. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  192. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  193. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  194. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  195. package/dist/src/cli/commands/extension-create.d.ts +2 -0
  196. package/dist/src/cli/commands/extension-create.js +165 -0
  197. package/dist/src/cli/commands/extension-create.js.map +1 -0
  198. package/dist/src/cli/commands/extension-dev.js +1 -3
  199. package/dist/src/cli/commands/extension-dev.js.map +1 -1
  200. package/dist/src/cli/commands/extension-marketplace.js +105 -81
  201. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  202. package/dist/src/cli/commands/extension-pack.d.ts +13 -0
  203. package/dist/src/cli/commands/extension-pack.js +159 -91
  204. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  205. package/dist/src/cli/commands/extension.d.ts +2 -0
  206. package/dist/src/cli/commands/extension.js +375 -3
  207. package/dist/src/cli/commands/extension.js.map +1 -1
  208. package/dist/src/cli/commands/gateway/logs.js +1 -1
  209. package/dist/src/cli/commands/gateway/run-foreground.js +1 -2
  210. package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
  211. package/dist/src/cli/commands/image.js +1 -1
  212. package/dist/src/cli/commands/init.js +3 -3
  213. package/dist/src/cli/commands/models.js +1 -1
  214. package/dist/src/cli/commands/onboard/model.js +2 -2
  215. package/dist/src/cli/commands/onboard.js +0 -2
  216. package/dist/src/cli/commands/onboard.js.map +1 -1
  217. package/dist/src/cli/commands/setup.js +0 -2
  218. package/dist/src/cli/commands/setup.js.map +1 -1
  219. package/dist/src/cli/utils/init-workspace-core.js +10 -7
  220. package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
  221. package/dist/src/config/agent-profile.js +1 -1
  222. package/dist/src/config/agent-typed-models.js +1 -1
  223. package/dist/src/config/gateway-bind.js +1 -1
  224. package/dist/src/config/index.js +5 -5
  225. package/dist/src/config/loader.js +2 -2
  226. package/dist/src/config/models-json.js +2 -2
  227. package/dist/src/config/paths-state.js +1 -1
  228. package/dist/src/config/paths.d.ts +2 -2
  229. package/dist/src/config/paths.js +6 -5
  230. package/dist/src/config/paths.js.map +1 -1
  231. package/dist/src/config/profile.js +2 -2
  232. package/dist/src/config/schema.d.ts +2 -0
  233. package/dist/src/config/schema.js +3 -1
  234. package/dist/src/config/schema.js.map +1 -1
  235. package/dist/src/config/workspace-path.js +1 -1
  236. package/dist/src/connectors/health.js +1 -1
  237. package/dist/src/connectors/install.js +1 -1
  238. package/dist/src/cron/executor.js +2 -2
  239. package/dist/src/cron/persistence.js +1 -1
  240. package/dist/src/daemon/constants.js +1 -1
  241. package/dist/src/daemon/install-plan.js +2 -2
  242. package/dist/src/daemon/launchd.js +2 -2
  243. package/dist/src/daemon/schtasks.js +2 -2
  244. package/dist/src/daemon/systemd.js +2 -2
  245. package/dist/src/extensions/api.d.ts +4 -2
  246. package/dist/src/extensions/api.js +31 -12
  247. package/dist/src/extensions/api.js.map +1 -1
  248. package/dist/src/extensions/bundle-mcp.js +1 -1
  249. package/dist/src/extensions/discover-extensions.js +2 -1
  250. package/dist/src/extensions/discover-extensions.js.map +1 -1
  251. package/dist/src/extensions/health.js +1 -1
  252. package/dist/src/extensions/install.d.ts +1 -0
  253. package/dist/src/extensions/install.js +51 -8
  254. package/dist/src/extensions/install.js.map +1 -1
  255. package/dist/src/extensions/loader.d.ts +0 -4
  256. package/dist/src/extensions/loader.js +55 -88
  257. package/dist/src/extensions/loader.js.map +1 -1
  258. package/dist/src/extensions/lockfile.d.ts +9 -1
  259. package/dist/src/extensions/lockfile.js +2 -2
  260. package/dist/src/extensions/lockfile.js.map +1 -1
  261. package/dist/src/extensions/normalize-manifest.js +20 -4
  262. package/dist/src/extensions/normalize-manifest.js.map +1 -1
  263. package/dist/src/extensions/package-contract.d.ts +12 -0
  264. package/dist/src/extensions/package-contract.js +59 -0
  265. package/dist/src/extensions/package-contract.js.map +1 -0
  266. package/dist/src/extensions/sdk/core.d.ts +1 -1
  267. package/dist/src/extensions/sdk/index.d.ts +1 -1
  268. package/dist/src/extensions/sdk/index.js.map +1 -1
  269. package/dist/src/extensions/types/manifest.d.ts +15 -0
  270. package/dist/src/extensions/update.js +1 -1
  271. package/dist/src/gateway/agents-admin.d.ts +0 -8
  272. package/dist/src/gateway/agents-admin.js +3 -28
  273. package/dist/src/gateway/agents-admin.js.map +1 -1
  274. package/dist/src/gateway/file-path-classifier.js +2 -2
  275. package/dist/src/gateway/heartbeat/service.js +1 -1
  276. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  277. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  278. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  279. package/dist/src/gateway/hono/oauth-async.js +1 -1
  280. package/dist/src/gateway/hono/oauth.js +1 -1
  281. package/dist/src/gateway/hono/routes/agents.js +2 -56
  282. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  283. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  284. package/dist/src/gateway/hono/routes/channels.js +10 -1
  285. package/dist/src/gateway/hono/routes/channels.js.map +1 -1
  286. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  287. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  288. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  289. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  290. package/dist/src/gateway/hono/routes/models.js +1 -1
  291. package/dist/src/gateway/hono/routes/shares.js +1 -1
  292. package/dist/src/gateway/hono/routes/workflows.js +130 -0
  293. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  294. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  295. package/dist/src/gateway/lock.js +3 -3
  296. package/dist/src/gateway/ports.js +1 -1
  297. package/dist/src/gateway/service/agent-runner.js +2 -2
  298. package/dist/src/gateway/service/marketplace-service.js +2 -2
  299. package/dist/src/gateway/service.d.ts +2 -0
  300. package/dist/src/gateway/service.js +45 -1
  301. package/dist/src/gateway/service.js.map +1 -1
  302. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  303. package/dist/src/heartbeat/index.js +1 -1
  304. package/dist/src/infra/brew.js +1 -1
  305. package/dist/src/infra/package-json.js +1 -1
  306. package/dist/src/infra/package-update-steps.js +1 -1
  307. package/dist/src/infra/path-env.js +2 -2
  308. package/dist/src/infra/restart.js +2 -2
  309. package/dist/src/infra/stable-node-path.js +1 -1
  310. package/dist/src/infra/update-check.js +1 -1
  311. package/dist/src/infra/update-global.js +1 -1
  312. package/dist/src/infra/update-lock.js +3 -3
  313. package/dist/src/infra/update-runner.js +1 -1
  314. package/dist/src/infra/update-startup.js +2 -2
  315. package/dist/src/infra/write-file-atomic.js +2 -2
  316. package/dist/src/media/store.js +1 -1
  317. package/dist/src/notes/agent-context.d.ts +12 -4
  318. package/dist/src/notes/agent-context.js +1 -1
  319. package/dist/src/notes/agent-context.js.map +1 -1
  320. package/dist/src/notes/store.js +2 -2
  321. package/dist/src/project-trust/trust-store.js +2 -2
  322. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  323. package/dist/src/providers/index.js +2 -2
  324. package/dist/src/providers/model-registry.js +1 -1
  325. package/dist/src/session/init-session-turn.js +2 -2
  326. package/dist/src/session/resolve-session.js +3 -3
  327. package/dist/src/session/session-title.js +2 -2
  328. package/dist/src/session/store.js +2 -2
  329. package/dist/src/share/share-auto.js +2 -2
  330. package/dist/src/share/share-store.js +3 -3
  331. package/dist/src/share/share-thumbnail.js +2 -2
  332. package/dist/src/share/share-zip.js +1 -1
  333. package/dist/src/share/site-share-store.js +3 -3
  334. package/dist/src/share/site-static-serve.js +1 -1
  335. package/dist/src/storage/sqlite/connection.js +2 -2
  336. package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
  337. package/dist/src/storage/sqlite/migrations/discover.js +1 -1
  338. package/dist/src/storage/sqlite/migrations/runner.js +1 -1
  339. package/dist/src/storage/sqlite/schema.js +1 -1
  340. package/dist/src/tui/backends/embedded-backend.js +1 -8
  341. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  342. package/dist/src/tui/backends/gateway-sse-backend.js +0 -7
  343. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  344. package/dist/src/tui/clipboard-image.js +3 -3
  345. package/dist/src/tui/theme-manager.js +1 -1
  346. package/dist/src/tui/tui-backend.d.ts +0 -1
  347. package/dist/src/tui/tui-command-formatters.js +3 -3
  348. package/dist/src/tui/tui-commands.js +3 -3
  349. package/dist/src/tui/tui-commands.js.map +1 -1
  350. package/dist/src/tui/tui-keybindings-file.js +1 -1
  351. package/dist/src/tui/tui-picker-overlay.js +1 -1
  352. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  353. package/dist/src/tui/tui-scoped-models.js +2 -2
  354. package/dist/src/tui/tui-settings.js +1 -1
  355. package/dist/src/tui/tui-startup-resources.js +2 -2
  356. package/dist/src/tui/tui.js +5 -5
  357. package/dist/src/tunnel/frpc-binary.js +3 -3
  358. package/dist/src/tunnel/frpc-config.js +1 -1
  359. package/dist/src/tunnel/frpc-extract.js +1 -1
  360. package/dist/src/tunnel/tunnel-state.js +1 -1
  361. package/dist/src/utils/logger/audit.js +1 -1
  362. package/dist/src/utils/logger/log-store.js +1 -1
  363. package/dist/src/utils/logger/rotation.js +1 -1
  364. package/dist/src/voice/stt/availability.d.ts +6 -0
  365. package/dist/src/voice/stt/availability.js +14 -6
  366. package/dist/src/voice/stt/availability.js.map +1 -1
  367. package/dist/src/voice/stt/index.js +2 -1
  368. package/dist/src/voice/stt/index.js.map +1 -1
  369. package/dist/src/voice/stt/mention.d.ts +2 -0
  370. package/dist/src/voice/stt/mention.js +20 -0
  371. package/dist/src/voice/stt/mention.js.map +1 -0
  372. package/dist/src/voice/stt/preflight.d.ts +1 -4
  373. package/dist/src/voice/stt/preflight.js +1 -18
  374. package/dist/src/voice/stt/preflight.js.map +1 -1
  375. package/dist/src/voice/tts/audio.js +1 -1
  376. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  377. package/dist/src/workflows/domain/definition-utils.d.ts +1 -0
  378. package/dist/src/workflows/domain/definition-utils.js +32 -2
  379. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  380. package/dist/src/workflows/domain/definition.d.ts +2 -0
  381. package/dist/src/workflows/domain/event.d.ts +2 -1
  382. package/dist/src/workflows/domain/index.d.ts +1 -0
  383. package/dist/src/workflows/domain/index.js +3 -2
  384. package/dist/src/workflows/domain/run.d.ts +27 -1
  385. package/dist/src/workflows/domain/run.js.map +1 -1
  386. package/dist/src/workflows/domain/schema-validation.d.ts +8 -0
  387. package/dist/src/workflows/domain/schema-validation.js +28 -0
  388. package/dist/src/workflows/domain/schema-validation.js.map +1 -0
  389. package/dist/src/workflows/draft/index.d.ts +3 -0
  390. package/dist/src/workflows/draft/index.js +3 -0
  391. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +23 -0
  392. package/dist/src/workflows/draft/workflow-draft-prompt.js +98 -0
  393. package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -0
  394. package/dist/src/workflows/draft/workflow-draft-service.d.ts +12 -0
  395. package/dist/src/workflows/draft/workflow-draft-service.js +131 -0
  396. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -0
  397. package/dist/src/workflows/draft/workflow-draft-validator.d.ts +4 -0
  398. package/dist/src/workflows/draft/workflow-draft-validator.js +133 -0
  399. package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -0
  400. package/dist/src/workflows/draft/workflow-draft.types.d.ts +44 -0
  401. package/dist/src/workflows/draft/workflow-draft.types.js +1 -0
  402. package/dist/src/workflows/engine/projector.js +1 -0
  403. package/dist/src/workflows/engine/projector.js.map +1 -1
  404. package/dist/src/workflows/engine/workflow-engine.d.ts +18 -0
  405. package/dist/src/workflows/engine/workflow-engine.js +320 -11
  406. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  407. package/dist/src/workflows/index.js +4 -3
  408. package/dist/src/workflows/service/workflow-run-service.d.ts +14 -3
  409. package/dist/src/workflows/service/workflow-run-service.js +227 -6
  410. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  411. package/dist/src/workflows/service/workflow-run-service.types.d.ts +7 -2
  412. package/dist/src/workflows/store/event-store.js +1 -1
  413. package/dist/src/workflows/store/run-store.js +1 -1
  414. package/package.json +5 -3
  415. package/dist/gateway/static/root/assets/agents-XzgIVKcI.js +0 -396
  416. package/dist/gateway/static/root/assets/apps-page-B7Us3RMl.js +0 -1
  417. package/dist/gateway/static/root/assets/channels-settings-BgeV6fzw.js +0 -1
  418. package/dist/gateway/static/root/assets/cron-page-DKGHEeAU.js +0 -1
  419. package/dist/gateway/static/root/assets/index-50FVtgXU.js +0 -4845
  420. package/dist/gateway/static/root/assets/index-BPYKW7FB.css +0 -1
  421. package/dist/gateway/static/root/assets/notes-page-CsWIw35Q.js +0 -1
  422. package/dist/gateway/static/root/assets/sessions-page-CLPsbyOW.js +0 -1
  423. package/dist/gateway/static/root/assets/settings-page-CRGHT_bm.js +0 -3
  424. package/dist/gateway/static/root/assets/skills-page-Ce-RIH2y.js +0 -2
  425. package/dist/gateway/static/root/assets/url-DPEStU4M.js +0 -3
  426. package/dist/gateway/static/root/assets/voice-api-key-field-CJGTidqc.js +0 -1
  427. package/dist/gateway/static/root/assets/workflows-page-o63aaARK.js +0 -27
  428. package/dist/src/agent/builtin-agent-ids.d.ts +0 -2
  429. package/dist/src/agent/builtin-agent-ids.js +0 -17
  430. package/dist/src/agent/builtin-agent-ids.js.map +0 -1
@@ -25,7 +25,7 @@ var ExtensionApiImpl = class {
25
25
  _registeredMediaUnderstandingProviderIds = [];
26
26
  _registeredMarketplaceAdapterIds = [];
27
27
  _manifestCommands = /* @__PURE__ */ new Map();
28
- constructor(id, name, version, source, config, extensionConfig, _logger, _resolvePath, _coreRegistry, runtime) {
28
+ constructor(id, name, version, source, config, extensionConfig, _logger, _resolvePath, _coreRegistry, _contracts = {}, runtime) {
29
29
  this.id = id;
30
30
  this.name = name;
31
31
  this.version = version;
@@ -35,6 +35,7 @@ var ExtensionApiImpl = class {
35
35
  this._logger = _logger;
36
36
  this._resolvePath = _resolvePath;
37
37
  this._coreRegistry = _coreRegistry;
38
+ this._contracts = _contracts;
38
39
  this._typedEventBus = new TypedEventBus({ logger: _logger });
39
40
  this._registry = _coreRegistry ?? new ExtensionRegistryImpl();
40
41
  this._runtime = runtime ?? {
@@ -48,12 +49,23 @@ var ExtensionApiImpl = class {
48
49
  get runtime() {
49
50
  return this._runtime;
50
51
  }
52
+ _assertContract(kind, value) {
53
+ const declared = this._contracts[kind];
54
+ if (!declared?.length) throw new Error(`Extension ${this.id} attempted to register ${kind}:${value}, but manifest contracts.${kind} is missing`);
55
+ if (!declared.some((entry) => {
56
+ if (entry === value) return true;
57
+ if (entry.endsWith("*")) return value.startsWith(entry.slice(0, -1));
58
+ return false;
59
+ })) throw new Error(`Extension ${this.id} attempted to register ${kind}:${value}, but it is not declared in manifest contracts.${kind}`);
60
+ }
51
61
  registerTool(tool) {
62
+ this._assertContract("tools", tool.name);
52
63
  if (this._tools.has(tool.name)) this._logger.warn(`Tool ${tool.name} already registered, overwriting`);
53
64
  this._tools.set(tool.name, tool);
54
65
  this._logger.info(`Registered tool: ${tool.name}`);
55
66
  }
56
67
  registerHook(event, handler, opts) {
68
+ this._assertContract("hooks", event);
57
69
  if (!this._hooks.has(event)) this._hooks.set(event, /* @__PURE__ */ new Set());
58
70
  this._hooks.get(event).add(handler);
59
71
  if (opts?.once) {
@@ -63,6 +75,7 @@ var ExtensionApiImpl = class {
63
75
  };
64
76
  this._hooks.get(event).add(wrapper);
65
77
  }
78
+ this._registry.addHook(event, handler, this.id, opts?.priority ?? 0);
66
79
  this._logger.info(`Registered hook: ${event}`);
67
80
  }
68
81
  /**
@@ -76,6 +89,7 @@ var ExtensionApiImpl = class {
76
89
  * });
77
90
  */
78
91
  onHook(hookName, handler, _opts) {
92
+ this._assertContract("hooks", hookName);
79
93
  const mode = HOOK_EXECUTION_MODES[hookName];
80
94
  if (!this._typedHooks.has(hookName)) this._typedHooks.set(hookName, /* @__PURE__ */ new Set());
81
95
  this._typedHooks.get(hookName).add(handler);
@@ -91,11 +105,14 @@ var ExtensionApiImpl = class {
91
105
  /** Adds a ChannelPlugin to the extension registry; emits `channel:register` for observability. */
92
106
  registerChannel(registration) {
93
107
  const plugin = registration.plugin;
108
+ this._assertContract("channels", plugin.id);
94
109
  this._registry.addChannelPlugin(plugin);
95
110
  this._eventBus.emit("channel:register", plugin);
96
111
  this._logger.info(`Registered channel plugin: ${plugin.id}`);
97
112
  }
98
113
  registerHttpRoute(path, handler) {
114
+ this._assertContract("httpRoutes", path);
115
+ this._registry.addHttpRoute(path, handler);
99
116
  this._eventBus.emit("http:route", {
100
117
  path,
101
118
  handler
@@ -103,6 +120,7 @@ var ExtensionApiImpl = class {
103
120
  this._logger.info(`Registered HTTP route: ${path}`);
104
121
  }
105
122
  registerCommand(command) {
123
+ this._assertContract("commands", command.name);
106
124
  const commandId = `ext.${this.id}.${command.name}`;
107
125
  const definition = {
108
126
  id: commandId,
@@ -145,16 +163,7 @@ var ExtensionApiImpl = class {
145
163
  }
146
164
  onCommand(commandId, handler) {
147
165
  const meta = this._manifestCommands.get(commandId);
148
- if (!meta) {
149
- this._logger.warn(`onCommand: unknown command id "${commandId}" — registering runtime-only chat command`);
150
- const name = commandId.includes(".") ? (commandId.split(".").pop() ?? commandId).trim() : commandId;
151
- this.registerCommand({
152
- name: name || commandId,
153
- description: commandId,
154
- handler
155
- });
156
- return;
157
- }
166
+ if (!meta) throw new Error(`Extension ${this.id} attempted to bind command ${commandId}, but it is not declared in manifest ui.contributions.commands`);
158
167
  let name;
159
168
  if (meta.chatAlias?.trim()) name = meta.chatAlias.trim().replace(/^\//, "");
160
169
  else name = meta.id.includes(".") ? meta.id.split(".").pop() ?? meta.id : meta.id;
@@ -180,10 +189,14 @@ var ExtensionApiImpl = class {
180
189
  this._reloadConfigPrefixes = [...prefixes];
181
190
  }
182
191
  registerService(service) {
192
+ this._assertContract("services", service.id);
193
+ this._registry.addService(service);
183
194
  this._eventBus.emit("service:register", service);
184
195
  this._logger.info(`Registered service: ${service.id}`);
185
196
  }
186
197
  registerGatewayMethod(method, handler) {
198
+ this._assertContract("gatewayMethods", method);
199
+ this._registry.addGatewayMethod(method, handler);
187
200
  this._eventBus.emit("gateway:method", {
188
201
  method,
189
202
  handler
@@ -191,6 +204,7 @@ var ExtensionApiImpl = class {
191
204
  this._logger.info(`Registered gateway method: ${method}`);
192
205
  }
193
206
  registerCli(factory, opts) {
207
+ for (const command of opts?.commands ?? []) this._assertContract("cliCommands", command);
194
208
  const reg = {
195
209
  extensionId: this.id,
196
210
  commands: opts?.commands ?? [],
@@ -219,6 +233,7 @@ var ExtensionApiImpl = class {
219
233
  * Register a full ProviderPlugin
220
234
  */
221
235
  registerProvider(plugin) {
236
+ this._assertContract("providers", plugin.id);
222
237
  import("../providers/plugin-registry.js").then(({ getProviderRegistry }) => {
223
238
  getProviderRegistry().register(plugin);
224
239
  this._logger.info(`Extension registered provider: ${plugin.id}`);
@@ -233,6 +248,7 @@ var ExtensionApiImpl = class {
233
248
  this.registerProvider(plugin);
234
249
  }
235
250
  registerSpeechProvider(plugin) {
251
+ this._assertContract("speechProviders", plugin.id);
236
252
  registerSpeechProvider(plugin);
237
253
  if (!this._registeredSpeechProviderIds.includes(plugin.id)) this._registeredSpeechProviderIds.push(plugin.id);
238
254
  this._logger.info(`Registered speech provider: ${plugin.id}`);
@@ -242,6 +258,7 @@ var ExtensionApiImpl = class {
242
258
  return [...this._registeredSpeechProviderIds];
243
259
  }
244
260
  registerMediaUnderstandingProvider(plugin) {
261
+ this._assertContract("mediaUnderstandingProviders", plugin.id);
245
262
  registerMediaUnderstandingProvider(plugin);
246
263
  if (!this._registeredMediaUnderstandingProviderIds.includes(plugin.id)) this._registeredMediaUnderstandingProviderIds.push(plugin.id);
247
264
  this._logger.info(`Registered media understanding provider: ${plugin.id}`);
@@ -254,8 +271,9 @@ var ExtensionApiImpl = class {
254
271
  * Register a skills marketplace adapter so it appears in the UI provider picker.
255
272
  */
256
273
  registerMarketplaceAdapter(registration) {
257
- registerMarketplaceAdapter(registration);
258
274
  const adapterId = registration.adapter.id;
275
+ this._assertContract("marketplaceAdapters", adapterId);
276
+ registerMarketplaceAdapter(registration);
259
277
  if (!this._registeredMarketplaceAdapterIds.includes(adapterId)) this._registeredMarketplaceAdapterIds.push(adapterId);
260
278
  this._logger.info(`Extension registered marketplace adapter: ${adapterId}`);
261
279
  }
@@ -263,6 +281,7 @@ var ExtensionApiImpl = class {
263
281
  getFlag(_name) {}
264
282
  registerShortcut(_key, _config) {}
265
283
  registerTui(register) {
284
+ this._assertContract("tui", this.id);
266
285
  this._registry.addTuiRegistration(this.id, register);
267
286
  this._logger.info("Registered TUI contributions (deferred until xopc tui starts)");
268
287
  }
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","names":[],"sources":["../../../src/extensions/api.ts"],"sourcesContent":["/**\n * Extension API Implementation\n * \n * Complete extension API with strong typing, security, and provider support.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Command } from 'commander';\nimport type {\n ExtensionApi,\n ExtensionLogger,\n ExtensionRuntime,\n ExtensionCliRegistration,\n GatewayMethodHandler,\n HttpRequestHandler,\n ExtensionCommand,\n ExtensionCommandContext,\n ExtensionCommandHandler,\n ExtensionReloadHandler,\n ExtensionService,\n FlagConfig,\n FlagValue,\n ShortcutConfig,\n HookHandlerMap,\n ExtensionHookEvent,\n HookExecutionMode,\n TuiExtensionRegistrar,\n ExtensionSendUserMessageOptions,\n ExtensionUserMessageContent,\n ExtensionCustomMessage,\n ExtensionSendMessageOptions,\n} from './types/index.js';\nimport type { CommandContribution } from './types/manifest.js';\nimport type { CommandDefinition } from '../chat-commands/types.js';\nimport { commandRegistry } from '../chat-commands/registry.js';\nimport type { ChannelPlugin } from '../channels/plugin-types.js';\nimport {\n HOOK_EXECUTION_MODES,\n} from './types/hooks.js';\nimport type { Config } from '../config/config-surface.js';\nimport type { Config as SchemaConfig } from '../config/schema.js';\nimport { resolve, isAbsolute } from 'path';\nimport { EventEmitter } from 'events';\nimport { createLogger } from '../utils/logger.js';\nimport { TypedEventBus } from './typed-event-bus.js';\nimport { ExtensionRegistryImpl } from './extension-registry-impl.js';\nimport { registerMarketplaceAdapter as _registerMarketplaceAdapter, unregisterMarketplaceAdapter as _unregisterMarketplaceAdapter } from '../agent/skills/marketplace/registry.js';\nimport { registerSpeechProvider as registerSpeechProviderInRegistry } from '../voice/tts/speech-registry.js';\nimport type { SpeechProviderPlugin } from '../voice/tts/speech-provider-types.js';\nimport { registerMediaUnderstandingProvider as registerMediaUnderstandingProviderInRegistry } from '../media-understanding/registry.js';\nimport type { MediaUnderstandingProvider } from '../media-understanding/types.js';\n\nexport class ExtensionApiImpl implements ExtensionApi {\n private _tools: Map<string, AgentTool> = new Map();\n private _hooks: Map<string, Set<Function>> = new Map();\n // Strongly typed hooks (for on() method)\n private _typedHooks: Map<ExtensionHookEvent, Set<Function>> = new Map();\n private _eventBus = new EventEmitter();\n private _typedEventBus: TypedEventBus;\n \n // Unified Registry\n private _registry: ExtensionRegistryImpl;\n\n private readonly _runtime: ExtensionRuntime;\n\n private _reloadConfigPrefixes: string[] = [];\n private _registeredCommandIds: string[] = [];\n private _registeredSpeechProviderIds: string[] = [];\n private _registeredMediaUnderstandingProviderIds: string[] = [];\n private _registeredMarketplaceAdapterIds: string[] = [];\n private readonly _manifestCommands = new Map<string, CommandContribution>();\n\n constructor(\n public readonly id: string,\n public readonly name: string,\n public readonly version: string | undefined,\n public readonly source: string,\n public readonly config: Config,\n public readonly extensionConfig: Record<string, unknown>,\n private readonly _logger: ExtensionLogger,\n private readonly _resolvePath: (input: string) => string,\n private readonly _coreRegistry?: ExtensionRegistryImpl,\n runtime?: ExtensionRuntime,\n ) {\n // Initialize typed event bus\n this._typedEventBus = new TypedEventBus({\n logger: _logger,\n });\n \n this._registry = _coreRegistry ?? new ExtensionRegistryImpl();\n this._runtime =\n runtime ??\n ({\n config: this.config,\n log: this._logger,\n } as ExtensionRuntime);\n }\n\n get logger(): ExtensionLogger {\n return this._logger;\n }\n\n get runtime(): ExtensionRuntime {\n return this._runtime;\n }\n\n registerTool(tool: AgentTool): void {\n if (this._tools.has(tool.name)) {\n this._logger.warn(`Tool ${tool.name} already registered, overwriting`);\n }\n this._tools.set(tool.name, tool);\n this._logger.info(`Registered tool: ${tool.name}`);\n }\n\n registerHook(event: string, handler: Function, opts?: { priority?: number; once?: boolean }): void {\n if (!this._hooks.has(event)) {\n this._hooks.set(event, new Set());\n }\n this._hooks.get(event)!.add(handler);\n\n if (opts?.once) {\n const wrapper = async (...args: unknown[]) => {\n await handler(...args);\n this._hooks.get(event)?.delete(wrapper);\n };\n this._hooks.get(event)!.add(wrapper);\n }\n\n this._logger.info(`Registered hook: ${event}`);\n }\n\n /**\n * Strongly typed hook registration\n * Provides compile-time type checking and IDE autocomplete\n * \n * @example\n * api.on('before_agent_start', async (event, ctx) => {\n * console.log('Agent starting with prompt:', event.prompt);\n * return { systemPrompt: event.systemPrompt };\n * });\n */\n onHook<K extends ExtensionHookEvent>(\n hookName: K,\n handler: HookHandlerMap[K],\n _opts?: { priority?: number },\n ): void {\n // Get execution mode for this hook\n const mode = (HOOK_EXECUTION_MODES as Record<string, HookExecutionMode>)[hookName];\n \n if (!this._typedHooks.has(hookName)) {\n this._typedHooks.set(hookName, new Set());\n }\n \n this._typedHooks.get(hookName)!.add(handler);\n\n this._logger.debug(`Registered typed hook: ${hookName} (mode: ${mode})`);\n }\n\n /**\n * Get typed hooks for a specific event\n */\n _getTypedHooks<K extends ExtensionHookEvent>(hookName: K): HookHandlerMap[K][] {\n const hooks = this._typedHooks.get(hookName);\n return hooks ? Array.from(hooks) as HookHandlerMap[K][] : [];\n }\n\n /** Adds a ChannelPlugin to the extension registry; emits `channel:register` for observability. */\n registerChannel(registration: { plugin: ChannelPlugin }): void {\n const plugin = registration.plugin;\n this._registry.addChannelPlugin(plugin);\n this._eventBus.emit('channel:register', plugin);\n this._logger.info(`Registered channel plugin: ${plugin.id}`);\n }\n\n registerHttpRoute(path: string, handler: HttpRequestHandler): void {\n this._eventBus.emit('http:route', { path, handler });\n this._logger.info(`Registered HTTP route: ${path}`);\n }\n\n registerCommand(command: ExtensionCommand): void {\n const commandId = `ext.${this.id}.${command.name}`;\n\n const definition: CommandDefinition = {\n id: commandId,\n name: command.name,\n aliases: command.aliases,\n description: command.description,\n category: 'extension',\n scope: command.scope ?? ['global'],\n acceptsArgs: command.acceptsArgs,\n examples: command.examples,\n handler: async (ctx, args) => {\n const extensionCtx: ExtensionCommandContext = {\n sessionKey: ctx.sessionKey,\n source: ctx.source,\n isGroup: ctx.isGroup,\n config: ctx.config as SchemaConfig as ExtensionCommandContext['config'],\n reply: (text: string) => ctx.reply(text),\n };\n\n const result = await command.handler(args, extensionCtx);\n\n if (!result) {\n return { content: '', success: true };\n }\n return {\n content: result.content,\n success: result.success ?? true,\n };\n },\n };\n\n commandRegistry.register(definition);\n this._registeredCommandIds.push(commandId);\n this._registry.addCommand(command);\n\n this._eventBus.emit('command:register', command);\n this._logger.info(`Registered chat command: /${command.name}`);\n }\n\n /** Injected from manifest `ui.contributions.commands` by the loader. */\n _setManifestCommands(commands: CommandContribution[]): void {\n this._manifestCommands.clear();\n for (const c of commands) {\n this._manifestCommands.set(c.id, c);\n }\n }\n\n onCommand(commandId: string, handler: ExtensionCommandHandler): void {\n const meta = this._manifestCommands.get(commandId);\n if (!meta) {\n this._logger.warn(\n `onCommand: unknown command id \"${commandId}\" — registering runtime-only chat command`,\n );\n const name = commandId.includes('.')\n ? (commandId.split('.').pop() ?? commandId).trim()\n : commandId;\n this.registerCommand({\n name: name || commandId,\n description: commandId,\n handler,\n });\n return;\n }\n let name: string;\n if (meta.chatAlias?.trim()) {\n name = meta.chatAlias.trim().replace(/^\\//, '');\n } else {\n name = meta.id.includes('.') ? (meta.id.split('.').pop() ?? meta.id) : meta.id;\n }\n if (!name) {\n name = meta.id;\n }\n this.registerCommand({\n name,\n description: meta.title,\n handler,\n });\n this._logger.info(`Bound manifest command \"${commandId}\" as /${name}`);\n }\n\n registerReload(handler: ExtensionReloadHandler): void {\n const prefixes =\n this._reloadConfigPrefixes.length > 0\n ? this._reloadConfigPrefixes\n : [`extensions.${this.id}`];\n\n this._registry.addReloadRegistration({\n extensionId: this.id,\n handler,\n configPrefixes: prefixes,\n });\n this._logger.info('Registered reload handler');\n }\n\n /** Called from loader when manifest declares `reload.configPrefixes`. */\n _setReloadConfigPrefixes(prefixes: string[]): void {\n this._reloadConfigPrefixes = [...prefixes];\n }\n\n registerService(service: ExtensionService): void {\n this._eventBus.emit('service:register', service);\n this._logger.info(`Registered service: ${service.id}`);\n }\n\n registerGatewayMethod(method: string, handler: GatewayMethodHandler): void {\n this._eventBus.emit('gateway:method', { method, handler });\n this._logger.info(`Registered gateway method: ${method}`);\n }\n\n registerCli(\n factory: (ctx: { program: Command }) => void,\n opts?: { commands: string[] },\n ): void {\n const reg: ExtensionCliRegistration = {\n extensionId: this.id,\n commands: opts?.commands ?? [],\n factory,\n };\n this._registry.addCliRegistration(reg);\n this._eventBus.emit('cli:register', reg);\n this._logger.info(\n `Registered CLI factory${opts?.commands?.length ? ` (${opts.commands.join(', ')})` : ''}`,\n );\n }\n\n resolvePath(input: string): string {\n return this._resolvePath(input);\n }\n\n emit(event: string, data: unknown): void {\n this._eventBus.emit(event, data);\n }\n\n on(event: string, handler: (data: unknown) => void): void {\n this._eventBus.on(event, handler);\n }\n\n off(event: string, handler: (data: unknown) => void): void {\n this._eventBus.off(event, handler);\n }\n\n // Typed Event Bus\n get events(): TypedEventBus {\n return this._typedEventBus;\n }\n\n // Unified Registry Methods\n \n /**\n * Register a full ProviderPlugin\n */\n registerProvider(plugin: import('./types/providers.js').ProviderPlugin): void {\n import('../providers/plugin-registry.js').then(({ getProviderRegistry }) => {\n const registry = getProviderRegistry();\n registry.register(plugin);\n this._logger.info(`Extension registered provider: ${plugin.id}`);\n }).catch((err: unknown) => {\n this._logger.error(`Failed to register provider: ${err instanceof Error ? err.message : String(err)}`);\n });\n }\n\n /**\n * Register a full ProviderPlugin (alias for registerProvider)\n */\n registerProviderPlugin(plugin: import('./types/providers.js').ProviderPlugin): void {\n this.registerProvider(plugin);\n }\n\n registerSpeechProvider(plugin: SpeechProviderPlugin): void {\n registerSpeechProviderInRegistry(plugin);\n if (!this._registeredSpeechProviderIds.includes(plugin.id)) {\n this._registeredSpeechProviderIds.push(plugin.id);\n }\n this._logger.info(`Registered speech provider: ${plugin.id}`);\n }\n\n /** Speech provider ids registered through this extension API instance. */\n getRegisteredSpeechProviderIds(): readonly string[] {\n return [...this._registeredSpeechProviderIds];\n }\n\n registerMediaUnderstandingProvider(plugin: MediaUnderstandingProvider): void {\n registerMediaUnderstandingProviderInRegistry(plugin);\n if (!this._registeredMediaUnderstandingProviderIds.includes(plugin.id)) {\n this._registeredMediaUnderstandingProviderIds.push(plugin.id);\n }\n this._logger.info(`Registered media understanding provider: ${plugin.id}`);\n }\n\n /** Media understanding provider ids registered through this extension API instance. */\n getRegisteredMediaUnderstandingProviderIds(): readonly string[] {\n return [...this._registeredMediaUnderstandingProviderIds];\n }\n\n /**\n * Register a skills marketplace adapter so it appears in the UI provider picker.\n */\n registerMarketplaceAdapter(registration: {\n adapter: import('../agent/skills/marketplace/adapter.types.js').SkillsMarketplaceAdapter;\n displayName?: string;\n }): void {\n _registerMarketplaceAdapter(registration);\n const adapterId = registration.adapter.id;\n if (!this._registeredMarketplaceAdapterIds.includes(adapterId)) {\n this._registeredMarketplaceAdapterIds.push(adapterId);\n }\n this._logger.info(`Extension registered marketplace adapter: ${adapterId}`);\n }\n\n registerFlag(_name: string, _config: FlagConfig): void {\n // this._registry.registerFlag(name, config, this.id);\n }\n\n getFlag(_name: string): FlagValue {\n return undefined; // this._registry.getFlag(name);\n }\n\n registerShortcut(_key: string, _config: ShortcutConfig): void {\n // this._registry.registerShortcut(key, config, { extensionId: this.id });\n }\n\n registerTui(register: TuiExtensionRegistrar): void {\n this._registry.addTuiRegistration(this.id, register);\n this._logger.info('Registered TUI contributions (deferred until xopc tui starts)');\n }\n\n setLabel(entryId: string, label: string | undefined): void {\n this._runtime.setLabel?.(entryId, label);\n }\n\n sendUserMessage(\n content: ExtensionUserMessageContent,\n options?: ExtensionSendUserMessageOptions,\n ): void {\n this._runtime.sendUserMessage?.(content, options);\n }\n\n appendEntry<T = unknown>(customType: string, data?: T): void {\n this._runtime.appendEntry?.(customType, data);\n }\n\n sendMessage<T = unknown>(\n message: ExtensionCustomMessage<T>,\n options?: ExtensionSendMessageOptions,\n ): void {\n this._runtime.sendMessage?.(message, options);\n }\n\n // Internal methods for extension manager\n _getTools(): Map<string, AgentTool> {\n return this._tools;\n }\n\n _getHooks(): Map<string, Set<Function>> {\n return this._hooks;\n }\n\n _getEventBus(): EventEmitter {\n return this._eventBus;\n }\n\n _cleanup(): void {\n for (const commandId of this._registeredCommandIds) {\n commandRegistry.unregister(commandId);\n }\n this._registeredCommandIds = [];\n this._manifestCommands.clear();\n\n this._registry.removeReloadRegistration(this.id);\n\n for (const adapterId of this._registeredMarketplaceAdapterIds) {\n _unregisterMarketplaceAdapter(adapterId);\n }\n this._registeredMarketplaceAdapterIds = [];\n\n this._typedEventBus.cleanupAll();\n this._eventBus.removeAllListeners();\n this._hooks.clear();\n this._typedHooks.clear();\n }\n}\n\n// ============================================================================\n// Default Logger\n// ============================================================================\n\nexport function createExtensionLogger(prefix: string): ExtensionLogger {\n const childLogger = createLogger(`Extension:${prefix}`);\n\n return {\n debug: (msg: string) => childLogger.debug(msg),\n info: (msg: string) => childLogger.info(msg),\n warn: (msg: string) => childLogger.warn(msg),\n error: (msg: string) => childLogger.error(msg),\n };\n}\n\n// ============================================================================\n// Path Resolver\n// ============================================================================\n\nexport function createPathResolver(extensionDir: string, workspaceDir: string) {\n return (input: string): string => {\n if (input.startsWith('~')) {\n return input.replace('~', process.env.HOME || '');\n }\n if (input.startsWith('.')) {\n return resolve(extensionDir, input);\n }\n if (!isAbsolute(input)) {\n return resolve(workspaceDir, input);\n }\n return input;\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"api.js","names":[],"sources":["../../../src/extensions/api.ts"],"sourcesContent":["/**\n * Extension API Implementation\n * \n * Complete extension API with strong typing, security, and provider support.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Command } from 'commander';\nimport type {\n ExtensionApi,\n ExtensionLogger,\n ExtensionRuntime,\n ExtensionCliRegistration,\n GatewayMethodHandler,\n HttpRequestHandler,\n ExtensionCommand,\n ExtensionCommandContext,\n ExtensionCommandHandler,\n ExtensionReloadHandler,\n ExtensionService,\n FlagConfig,\n FlagValue,\n ShortcutConfig,\n HookHandlerMap,\n ExtensionHookEvent,\n ExtensionHookHandler,\n HookExecutionMode,\n TuiExtensionRegistrar,\n ExtensionSendUserMessageOptions,\n ExtensionUserMessageContent,\n ExtensionCustomMessage,\n ExtensionSendMessageOptions,\n} from './types/index.js';\nimport type { CommandContribution, ContractDeclaration } from './types/manifest.js';\nimport type { CommandDefinition } from '../chat-commands/types.js';\nimport { commandRegistry } from '../chat-commands/registry.js';\nimport type { ChannelPlugin } from '../channels/plugin-types.js';\nimport {\n HOOK_EXECUTION_MODES,\n} from './types/hooks.js';\nimport type { Config } from '../config/config-surface.js';\nimport type { Config as SchemaConfig } from '../config/schema.js';\nimport { resolve, isAbsolute } from 'path';\nimport { EventEmitter } from 'events';\nimport { createLogger } from '../utils/logger.js';\nimport { TypedEventBus } from './typed-event-bus.js';\nimport { ExtensionRegistryImpl } from './extension-registry-impl.js';\nimport { registerMarketplaceAdapter as _registerMarketplaceAdapter, unregisterMarketplaceAdapter as _unregisterMarketplaceAdapter } from '../agent/skills/marketplace/registry.js';\nimport { registerSpeechProvider as registerSpeechProviderInRegistry } from '../voice/tts/speech-registry.js';\nimport type { SpeechProviderPlugin } from '../voice/tts/speech-provider-types.js';\nimport { registerMediaUnderstandingProvider as registerMediaUnderstandingProviderInRegistry } from '../media-understanding/registry.js';\nimport type { MediaUnderstandingProvider } from '../media-understanding/types.js';\n\nexport class ExtensionApiImpl implements ExtensionApi {\n private _tools: Map<string, AgentTool> = new Map();\n private _hooks: Map<string, Set<Function>> = new Map();\n // Strongly typed hooks (for on() method)\n private _typedHooks: Map<ExtensionHookEvent, Set<Function>> = new Map();\n private _eventBus = new EventEmitter();\n private _typedEventBus: TypedEventBus;\n \n // Unified Registry\n private _registry: ExtensionRegistryImpl;\n\n private readonly _runtime: ExtensionRuntime;\n\n private _reloadConfigPrefixes: string[] = [];\n private _registeredCommandIds: string[] = [];\n private _registeredSpeechProviderIds: string[] = [];\n private _registeredMediaUnderstandingProviderIds: string[] = [];\n private _registeredMarketplaceAdapterIds: string[] = [];\n private readonly _manifestCommands = new Map<string, CommandContribution>();\n\n constructor(\n public readonly id: string,\n public readonly name: string,\n public readonly version: string | undefined,\n public readonly source: string,\n public readonly config: Config,\n public readonly extensionConfig: Record<string, unknown>,\n private readonly _logger: ExtensionLogger,\n private readonly _resolvePath: (input: string) => string,\n private readonly _coreRegistry?: ExtensionRegistryImpl,\n private readonly _contracts: ContractDeclaration = {},\n runtime?: ExtensionRuntime,\n ) {\n // Initialize typed event bus\n this._typedEventBus = new TypedEventBus({\n logger: _logger,\n });\n \n this._registry = _coreRegistry ?? new ExtensionRegistryImpl();\n this._runtime =\n runtime ??\n ({\n config: this.config,\n log: this._logger,\n } as ExtensionRuntime);\n }\n\n get logger(): ExtensionLogger {\n return this._logger;\n }\n\n get runtime(): ExtensionRuntime {\n return this._runtime;\n }\n\n private _assertContract(kind: keyof ContractDeclaration, value: string): void {\n const declared = this._contracts[kind];\n if (!declared?.length) {\n throw new Error(\n `Extension ${this.id} attempted to register ${kind}:${value}, but manifest contracts.${kind} is missing`,\n );\n }\n const allowed = declared.some((entry) => {\n if (entry === value) return true;\n if (entry.endsWith('*')) return value.startsWith(entry.slice(0, -1));\n return false;\n });\n if (!allowed) {\n throw new Error(\n `Extension ${this.id} attempted to register ${kind}:${value}, but it is not declared in manifest contracts.${kind}`,\n );\n }\n }\n\n registerTool(tool: AgentTool): void {\n this._assertContract('tools', tool.name);\n if (this._tools.has(tool.name)) {\n this._logger.warn(`Tool ${tool.name} already registered, overwriting`);\n }\n this._tools.set(tool.name, tool);\n this._logger.info(`Registered tool: ${tool.name}`);\n }\n\n registerHook(event: string, handler: Function, opts?: { priority?: number; once?: boolean }): void {\n this._assertContract('hooks', event);\n if (!this._hooks.has(event)) {\n this._hooks.set(event, new Set());\n }\n this._hooks.get(event)!.add(handler);\n\n if (opts?.once) {\n const wrapper = async (...args: unknown[]) => {\n await handler(...args);\n this._hooks.get(event)?.delete(wrapper);\n };\n this._hooks.get(event)!.add(wrapper);\n }\n\n this._registry.addHook(event as ExtensionHookEvent, handler as ExtensionHookHandler, this.id, opts?.priority ?? 0);\n this._logger.info(`Registered hook: ${event}`);\n }\n\n /**\n * Strongly typed hook registration\n * Provides compile-time type checking and IDE autocomplete\n * \n * @example\n * api.on('before_agent_start', async (event, ctx) => {\n * console.log('Agent starting with prompt:', event.prompt);\n * return { systemPrompt: event.systemPrompt };\n * });\n */\n onHook<K extends ExtensionHookEvent>(\n hookName: K,\n handler: HookHandlerMap[K],\n _opts?: { priority?: number },\n ): void {\n this._assertContract('hooks', hookName);\n // Get execution mode for this hook\n const mode = (HOOK_EXECUTION_MODES as Record<string, HookExecutionMode>)[hookName];\n \n if (!this._typedHooks.has(hookName)) {\n this._typedHooks.set(hookName, new Set());\n }\n \n this._typedHooks.get(hookName)!.add(handler);\n\n this._logger.debug(`Registered typed hook: ${hookName} (mode: ${mode})`);\n }\n\n /**\n * Get typed hooks for a specific event\n */\n _getTypedHooks<K extends ExtensionHookEvent>(hookName: K): HookHandlerMap[K][] {\n const hooks = this._typedHooks.get(hookName);\n return hooks ? Array.from(hooks) as HookHandlerMap[K][] : [];\n }\n\n /** Adds a ChannelPlugin to the extension registry; emits `channel:register` for observability. */\n registerChannel(registration: { plugin: ChannelPlugin }): void {\n const plugin = registration.plugin;\n this._assertContract('channels', plugin.id);\n this._registry.addChannelPlugin(plugin);\n this._eventBus.emit('channel:register', plugin);\n this._logger.info(`Registered channel plugin: ${plugin.id}`);\n }\n\n registerHttpRoute(path: string, handler: HttpRequestHandler): void {\n this._assertContract('httpRoutes', path);\n this._registry.addHttpRoute(path, handler);\n this._eventBus.emit('http:route', { path, handler });\n this._logger.info(`Registered HTTP route: ${path}`);\n }\n\n registerCommand(command: ExtensionCommand): void {\n this._assertContract('commands', command.name);\n const commandId = `ext.${this.id}.${command.name}`;\n\n const definition: CommandDefinition = {\n id: commandId,\n name: command.name,\n aliases: command.aliases,\n description: command.description,\n category: 'extension',\n scope: command.scope ?? ['global'],\n acceptsArgs: command.acceptsArgs,\n examples: command.examples,\n handler: async (ctx, args) => {\n const extensionCtx: ExtensionCommandContext = {\n sessionKey: ctx.sessionKey,\n source: ctx.source,\n isGroup: ctx.isGroup,\n config: ctx.config as SchemaConfig as ExtensionCommandContext['config'],\n reply: (text: string) => ctx.reply(text),\n };\n\n const result = await command.handler(args, extensionCtx);\n\n if (!result) {\n return { content: '', success: true };\n }\n return {\n content: result.content,\n success: result.success ?? true,\n };\n },\n };\n\n commandRegistry.register(definition);\n this._registeredCommandIds.push(commandId);\n this._registry.addCommand(command);\n\n this._eventBus.emit('command:register', command);\n this._logger.info(`Registered chat command: /${command.name}`);\n }\n\n /** Injected from manifest `ui.contributions.commands` by the loader. */\n _setManifestCommands(commands: CommandContribution[]): void {\n this._manifestCommands.clear();\n for (const c of commands) {\n this._manifestCommands.set(c.id, c);\n }\n }\n\n onCommand(commandId: string, handler: ExtensionCommandHandler): void {\n const meta = this._manifestCommands.get(commandId);\n if (!meta) {\n throw new Error(\n `Extension ${this.id} attempted to bind command ${commandId}, but it is not declared in manifest ui.contributions.commands`,\n );\n }\n let name: string;\n if (meta.chatAlias?.trim()) {\n name = meta.chatAlias.trim().replace(/^\\//, '');\n } else {\n name = meta.id.includes('.') ? (meta.id.split('.').pop() ?? meta.id) : meta.id;\n }\n if (!name) {\n name = meta.id;\n }\n this.registerCommand({\n name,\n description: meta.title,\n handler,\n });\n this._logger.info(`Bound manifest command \"${commandId}\" as /${name}`);\n }\n\n registerReload(handler: ExtensionReloadHandler): void {\n const prefixes =\n this._reloadConfigPrefixes.length > 0\n ? this._reloadConfigPrefixes\n : [`extensions.${this.id}`];\n\n this._registry.addReloadRegistration({\n extensionId: this.id,\n handler,\n configPrefixes: prefixes,\n });\n this._logger.info('Registered reload handler');\n }\n\n /** Called from loader when manifest declares `reload.configPrefixes`. */\n _setReloadConfigPrefixes(prefixes: string[]): void {\n this._reloadConfigPrefixes = [...prefixes];\n }\n\n registerService(service: ExtensionService): void {\n this._assertContract('services', service.id);\n this._registry.addService(service);\n this._eventBus.emit('service:register', service);\n this._logger.info(`Registered service: ${service.id}`);\n }\n\n registerGatewayMethod(method: string, handler: GatewayMethodHandler): void {\n this._assertContract('gatewayMethods', method);\n this._registry.addGatewayMethod(method, handler);\n this._eventBus.emit('gateway:method', { method, handler });\n this._logger.info(`Registered gateway method: ${method}`);\n }\n\n registerCli(\n factory: (ctx: { program: Command }) => void,\n opts?: { commands: string[] },\n ): void {\n for (const command of opts?.commands ?? []) {\n this._assertContract('cliCommands', command);\n }\n const reg: ExtensionCliRegistration = {\n extensionId: this.id,\n commands: opts?.commands ?? [],\n factory,\n };\n this._registry.addCliRegistration(reg);\n this._eventBus.emit('cli:register', reg);\n this._logger.info(\n `Registered CLI factory${opts?.commands?.length ? ` (${opts.commands.join(', ')})` : ''}`,\n );\n }\n\n resolvePath(input: string): string {\n return this._resolvePath(input);\n }\n\n emit(event: string, data: unknown): void {\n this._eventBus.emit(event, data);\n }\n\n on(event: string, handler: (data: unknown) => void): void {\n this._eventBus.on(event, handler);\n }\n\n off(event: string, handler: (data: unknown) => void): void {\n this._eventBus.off(event, handler);\n }\n\n // Typed Event Bus\n get events(): TypedEventBus {\n return this._typedEventBus;\n }\n\n // Unified Registry Methods\n \n /**\n * Register a full ProviderPlugin\n */\n registerProvider(plugin: import('./types/providers.js').ProviderPlugin): void {\n this._assertContract('providers', plugin.id);\n import('../providers/plugin-registry.js').then(({ getProviderRegistry }) => {\n const registry = getProviderRegistry();\n registry.register(plugin);\n this._logger.info(`Extension registered provider: ${plugin.id}`);\n }).catch((err: unknown) => {\n this._logger.error(`Failed to register provider: ${err instanceof Error ? err.message : String(err)}`);\n });\n }\n\n /**\n * Register a full ProviderPlugin (alias for registerProvider)\n */\n registerProviderPlugin(plugin: import('./types/providers.js').ProviderPlugin): void {\n this.registerProvider(plugin);\n }\n\n registerSpeechProvider(plugin: SpeechProviderPlugin): void {\n this._assertContract('speechProviders', plugin.id);\n registerSpeechProviderInRegistry(plugin);\n if (!this._registeredSpeechProviderIds.includes(plugin.id)) {\n this._registeredSpeechProviderIds.push(plugin.id);\n }\n this._logger.info(`Registered speech provider: ${plugin.id}`);\n }\n\n /** Speech provider ids registered through this extension API instance. */\n getRegisteredSpeechProviderIds(): readonly string[] {\n return [...this._registeredSpeechProviderIds];\n }\n\n registerMediaUnderstandingProvider(plugin: MediaUnderstandingProvider): void {\n this._assertContract('mediaUnderstandingProviders', plugin.id);\n registerMediaUnderstandingProviderInRegistry(plugin);\n if (!this._registeredMediaUnderstandingProviderIds.includes(plugin.id)) {\n this._registeredMediaUnderstandingProviderIds.push(plugin.id);\n }\n this._logger.info(`Registered media understanding provider: ${plugin.id}`);\n }\n\n /** Media understanding provider ids registered through this extension API instance. */\n getRegisteredMediaUnderstandingProviderIds(): readonly string[] {\n return [...this._registeredMediaUnderstandingProviderIds];\n }\n\n /**\n * Register a skills marketplace adapter so it appears in the UI provider picker.\n */\n registerMarketplaceAdapter(registration: {\n adapter: import('../agent/skills/marketplace/adapter.types.js').SkillsMarketplaceAdapter;\n displayName?: string;\n }): void {\n const adapterId = registration.adapter.id;\n this._assertContract('marketplaceAdapters', adapterId);\n _registerMarketplaceAdapter(registration);\n if (!this._registeredMarketplaceAdapterIds.includes(adapterId)) {\n this._registeredMarketplaceAdapterIds.push(adapterId);\n }\n this._logger.info(`Extension registered marketplace adapter: ${adapterId}`);\n }\n\n registerFlag(_name: string, _config: FlagConfig): void {\n // this._registry.registerFlag(name, config, this.id);\n }\n\n getFlag(_name: string): FlagValue {\n return undefined; // this._registry.getFlag(name);\n }\n\n registerShortcut(_key: string, _config: ShortcutConfig): void {\n // this._registry.registerShortcut(key, config, { extensionId: this.id });\n }\n\n registerTui(register: TuiExtensionRegistrar): void {\n this._assertContract('tui', this.id);\n this._registry.addTuiRegistration(this.id, register);\n this._logger.info('Registered TUI contributions (deferred until xopc tui starts)');\n }\n\n setLabel(entryId: string, label: string | undefined): void {\n this._runtime.setLabel?.(entryId, label);\n }\n\n sendUserMessage(\n content: ExtensionUserMessageContent,\n options?: ExtensionSendUserMessageOptions,\n ): void {\n this._runtime.sendUserMessage?.(content, options);\n }\n\n appendEntry<T = unknown>(customType: string, data?: T): void {\n this._runtime.appendEntry?.(customType, data);\n }\n\n sendMessage<T = unknown>(\n message: ExtensionCustomMessage<T>,\n options?: ExtensionSendMessageOptions,\n ): void {\n this._runtime.sendMessage?.(message, options);\n }\n\n // Internal methods for extension manager\n _getTools(): Map<string, AgentTool> {\n return this._tools;\n }\n\n _getHooks(): Map<string, Set<Function>> {\n return this._hooks;\n }\n\n _getEventBus(): EventEmitter {\n return this._eventBus;\n }\n\n _cleanup(): void {\n for (const commandId of this._registeredCommandIds) {\n commandRegistry.unregister(commandId);\n }\n this._registeredCommandIds = [];\n this._manifestCommands.clear();\n\n this._registry.removeReloadRegistration(this.id);\n\n for (const adapterId of this._registeredMarketplaceAdapterIds) {\n _unregisterMarketplaceAdapter(adapterId);\n }\n this._registeredMarketplaceAdapterIds = [];\n\n this._typedEventBus.cleanupAll();\n this._eventBus.removeAllListeners();\n this._hooks.clear();\n this._typedHooks.clear();\n }\n}\n\n// ============================================================================\n// Default Logger\n// ============================================================================\n\nexport function createExtensionLogger(prefix: string): ExtensionLogger {\n const childLogger = createLogger(`Extension:${prefix}`);\n\n return {\n debug: (msg: string) => childLogger.debug(msg),\n info: (msg: string) => childLogger.info(msg),\n warn: (msg: string) => childLogger.warn(msg),\n error: (msg: string) => childLogger.error(msg),\n };\n}\n\n// ============================================================================\n// Path Resolver\n// ============================================================================\n\nexport function createPathResolver(extensionDir: string, workspaceDir: string) {\n return (input: string): string => {\n if (input.startsWith('~')) {\n return input.replace('~', process.env.HOME || '');\n }\n if (input.startsWith('.')) {\n return resolve(extensionDir, input);\n }\n if (!isAbsolute(input)) {\n return resolve(workspaceDir, input);\n }\n return input;\n };\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir } from "../config/paths.js";
2
2
  import { isRecord } from "../utils/is-record.js";
3
3
  import { normalizeConfiguredMcpServers } from "../config/mcp-config-normalize.js";
4
- import { existsSync, readFileSync, readdirSync } from "node:fs";
5
4
  import { join } from "node:path";
5
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
6
6
  //#region src/extensions/bundle-mcp.ts
7
7
  init_paths();
8
8
  function extractMcpServerMap(raw) {
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
+ import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
2
3
  import { createLogger } from "../utils/logger/index.js";
3
4
  import { init_logger } from "../utils/logger.js";
4
- import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
5
5
  import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir, resolveWorkspaceExtensionsDir } from "../config/paths.js";
6
6
  import { init_normalize_manifest, normalizeExtensionManifest } from "./normalize-manifest.js";
7
7
  import { join } from "path";
@@ -127,6 +127,7 @@ function discoverExtensionsFromDisk(options = {}, config) {
127
127
  const discovered = /* @__PURE__ */ new Map();
128
128
  const paths = resolveDiscoveryPaths(options, config);
129
129
  if (paths.bundledDir) discoverInDirectory(paths.bundledDir, "bundled", discovered);
130
+ if (process.env.XOPC_BUNDLED_EXTENSIONS_ROOT || paths.bundledDir?.includes(`${join("dist", "electron", "extensions")}`)) return Array.from(discovered.values());
130
131
  discoverInDirectory(paths.globalDir, "global", discovered);
131
132
  if (paths.workspaceExtensionsDir) discoverInDirectory(paths.workspaceExtensionsDir, "workspace", discovered);
132
133
  return Array.from(discovered.values());
@@ -1 +1 @@
1
- {"version":3,"file":"discover-extensions.js","names":[],"sources":["../../../src/extensions/discover-extensions.ts"],"sourcesContent":["/**\n * Filesystem-only extension discovery (manifest parse, no module load).\n */\n\nimport { existsSync, readdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\n\nimport { resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport type { Config } from '../config/schema.js';\nimport {\n resolveBundledExtensionsDir,\n resolveExtensionsDir,\n resolveWorkspaceExtensionsDir,\n} from '../config/paths.js';\nimport { createLogger } from '../utils/logger.js';\nimport { normalizeExtensionManifest } from './normalize-manifest.js';\nimport type { ExtensionManifest } from './types/manifest.js';\nimport type { DiscoveredExtension } from './types/loader.js';\n\n/** App config slice used for discovery (any loaded config shape). */\nexport type DiscoverConfig = Record<string, unknown>;\n\nfunction asSchemaConfig(config: DiscoverConfig): Config {\n return config as Config;\n}\n\nconst EXTENSION_MANIFEST_FILE = 'xopc.extension.json';\n\nconst log = createLogger('ExtensionDiscover');\n\nexport type ExtensionSourceOrigin = 'workspace' | 'global' | 'bundled' | 'config';\n\nexport interface ExtensionLoaderOptions {\n workspaceDir?: string;\n extensionsDir?: string;\n workspaceExtensionsDir?: string;\n bundledExtensions?: string[];\n}\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nfunction loadManifest(extensionPath: string): ExtensionManifest | null {\n const manifestPath = join(extensionPath, EXTENSION_MANIFEST_FILE);\n\n if (existsSync(manifestPath)) {\n try {\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n log.error({ manifestPath }, 'Manifest root must be a JSON object');\n return null;\n }\n return normalizeExtensionManifest(raw as Record<string, unknown>);\n } catch (error) {\n log.error({ err: error, manifestPath }, 'Failed to parse manifest');\n return null;\n }\n }\n\n const packagePath = join(extensionPath, 'package.json');\n if (existsSync(packagePath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));\n\n if (packageJson.xopc?.extension) {\n const xopcConfig = packageJson.xopc;\n return normalizeExtensionManifest({\n id: xopcConfig.id || packageJson.name,\n name: xopcConfig.name || packageJson.name,\n description: xopcConfig.description || packageJson.description,\n version: xopcConfig.version || packageJson.version || '1.0.0',\n kind: xopcConfig.kind || 'utility',\n main: xopcConfig.main || packageJson.main || 'index.js',\n configSchema: xopcConfig.configSchema,\n });\n }\n\n if (packageJson.name?.startsWith('xopc-extension-')) {\n const id = packageJson.name.replace('xopc-extension-', '');\n return normalizeExtensionManifest({\n id,\n name: packageJson.name,\n description: packageJson.description,\n version: packageJson.version || '1.0.0',\n kind: 'utility',\n main: packageJson.main || 'index.js',\n });\n }\n } catch (error) {\n log.error({ err: error, packagePath }, 'Failed to parse package.json');\n }\n }\n\n return null;\n}\n\nfunction discoverInDirectory(\n dir: string,\n source: ExtensionSourceOrigin,\n discovered: Map<string, DiscoveredExtension>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const extensionPath = join(dir, entry);\n\n try {\n if (!existsSync(extensionPath)) continue;\n } catch {\n continue;\n }\n\n const manifest = loadManifest(extensionPath);\n if (!manifest) continue;\n\n const extensionId = manifest.id || entry;\n\n const existing = discovered.get(extensionId);\n if (existing) {\n const priority = { workspace: 3, global: 2, bundled: 1, config: 0 };\n if (priority[source] <= priority[existing.source]) {\n log.debug(\n { extensionId, from: source, existing: existing.source },\n 'Skipping lower priority extension',\n );\n continue;\n }\n log.info(\n { extensionId, from: source, overriding: existing.source },\n 'Extension override by higher priority source',\n );\n }\n\n discovered.set(extensionId, {\n id: extensionId,\n path: extensionPath,\n source,\n manifest,\n });\n }\n}\n\nfunction resolveDiscoveryPaths(\n options: ExtensionLoaderOptions,\n config?: DiscoverConfig,\n): {\n bundledDir: string | null;\n globalDir: string;\n workspaceExtensionsDir: string | null;\n} {\n const cfg = config ? asSchemaConfig(config) : null;\n const aid = cfg ? resolveDefaultAgentId(cfg) : null;\n\n return {\n bundledDir: resolveBundledExtensionsDir(),\n globalDir: options.extensionsDir ?? resolveExtensionsDir(),\n workspaceExtensionsDir:\n options.workspaceExtensionsDir ??\n (cfg && aid ? resolveWorkspaceExtensionsDir(cfg, aid) : null),\n };\n}\n\n/**\n * Discover extensions from workspace, global, and bundled tiers without loading code.\n */\nexport function discoverExtensionsFromDisk(\n options: ExtensionLoaderOptions = {},\n config?: DiscoverConfig,\n): DiscoveredExtension[] {\n const discovered = new Map<string, DiscoveredExtension>();\n const paths = resolveDiscoveryPaths(options, config);\n\n if (paths.bundledDir) {\n discoverInDirectory(paths.bundledDir, 'bundled', discovered);\n }\n\n discoverInDirectory(paths.globalDir, 'global', discovered);\n if (paths.workspaceExtensionsDir) {\n discoverInDirectory(paths.workspaceExtensionsDir, 'workspace', discovered);\n }\n\n return Array.from(discovered.values());\n}\n\n/** True when extension discovery/load should be skipped entirely. */\nexport function areExtensionsGloballyDisabled(config?: DiscoverConfig): boolean {\n if (\n process.env.XOPC_SKIP_EXTENSIONS === '1' ||\n process.env.XOPC_SKIP_EXTENSIONS === 'true'\n ) {\n return true;\n }\n\n const ext =\n config && isRecord(config) && isRecord((config as Record<string, unknown>).extensions)\n ? ((config as Record<string, unknown>).extensions as Record<string, unknown>)\n : undefined;\n\n return ext?.enabled === false;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"discover-extensions.js","names":[],"sources":["../../../src/extensions/discover-extensions.ts"],"sourcesContent":["/**\n * Filesystem-only extension discovery (manifest parse, no module load).\n */\n\nimport { existsSync, readdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\n\nimport { resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport type { Config } from '../config/schema.js';\nimport {\n resolveBundledExtensionsDir,\n resolveExtensionsDir,\n resolveWorkspaceExtensionsDir,\n} from '../config/paths.js';\nimport { createLogger } from '../utils/logger.js';\nimport { normalizeExtensionManifest } from './normalize-manifest.js';\nimport type { ExtensionManifest } from './types/manifest.js';\nimport type { DiscoveredExtension } from './types/loader.js';\n\n/** App config slice used for discovery (any loaded config shape). */\nexport type DiscoverConfig = Record<string, unknown>;\n\nfunction asSchemaConfig(config: DiscoverConfig): Config {\n return config as Config;\n}\n\nconst EXTENSION_MANIFEST_FILE = 'xopc.extension.json';\n\nconst log = createLogger('ExtensionDiscover');\n\nexport type ExtensionSourceOrigin = 'workspace' | 'global' | 'bundled' | 'config';\n\nexport interface ExtensionLoaderOptions {\n workspaceDir?: string;\n extensionsDir?: string;\n workspaceExtensionsDir?: string;\n bundledExtensions?: string[];\n}\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nfunction loadManifest(extensionPath: string): ExtensionManifest | null {\n const manifestPath = join(extensionPath, EXTENSION_MANIFEST_FILE);\n\n if (existsSync(manifestPath)) {\n try {\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n log.error({ manifestPath }, 'Manifest root must be a JSON object');\n return null;\n }\n return normalizeExtensionManifest(raw as Record<string, unknown>);\n } catch (error) {\n log.error({ err: error, manifestPath }, 'Failed to parse manifest');\n return null;\n }\n }\n\n const packagePath = join(extensionPath, 'package.json');\n if (existsSync(packagePath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));\n\n if (packageJson.xopc?.extension) {\n const xopcConfig = packageJson.xopc;\n return normalizeExtensionManifest({\n id: xopcConfig.id || packageJson.name,\n name: xopcConfig.name || packageJson.name,\n description: xopcConfig.description || packageJson.description,\n version: xopcConfig.version || packageJson.version || '1.0.0',\n kind: xopcConfig.kind || 'utility',\n main: xopcConfig.main || packageJson.main || 'index.js',\n configSchema: xopcConfig.configSchema,\n });\n }\n\n if (packageJson.name?.startsWith('xopc-extension-')) {\n const id = packageJson.name.replace('xopc-extension-', '');\n return normalizeExtensionManifest({\n id,\n name: packageJson.name,\n description: packageJson.description,\n version: packageJson.version || '1.0.0',\n kind: 'utility',\n main: packageJson.main || 'index.js',\n });\n }\n } catch (error) {\n log.error({ err: error, packagePath }, 'Failed to parse package.json');\n }\n }\n\n return null;\n}\n\nfunction discoverInDirectory(\n dir: string,\n source: ExtensionSourceOrigin,\n discovered: Map<string, DiscoveredExtension>,\n): void {\n if (!existsSync(dir)) {\n return;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const extensionPath = join(dir, entry);\n\n try {\n if (!existsSync(extensionPath)) continue;\n } catch {\n continue;\n }\n\n const manifest = loadManifest(extensionPath);\n if (!manifest) continue;\n\n const extensionId = manifest.id || entry;\n\n const existing = discovered.get(extensionId);\n if (existing) {\n const priority = { workspace: 3, global: 2, bundled: 1, config: 0 };\n if (priority[source] <= priority[existing.source]) {\n log.debug(\n { extensionId, from: source, existing: existing.source },\n 'Skipping lower priority extension',\n );\n continue;\n }\n log.info(\n { extensionId, from: source, overriding: existing.source },\n 'Extension override by higher priority source',\n );\n }\n\n discovered.set(extensionId, {\n id: extensionId,\n path: extensionPath,\n source,\n manifest,\n });\n }\n}\n\nfunction resolveDiscoveryPaths(\n options: ExtensionLoaderOptions,\n config?: DiscoverConfig,\n): {\n bundledDir: string | null;\n globalDir: string;\n workspaceExtensionsDir: string | null;\n} {\n const cfg = config ? asSchemaConfig(config) : null;\n const aid = cfg ? resolveDefaultAgentId(cfg) : null;\n\n return {\n bundledDir: resolveBundledExtensionsDir(),\n globalDir: options.extensionsDir ?? resolveExtensionsDir(),\n workspaceExtensionsDir:\n options.workspaceExtensionsDir ??\n (cfg && aid ? resolveWorkspaceExtensionsDir(cfg, aid) : null),\n };\n}\n\n/**\n * Discover extensions from workspace, global, and bundled tiers without loading code.\n */\nexport function discoverExtensionsFromDisk(\n options: ExtensionLoaderOptions = {},\n config?: DiscoverConfig,\n): DiscoveredExtension[] {\n const discovered = new Map<string, DiscoveredExtension>();\n const paths = resolveDiscoveryPaths(options, config);\n\n if (paths.bundledDir) {\n discoverInDirectory(paths.bundledDir, 'bundled', discovered);\n }\n\n // Electron ships self-contained extension bundles. Do not let stale user/global source\n // extensions override those packaged manifests.\n if (process.env.XOPC_BUNDLED_EXTENSIONS_ROOT || paths.bundledDir?.includes(`${join('dist', 'electron', 'extensions')}`)) {\n return Array.from(discovered.values());\n }\n\n discoverInDirectory(paths.globalDir, 'global', discovered);\n if (paths.workspaceExtensionsDir) {\n discoverInDirectory(paths.workspaceExtensionsDir, 'workspace', discovered);\n }\n\n return Array.from(discovered.values());\n}\n\n/** True when extension discovery/load should be skipped entirely. */\nexport function areExtensionsGloballyDisabled(config?: DiscoverConfig): boolean {\n if (\n process.env.XOPC_SKIP_EXTENSIONS === '1' ||\n process.env.XOPC_SKIP_EXTENSIONS === 'true'\n ) {\n return true;\n }\n\n const ext =\n config && isRecord(config) && isRecord((config as Record<string, unknown>).extensions)\n ? ((config as Record<string, unknown>).extensions as Record<string, unknown>)\n : undefined;\n\n return ext?.enabled === false;\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveExtensionsDir } from "../config/paths.js";
2
2
  import { getExtensionLockfileManager } from "./lockfile.js";
3
- import { readFile, readdir } from "fs/promises";
4
3
  import { join } from "path";
5
4
  import { existsSync } from "fs";
5
+ import { readFile, readdir } from "fs/promises";
6
6
  //#region src/extensions/health.ts
7
7
  init_paths();
8
8
  var ExtensionHealthChecker = class {
@@ -24,6 +24,7 @@ export interface ListedExtension {
24
24
  path: string;
25
25
  origin: 'workspace' | 'global' | 'bundled';
26
26
  }
27
+ export declare function peekExtensionManifestFromStoreZip(buffer: Buffer): Record<string, unknown> | undefined;
27
28
  /** Read `id` from the shallowest xopc.extension.json in a store zip (for --force / preflight). */
28
29
  export declare function peekExtensionIdFromStoreZip(buffer: Buffer): string | undefined;
29
30
  /**
@@ -1,6 +1,9 @@
1
+ import { PACKAGE_VERSION, init_package_version } from "../package-version.js";
1
2
  import { createLogger } from "../utils/logger/index.js";
2
3
  import { init_logger } from "../utils/logger.js";
3
4
  import { init_paths, resolveBundledExtensionsDir, resolveExtensionsDir as resolveExtensionsDir$1 } from "../config/paths.js";
5
+ import { checkEngineCompatibility } from "./engine-check.js";
6
+ import { collectExtensionPackageDependencyIssues } from "./package-contract.js";
4
7
  import { MAX_EXTENSION_STORE_ZIP_BYTES } from "./store-zip-limits.js";
5
8
  import { dirname, isAbsolute, join, resolve, sep } from "path";
6
9
  import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs";
@@ -14,6 +17,7 @@ import AdmZip from "adm-zip";
14
17
  * Supports three-tier storage: workspace, global, bundled
15
18
  */
16
19
  init_paths();
20
+ init_package_version();
17
21
  init_logger();
18
22
  const log = createLogger("ExtensionInstall");
19
23
  const NPM_INSTALL_ENV = process.env.XOPC_EXTENSION_NPM_INSTALL?.trim().toLowerCase();
@@ -111,8 +115,7 @@ function inferExtensionStripPrefix(primaryManifestPath) {
111
115
  if (!lower.endsWith(suff)) return "";
112
116
  return norm.slice(0, norm.length - 19);
113
117
  }
114
- /** Read `id` from the shallowest xopc.extension.json in a store zip (for --force / preflight). */
115
- function peekExtensionIdFromStoreZip(buffer) {
118
+ function readShallowestExtensionManifestFromZip(buffer) {
116
119
  if (buffer.length > 10485760) return void 0;
117
120
  let zip;
118
121
  try {
@@ -129,14 +132,22 @@ function peekExtensionIdFromStoreZip(buffer) {
129
132
  if (!entry) return void 0;
130
133
  try {
131
134
  const raw = entry.getData().toString("utf8");
132
- const m = JSON.parse(raw);
133
- const id = typeof m.id === "string" ? m.id.trim() : "";
134
- if (!id || id.includes("/") || id.includes("\\")) return void 0;
135
- return id;
135
+ const parsed = JSON.parse(raw);
136
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : void 0;
136
137
  } catch {
137
138
  return;
138
139
  }
139
140
  }
141
+ function peekExtensionManifestFromStoreZip(buffer) {
142
+ return readShallowestExtensionManifestFromZip(buffer);
143
+ }
144
+ /** Read `id` from the shallowest xopc.extension.json in a store zip (for --force / preflight). */
145
+ function peekExtensionIdFromStoreZip(buffer) {
146
+ const m = readShallowestExtensionManifestFromZip(buffer);
147
+ const id = typeof m?.id === "string" ? m.id.trim() : "";
148
+ if (!id || id.includes("/") || id.includes("\\")) return void 0;
149
+ return id;
150
+ }
140
151
  /**
141
152
  * Install an extension from an xopc-store zip buffer (layout: manifest at archive root
142
153
  * or under a single top-level folder).
@@ -293,6 +304,13 @@ async function installFromDirectory(sourceDir, extensionsDir) {
293
304
  if (existsSync(packagePath)) try {
294
305
  packageJson = JSON.parse(readFileSync(packagePath, "utf-8"));
295
306
  } catch {}
307
+ if (packageJson) {
308
+ const packageIssues = collectExtensionPackageDependencyIssues(packageJson, { strictRuntimeSdkDeps: true });
309
+ if (packageIssues.length > 0) return {
310
+ ok: false,
311
+ error: `Extension package is not installable as an independent package:\n${packageIssues.map((issue) => `- ${issue.message}`).join("\n")}`
312
+ };
313
+ }
296
314
  const extensionId = manifest?.id || packageJson?.name;
297
315
  if (!extensionId) return {
298
316
  ok: false,
@@ -307,7 +325,32 @@ async function installFromDirectory(sourceDir, extensionsDir) {
307
325
  ok: false,
308
326
  error: `Extension already exists at ${targetDir}. Use update instead.`
309
327
  };
310
- const mainFile = manifest?.main || "index.js";
328
+ if (!manifest) return {
329
+ ok: false,
330
+ error: "Extension must include xopc.extension.json"
331
+ };
332
+ if (!manifest.engines?.xopc) return {
333
+ ok: false,
334
+ error: "Extension manifest must declare engines.xopc"
335
+ };
336
+ const engineCheck = checkEngineCompatibility(PACKAGE_VERSION, manifest.engines.xopc);
337
+ if (engineCheck.parseWarning) return {
338
+ ok: false,
339
+ error: engineCheck.reason ?? `Could not parse engines.xopc ${manifest.engines.xopc}`
340
+ };
341
+ if (!engineCheck.compatible) return {
342
+ ok: false,
343
+ error: engineCheck.reason ?? `xopc ${PACKAGE_VERSION} does not satisfy engines.xopc ${manifest.engines.xopc}`
344
+ };
345
+ if (!manifest.main) return {
346
+ ok: false,
347
+ error: "Extension manifest must declare main"
348
+ };
349
+ if (!/\.(mjs|cjs|js)$/i.test(manifest.main)) return {
350
+ ok: false,
351
+ error: `Extension main must point at built JavaScript (.js/.mjs/.cjs), got: ${manifest.main}`
352
+ };
353
+ const mainFile = manifest.main;
311
354
  if (!existsSync(join(sourceDir, mainFile))) return {
312
355
  ok: false,
313
356
  error: `Main entry not found: ${mainFile}`
@@ -467,6 +510,6 @@ function readManifest(extensionDir) {
467
510
  }
468
511
  }
469
512
  //#endregion
470
- export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, removeExtension, resolveExtensionsDir };
513
+ export { installExtensionFromStoreZip, installFromLocal, installFromNpm, listAllExtensions, peekExtensionIdFromStoreZip, peekExtensionManifestFromStoreZip, removeExtension, resolveExtensionsDir };
471
514
 
472
515
  //# sourceMappingURL=install.js.map