@xopcai/xopc 0.0.127 → 0.0.129

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 (334) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CgGgO4OV.js → agent-avatar-dicebear-DHzfg5D-.js} +1 -1
  4. package/dist/gateway/static/root/assets/agents-CMxKKFQD.js +2 -0
  5. package/dist/gateway/static/root/assets/app-management-settings-panel-ptk9c5BN.js +1 -0
  6. package/dist/gateway/static/root/assets/{appearance-settings-BnHQW7Hv.js → appearance-settings-bYeEj3IW.js} +1 -1
  7. package/dist/gateway/static/root/assets/apps-page-DdZvDf5B.js +1 -0
  8. package/dist/gateway/static/root/assets/{archive-plugin-5NXT7Zqv.js → archive-plugin-Dy6lsTHw.js} +1 -1
  9. package/dist/gateway/static/root/assets/{attachment-load-DghwhYe0.js → attachment-load-qOtBYR6Y.js} +1 -1
  10. package/dist/gateway/static/root/assets/{automation-suggestion-card-DYmESgwl.js → automation-suggestion-card-BFH-RfaV.js} +1 -1
  11. package/dist/gateway/static/root/assets/automations-page-B8JTjkCr.js +4 -0
  12. package/dist/gateway/static/root/assets/{binary-plugins-DSbPKdWX.js → binary-plugins-DJvi_thc.js} +1 -1
  13. package/dist/gateway/static/root/assets/{block-editor-CoZ-_np-.js → block-editor-DlMnizlt.js} +4 -4
  14. package/dist/gateway/static/root/assets/browser-settings-page-slHLiZgi.js +8 -0
  15. package/dist/gateway/static/root/assets/capability-presets-api-D4q7vHVJ.js +1 -0
  16. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Dng8Grpv.js +1 -0
  17. package/dist/gateway/static/root/assets/channel-recipient-api-BrW5Kcgc.js +1 -0
  18. package/dist/gateway/static/root/assets/channels-settings-KIsISXw0.js +1 -0
  19. package/dist/gateway/static/root/assets/{code-editor-gbRgS14t.js → code-editor--tMO38Tr.js} +1 -1
  20. package/dist/gateway/static/root/assets/connectors-page-C5fx4Qs9.js +2 -0
  21. package/dist/gateway/static/root/assets/desktop-pet-Jmdn6q47.js +1 -0
  22. package/dist/gateway/static/root/assets/{desktop-pet-settings-npJ0Oh5p.js → desktop-pet-settings-B-u63N4e.js} +1 -1
  23. package/dist/gateway/static/root/assets/{directory-picker-path-field-BR2ItBuf.js → directory-picker-path-field-8p1ehIHn.js} +1 -1
  24. package/dist/gateway/static/root/assets/dreaming-settings-CCkKP-I4.js +3 -0
  25. package/dist/gateway/static/root/assets/{extension-debug-page-Tl0f1rNv.js → extension-debug-page-DJ1ABK95.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-page-Ck7QuwE3.js → extension-page-CP9P2lGM.js} +1 -1
  27. package/dist/gateway/static/root/assets/extension-settings-page-DnhU-tx0.js +1 -0
  28. package/dist/gateway/static/root/assets/fetch-BMjlW0g1.js +1 -0
  29. package/dist/gateway/static/root/assets/gateway-config-api-CjxDn46s.js +1 -0
  30. package/dist/gateway/static/root/assets/gateway-settings-TING7224.js +1 -0
  31. package/dist/gateway/static/root/assets/{gateway-startup-retry-Yh8h3hkj.js → gateway-startup-retry-CY5W2Pp4.js} +1 -1
  32. package/dist/gateway/static/root/assets/goal-create-dialog-2lPbGfp3.js +1 -0
  33. package/dist/gateway/static/root/assets/goal-detail-page-DHWVRafk.js +4 -0
  34. package/dist/gateway/static/root/assets/goals-config-api-BqhuxG8P.js +1 -0
  35. package/dist/gateway/static/root/assets/goals-page-CMk-9ZYN.js +2 -0
  36. package/dist/gateway/static/root/assets/goals-settings-BHzOAU_l.js +1 -0
  37. package/dist/gateway/static/root/assets/heartbeat-settings-BQIm0P3V.js +1 -0
  38. package/dist/gateway/static/root/assets/{html-workspace-editor-DV90ddkE.js → html-workspace-editor-COqmtESs.js} +1 -1
  39. package/dist/gateway/static/root/assets/index-C4k6QSXw.js +257 -0
  40. package/dist/gateway/static/root/assets/index-EKmpPvZj.css +1 -0
  41. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CfQrt_Rb.js → keyboard-shortcuts-settings-BrENZzM7.js} +1 -1
  42. package/dist/gateway/static/root/assets/logs-page-BiL302Ve.js +2 -0
  43. package/dist/gateway/static/root/assets/{markdown-editor-BFOjBBla.js → markdown-editor-jD1LPiP-.js} +2 -2
  44. package/dist/gateway/static/root/assets/{markdown-split-BwiMdCf_.js → markdown-split-BYF4ReGM.js} +1 -1
  45. package/dist/gateway/static/root/assets/{media-plugins-DhoizyZv.js → media-plugins-CpQDz-QJ.js} +1 -1
  46. package/dist/gateway/static/root/assets/messages-YzjnURPJ.js +3 -0
  47. package/dist/gateway/static/root/assets/models-hub-panel-CFPpl3Cq.js +2 -0
  48. package/dist/gateway/static/root/assets/notes-page-BurgcdVZ.js +1 -0
  49. package/dist/gateway/static/root/assets/notes-workbench-BAELRM_O.js +2 -0
  50. package/dist/gateway/static/root/assets/{page-tabs-DDC2t4Z8.js → page-tabs-RnYYOIWO.js} +1 -1
  51. package/dist/gateway/static/root/assets/{preview-open-alternatives-BTmk-XDM.js → preview-open-alternatives-CTRt06Ri.js} +1 -1
  52. package/dist/gateway/static/root/assets/project-detail-page-iXX1Ceo2.js +1 -0
  53. package/dist/gateway/static/root/assets/projects-page-GDVTFAY7.js +1 -0
  54. package/dist/gateway/static/root/assets/remote-access-hub-BUrbUnwv.js +1 -0
  55. package/dist/gateway/static/root/assets/{save-bar-controls-DqU-yKIh.js → save-bar-controls-c4pZeikq.js} +1 -1
  56. package/dist/gateway/static/root/assets/{schedule-field-CUttkoSB.js → schedule-field-Cb6R7iuP.js} +1 -1
  57. package/dist/gateway/static/root/assets/{schema-form-CVSQA9nI.js → schema-form-BqET_hEP.js} +1 -1
  58. package/dist/gateway/static/root/assets/sessions-page-CiOreA2k.js +1 -0
  59. package/dist/gateway/static/root/assets/settings-advanced-gate-C-qvptlu.js +1 -0
  60. package/dist/gateway/static/root/assets/{settings-collapsible-section-CK7ogS-P.js → settings-collapsible-section-DuOvqNsI.js} +1 -1
  61. package/dist/gateway/static/root/assets/{settings-form-section-Bugp38Fa.js → settings-form-section-DptSsbWd.js} +1 -1
  62. package/dist/gateway/static/root/assets/settings-loading-skeleton-BlVfBCb9.js +1 -0
  63. package/dist/gateway/static/root/assets/{settings-page-layout-DBRWwdhh.js → settings-page-layout-DVt69dJJ.js} +1 -1
  64. package/dist/gateway/static/root/assets/settings-page-xQx2Pkg5.js +1 -0
  65. package/dist/gateway/static/root/assets/setup-status-panel-DWB8VdLK.js +1 -0
  66. package/dist/gateway/static/root/assets/share-preview-page-8m_ACH0z.js +2 -0
  67. package/dist/gateway/static/root/assets/shares-settings-CgxfhNxI.js +1 -0
  68. package/dist/gateway/static/root/assets/skill-reload-api-BBFUOxmf.js +1 -0
  69. package/dist/gateway/static/root/assets/skills-page-bo695odu.js +2 -0
  70. package/dist/gateway/static/root/assets/{system-settings-panel-DJ6YuLqR.js → system-settings-panel-CW22OkZ4.js} +1 -1
  71. package/dist/gateway/static/root/assets/{typed-models-lib-B0T7N8Km.js → typed-models-lib-BqpGAKxV.js} +1 -1
  72. package/dist/gateway/static/root/assets/url-DFGNSBNT.js +1 -0
  73. package/dist/gateway/static/root/assets/use-channel-catalog-CPdJ0o0i.js +1 -0
  74. package/dist/gateway/static/root/assets/user-profile-settings-panel-CERVLuaW.js +1 -0
  75. package/dist/gateway/static/root/assets/{utils-CehXcWAY.js → utils-BnmysurA.js} +1 -1
  76. package/dist/gateway/static/root/assets/vendor-codemirror-C1WKjCk5.js +45 -0
  77. package/dist/gateway/static/root/assets/voice-api-key-field-Jr3jvPcB.js +1 -0
  78. package/dist/gateway/static/root/assets/work-item-detail-page-B-8rex4u.js +1 -0
  79. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-c4jeaohQ.js → workflow-run-setup-panel-Ci9GSPnS.js} +2 -2
  80. package/dist/gateway/static/root/assets/{workflow-start-dialog-ENRHjoqa.js → workflow-start-dialog-BhDj8pqH.js} +1 -1
  81. package/dist/gateway/static/root/assets/workflows-page-Brb3UGvs.js +18 -0
  82. package/dist/gateway/static/root/index.html +7 -6
  83. package/dist/package.js +1 -1
  84. package/dist/src/agent/agent-manager.d.ts +3 -0
  85. package/dist/src/agent/agent-manager.js +14 -6
  86. package/dist/src/agent/agent-manager.js.map +1 -1
  87. package/dist/src/agent/capabilities/definitions.d.ts +14 -0
  88. package/dist/src/agent/capabilities/definitions.js +19 -0
  89. package/dist/src/agent/capabilities/definitions.js.map +1 -1
  90. package/dist/src/agent/goals/post-turn.js +23 -2
  91. package/dist/src/agent/goals/post-turn.js.map +1 -1
  92. package/dist/src/agent/messaging/command-handler.d.ts +4 -0
  93. package/dist/src/agent/messaging/command-handler.js +6 -0
  94. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  95. package/dist/src/agent/service.d.ts +2 -0
  96. package/dist/src/agent/service.js +23 -0
  97. package/dist/src/agent/service.js.map +1 -1
  98. package/dist/src/agent/skills/hub-lock.d.ts +5 -5
  99. package/dist/src/agent/skills/hub-lock.js +12 -12
  100. package/dist/src/agent/skills/hub-lock.js.map +1 -1
  101. package/dist/src/agent/skills/hub-pull.d.ts +15 -0
  102. package/dist/src/agent/skills/hub-pull.js +299 -24
  103. package/dist/src/agent/skills/hub-pull.js.map +1 -1
  104. package/dist/src/agent/skills/index.js +4 -40
  105. package/dist/src/agent/skills/index.js.map +1 -1
  106. package/dist/src/agent/skills/install-target.d.ts +3 -0
  107. package/dist/src/agent/skills/install-target.js +11 -0
  108. package/dist/src/agent/skills/install-target.js.map +1 -0
  109. package/dist/src/agent/skills/managed-store.d.ts +5 -3
  110. package/dist/src/agent/skills/managed-store.js +10 -9
  111. package/dist/src/agent/skills/managed-store.js.map +1 -1
  112. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +5 -3
  113. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
  114. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +21 -1
  115. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +62 -6
  116. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
  117. package/dist/src/agent/skills/marketplace/resolve-adapter.js +1 -1
  118. package/dist/src/agent/skills/marketplace/resolve-adapter.js.map +1 -1
  119. package/dist/src/agent/skills/skill-manage-ops.js +2 -2
  120. package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
  121. package/dist/src/agent/skills/skill-manager.js +1 -6
  122. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  123. package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
  124. package/dist/src/agent/skills/workspace-skills-dir.js +5 -1
  125. package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -1
  126. package/dist/src/agent/tools/automation-tool.d.ts +6 -6
  127. package/dist/src/agent/tools/browser/tool/schemas.d.ts +20 -20
  128. package/dist/src/agent/tools/composio-tool.d.ts +3 -3
  129. package/dist/src/agent/tools/desktop-pet-tool.d.ts +7 -7
  130. package/dist/src/agent/tools/factory.d.ts +3 -0
  131. package/dist/src/agent/tools/factory.js +6 -1
  132. package/dist/src/agent/tools/factory.js.map +1 -1
  133. package/dist/src/agent/tools/goal-tool.d.ts +16 -16
  134. package/dist/src/agent/tools/index.d.ts +1 -0
  135. package/dist/src/agent/tools/index.js +2 -1
  136. package/dist/src/agent/tools/skill-install-tool.d.ts +28 -0
  137. package/dist/src/agent/tools/skill-install-tool.js +81 -0
  138. package/dist/src/agent/tools/skill-install-tool.js.map +1 -0
  139. package/dist/src/agent/tools/skill-manage-tool.js +3 -6
  140. package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
  141. package/dist/src/agent/tools/tool-manual-tool.d.ts +2 -2
  142. package/dist/src/agent/tools/xopc-use-tool.d.ts +5 -5
  143. package/dist/src/automations/domain/types.d.ts +1 -0
  144. package/dist/src/automations/draft/automation-draft-service.js +1 -1
  145. package/dist/src/automations/service/automation-service.js +9 -0
  146. package/dist/src/automations/service/automation-service.js.map +1 -1
  147. package/dist/src/browser/schemas.d.ts +52 -52
  148. package/dist/src/capabilities/store-connector.d.ts +17 -0
  149. package/dist/src/capabilities/store-connector.js +191 -0
  150. package/dist/src/capabilities/store-connector.js.map +1 -0
  151. package/dist/src/chat-commands/builtins/skill.d.ts +1 -0
  152. package/dist/src/chat-commands/builtins/skill.js +132 -0
  153. package/dist/src/chat-commands/builtins/skill.js.map +1 -0
  154. package/dist/src/chat-commands/context.d.ts +3 -0
  155. package/dist/src/chat-commands/context.js +2 -0
  156. package/dist/src/chat-commands/context.js.map +1 -1
  157. package/dist/src/chat-commands/index.d.ts +1 -0
  158. package/dist/src/chat-commands/index.js +3 -1
  159. package/dist/src/chat-commands/index.js.map +1 -1
  160. package/dist/src/chat-commands/types.d.ts +17 -0
  161. package/dist/src/cli/command-loaders.js +1 -0
  162. package/dist/src/cli/command-loaders.js.map +1 -1
  163. package/dist/src/cli/command-manifest.js +4 -0
  164. package/dist/src/cli/command-manifest.js.map +1 -1
  165. package/dist/src/cli/commands/agent.js +2 -2
  166. package/dist/src/cli/commands/connectors.d.ts +4 -0
  167. package/dist/src/cli/commands/connectors.js +96 -0
  168. package/dist/src/cli/commands/connectors.js.map +1 -0
  169. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  170. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  171. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  172. package/dist/src/cli/commands/models.js +1 -1
  173. package/dist/src/cli/commands/onboard.js +1 -1
  174. package/dist/src/cli/commands/profile.js +1 -1
  175. package/dist/src/cli/commands/skills.js +1 -1
  176. package/dist/src/cli/commands/tunnel.js +1 -1
  177. package/dist/src/cli/commands/update.js +1 -1
  178. package/dist/src/cli/extension-cli-register.js +1 -1
  179. package/dist/src/config/agent-profile.js +1 -1
  180. package/dist/src/config/index.js +1 -1
  181. package/dist/src/config/schema.js +2 -2
  182. package/dist/src/config/schema.js.map +1 -1
  183. package/dist/src/connectors/health.js +1 -1
  184. package/dist/src/connectors/install.js +3 -1
  185. package/dist/src/connectors/install.js.map +1 -1
  186. package/dist/src/connectors/materialize.js +2 -0
  187. package/dist/src/connectors/materialize.js.map +1 -1
  188. package/dist/src/connectors/types.d.ts +19 -1
  189. package/dist/src/extensions/install.js +1 -1
  190. package/dist/src/extensions/types/manifest.d.ts +1 -1
  191. package/dist/src/extensions/update.js +5 -3
  192. package/dist/src/extensions/update.js.map +1 -1
  193. package/dist/src/gateway/agents-admin.js +1 -1
  194. package/dist/src/gateway/chat-stream/mapper.js +5 -1
  195. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  196. package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
  197. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  198. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  199. package/dist/src/gateway/hono/middleware/auth.d.ts +2 -2
  200. package/dist/src/gateway/hono/middleware/logger.d.ts +1 -1
  201. package/dist/src/gateway/hono/middleware/route-errors.d.ts +1 -1
  202. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +2 -2
  203. package/dist/src/gateway/hono/routes/capabilities.d.ts +3 -0
  204. package/dist/src/gateway/hono/routes/capabilities.js +79 -0
  205. package/dist/src/gateway/hono/routes/capabilities.js.map +1 -0
  206. package/dist/src/gateway/hono/routes/commands-skills.js +81 -3
  207. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  208. package/dist/src/gateway/hono/routes/connectors.js +2 -2
  209. package/dist/src/gateway/hono/routes/goals.js +212 -3
  210. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  211. package/dist/src/gateway/hono/routes/index.js +2 -0
  212. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  213. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  214. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  215. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  216. package/dist/src/gateway/hono/routes/mobile.d.ts +3 -0
  217. package/dist/src/gateway/hono/routes/mobile.js +113 -0
  218. package/dist/src/gateway/hono/routes/mobile.js.map +1 -0
  219. package/dist/src/gateway/hono/routes/projects.js +17 -0
  220. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  221. package/dist/src/gateway/hono/routes/workspace.js +4 -1
  222. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  223. package/dist/src/gateway/hono/sse.d.ts +3 -3
  224. package/dist/src/gateway/run-loop.js +1 -1
  225. package/dist/src/gateway/service/marketplace-service.d.ts +23 -1
  226. package/dist/src/gateway/service/marketplace-service.js +57 -6
  227. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  228. package/dist/src/gateway/service.d.ts +2 -0
  229. package/dist/src/gateway/service.js +12 -2
  230. package/dist/src/gateway/service.js.map +1 -1
  231. package/dist/src/goals/goal-contract-draft.d.ts +15 -0
  232. package/dist/src/goals/goal-contract-draft.js +114 -0
  233. package/dist/src/goals/goal-contract-draft.js.map +1 -0
  234. package/dist/src/goals/goal-evidence-review.d.ts +15 -0
  235. package/dist/src/goals/goal-evidence-review.js +91 -0
  236. package/dist/src/goals/goal-evidence-review.js.map +1 -0
  237. package/dist/src/goals/goal-runner.js +3 -1
  238. package/dist/src/goals/goal-runner.js.map +1 -1
  239. package/dist/src/goals/goal-service.d.ts +17 -1
  240. package/dist/src/goals/goal-service.js +44 -3
  241. package/dist/src/goals/goal-service.js.map +1 -1
  242. package/dist/src/goals/goal-store.d.ts +18 -1
  243. package/dist/src/goals/goal-store.js +190 -1
  244. package/dist/src/goals/goal-store.js.map +1 -1
  245. package/dist/src/goals/index.d.ts +4 -0
  246. package/dist/src/goals/index.js +3 -1
  247. package/dist/src/goals/types.d.ts +42 -0
  248. package/dist/src/mcp/channel-bridge.js +1 -1
  249. package/dist/src/mobile/notification-service.d.ts +8 -0
  250. package/dist/src/mobile/notification-service.js +139 -0
  251. package/dist/src/mobile/notification-service.js.map +1 -0
  252. package/dist/src/mobile/notification-store.d.ts +28 -0
  253. package/dist/src/mobile/notification-store.js +134 -0
  254. package/dist/src/mobile/notification-store.js.map +1 -0
  255. package/dist/src/mobile/notification-types.d.ts +37 -0
  256. package/dist/src/mobile/notification-types.js +11 -0
  257. package/dist/src/mobile/notification-types.js.map +1 -0
  258. package/dist/src/storage/sqlite/migrations/026_goal_contracts.sql +10 -0
  259. package/dist/src/storage/sqlite/migrations/027_mobile_notifications.sql +43 -0
  260. package/dist/src/storage/sqlite/migrations/028_goal_evidence_requirements.sql +47 -0
  261. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  262. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  263. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  264. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  265. package/dist/src/storage/sqlite/schema.js +1 -1
  266. package/dist/src/storage/sqlite/schema.sql +44 -0
  267. package/dist/src/tui/tui-startup-resources.js +1 -1
  268. package/package.json +1 -1
  269. package/skills/THIRD_PARTY_NOTICES.md +16 -0
  270. package/skills/creative/algorithmic-art/SKILL.md +37 -0
  271. package/skills/creative/algorithmic-art/templates/generator-template.js +27 -0
  272. package/skills/creative/algorithmic-art/templates/viewer.html +27 -0
  273. package/skills/documents/doc-coauthoring/SKILL.md +40 -0
  274. package/skills/documents/doc-coauthoring/references/reader-review.md +9 -0
  275. package/skills/documents/docx/SKILL.md +40 -0
  276. package/skills/documents/docx/references/editing-checklist.md +8 -0
  277. package/skills/documents/docx/scripts/inspect_ooxml.py +36 -0
  278. package/skills/documents/docx/scripts/render_docx.py +33 -0
  279. package/skills/documents/pdf/SKILL.md +47 -0
  280. package/skills/documents/pdf/references/operations.md +16 -0
  281. package/skills/documents/pdf/scripts/inspect_pdf.py +41 -0
  282. package/skills/documents/pdf/scripts/render_pdf.py +32 -0
  283. package/skills/documents/pptx/SKILL.md +41 -0
  284. package/skills/documents/pptx/references/qa-checklist.md +6 -0
  285. package/skills/documents/pptx/scripts/inspect_ooxml.py +34 -0
  286. package/skills/documents/pptx/scripts/render_pptx.py +33 -0
  287. package/skills/engineering/define-goal/SKILL.md +41 -0
  288. package/skills/engineering/define-goal/references/objective-rubric.md +12 -0
  289. package/dist/gateway/static/root/assets/agents-k59l7NMb.js +0 -2
  290. package/dist/gateway/static/root/assets/app-management-settings-panel-DeQsTsyy.js +0 -1
  291. package/dist/gateway/static/root/assets/apps-page-BG9b4abG.js +0 -1
  292. package/dist/gateway/static/root/assets/automations-page-De8mVutL.js +0 -4
  293. package/dist/gateway/static/root/assets/browser-settings-page-C_ZRa4LF.js +0 -8
  294. package/dist/gateway/static/root/assets/capability-presets-api-hny224j-.js +0 -1
  295. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Drc0qLsw.js +0 -1
  296. package/dist/gateway/static/root/assets/channel-recipient-api-DAlOHxKJ.js +0 -1
  297. package/dist/gateway/static/root/assets/channels-settings-CA20zBV9.js +0 -1
  298. package/dist/gateway/static/root/assets/connectors-page-qMyMB5te.js +0 -2
  299. package/dist/gateway/static/root/assets/desktop-pet-XG6Vb_fZ.js +0 -1
  300. package/dist/gateway/static/root/assets/dreaming-settings-CkUZ997f.js +0 -3
  301. package/dist/gateway/static/root/assets/extension-settings-page-3RMhQtZ3.js +0 -1
  302. package/dist/gateway/static/root/assets/fetch-pg2ErdAk.js +0 -1
  303. package/dist/gateway/static/root/assets/gateway-config-api-DbG97ia2.js +0 -1
  304. package/dist/gateway/static/root/assets/gateway-settings-B8cyqKk-.js +0 -1
  305. package/dist/gateway/static/root/assets/goal-create-dialog-DmeW7Zz3.js +0 -1
  306. package/dist/gateway/static/root/assets/goal-detail-page-DrTyGbVD.js +0 -1
  307. package/dist/gateway/static/root/assets/goals-config-api-CxCWGIBB.js +0 -1
  308. package/dist/gateway/static/root/assets/goals-page-DV1bJhIh.js +0 -2
  309. package/dist/gateway/static/root/assets/goals-settings-9DrfOkP5.js +0 -1
  310. package/dist/gateway/static/root/assets/heartbeat-settings-KaDpZrv0.js +0 -1
  311. package/dist/gateway/static/root/assets/index-C2F0Clvm.js +0 -256
  312. package/dist/gateway/static/root/assets/index-COQSX5d_.css +0 -1
  313. package/dist/gateway/static/root/assets/logs-page-C9dpiNTF.js +0 -2
  314. package/dist/gateway/static/root/assets/messages-DmnbiNxU.js +0 -3
  315. package/dist/gateway/static/root/assets/models-hub-panel-zdCdmBmH.js +0 -2
  316. package/dist/gateway/static/root/assets/notes-page-MpGeFfPt.js +0 -1
  317. package/dist/gateway/static/root/assets/notes-workbench-DYCM3yd2.js +0 -2
  318. package/dist/gateway/static/root/assets/project-detail-page-Cu0ElRnS.js +0 -1
  319. package/dist/gateway/static/root/assets/projects-page-DakNaUjZ.js +0 -1
  320. package/dist/gateway/static/root/assets/remote-access-hub-DYKjt7L9.js +0 -1
  321. package/dist/gateway/static/root/assets/sessions-page-CcGHDsz1.js +0 -1
  322. package/dist/gateway/static/root/assets/settings-advanced-gate-CuFdeKNu.js +0 -1
  323. package/dist/gateway/static/root/assets/settings-page-0AJoUvxi.js +0 -1
  324. package/dist/gateway/static/root/assets/setup-status-panel-D6a_hEk7.js +0 -1
  325. package/dist/gateway/static/root/assets/share-preview-page-BtsuETKF.js +0 -2
  326. package/dist/gateway/static/root/assets/shares-settings-CcEFT7S9.js +0 -1
  327. package/dist/gateway/static/root/assets/skill-reload-api-BcN_RuTD.js +0 -1
  328. package/dist/gateway/static/root/assets/skills-page-BbRZZZA5.js +0 -2
  329. package/dist/gateway/static/root/assets/use-channel-catalog-C6vrxdzZ.js +0 -1
  330. package/dist/gateway/static/root/assets/user-profile-settings-panel-DZ0nKMgj.js +0 -1
  331. package/dist/gateway/static/root/assets/vendor-codemirror-BvNgyE1Q.js +0 -45
  332. package/dist/gateway/static/root/assets/voice-api-key-field-2QKflCx8.js +0 -1
  333. package/dist/gateway/static/root/assets/work-item-detail-page-DfJnuWq1.js +0 -1
  334. package/dist/gateway/static/root/assets/workflows-page-BJwwFTm_.js +0 -18
@@ -1 +1 @@
1
- {"version":3,"file":"automation-service.js","names":[],"sources":["../../../../src/automations/service/automation-service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createLogger } from '../../utils/logger.js';\nimport {\n computeNextAutomationRunAtMs,\n timerDelayUntil,\n} from '../domain/schedule.js';\nimport type {\n Automation,\n AutomationDeps,\n AutomationEvent,\n AutomationMetrics,\n AutomationProductEventRun,\n AutomationRun,\n AutomationRunEvent,\n AutomationRunEventType,\n AutomationRunStatus,\n} from '../domain/types.js';\nimport {\n CreateAutomationSchema,\n UpdateAutomationSchema,\n type CreateAutomationInput,\n type UpdateAutomationInput,\n AutomationSchema,\n} from '../domain/validation.js';\nimport {\n appendAutomationRunEvent,\n deleteAutomation,\n getAutomation,\n getAutomationRun,\n listAutomationRunEvents,\n listAutomationRuns,\n listAutomationRunsForProductEvent,\n listAutomations,\n saveAutomation,\n saveAutomationRun,\n saveAutomations,\n} from '../storage/index.js';\nimport { AutomationActionExecutor } from './action-executor.js';\n\nconst log = createLogger('AutomationService');\n\ntype TimerHandle = ReturnType<typeof setTimeout> & { unref?: () => void };\n\nconst DEFAULT_MAX_CONCURRENT_RUNS = 5;\nconst MISSED_RUN_STAGGER_MS = 5_000;\n\nexport class AutomationAlreadyRunningError extends Error {\n constructor(readonly automationId: string, readonly runningRunId?: string) {\n super(`Automation is already running: ${automationId}`);\n this.name = 'AutomationAlreadyRunningError';\n }\n}\n\nexport class AutomationService {\n private readonly executor = new AutomationActionExecutor();\n private timer: TimerHandle | null = null;\n private stopped = true;\n private runningScheduler = false;\n private deps: AutomationDeps = {};\n private maxConcurrentRuns = DEFAULT_MAX_CONCURRENT_RUNS;\n private readonly activeRuns = new Map<string, AbortController>();\n\n setDeps(deps: AutomationDeps): void {\n this.deps = { ...this.deps, ...deps };\n this.executor.setDeps(this.deps);\n }\n\n async initialize(options?: { maxConcurrentRuns?: number }): Promise<void> {\n this.maxConcurrentRuns = Math.max(1, Math.floor(options?.maxConcurrentRuns ?? DEFAULT_MAX_CONCURRENT_RUNS));\n this.stopped = false;\n await this.recomputeNextRuns({ catchUp: true });\n this.armTimer();\n log.info('Automation service initialized');\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n for (const controller of this.activeRuns.values()) {\n controller.abort();\n }\n log.info('Automation service stopped');\n }\n\n async create(input: CreateAutomationInput): Promise<Automation> {\n const parsed = CreateAutomationSchema.parse(input);\n const now = Date.now();\n const automation = AutomationSchema.parse({\n ...parsed,\n id: parsed.id?.trim() || randomUUID().slice(0, 12),\n enabled: parsed.enabled ?? true,\n safety: parsed.safety ?? { mode: 'auto_apply' },\n afterRun: parsed.afterRun ?? { kind: 'none' },\n state: parsed.state ?? {},\n createdAtMs: now,\n updatedAtMs: now,\n }) as Automation;\n automation.state.nextRunAtMs = computeNextAutomationRunAtMs(automation, now);\n saveAutomation(automation);\n this.armTimer();\n return automation;\n }\n\n async list(options?: { projectId?: string }): Promise<Automation[]> {\n return listAutomations(options);\n }\n\n async get(id: string): Promise<Automation | null> {\n return getAutomation(id);\n }\n\n async update(id: string, patch: UpdateAutomationInput): Promise<Automation | null> {\n const parsed = UpdateAutomationSchema.parse(patch);\n const current = getAutomation(id);\n if (!current) return null;\n const now = Date.now();\n const next = AutomationSchema.parse({\n ...current,\n ...parsed,\n id: current.id,\n createdAtMs: current.createdAtMs,\n updatedAtMs: now,\n state: {\n ...current.state,\n ...(parsed.state ?? {}),\n },\n }) as Automation;\n if ('enabled' in parsed || 'trigger' in parsed) {\n next.state.nextRunAtMs = computeNextAutomationRunAtMs(next, now);\n }\n saveAutomation(next);\n this.armTimer();\n return next;\n }\n\n async remove(id: string): Promise<boolean> {\n const automation = getAutomation(id);\n if (automation?.state.runningRunId) {\n this.activeRuns.get(automation.state.runningRunId)?.abort();\n }\n const removed = deleteAutomation(id);\n if (removed) {\n this.armTimer();\n }\n return removed;\n }\n\n async pause(id: string): Promise<Automation | null> {\n return this.update(id, { enabled: false });\n }\n\n async resume(id: string): Promise<Automation | null> {\n return this.update(id, { enabled: true });\n }\n\n async runNow(id: string): Promise<AutomationRun> {\n const automation = getAutomation(id);\n if (!automation) throw new Error(`Automation not found: ${id}`);\n if (automation.state.runningRunId) {\n throw new AutomationAlreadyRunningError(id, automation.state.runningRunId);\n }\n return this.startRun(automation, { manual: true });\n }\n\n async rerunFromRun(runId: string): Promise<AutomationRun> {\n const previous = getAutomationRun(runId);\n if (!previous) throw new Error(`Automation run not found: ${runId}`);\n const automation = getAutomation(previous.automationId);\n if (!automation) throw new Error(`Automation not found: ${previous.automationId}`);\n if (automation.state.runningRunId) {\n throw new AutomationAlreadyRunningError(automation.id, automation.state.runningRunId);\n }\n const triggerEvent = listAutomationRunEvents(runId)\n .map((event) => readAutomationEventFromRunEvent(event))\n .find((event): event is AutomationEvent => event !== null);\n return this.startRun(automation, triggerEvent ? { manual: false, event: triggerEvent } : { manual: true });\n }\n\n async triggerEvent(event: AutomationEvent): Promise<AutomationRun[]> {\n const normalized: AutomationEvent = {\n ...event,\n occurredAtMs: event.occurredAtMs ?? Date.now(),\n };\n const automations = listAutomations().filter(\n (automation) =>\n automation.enabled &&\n automation.trigger.kind === 'event' &&\n !automation.state.runningRunId &&\n matchesAutomationEvent(automation.trigger, normalized),\n );\n const availableSlots = Math.max(0, this.maxConcurrentRuns - this.activeRuns.size);\n const started: AutomationRun[] = [];\n for (const automation of automations.slice(0, availableSlots)) {\n started.push(await this.startRun(automation, { manual: false, event: normalized }));\n }\n return started;\n }\n\n async listRuns(options?: { automationId?: string; projectId?: string; limit?: number }): Promise<AutomationRun[]> {\n return listAutomationRuns(options);\n }\n\n async listRunsForProductEvent(options: {\n eventType: string;\n source?: string;\n payloadKey?: string;\n payloadValue?: string;\n limit?: number;\n }): Promise<AutomationProductEventRun[]> {\n return listAutomationRunsForProductEvent(options);\n }\n\n async getRun(runId: string): Promise<AutomationRun | null> {\n return getAutomationRun(runId);\n }\n\n async listRunEvents(runId: string): Promise<AutomationRunEvent[]> {\n return listAutomationRunEvents(runId);\n }\n\n async cancelRun(runId: string): Promise<boolean> {\n const controller = this.activeRuns.get(runId);\n if (!controller) return false;\n controller.abort();\n return true;\n }\n\n async getMetrics(): Promise<AutomationMetrics> {\n const automations = listAutomations();\n const enabled = automations.filter((automation) => automation.enabled);\n const next = enabled\n .filter((automation) => automation.state.nextRunAtMs != null)\n .toSorted((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0))[0];\n const oneHourAgo = Date.now() - 60 * 60_000;\n return {\n totalAutomations: automations.length,\n enabledAutomations: enabled.length,\n runningRuns: this.activeRuns.size,\n failedLastHour: automations.filter(\n (automation) =>\n (automation.state.lastRunStatus === 'failed' || automation.state.lastRunStatus === 'timeout') &&\n (automation.state.lastRunAtMs ?? 0) >= oneHourAgo,\n ).length,\n nextRun: next?.state.nextRunAtMs\n ? {\n automationId: next.id,\n name: next.name,\n runAtMs: next.state.nextRunAtMs,\n }\n : undefined,\n };\n }\n\n private async recomputeNextRuns(options?: { catchUp?: boolean }): Promise<void> {\n const now = Date.now();\n const automations = listAutomations().map((automation, index) => {\n const next: Automation = {\n ...automation,\n state: { ...automation.state },\n };\n if (next.state.runningRunId) {\n next.state.lastRunStatus = 'failed';\n next.state.lastError = 'Interrupted by gateway restart';\n next.state.consecutiveFailures = (next.state.consecutiveFailures ?? 0) + 1;\n delete next.state.runningRunId;\n }\n const computed = computeNextAutomationRunAtMs(next, now);\n next.state.nextRunAtMs =\n options?.catchUp && computed != null && computed <= now\n ? now + index * MISSED_RUN_STAGGER_MS\n : computed;\n return next;\n });\n saveAutomations(automations);\n }\n\n private armTimer(): void {\n if (this.stopped) return;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n const next = listAutomations()\n .filter((automation) => automation.enabled && automation.state.nextRunAtMs != null)\n .toSorted((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0))[0];\n if (!next?.state.nextRunAtMs) return;\n this.timer = setTimeout(() => {\n void this.onTimer();\n }, timerDelayUntil(next.state.nextRunAtMs)) as TimerHandle;\n this.timer.unref?.();\n }\n\n private async onTimer(): Promise<void> {\n if (this.stopped) return;\n if (this.runningScheduler) {\n this.armTimer();\n return;\n }\n this.runningScheduler = true;\n try {\n const now = Date.now();\n const due = listAutomations()\n .filter(\n (automation) =>\n automation.enabled &&\n automation.trigger.kind === 'schedule' &&\n automation.state.nextRunAtMs != null &&\n automation.state.nextRunAtMs <= now &&\n !automation.state.runningRunId,\n )\n .slice(0, this.maxConcurrentRuns);\n await Promise.all(due.map((automation) => this.startRun(automation, { manual: false })));\n } finally {\n this.runningScheduler = false;\n this.armTimer();\n }\n }\n\n private async startRun(\n automation: Automation,\n opts: { manual: boolean; event?: AutomationEvent },\n ): Promise<AutomationRun> {\n const now = Date.now();\n const run: AutomationRun = {\n id: randomUUID(),\n automationId: automation.id,\n automationName: automation.name,\n status: 'queued',\n triggerSnapshot: automation.trigger,\n actionSnapshot: automation.action,\n manual: opts.manual,\n createdAtMs: now,\n };\n saveAutomationRun(run);\n this.appendRunEvent(\n run,\n 'run.queued',\n opts.event\n ? `Event ${opts.event.type} queued automation`\n : opts.manual\n ? 'Manual run queued'\n : 'Scheduled run queued',\n {\n trigger: automation.trigger,\n actionKind: automation.action.kind,\n safety: automation.safety ?? { mode: 'auto_apply' },\n event: opts.event,\n },\n );\n const nextAutomation: Automation = {\n ...automation,\n state: {\n ...automation.state,\n runningRunId: run.id,\n },\n };\n saveAutomation(nextAutomation);\n\n void this.executeRun(nextAutomation, run).catch((err) => {\n log.error(\n { err, automationId: automation.id, runId: run.id },\n `Automation run failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n\n return run;\n }\n\n private async executeRun(automation: Automation, initialRun: AutomationRun): Promise<void> {\n const controller = new AbortController();\n this.activeRuns.set(initialRun.id, controller);\n const startedAtMs = Date.now();\n let run: AutomationRun = {\n ...initialRun,\n status: 'running',\n startedAtMs,\n };\n saveAutomationRun(run);\n this.appendRunEvent(run, 'run.started', 'Automation run started');\n\n let status: AutomationRunStatus = 'failed';\n let error: string | undefined;\n let activePhase: 'action' | 'after_run' = 'action';\n try {\n this.appendRunEvent(run, 'action.started', `Running ${automation.action.kind} action`, {\n actionKind: automation.action.kind,\n safety: automation.safety ?? { mode: 'auto_apply' },\n });\n const outcome = await this.executor.execute(automation, run, controller.signal);\n status = outcome.status;\n error = outcome.error;\n this.appendRunEvent(\n run,\n status === 'succeeded' ? 'action.completed' : 'action.failed',\n status === 'succeeded'\n ? `${automation.action.kind} action completed`\n : `${automation.action.kind} action ${status}`,\n {\n summary: outcome.summary,\n error: outcome.error,\n sessionKey: outcome.sessionKey,\n workflowRunId: outcome.workflowRunId,\n model: outcome.model,\n },\n );\n run = {\n ...run,\n status,\n summary: outcome.summary,\n error,\n sessionKey: outcome.sessionKey,\n workflowRunId: outcome.workflowRunId,\n model: outcome.model,\n };\n if ((automation.safety?.mode ?? 'auto_apply') !== 'auto_apply' && automation.afterRun?.kind === 'webhook') {\n this.appendRunEvent(run, 'after_run.completed', 'After-run webhook skipped by safety mode', {\n safety: automation.safety ?? { mode: 'auto_apply' },\n });\n } else if (automation.afterRun?.kind === 'webhook') {\n activePhase = 'after_run';\n this.appendRunEvent(run, 'after_run.started', 'Calling after-run webhook', {\n url: automation.afterRun.url,\n });\n await this.postAfterRunWebhook(automation.afterRun.url, run);\n this.appendRunEvent(run, 'after_run.completed', 'After-run webhook completed');\n }\n } catch (err) {\n error = err instanceof Error ? err.message : String(err);\n status = controller.signal.aborted ? 'cancelled' : 'failed';\n this.appendRunEvent(run, activePhase === 'after_run' ? 'after_run.failed' : 'action.failed', `Automation run ${status}`, {\n error,\n });\n run = { ...run, status, error };\n } finally {\n const endedAtMs = Date.now();\n run = {\n ...run,\n status,\n endedAtMs,\n durationMs: endedAtMs - startedAtMs,\n };\n saveAutomationRun(run);\n this.appendRunEvent(run, 'run.completed', `Automation run ${status}`, {\n status,\n durationMs: run.durationMs,\n error,\n });\n this.activeRuns.delete(initialRun.id);\n this.finishAutomationRun(automation.id, status, error, endedAtMs);\n }\n }\n\n private appendRunEvent(\n run: Pick<AutomationRun, 'id' | 'automationId'>,\n type: AutomationRunEventType,\n message: string,\n data?: unknown,\n ): void {\n appendAutomationRunEvent({\n id: randomUUID(),\n runId: run.id,\n automationId: run.automationId,\n type,\n message,\n data,\n createdAtMs: Date.now(),\n });\n }\n\n private finishAutomationRun(\n automationId: string,\n status: AutomationRunStatus,\n error: string | undefined,\n finishedAtMs: number,\n ): void {\n const current = getAutomation(automationId);\n if (!current) return;\n const failed = status === 'failed' || status === 'timeout';\n const consecutiveFailures = failed ? (current.state.consecutiveFailures ?? 0) + 1 : 0;\n const disableAfter = current.reliability?.disableAfterConsecutiveFailures;\n const shouldDisable = disableAfter != null && consecutiveFailures >= disableAfter;\n const next: Automation = {\n ...current,\n enabled: shouldDisable ? false : current.enabled,\n state: {\n ...current.state,\n lastRunAtMs: finishedAtMs,\n lastRunStatus: status,\n lastError: error,\n consecutiveFailures,\n },\n updatedAtMs: shouldDisable ? finishedAtMs : current.updatedAtMs,\n };\n delete next.state.runningRunId;\n next.state.nextRunAtMs = computeNextAutomationRunAtMs(next, finishedAtMs);\n saveAutomation(next);\n this.armTimer();\n }\n\n private async postAfterRunWebhook(url: string, run: AutomationRun): Promise<void> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ run }),\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(`Automation webhook failed: HTTP ${response.status}${text ? ` ${text.slice(0, 200)}` : ''}`);\n }\n }\n}\n\nfunction matchesAutomationEvent(\n trigger: Extract<Automation['trigger'], { kind: 'event' }>,\n event: AutomationEvent,\n): boolean {\n if (trigger.eventType !== event.type) return false;\n if (trigger.source && trigger.source !== event.source) return false;\n const payloadMatch = trigger.payloadMatch;\n if (!payloadMatch) return true;\n const payload = event.payload ?? {};\n return Object.entries(payloadMatch).every(([key, expected]) => Object.is(payload[key], expected));\n}\n\nfunction readAutomationEventFromRunEvent(event: AutomationRunEvent): AutomationEvent | null {\n if (!event.data || typeof event.data !== 'object' || Array.isArray(event.data)) return null;\n const raw = (event.data as { event?: unknown }).event;\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const candidate = raw as Partial<AutomationEvent>;\n if (typeof candidate.type !== 'string' || !candidate.type.trim()) return null;\n return {\n type: candidate.type,\n source: typeof candidate.source === 'string' ? candidate.source : undefined,\n payload: candidate.payload && typeof candidate.payload === 'object' && !Array.isArray(candidate.payload)\n ? candidate.payload as Record<string, unknown>\n : undefined,\n occurredAtMs: typeof candidate.occurredAtMs === 'number' ? candidate.occurredAtMs : undefined,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"automation-service.js","names":[],"sources":["../../../../src/automations/service/automation-service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport { createLogger } from '../../utils/logger.js';\nimport {\n computeNextAutomationRunAtMs,\n timerDelayUntil,\n} from '../domain/schedule.js';\nimport type {\n Automation,\n AutomationDeps,\n AutomationEvent,\n AutomationMetrics,\n AutomationProductEventRun,\n AutomationRun,\n AutomationRunEvent,\n AutomationRunEventType,\n AutomationRunStatus,\n} from '../domain/types.js';\nimport {\n CreateAutomationSchema,\n UpdateAutomationSchema,\n type CreateAutomationInput,\n type UpdateAutomationInput,\n AutomationSchema,\n} from '../domain/validation.js';\nimport {\n appendAutomationRunEvent,\n deleteAutomation,\n getAutomation,\n getAutomationRun,\n listAutomationRunEvents,\n listAutomationRuns,\n listAutomationRunsForProductEvent,\n listAutomations,\n saveAutomation,\n saveAutomationRun,\n saveAutomations,\n} from '../storage/index.js';\nimport { AutomationActionExecutor } from './action-executor.js';\n\nconst log = createLogger('AutomationService');\n\ntype TimerHandle = ReturnType<typeof setTimeout> & { unref?: () => void };\n\nconst DEFAULT_MAX_CONCURRENT_RUNS = 5;\nconst MISSED_RUN_STAGGER_MS = 5_000;\n\nexport class AutomationAlreadyRunningError extends Error {\n constructor(readonly automationId: string, readonly runningRunId?: string) {\n super(`Automation is already running: ${automationId}`);\n this.name = 'AutomationAlreadyRunningError';\n }\n}\n\nexport class AutomationService {\n private readonly executor = new AutomationActionExecutor();\n private timer: TimerHandle | null = null;\n private stopped = true;\n private runningScheduler = false;\n private deps: AutomationDeps = {};\n private maxConcurrentRuns = DEFAULT_MAX_CONCURRENT_RUNS;\n private readonly activeRuns = new Map<string, AbortController>();\n\n setDeps(deps: AutomationDeps): void {\n this.deps = { ...this.deps, ...deps };\n this.executor.setDeps(this.deps);\n }\n\n async initialize(options?: { maxConcurrentRuns?: number }): Promise<void> {\n this.maxConcurrentRuns = Math.max(1, Math.floor(options?.maxConcurrentRuns ?? DEFAULT_MAX_CONCURRENT_RUNS));\n this.stopped = false;\n await this.recomputeNextRuns({ catchUp: true });\n this.armTimer();\n log.info('Automation service initialized');\n }\n\n async stop(): Promise<void> {\n this.stopped = true;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n for (const controller of this.activeRuns.values()) {\n controller.abort();\n }\n log.info('Automation service stopped');\n }\n\n async create(input: CreateAutomationInput): Promise<Automation> {\n const parsed = CreateAutomationSchema.parse(input);\n const now = Date.now();\n const automation = AutomationSchema.parse({\n ...parsed,\n id: parsed.id?.trim() || randomUUID().slice(0, 12),\n enabled: parsed.enabled ?? true,\n safety: parsed.safety ?? { mode: 'auto_apply' },\n afterRun: parsed.afterRun ?? { kind: 'none' },\n state: parsed.state ?? {},\n createdAtMs: now,\n updatedAtMs: now,\n }) as Automation;\n automation.state.nextRunAtMs = computeNextAutomationRunAtMs(automation, now);\n saveAutomation(automation);\n this.armTimer();\n return automation;\n }\n\n async list(options?: { projectId?: string }): Promise<Automation[]> {\n return listAutomations(options);\n }\n\n async get(id: string): Promise<Automation | null> {\n return getAutomation(id);\n }\n\n async update(id: string, patch: UpdateAutomationInput): Promise<Automation | null> {\n const parsed = UpdateAutomationSchema.parse(patch);\n const current = getAutomation(id);\n if (!current) return null;\n const now = Date.now();\n const next = AutomationSchema.parse({\n ...current,\n ...parsed,\n id: current.id,\n createdAtMs: current.createdAtMs,\n updatedAtMs: now,\n state: {\n ...current.state,\n ...(parsed.state ?? {}),\n },\n }) as Automation;\n if ('enabled' in parsed || 'trigger' in parsed) {\n next.state.nextRunAtMs = computeNextAutomationRunAtMs(next, now);\n }\n saveAutomation(next);\n this.armTimer();\n return next;\n }\n\n async remove(id: string): Promise<boolean> {\n const automation = getAutomation(id);\n if (automation?.state.runningRunId) {\n this.activeRuns.get(automation.state.runningRunId)?.abort();\n }\n const removed = deleteAutomation(id);\n if (removed) {\n this.armTimer();\n }\n return removed;\n }\n\n async pause(id: string): Promise<Automation | null> {\n return this.update(id, { enabled: false });\n }\n\n async resume(id: string): Promise<Automation | null> {\n return this.update(id, { enabled: true });\n }\n\n async runNow(id: string): Promise<AutomationRun> {\n const automation = getAutomation(id);\n if (!automation) throw new Error(`Automation not found: ${id}`);\n if (automation.state.runningRunId) {\n throw new AutomationAlreadyRunningError(id, automation.state.runningRunId);\n }\n return this.startRun(automation, { manual: true });\n }\n\n async rerunFromRun(runId: string): Promise<AutomationRun> {\n const previous = getAutomationRun(runId);\n if (!previous) throw new Error(`Automation run not found: ${runId}`);\n const automation = getAutomation(previous.automationId);\n if (!automation) throw new Error(`Automation not found: ${previous.automationId}`);\n if (automation.state.runningRunId) {\n throw new AutomationAlreadyRunningError(automation.id, automation.state.runningRunId);\n }\n const triggerEvent = listAutomationRunEvents(runId)\n .map((event) => readAutomationEventFromRunEvent(event))\n .find((event): event is AutomationEvent => event !== null);\n return this.startRun(automation, triggerEvent ? { manual: false, event: triggerEvent } : { manual: true });\n }\n\n async triggerEvent(event: AutomationEvent): Promise<AutomationRun[]> {\n const normalized: AutomationEvent = {\n ...event,\n occurredAtMs: event.occurredAtMs ?? Date.now(),\n };\n const automations = listAutomations().filter(\n (automation) =>\n automation.enabled &&\n automation.trigger.kind === 'event' &&\n !automation.state.runningRunId &&\n matchesAutomationEvent(automation.trigger, normalized),\n );\n const availableSlots = Math.max(0, this.maxConcurrentRuns - this.activeRuns.size);\n const started: AutomationRun[] = [];\n for (const automation of automations.slice(0, availableSlots)) {\n started.push(await this.startRun(automation, { manual: false, event: normalized }));\n }\n return started;\n }\n\n async listRuns(options?: { automationId?: string; projectId?: string; limit?: number }): Promise<AutomationRun[]> {\n return listAutomationRuns(options);\n }\n\n async listRunsForProductEvent(options: {\n eventType: string;\n source?: string;\n payloadKey?: string;\n payloadValue?: string;\n limit?: number;\n }): Promise<AutomationProductEventRun[]> {\n return listAutomationRunsForProductEvent(options);\n }\n\n async getRun(runId: string): Promise<AutomationRun | null> {\n return getAutomationRun(runId);\n }\n\n async listRunEvents(runId: string): Promise<AutomationRunEvent[]> {\n return listAutomationRunEvents(runId);\n }\n\n async cancelRun(runId: string): Promise<boolean> {\n const controller = this.activeRuns.get(runId);\n if (!controller) return false;\n controller.abort();\n return true;\n }\n\n async getMetrics(): Promise<AutomationMetrics> {\n const automations = listAutomations();\n const enabled = automations.filter((automation) => automation.enabled);\n const next = enabled\n .filter((automation) => automation.state.nextRunAtMs != null)\n .toSorted((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0))[0];\n const oneHourAgo = Date.now() - 60 * 60_000;\n return {\n totalAutomations: automations.length,\n enabledAutomations: enabled.length,\n runningRuns: this.activeRuns.size,\n failedLastHour: automations.filter(\n (automation) =>\n (automation.state.lastRunStatus === 'failed' || automation.state.lastRunStatus === 'timeout') &&\n (automation.state.lastRunAtMs ?? 0) >= oneHourAgo,\n ).length,\n nextRun: next?.state.nextRunAtMs\n ? {\n automationId: next.id,\n name: next.name,\n runAtMs: next.state.nextRunAtMs,\n }\n : undefined,\n };\n }\n\n private async recomputeNextRuns(options?: { catchUp?: boolean }): Promise<void> {\n const now = Date.now();\n const automations = listAutomations().map((automation, index) => {\n const next: Automation = {\n ...automation,\n state: { ...automation.state },\n };\n if (next.state.runningRunId) {\n next.state.lastRunStatus = 'failed';\n next.state.lastError = 'Interrupted by gateway restart';\n next.state.consecutiveFailures = (next.state.consecutiveFailures ?? 0) + 1;\n delete next.state.runningRunId;\n }\n const computed = computeNextAutomationRunAtMs(next, now);\n next.state.nextRunAtMs =\n options?.catchUp && computed != null && computed <= now\n ? now + index * MISSED_RUN_STAGGER_MS\n : computed;\n return next;\n });\n saveAutomations(automations);\n }\n\n private armTimer(): void {\n if (this.stopped) return;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n const next = listAutomations()\n .filter((automation) => automation.enabled && automation.state.nextRunAtMs != null)\n .toSorted((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0))[0];\n if (!next?.state.nextRunAtMs) return;\n this.timer = setTimeout(() => {\n void this.onTimer();\n }, timerDelayUntil(next.state.nextRunAtMs)) as TimerHandle;\n this.timer.unref?.();\n }\n\n private async onTimer(): Promise<void> {\n if (this.stopped) return;\n if (this.runningScheduler) {\n this.armTimer();\n return;\n }\n this.runningScheduler = true;\n try {\n const now = Date.now();\n const due = listAutomations()\n .filter(\n (automation) =>\n automation.enabled &&\n automation.trigger.kind === 'schedule' &&\n automation.state.nextRunAtMs != null &&\n automation.state.nextRunAtMs <= now &&\n !automation.state.runningRunId,\n )\n .slice(0, this.maxConcurrentRuns);\n await Promise.all(due.map((automation) => this.startRun(automation, { manual: false })));\n } finally {\n this.runningScheduler = false;\n this.armTimer();\n }\n }\n\n private async startRun(\n automation: Automation,\n opts: { manual: boolean; event?: AutomationEvent },\n ): Promise<AutomationRun> {\n const now = Date.now();\n const run: AutomationRun = {\n id: randomUUID(),\n automationId: automation.id,\n automationName: automation.name,\n status: 'queued',\n triggerSnapshot: automation.trigger,\n actionSnapshot: automation.action,\n manual: opts.manual,\n createdAtMs: now,\n };\n saveAutomationRun(run);\n this.appendRunEvent(\n run,\n 'run.queued',\n opts.event\n ? `Event ${opts.event.type} queued automation`\n : opts.manual\n ? 'Manual run queued'\n : 'Scheduled run queued',\n {\n trigger: automation.trigger,\n actionKind: automation.action.kind,\n safety: automation.safety ?? { mode: 'auto_apply' },\n event: opts.event,\n },\n );\n const nextAutomation: Automation = {\n ...automation,\n state: {\n ...automation.state,\n runningRunId: run.id,\n },\n };\n saveAutomation(nextAutomation);\n\n void this.executeRun(nextAutomation, run).catch((err) => {\n log.error(\n { err, automationId: automation.id, runId: run.id },\n `Automation run failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n\n return run;\n }\n\n private async executeRun(automation: Automation, initialRun: AutomationRun): Promise<void> {\n const controller = new AbortController();\n this.activeRuns.set(initialRun.id, controller);\n const startedAtMs = Date.now();\n let run: AutomationRun = {\n ...initialRun,\n status: 'running',\n startedAtMs,\n };\n saveAutomationRun(run);\n this.appendRunEvent(run, 'run.started', 'Automation run started');\n\n let status: AutomationRunStatus = 'failed';\n let error: string | undefined;\n let activePhase: 'action' | 'after_run' = 'action';\n try {\n this.appendRunEvent(run, 'action.started', `Running ${automation.action.kind} action`, {\n actionKind: automation.action.kind,\n safety: automation.safety ?? { mode: 'auto_apply' },\n });\n const outcome = await this.executor.execute(automation, run, controller.signal);\n status = outcome.status;\n error = outcome.error;\n this.appendRunEvent(\n run,\n status === 'succeeded' ? 'action.completed' : 'action.failed',\n status === 'succeeded'\n ? `${automation.action.kind} action completed`\n : `${automation.action.kind} action ${status}`,\n {\n summary: outcome.summary,\n error: outcome.error,\n sessionKey: outcome.sessionKey,\n workflowRunId: outcome.workflowRunId,\n model: outcome.model,\n },\n );\n run = {\n ...run,\n status,\n summary: outcome.summary,\n error,\n sessionKey: outcome.sessionKey,\n workflowRunId: outcome.workflowRunId,\n model: outcome.model,\n };\n if ((automation.safety?.mode ?? 'auto_apply') !== 'auto_apply' && automation.afterRun?.kind === 'webhook') {\n this.appendRunEvent(run, 'after_run.completed', 'After-run webhook skipped by safety mode', {\n safety: automation.safety ?? { mode: 'auto_apply' },\n });\n } else if (automation.afterRun?.kind === 'webhook') {\n activePhase = 'after_run';\n this.appendRunEvent(run, 'after_run.started', 'Calling after-run webhook', {\n url: automation.afterRun.url,\n });\n await this.postAfterRunWebhook(automation.afterRun.url, run);\n this.appendRunEvent(run, 'after_run.completed', 'After-run webhook completed');\n }\n } catch (err) {\n error = err instanceof Error ? err.message : String(err);\n status = controller.signal.aborted ? 'cancelled' : 'failed';\n this.appendRunEvent(run, activePhase === 'after_run' ? 'after_run.failed' : 'action.failed', `Automation run ${status}`, {\n error,\n });\n run = { ...run, status, error };\n } finally {\n const endedAtMs = Date.now();\n run = {\n ...run,\n status,\n endedAtMs,\n durationMs: endedAtMs - startedAtMs,\n };\n saveAutomationRun(run);\n this.appendRunEvent(run, 'run.completed', `Automation run ${status}`, {\n status,\n durationMs: run.durationMs,\n error,\n });\n this.activeRuns.delete(initialRun.id);\n this.finishAutomationRun(automation.id, status, error, endedAtMs);\n try {\n this.deps.onRunCompleted?.(run);\n } catch (err) {\n log.warn({ err, automationId: automation.id, runId: run.id }, 'Automation completion hook failed');\n }\n }\n }\n\n private appendRunEvent(\n run: Pick<AutomationRun, 'id' | 'automationId'>,\n type: AutomationRunEventType,\n message: string,\n data?: unknown,\n ): void {\n appendAutomationRunEvent({\n id: randomUUID(),\n runId: run.id,\n automationId: run.automationId,\n type,\n message,\n data,\n createdAtMs: Date.now(),\n });\n }\n\n private finishAutomationRun(\n automationId: string,\n status: AutomationRunStatus,\n error: string | undefined,\n finishedAtMs: number,\n ): void {\n const current = getAutomation(automationId);\n if (!current) return;\n const failed = status === 'failed' || status === 'timeout';\n const consecutiveFailures = failed ? (current.state.consecutiveFailures ?? 0) + 1 : 0;\n const disableAfter = current.reliability?.disableAfterConsecutiveFailures;\n const shouldDisable = disableAfter != null && consecutiveFailures >= disableAfter;\n const next: Automation = {\n ...current,\n enabled: shouldDisable ? false : current.enabled,\n state: {\n ...current.state,\n lastRunAtMs: finishedAtMs,\n lastRunStatus: status,\n lastError: error,\n consecutiveFailures,\n },\n updatedAtMs: shouldDisable ? finishedAtMs : current.updatedAtMs,\n };\n delete next.state.runningRunId;\n next.state.nextRunAtMs = computeNextAutomationRunAtMs(next, finishedAtMs);\n saveAutomation(next);\n this.armTimer();\n }\n\n private async postAfterRunWebhook(url: string, run: AutomationRun): Promise<void> {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ run }),\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(`Automation webhook failed: HTTP ${response.status}${text ? ` ${text.slice(0, 200)}` : ''}`);\n }\n }\n}\n\nfunction matchesAutomationEvent(\n trigger: Extract<Automation['trigger'], { kind: 'event' }>,\n event: AutomationEvent,\n): boolean {\n if (trigger.eventType !== event.type) return false;\n if (trigger.source && trigger.source !== event.source) return false;\n const payloadMatch = trigger.payloadMatch;\n if (!payloadMatch) return true;\n const payload = event.payload ?? {};\n return Object.entries(payloadMatch).every(([key, expected]) => Object.is(payload[key], expected));\n}\n\nfunction readAutomationEventFromRunEvent(event: AutomationRunEvent): AutomationEvent | null {\n if (!event.data || typeof event.data !== 'object' || Array.isArray(event.data)) return null;\n const raw = (event.data as { event?: unknown }).event;\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const candidate = raw as Partial<AutomationEvent>;\n if (typeof candidate.type !== 'string' || !candidate.type.trim()) return null;\n return {\n type: candidate.type,\n source: typeof candidate.source === 'string' ? candidate.source : undefined,\n payload: candidate.payload && typeof candidate.payload === 'object' && !Array.isArray(candidate.payload)\n ? candidate.payload as Record<string, unknown>\n : undefined,\n occurredAtMs: typeof candidate.occurredAtMs === 'number' ? candidate.occurredAtMs : undefined,\n };\n}\n"],"mappings":"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"}
@@ -1,53 +1,53 @@
1
- export declare const BrowserNavigateSchema: import("@sinclair/typebox/build/cjs").TObject<{
2
- url: import("@sinclair/typebox/build/cjs").TString;
3
- waitFor: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TUnion<[import("@sinclair/typebox/build/cjs").TLiteral<"load">, import("@sinclair/typebox/build/cjs").TLiteral<"domcontentloaded">, import("@sinclair/typebox/build/cjs").TLiteral<"networkidle">]>>;
4
- }>;
5
- export declare const BrowserSnapshotSchema: import("@sinclair/typebox/build/cjs").TObject<{
6
- selector: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
7
- maxLength: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TNumber>;
8
- }>;
9
- export declare const BrowserClickSchema: import("@sinclair/typebox/build/cjs").TObject<{
10
- selector: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
11
- text: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
12
- role: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
13
- }>;
14
- export declare const BrowserTypeSchema: import("@sinclair/typebox/build/cjs").TObject<{
15
- selector: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
16
- label: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
17
- text: import("@sinclair/typebox/build/cjs").TString;
18
- pressEnter: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TBoolean>;
19
- }>;
20
- export declare const BrowserScrollSchema: import("@sinclair/typebox/build/cjs").TObject<{
21
- direction: import("@sinclair/typebox/build/cjs").TUnion<[import("@sinclair/typebox/build/cjs").TLiteral<"down">, import("@sinclair/typebox/build/cjs").TLiteral<"up">]>;
22
- amount: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TNumber>;
23
- }>;
24
- export declare const BrowserScreenshotSchema: import("@sinclair/typebox/build/cjs").TObject<{
25
- selector: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
26
- description: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
27
- }>;
28
- export declare const BrowserBackSchema: import("@sinclair/typebox/build/cjs").TObject<{
29
- waitFor: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TUnion<[import("@sinclair/typebox/build/cjs").TLiteral<"load">, import("@sinclair/typebox/build/cjs").TLiteral<"domcontentloaded">, import("@sinclair/typebox/build/cjs").TLiteral<"networkidle">]>>;
30
- }>;
31
- export declare const BrowserPressSchema: import("@sinclair/typebox/build/cjs").TObject<{
32
- key: import("@sinclair/typebox/build/cjs").TString;
33
- }>;
34
- export declare const BrowserConsoleSchema: import("@sinclair/typebox/build/cjs").TObject<{
35
- javascript: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
36
- }>;
37
- export declare const BrowserGetImagesSchema: import("@sinclair/typebox/build/cjs").TObject<{
38
- selector: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
39
- maxImages: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TNumber>;
40
- }>;
41
- export declare const BrowserCloseSchema: import("@sinclair/typebox/build/cjs").TObject<{}>;
42
- export declare const BrowserVisionSchema: import("@sinclair/typebox/build/cjs").TObject<{
43
- prompt: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
44
- selector: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
45
- }>;
46
- export declare const BrowserDialogSchema: import("@sinclair/typebox/build/cjs").TObject<{
47
- action: import("@sinclair/typebox/build/cjs").TUnion<[import("@sinclair/typebox/build/cjs").TLiteral<"accept">, import("@sinclair/typebox/build/cjs").TLiteral<"dismiss">]>;
48
- promptText: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
49
- }>;
50
- export declare const BrowserCdpSchema: import("@sinclair/typebox/build/cjs").TObject<{
51
- method: import("@sinclair/typebox/build/cjs").TString;
52
- params: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TRecord<import("@sinclair/typebox/build/cjs").TString, import("@sinclair/typebox/build/cjs").TUnknown>>;
1
+ export declare const BrowserNavigateSchema: import("@sinclair/typebox").TObject<{
2
+ url: import("@sinclair/typebox").TString;
3
+ waitFor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"load">, import("@sinclair/typebox").TLiteral<"domcontentloaded">, import("@sinclair/typebox").TLiteral<"networkidle">]>>;
4
+ }>;
5
+ export declare const BrowserSnapshotSchema: import("@sinclair/typebox").TObject<{
6
+ selector: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
7
+ maxLength: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
8
+ }>;
9
+ export declare const BrowserClickSchema: import("@sinclair/typebox").TObject<{
10
+ selector: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
11
+ text: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
12
+ role: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
13
+ }>;
14
+ export declare const BrowserTypeSchema: import("@sinclair/typebox").TObject<{
15
+ selector: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
16
+ label: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
17
+ text: import("@sinclair/typebox").TString;
18
+ pressEnter: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
19
+ }>;
20
+ export declare const BrowserScrollSchema: import("@sinclair/typebox").TObject<{
21
+ direction: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"down">, import("@sinclair/typebox").TLiteral<"up">]>;
22
+ amount: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
23
+ }>;
24
+ export declare const BrowserScreenshotSchema: import("@sinclair/typebox").TObject<{
25
+ selector: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
26
+ description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
27
+ }>;
28
+ export declare const BrowserBackSchema: import("@sinclair/typebox").TObject<{
29
+ waitFor: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"load">, import("@sinclair/typebox").TLiteral<"domcontentloaded">, import("@sinclair/typebox").TLiteral<"networkidle">]>>;
30
+ }>;
31
+ export declare const BrowserPressSchema: import("@sinclair/typebox").TObject<{
32
+ key: import("@sinclair/typebox").TString;
33
+ }>;
34
+ export declare const BrowserConsoleSchema: import("@sinclair/typebox").TObject<{
35
+ javascript: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
36
+ }>;
37
+ export declare const BrowserGetImagesSchema: import("@sinclair/typebox").TObject<{
38
+ selector: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
39
+ maxImages: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
40
+ }>;
41
+ export declare const BrowserCloseSchema: import("@sinclair/typebox").TObject<{}>;
42
+ export declare const BrowserVisionSchema: import("@sinclair/typebox").TObject<{
43
+ prompt: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
44
+ selector: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
45
+ }>;
46
+ export declare const BrowserDialogSchema: import("@sinclair/typebox").TObject<{
47
+ action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"accept">, import("@sinclair/typebox").TLiteral<"dismiss">]>;
48
+ promptText: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
49
+ }>;
50
+ export declare const BrowserCdpSchema: import("@sinclair/typebox").TObject<{
51
+ method: import("@sinclair/typebox").TString;
52
+ params: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
53
53
  }>;
@@ -0,0 +1,17 @@
1
+ import type { Config } from '../config/schema.js';
2
+ import type { ConnectorDefinition, ConnectorInstallInput, ConnectorPermissions } from '../connectors/types.js';
3
+ import { type SkillsStoreListParams } from '../agent/skills/marketplace/adapters/store/store-api-client.js';
4
+ export type StoreConnectorInstallPlan = {
5
+ packageName: string;
6
+ version: string;
7
+ definition: ConnectorDefinition;
8
+ permissions: ConnectorPermissions;
9
+ requiresRestart: false;
10
+ requiresOAuth: boolean;
11
+ };
12
+ export declare function listStoreConnectors(config: Config, params: SkillsStoreListParams): Promise<import("../agent/skills/skills-marketplace.js").SkillsStoreListResponse>;
13
+ export declare function getStoreConnectorInstallPlan(config: Config, packageName: string, version?: string): Promise<StoreConnectorInstallPlan>;
14
+ export declare function installStoreConnector(config: Config, packageName: string, input: ConnectorInstallInput, version?: string): Promise<{
15
+ instance: import("../connectors/types.js").ConnectorInstance;
16
+ plan: StoreConnectorInstallPlan;
17
+ }>;
@@ -0,0 +1,191 @@
1
+ import { installConnectorDefinition } from "../connectors/install.js";
2
+ import { downloadConnectorStoreZipBuffer, fetchStoreConnectorPackageDetail, listConnectorPackages, resolveSkillsStoreBaseUrl } from "../agent/skills/marketplace/adapters/store/store-api-client.js";
3
+ import { createHash } from "node:crypto";
4
+ import { isIP } from "node:net";
5
+ import AdmZip from "adm-zip";
6
+ //#region src/capabilities/store-connector.ts
7
+ function asRecord(value, label) {
8
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object.`);
9
+ return value;
10
+ }
11
+ function asString(value, label) {
12
+ if (typeof value !== "string" || !value.trim()) throw new Error(`${label} must be a non-empty string.`);
13
+ return value.trim();
14
+ }
15
+ function asStringArray(value, label) {
16
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string" || !item.trim())) throw new Error(`${label} must be an array of non-empty strings.`);
17
+ return value.map((item) => item.trim());
18
+ }
19
+ const NPM_PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
20
+ const EXACT_SEMVER = /^v?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
21
+ function assertSafeRemoteUrl(value) {
22
+ const urlString = asString(value, "Connector MCP endpoint");
23
+ let url;
24
+ try {
25
+ url = new URL(urlString);
26
+ } catch {
27
+ throw new Error("Connector MCP endpoint must be a valid URL.");
28
+ }
29
+ const hostname = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
30
+ if (url.protocol !== "https:" || url.username || url.password || hostname === "localhost" || hostname.endsWith(".localhost") || isIP(hostname)) throw new Error("Store connectors must use a public HTTPS MCP endpoint.");
31
+ return url.toString();
32
+ }
33
+ function readPermissions(value, isLocal) {
34
+ const permissions = asRecord(value, "Connector permissions");
35
+ if (permissions.localExec !== isLocal) {
36
+ if (isLocal) throw new Error("Local Store connectors must explicitly allow local command execution.");
37
+ throw new Error("Store connectors must explicitly deny local command execution.");
38
+ }
39
+ const filesystem = permissions.filesystem === void 0 ? [] : asStringArray(permissions.filesystem, "Connector filesystem permissions");
40
+ if (filesystem.length > 0) throw new Error("Store connectors cannot request filesystem access.");
41
+ const networkDomains = asStringArray(permissions.networkDomains, "Connector network domains");
42
+ if (!isLocal && networkDomains.length === 0) throw new Error("Store connectors must declare at least one network domain.");
43
+ return {
44
+ ...permissions.data === void 0 ? {} : { data: asStringArray(permissions.data, "Connector data permissions") },
45
+ networkDomains,
46
+ localExec: isLocal,
47
+ filesystem
48
+ };
49
+ }
50
+ function readPinnedLocalRuntime(runtime, template) {
51
+ if (runtime.localPackage === void 0) return null;
52
+ const localPackage = asRecord(runtime.localPackage, "Connector localPackage");
53
+ if (localPackage.registry !== "npm") throw new Error("Local Store connectors must use the npm registry.");
54
+ const name = asString(localPackage.name, "Connector local package name");
55
+ const version = asString(localPackage.version, "Connector local package version");
56
+ if (!NPM_PACKAGE_NAME.test(name) || !EXACT_SEMVER.test(version)) throw new Error("Local Store connectors must use a valid exact npm package version.");
57
+ if (template.command !== "npx" || JSON.stringify(asStringArray(template.args, "Connector local MCP arguments")) !== JSON.stringify(["--yes", `${name}@${version}`])) throw new Error("Local Store connectors must use the pinned npx launch form.");
58
+ for (const field of [
59
+ "url",
60
+ "env",
61
+ "cwd",
62
+ "workingDirectory",
63
+ "headers",
64
+ "transport"
65
+ ]) if (field in template) throw new Error("Local Store connectors cannot define additional MCP process fields.");
66
+ return {
67
+ registry: "npm",
68
+ name,
69
+ version
70
+ };
71
+ }
72
+ function readConnectorManifest(value, packageName, version, sha256) {
73
+ const manifest = asRecord(value, "Connector manifest");
74
+ if (asString(manifest.id, "Connector id") !== packageName) throw new Error("Connector manifest id does not match the store package name.");
75
+ const runtime = asRecord(manifest.runtime, "Connector runtime");
76
+ if (runtime.type !== "mcp") throw new Error("Store connectors must use the MCP runtime.");
77
+ const serverTemplate = asRecord(runtime.serverTemplate, "Connector MCP serverTemplate");
78
+ const localPackage = readPinnedLocalRuntime(runtime, serverTemplate);
79
+ const transport = serverTemplate.transport;
80
+ if (!localPackage && transport !== "streamable-http" && transport !== "sse") throw new Error("Store connectors must use streamable-http or sse transport.");
81
+ const authMode = asRecord(manifest.auth, "Connector auth").mode;
82
+ if (authMode !== "none" && authMode !== "apiKey" && authMode !== "oauth") throw new Error("Connector auth mode must be none, apiKey, or oauth.");
83
+ const category = asString(manifest.category, "Connector category");
84
+ if (![
85
+ "code",
86
+ "docs",
87
+ "browser",
88
+ "data",
89
+ "automation",
90
+ "custom"
91
+ ].includes(category)) throw new Error(`Unsupported connector category: ${category}`);
92
+ const capabilities = asStringArray(manifest.capabilities, "Connector capabilities");
93
+ const allowedCapabilities = new Set([
94
+ "tools",
95
+ "resources",
96
+ "prompts",
97
+ "context",
98
+ "events",
99
+ "auth.apiKey",
100
+ "auth.oauth",
101
+ "runtime.mcp.stdio",
102
+ "runtime.mcp.sse",
103
+ "runtime.mcp.streamableHttp"
104
+ ]);
105
+ if (capabilities.some((capability) => !allowedCapabilities.has(capability))) throw new Error("Connector manifest contains an unsupported capability.");
106
+ const setup = manifest.setup === void 0 ? {} : asRecord(manifest.setup, "Connector setup");
107
+ const permissions = readPermissions(manifest.permissions, Boolean(localPackage));
108
+ const endpoint = localPackage ? void 0 : assertSafeRemoteUrl(serverTemplate.url);
109
+ const hostname = endpoint ? new URL(endpoint).hostname : void 0;
110
+ if (hostname && permissions.networkDomains?.length && !permissions.networkDomains.includes(hostname)) throw new Error("Connector network permissions must include the MCP endpoint host.");
111
+ return {
112
+ id: packageName,
113
+ version,
114
+ displayName: asString(manifest.displayName, "Connector displayName"),
115
+ description: asString(manifest.description, "Connector description"),
116
+ category,
117
+ kind: "mcp",
118
+ source: "store",
119
+ capabilities,
120
+ ...Array.isArray(manifest.tags) ? { tags: asStringArray(manifest.tags, "Connector tags") } : {},
121
+ auth: { mode: authMode },
122
+ setup,
123
+ runtime: {
124
+ type: "mcp",
125
+ serverId: asString(runtime.serverId, "Connector MCP serverId"),
126
+ serverTemplate: localPackage ? serverTemplate : {
127
+ ...serverTemplate,
128
+ url: endpoint
129
+ },
130
+ ...localPackage ? { localPackage } : {}
131
+ },
132
+ permissions,
133
+ provenance: {
134
+ packageName,
135
+ sha256
136
+ }
137
+ };
138
+ }
139
+ function readConnectorManifestFromArchive(buffer) {
140
+ let archive;
141
+ try {
142
+ archive = new AdmZip(buffer);
143
+ } catch {
144
+ throw new Error("Store connector artifact is not a valid zip archive.");
145
+ }
146
+ const entry = archive.getEntries().find((candidate) => {
147
+ const path = candidate.entryName.replace(/\\/g, "/").replace(/^\/+/, "");
148
+ return !candidate.isDirectory && (path === "xopc.connector.json" || path.endsWith("/xopc.connector.json"));
149
+ });
150
+ if (!entry) throw new Error("Store connector artifact is missing xopc.connector.json.");
151
+ try {
152
+ return JSON.parse(entry.getData().toString("utf8"));
153
+ } catch {
154
+ throw new Error("Store connector manifest is not valid JSON.");
155
+ }
156
+ }
157
+ async function listStoreConnectors(config, params) {
158
+ return listConnectorPackages(resolveSkillsStoreBaseUrl(config), params);
159
+ }
160
+ async function getStoreConnectorInstallPlan(config, packageName, version) {
161
+ const storeBaseUrl = resolveSkillsStoreBaseUrl(config);
162
+ const detail = await fetchStoreConnectorPackageDetail(storeBaseUrl, packageName, version);
163
+ const sha256 = detail.latestVersion.sha256;
164
+ if (!sha256 || !/^[a-f0-9]{64}$/i.test(sha256)) throw new Error("Store connector version is missing a valid SHA-256 checksum.");
165
+ const archive = await downloadConnectorStoreZipBuffer(storeBaseUrl, detail.latestVersion.downloadUrl);
166
+ const actualSha256 = createHash("sha256").update(archive).digest("hex");
167
+ if (actualSha256 !== sha256.toLowerCase()) throw new Error("Store connector artifact checksum verification failed.");
168
+ const definition = readConnectorManifest(readConnectorManifestFromArchive(archive), detail.name, detail.latestVersion.version, actualSha256);
169
+ const storeManifest = readConnectorManifest(detail.latestVersion.manifest, detail.name, detail.latestVersion.version, actualSha256);
170
+ if (JSON.stringify(definition.runtime) !== JSON.stringify(storeManifest.runtime)) throw new Error("Store connector metadata does not match its verified artifact.");
171
+ return {
172
+ packageName: detail.name,
173
+ version: detail.latestVersion.version,
174
+ permissions: definition.permissions ?? {},
175
+ requiresRestart: false,
176
+ requiresOAuth: definition.auth.mode === "oauth",
177
+ definition
178
+ };
179
+ }
180
+ async function installStoreConnector(config, packageName, input, version) {
181
+ const plan = await getStoreConnectorInstallPlan(config, packageName, version);
182
+ if (plan.requiresOAuth && plan.definition.id !== "github") throw new Error("OAuth installation for store connectors is not available yet. Use an API-key connector or the built-in GitHub connector.");
183
+ return {
184
+ instance: await installConnectorDefinition(config, plan.definition, input),
185
+ plan
186
+ };
187
+ }
188
+ //#endregion
189
+ export { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors };
190
+
191
+ //# sourceMappingURL=store-connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-connector.js","names":[],"sources":["../../../src/capabilities/store-connector.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { isIP } from 'node:net';\n\nimport AdmZip from 'adm-zip';\n\nimport type { Config } from '../config/schema.js';\nimport { installConnectorDefinition } from '../connectors/install.js';\nimport type {\n ConnectorDefinition,\n ConnectorInstallInput,\n ConnectorPermissions,\n} from '../connectors/types.js';\nimport {\n downloadConnectorStoreZipBuffer,\n fetchStoreConnectorPackageDetail,\n listConnectorPackages,\n resolveSkillsStoreBaseUrl,\n type SkillsStoreListParams,\n} from '../agent/skills/marketplace/adapters/store/store-api-client.js';\n\ntype JsonRecord = Record<string, unknown>;\n\nexport type StoreConnectorInstallPlan = {\n packageName: string;\n version: string;\n definition: ConnectorDefinition;\n permissions: ConnectorPermissions;\n requiresRestart: false;\n requiresOAuth: boolean;\n};\n\nfunction asRecord(value: unknown, label: string): JsonRecord {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} must be an object.`);\n }\n return value as JsonRecord;\n}\n\nfunction asString(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value.trim()) {\n throw new Error(`${label} must be a non-empty string.`);\n }\n return value.trim();\n}\n\nfunction asStringArray(value: unknown, label: string): string[] {\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || !item.trim())) {\n throw new Error(`${label} must be an array of non-empty strings.`);\n }\n return value.map((item) => item.trim());\n}\n\nconst NPM_PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\\/)?[a-z0-9][a-z0-9._-]*$/;\nconst EXACT_SEMVER = /^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/;\n\nfunction assertSafeRemoteUrl(value: unknown): string {\n const urlString = asString(value, 'Connector MCP endpoint');\n let url: URL;\n try {\n url = new URL(urlString);\n } catch {\n throw new Error('Connector MCP endpoint must be a valid URL.');\n }\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n if (\n url.protocol !== 'https:' ||\n url.username ||\n url.password ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n isIP(hostname)\n ) {\n throw new Error('Store connectors must use a public HTTPS MCP endpoint.');\n }\n return url.toString();\n}\n\nfunction readPermissions(value: unknown, isLocal: boolean): ConnectorPermissions {\n const permissions = asRecord(value, 'Connector permissions');\n if (permissions.localExec !== isLocal) {\n if (isLocal) throw new Error('Local Store connectors must explicitly allow local command execution.');\n throw new Error('Store connectors must explicitly deny local command execution.');\n }\n const filesystem = permissions.filesystem === undefined\n ? []\n : asStringArray(permissions.filesystem, 'Connector filesystem permissions');\n if (filesystem.length > 0) {\n throw new Error('Store connectors cannot request filesystem access.');\n }\n const networkDomains = asStringArray(permissions.networkDomains, 'Connector network domains');\n if (!isLocal && networkDomains.length === 0) {\n throw new Error('Store connectors must declare at least one network domain.');\n }\n return {\n ...(permissions.data === undefined ? {} : { data: asStringArray(permissions.data, 'Connector data permissions') }),\n networkDomains,\n localExec: isLocal,\n filesystem,\n };\n}\n\nfunction readPinnedLocalRuntime(runtime: JsonRecord, template: JsonRecord): { registry: 'npm'; name: string; version: string } | null {\n if (runtime.localPackage === undefined) return null;\n const localPackage = asRecord(runtime.localPackage, 'Connector localPackage');\n if (localPackage.registry !== 'npm') {\n throw new Error('Local Store connectors must use the npm registry.');\n }\n const name = asString(localPackage.name, 'Connector local package name');\n const version = asString(localPackage.version, 'Connector local package version');\n if (!NPM_PACKAGE_NAME.test(name) || !EXACT_SEMVER.test(version)) {\n throw new Error('Local Store connectors must use a valid exact npm package version.');\n }\n if (template.command !== 'npx' ||\n JSON.stringify(asStringArray(template.args, 'Connector local MCP arguments')) !== JSON.stringify(['--yes', `${name}@${version}`])) {\n throw new Error('Local Store connectors must use the pinned npx launch form.');\n }\n for (const field of ['url', 'env', 'cwd', 'workingDirectory', 'headers', 'transport']) {\n if (field in template) throw new Error('Local Store connectors cannot define additional MCP process fields.');\n }\n return { registry: 'npm', name, version };\n}\n\nfunction readConnectorManifest(\n value: unknown,\n packageName: string,\n version: string,\n sha256: string,\n): ConnectorDefinition {\n const manifest = asRecord(value, 'Connector manifest');\n if (asString(manifest.id, 'Connector id') !== packageName) {\n throw new Error('Connector manifest id does not match the store package name.');\n }\n const runtime = asRecord(manifest.runtime, 'Connector runtime');\n if (runtime.type !== 'mcp') {\n throw new Error('Store connectors must use the MCP runtime.');\n }\n const serverTemplate = asRecord(runtime.serverTemplate, 'Connector MCP serverTemplate');\n const localPackage = readPinnedLocalRuntime(runtime, serverTemplate);\n const transport = serverTemplate.transport;\n if (!localPackage && transport !== 'streamable-http' && transport !== 'sse') {\n throw new Error('Store connectors must use streamable-http or sse transport.');\n }\n const auth = asRecord(manifest.auth, 'Connector auth');\n const authMode = auth.mode;\n if (authMode !== 'none' && authMode !== 'apiKey' && authMode !== 'oauth') {\n throw new Error('Connector auth mode must be none, apiKey, or oauth.');\n }\n const category = asString(manifest.category, 'Connector category');\n if (!['code', 'docs', 'browser', 'data', 'automation', 'custom'].includes(category)) {\n throw new Error(`Unsupported connector category: ${category}`);\n }\n const capabilities = asStringArray(manifest.capabilities, 'Connector capabilities');\n const allowedCapabilities = new Set([\n 'tools', 'resources', 'prompts', 'context', 'events', 'auth.apiKey', 'auth.oauth',\n 'runtime.mcp.stdio', 'runtime.mcp.sse', 'runtime.mcp.streamableHttp',\n ]);\n if (capabilities.some((capability) => !allowedCapabilities.has(capability))) {\n throw new Error('Connector manifest contains an unsupported capability.');\n }\n const setup = manifest.setup === undefined ? {} : asRecord(manifest.setup, 'Connector setup');\n const permissions = readPermissions(manifest.permissions, Boolean(localPackage));\n const endpoint = localPackage ? undefined : assertSafeRemoteUrl(serverTemplate.url);\n const hostname = endpoint ? new URL(endpoint).hostname : undefined;\n if (hostname && permissions.networkDomains?.length && !permissions.networkDomains.includes(hostname)) {\n throw new Error('Connector network permissions must include the MCP endpoint host.');\n }\n\n return {\n id: packageName,\n version,\n displayName: asString(manifest.displayName, 'Connector displayName'),\n description: asString(manifest.description, 'Connector description'),\n category: category as ConnectorDefinition['category'],\n kind: 'mcp',\n source: 'store',\n capabilities: capabilities as ConnectorDefinition['capabilities'],\n ...(Array.isArray(manifest.tags) ? { tags: asStringArray(manifest.tags, 'Connector tags') } : {}),\n auth: { mode: authMode },\n setup: setup as ConnectorDefinition['setup'],\n runtime: {\n type: 'mcp',\n serverId: asString(runtime.serverId, 'Connector MCP serverId'),\n serverTemplate: localPackage ? serverTemplate : { ...serverTemplate, url: endpoint },\n ...(localPackage ? { localPackage } : {}),\n },\n permissions,\n provenance: { packageName, sha256 },\n };\n}\n\nfunction readConnectorManifestFromArchive(buffer: Buffer): unknown {\n let archive: AdmZip;\n try {\n archive = new AdmZip(buffer);\n } catch {\n throw new Error('Store connector artifact is not a valid zip archive.');\n }\n const entry = archive.getEntries().find((candidate) => {\n const path = candidate.entryName.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n return !candidate.isDirectory && (path === 'xopc.connector.json' || path.endsWith('/xopc.connector.json'));\n });\n if (!entry) {\n throw new Error('Store connector artifact is missing xopc.connector.json.');\n }\n try {\n return JSON.parse(entry.getData().toString('utf8'));\n } catch {\n throw new Error('Store connector manifest is not valid JSON.');\n }\n}\n\nexport async function listStoreConnectors(config: Config, params: SkillsStoreListParams) {\n return listConnectorPackages(resolveSkillsStoreBaseUrl(config), params);\n}\n\nexport async function getStoreConnectorInstallPlan(\n config: Config,\n packageName: string,\n version?: string,\n): Promise<StoreConnectorInstallPlan> {\n const storeBaseUrl = resolveSkillsStoreBaseUrl(config);\n const detail = await fetchStoreConnectorPackageDetail(storeBaseUrl, packageName, version);\n const sha256 = detail.latestVersion.sha256;\n if (!sha256 || !/^[a-f0-9]{64}$/i.test(sha256)) {\n throw new Error('Store connector version is missing a valid SHA-256 checksum.');\n }\n const archive = await downloadConnectorStoreZipBuffer(storeBaseUrl, detail.latestVersion.downloadUrl);\n const actualSha256 = createHash('sha256').update(archive).digest('hex');\n if (actualSha256 !== sha256.toLowerCase()) {\n throw new Error('Store connector artifact checksum verification failed.');\n }\n const artifactManifest = readConnectorManifestFromArchive(archive);\n const definition = readConnectorManifest(\n artifactManifest,\n detail.name,\n detail.latestVersion.version,\n actualSha256,\n );\n const storeManifest = readConnectorManifest(\n detail.latestVersion.manifest,\n detail.name,\n detail.latestVersion.version,\n actualSha256,\n );\n if (JSON.stringify(definition.runtime) !== JSON.stringify(storeManifest.runtime)) {\n throw new Error('Store connector metadata does not match its verified artifact.');\n }\n return {\n packageName: detail.name,\n version: detail.latestVersion.version,\n permissions: definition.permissions ?? {},\n requiresRestart: false,\n requiresOAuth: definition.auth.mode === 'oauth',\n definition,\n };\n}\n\nexport async function installStoreConnector(\n config: Config,\n packageName: string,\n input: ConnectorInstallInput,\n version?: string,\n) {\n const plan = await getStoreConnectorInstallPlan(config, packageName, version);\n if (plan.requiresOAuth && plan.definition.id !== 'github') {\n throw new Error('OAuth installation for store connectors is not available yet. Use an API-key connector or the built-in GitHub connector.');\n }\n const instance = await installConnectorDefinition(config, plan.definition, input);\n return { instance, plan };\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function registerSkillCommand(): void;