@xopcai/xopc 0.0.126 → 0.0.128

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 (366) 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-C70vgt60.js → agent-avatar-dicebear-Dx3HQkOk.js} +1 -1
  4. package/dist/gateway/static/root/assets/agents-Ceb_WmSZ.js +2 -0
  5. package/dist/gateway/static/root/assets/app-management-settings-panel-DGtoXVvI.js +1 -0
  6. package/dist/gateway/static/root/assets/{appearance-settings-BHlahIDL.js → appearance-settings-BQQf_iLu.js} +1 -1
  7. package/dist/gateway/static/root/assets/apps-page-D05daQF8.js +1 -0
  8. package/dist/gateway/static/root/assets/{archive-plugin-B-aoIt0w.js → archive-plugin-HuCFa2UL.js} +1 -1
  9. package/dist/gateway/static/root/assets/{attachment-load-BD0G0FD5.js → attachment-load-N3csiRso.js} +1 -1
  10. package/dist/gateway/static/root/assets/{automation-suggestion-card-iJRVI7aZ.js → automation-suggestion-card-DeYEW2YQ.js} +1 -1
  11. package/dist/gateway/static/root/assets/automations-page-Dxn5-hGx.js +4 -0
  12. package/dist/gateway/static/root/assets/{binary-plugins-B0mNlVSz.js → binary-plugins-DnJO0VG7.js} +1 -1
  13. package/dist/gateway/static/root/assets/{block-editor-CJY9Lu5G.js → block-editor-DOAZkqfs.js} +27 -27
  14. package/dist/gateway/static/root/assets/browser-settings-page-DSB-ZKIX.js +8 -0
  15. package/dist/gateway/static/root/assets/capability-presets-api-DRCu-s6d.js +1 -0
  16. package/dist/gateway/static/root/assets/capability-presets-settings-panel-M7jOJxZX.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-C1iggCG3.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-Df0TJNgv.js +2 -0
  21. package/dist/gateway/static/root/assets/desktop-pet-MnqKnEgd.js +1 -0
  22. package/dist/gateway/static/root/assets/desktop-pet-settings-PRnTI9no.js +1 -0
  23. package/dist/gateway/static/root/assets/desktop-pet-sprite-DqZ6fbIj.js +1 -0
  24. package/dist/gateway/static/root/assets/directory-picker-path-field-DJNFtSWq.js +1 -0
  25. package/dist/gateway/static/root/assets/dreaming-settings-D0_2JavX.js +3 -0
  26. package/dist/gateway/static/root/assets/{extension-debug-page-BbyczVZ3.js → extension-debug-page-C4sQuETO.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-page-DLN1I3DR.js → extension-page-DhnpWAUJ.js} +1 -1
  28. package/dist/gateway/static/root/assets/extension-settings-page-D7JDxFGh.js +1 -0
  29. package/dist/gateway/static/root/assets/fetch-BMjlW0g1.js +1 -0
  30. package/dist/gateway/static/root/assets/gateway-config-api-B_VyPdKh.js +1 -0
  31. package/dist/gateway/static/root/assets/gateway-settings-C0TutwM5.js +1 -0
  32. package/dist/gateway/static/root/assets/{gateway-startup-retry-DEMad2wt.js → gateway-startup-retry-CY5W2Pp4.js} +1 -1
  33. package/dist/gateway/static/root/assets/goal-create-dialog-DrDGK2L5.js +1 -0
  34. package/dist/gateway/static/root/assets/goal-detail-page-aaIMRRor.js +4 -0
  35. package/dist/gateway/static/root/assets/goals-config-api-CzTu01a1.js +1 -0
  36. package/dist/gateway/static/root/assets/goals-page-CBfCPiNK.js +2 -0
  37. package/dist/gateway/static/root/assets/goals-settings-4rKUC3EH.js +1 -0
  38. package/dist/gateway/static/root/assets/heartbeat-settings-DqJBKlza.js +1 -0
  39. package/dist/gateway/static/root/assets/{html-workspace-editor-DV90ddkE.js → html-workspace-editor-COqmtESs.js} +1 -1
  40. package/dist/gateway/static/root/assets/index-38TSE7ng.js +257 -0
  41. package/dist/gateway/static/root/assets/index-EKmpPvZj.css +1 -0
  42. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-lKTg6St7.js → keyboard-shortcuts-settings-ClVhEihC.js} +1 -1
  43. package/dist/gateway/static/root/assets/logs-page-J8fw1O8x.js +2 -0
  44. package/dist/gateway/static/root/assets/{markdown-editor-BFOjBBla.js → markdown-editor-jD1LPiP-.js} +2 -2
  45. package/dist/gateway/static/root/assets/{markdown-split-Bv4k6iGJ.js → markdown-split-DQYDAL4r.js} +1 -1
  46. package/dist/gateway/static/root/assets/{media-plugins-Bbi8g3N8.js → media-plugins-o5fchHfb.js} +1 -1
  47. package/dist/gateway/static/root/assets/messages-YzjnURPJ.js +3 -0
  48. package/dist/gateway/static/root/assets/models-hub-panel-D9csuY5T.js +2 -0
  49. package/dist/gateway/static/root/assets/notes-page-CeWoUGI-.js +1 -0
  50. package/dist/gateway/static/root/assets/notes-workbench-D_oaF0Pq.js +2 -0
  51. package/dist/gateway/static/root/assets/{page-tabs-Cp395RYD.js → page-tabs-u0u41Gxz.js} +1 -1
  52. package/dist/gateway/static/root/assets/{preview-open-alternatives-DqV5OM4m.js → preview-open-alternatives-BaYRX55y.js} +1 -1
  53. package/dist/gateway/static/root/assets/project-detail-page-dkHzwhDL.js +1 -0
  54. package/dist/gateway/static/root/assets/projects-page-DBp2WExF.js +1 -0
  55. package/dist/gateway/static/root/assets/remote-access-hub-Cgzg4pNN.js +1 -0
  56. package/dist/gateway/static/root/assets/{save-bar-controls-BItmzAzI.js → save-bar-controls-8ebg7PIX.js} +1 -1
  57. package/dist/gateway/static/root/assets/{schedule-field-BQ8IjjCn.js → schedule-field-Cd7FPvsJ.js} +1 -1
  58. package/dist/gateway/static/root/assets/{schema-form-BRpD6x3d.js → schema-form-Bq9iqPeA.js} +1 -1
  59. package/dist/gateway/static/root/assets/sessions-page-vkORZvUB.js +1 -0
  60. package/dist/gateway/static/root/assets/settings-advanced-gate-BFJsnSvx.js +1 -0
  61. package/dist/gateway/static/root/assets/{settings-collapsible-section-BKSPQM4R.js → settings-collapsible-section-DaVKl6I7.js} +1 -1
  62. package/dist/gateway/static/root/assets/{settings-form-section-BmyfthNQ.js → settings-form-section-C92Shabe.js} +1 -1
  63. package/dist/gateway/static/root/assets/settings-loading-skeleton-EJwzElLr.js +1 -0
  64. package/dist/gateway/static/root/assets/settings-page-BLY6onMK.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-page-layout-Bls5tfbH.js → settings-page-layout-dTbdUfAB.js} +1 -1
  66. package/dist/gateway/static/root/assets/setup-status-panel-BU0JUWIA.js +1 -0
  67. package/dist/gateway/static/root/assets/share-preview-page-SgKIyNQ7.js +2 -0
  68. package/dist/gateway/static/root/assets/shares-settings-aiY_QGsl.js +1 -0
  69. package/dist/gateway/static/root/assets/skill-reload-api-C44tGvK7.js +1 -0
  70. package/dist/gateway/static/root/assets/skills-page-C1re61FQ.js +2 -0
  71. package/dist/gateway/static/root/assets/{system-settings-panel-DKDAojWM.js → system-settings-panel-CntJCZEg.js} +1 -1
  72. package/dist/gateway/static/root/assets/{typed-models-lib-BCCV4Kkp.js → typed-models-lib-CjULd6SF.js} +1 -1
  73. package/dist/gateway/static/root/assets/url-DFGNSBNT.js +1 -0
  74. package/dist/gateway/static/root/assets/use-channel-catalog-CPdJ0o0i.js +1 -0
  75. package/dist/gateway/static/root/assets/user-profile-settings-panel-DBgcbZfp.js +1 -0
  76. package/dist/gateway/static/root/assets/{utils-DPGVr3tS.js → utils-icmWvHl6.js} +1 -1
  77. package/dist/gateway/static/root/assets/vendor-codemirror-C1WKjCk5.js +45 -0
  78. package/dist/gateway/static/root/assets/voice-api-key-field-BfvNUIWI.js +1 -0
  79. package/dist/gateway/static/root/assets/work-item-detail-page-BYvZjBuJ.js +1 -0
  80. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BTkRVNAh.js → workflow-run-setup-panel-DMXd1znx.js} +2 -2
  81. package/dist/gateway/static/root/assets/{workflow-start-dialog-DAImVtdO.js → workflow-start-dialog-Dff4IHzz.js} +1 -1
  82. package/dist/gateway/static/root/assets/workflows-page-0-640fQi.js +18 -0
  83. package/dist/gateway/static/root/index.html +7 -6
  84. package/dist/package.js +1 -1
  85. package/dist/src/agent/agent-instance-gateway.d.ts +5 -0
  86. package/dist/src/agent/agent-manager.d.ts +17 -0
  87. package/dist/src/agent/agent-manager.js +125 -8
  88. package/dist/src/agent/agent-manager.js.map +1 -1
  89. package/dist/src/agent/capabilities/definitions.d.ts +167 -0
  90. package/dist/src/agent/capabilities/definitions.js +175 -0
  91. package/dist/src/agent/capabilities/definitions.js.map +1 -0
  92. package/dist/src/agent/capabilities/index.d.ts +2 -0
  93. package/dist/src/agent/capabilities/index.js +3 -0
  94. package/dist/src/agent/capabilities/registry.d.ts +10 -0
  95. package/dist/src/agent/capabilities/registry.js +51 -0
  96. package/dist/src/agent/capabilities/registry.js.map +1 -0
  97. package/dist/src/agent/goals/post-turn.js +23 -2
  98. package/dist/src/agent/goals/post-turn.js.map +1 -1
  99. package/dist/src/agent/messaging/command-handler.d.ts +4 -0
  100. package/dist/src/agent/messaging/command-handler.js +6 -0
  101. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  102. package/dist/src/agent/service/process-direct-one-shot.js +5 -3
  103. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  104. package/dist/src/agent/service/process-direct-streaming.js +4 -3
  105. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  106. package/dist/src/agent/service.d.ts +4 -0
  107. package/dist/src/agent/service.js +26 -0
  108. package/dist/src/agent/service.js.map +1 -1
  109. package/dist/src/agent/skills/hub-lock.d.ts +5 -5
  110. package/dist/src/agent/skills/hub-lock.js +12 -12
  111. package/dist/src/agent/skills/hub-lock.js.map +1 -1
  112. package/dist/src/agent/skills/hub-pull.d.ts +15 -0
  113. package/dist/src/agent/skills/hub-pull.js +299 -24
  114. package/dist/src/agent/skills/hub-pull.js.map +1 -1
  115. package/dist/src/agent/skills/index.js +4 -40
  116. package/dist/src/agent/skills/index.js.map +1 -1
  117. package/dist/src/agent/skills/install-target.d.ts +3 -0
  118. package/dist/src/agent/skills/install-target.js +11 -0
  119. package/dist/src/agent/skills/install-target.js.map +1 -0
  120. package/dist/src/agent/skills/managed-store.d.ts +5 -3
  121. package/dist/src/agent/skills/managed-store.js +10 -9
  122. package/dist/src/agent/skills/managed-store.js.map +1 -1
  123. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +5 -3
  124. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js.map +1 -1
  125. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.d.ts +21 -1
  126. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +62 -6
  127. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js.map +1 -1
  128. package/dist/src/agent/skills/marketplace/resolve-adapter.js +1 -1
  129. package/dist/src/agent/skills/marketplace/resolve-adapter.js.map +1 -1
  130. package/dist/src/agent/skills/parse-skill-metadata.js +9 -1
  131. package/dist/src/agent/skills/parse-skill-metadata.js.map +1 -1
  132. package/dist/src/agent/skills/skill-manage-ops.js +2 -2
  133. package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
  134. package/dist/src/agent/skills/skill-manager.d.ts +4 -0
  135. package/dist/src/agent/skills/skill-manager.js +18 -6
  136. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  137. package/dist/src/agent/skills/types.d.ts +5 -0
  138. package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
  139. package/dist/src/agent/skills/workspace-skills-dir.js +5 -1
  140. package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -1
  141. package/dist/src/agent/tools/automation-tool.d.ts +6 -6
  142. package/dist/src/agent/tools/browser/tool/schemas.d.ts +20 -20
  143. package/dist/src/agent/tools/composio-tool.d.ts +3 -3
  144. package/dist/src/agent/tools/desktop-pet-tool.d.ts +24 -0
  145. package/dist/src/agent/tools/desktop-pet-tool.js +90 -0
  146. package/dist/src/agent/tools/desktop-pet-tool.js.map +1 -0
  147. package/dist/src/agent/tools/factory.d.ts +5 -0
  148. package/dist/src/agent/tools/factory.js +22 -0
  149. package/dist/src/agent/tools/factory.js.map +1 -1
  150. package/dist/src/agent/tools/goal-tool.d.ts +16 -16
  151. package/dist/src/agent/tools/index.d.ts +2 -0
  152. package/dist/src/agent/tools/index.js +3 -1
  153. package/dist/src/agent/tools/skill-install-tool.d.ts +28 -0
  154. package/dist/src/agent/tools/skill-install-tool.js +81 -0
  155. package/dist/src/agent/tools/skill-install-tool.js.map +1 -0
  156. package/dist/src/agent/tools/skill-manage-tool.js +3 -6
  157. package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
  158. package/dist/src/agent/tools/tool-manual-tool.d.ts +2 -2
  159. package/dist/src/agent/tools/xopc-use-tool.d.ts +5 -5
  160. package/dist/src/automations/domain/types.d.ts +1 -0
  161. package/dist/src/automations/service/automation-service.js +9 -0
  162. package/dist/src/automations/service/automation-service.js.map +1 -1
  163. package/dist/src/browser/schemas.d.ts +52 -52
  164. package/dist/src/capabilities/store-connector.d.ts +17 -0
  165. package/dist/src/capabilities/store-connector.js +191 -0
  166. package/dist/src/capabilities/store-connector.js.map +1 -0
  167. package/dist/src/chat-commands/builtins/skill.d.ts +1 -0
  168. package/dist/src/chat-commands/builtins/skill.js +132 -0
  169. package/dist/src/chat-commands/builtins/skill.js.map +1 -0
  170. package/dist/src/chat-commands/context.d.ts +3 -0
  171. package/dist/src/chat-commands/context.js +2 -0
  172. package/dist/src/chat-commands/context.js.map +1 -1
  173. package/dist/src/chat-commands/index.d.ts +1 -0
  174. package/dist/src/chat-commands/index.js +3 -1
  175. package/dist/src/chat-commands/index.js.map +1 -1
  176. package/dist/src/chat-commands/types.d.ts +17 -0
  177. package/dist/src/cli/command-loaders.js +1 -0
  178. package/dist/src/cli/command-loaders.js.map +1 -1
  179. package/dist/src/cli/command-manifest.js +4 -0
  180. package/dist/src/cli/command-manifest.js.map +1 -1
  181. package/dist/src/cli/commands/connectors.d.ts +4 -0
  182. package/dist/src/cli/commands/connectors.js +96 -0
  183. package/dist/src/cli/commands/connectors.js.map +1 -0
  184. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  185. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  186. package/dist/src/cli/commands/skills.js +1 -1
  187. package/dist/src/config/agent-profile.js +1 -1
  188. package/dist/src/config/schema.js +2 -2
  189. package/dist/src/config/schema.js.map +1 -1
  190. package/dist/src/connectors/health.js +1 -1
  191. package/dist/src/connectors/install.js +3 -1
  192. package/dist/src/connectors/install.js.map +1 -1
  193. package/dist/src/connectors/materialize.js +2 -0
  194. package/dist/src/connectors/materialize.js.map +1 -1
  195. package/dist/src/connectors/types.d.ts +19 -1
  196. package/dist/src/extensions/install.js +1 -1
  197. package/dist/src/extensions/types/manifest.d.ts +1 -1
  198. package/dist/src/extensions/update.js +5 -3
  199. package/dist/src/extensions/update.js.map +1 -1
  200. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  201. package/dist/src/gateway/agent-builtin-tools.js +1 -0
  202. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  203. package/dist/src/gateway/agents-admin.js +1 -1
  204. package/dist/src/gateway/chat-stream/mapper.js +5 -1
  205. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  206. package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
  207. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  208. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  209. package/dist/src/gateway/hono/middleware/auth.d.ts +2 -2
  210. package/dist/src/gateway/hono/middleware/logger.d.ts +1 -1
  211. package/dist/src/gateway/hono/middleware/route-errors.d.ts +1 -1
  212. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +2 -2
  213. package/dist/src/gateway/hono/routes/capabilities.d.ts +3 -0
  214. package/dist/src/gateway/hono/routes/capabilities.js +79 -0
  215. package/dist/src/gateway/hono/routes/capabilities.js.map +1 -0
  216. package/dist/src/gateway/hono/routes/commands-skills.js +88 -3
  217. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  218. package/dist/src/gateway/hono/routes/connectors.js +2 -2
  219. package/dist/src/gateway/hono/routes/goals.js +212 -3
  220. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  221. package/dist/src/gateway/hono/routes/index.js +2 -0
  222. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  223. package/dist/src/gateway/hono/routes/lazy-bundles.js +10 -1
  224. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  225. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  226. package/dist/src/gateway/hono/routes/mobile.d.ts +3 -0
  227. package/dist/src/gateway/hono/routes/mobile.js +113 -0
  228. package/dist/src/gateway/hono/routes/mobile.js.map +1 -0
  229. package/dist/src/gateway/hono/routes/projects.js +45 -0
  230. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  231. package/dist/src/gateway/hono/routes/workspace.js +4 -1
  232. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  233. package/dist/src/gateway/hono/sse.d.ts +3 -3
  234. package/dist/src/gateway/service/marketplace-service.d.ts +23 -1
  235. package/dist/src/gateway/service/marketplace-service.js +57 -6
  236. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  237. package/dist/src/gateway/service/run-gateway-agent.js +6 -2
  238. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  239. package/dist/src/gateway/service.d.ts +2 -0
  240. package/dist/src/gateway/service.js +12 -2
  241. package/dist/src/gateway/service.js.map +1 -1
  242. package/dist/src/goals/goal-contract-draft.d.ts +15 -0
  243. package/dist/src/goals/goal-contract-draft.js +114 -0
  244. package/dist/src/goals/goal-contract-draft.js.map +1 -0
  245. package/dist/src/goals/goal-evidence-review.d.ts +15 -0
  246. package/dist/src/goals/goal-evidence-review.js +91 -0
  247. package/dist/src/goals/goal-evidence-review.js.map +1 -0
  248. package/dist/src/goals/goal-runner.js +3 -1
  249. package/dist/src/goals/goal-runner.js.map +1 -1
  250. package/dist/src/goals/goal-service.d.ts +17 -1
  251. package/dist/src/goals/goal-service.js +44 -3
  252. package/dist/src/goals/goal-service.js.map +1 -1
  253. package/dist/src/goals/goal-store.d.ts +18 -1
  254. package/dist/src/goals/goal-store.js +190 -1
  255. package/dist/src/goals/goal-store.js.map +1 -1
  256. package/dist/src/goals/index.d.ts +4 -0
  257. package/dist/src/goals/index.js +3 -1
  258. package/dist/src/goals/types.d.ts +42 -0
  259. package/dist/src/mcp/channel-bridge.js +1 -1
  260. package/dist/src/mobile/notification-service.d.ts +8 -0
  261. package/dist/src/mobile/notification-service.js +139 -0
  262. package/dist/src/mobile/notification-service.js.map +1 -0
  263. package/dist/src/mobile/notification-store.d.ts +28 -0
  264. package/dist/src/mobile/notification-store.js +134 -0
  265. package/dist/src/mobile/notification-store.js.map +1 -0
  266. package/dist/src/mobile/notification-types.d.ts +37 -0
  267. package/dist/src/mobile/notification-types.js +11 -0
  268. package/dist/src/mobile/notification-types.js.map +1 -0
  269. package/dist/src/pets/factory.d.ts +25 -0
  270. package/dist/src/pets/factory.js +327 -0
  271. package/dist/src/pets/factory.js.map +1 -0
  272. package/dist/src/pets/manifest.d.ts +2 -0
  273. package/dist/src/pets/manifest.js +16 -0
  274. package/dist/src/pets/manifest.js.map +1 -0
  275. package/dist/src/pets/validator.d.ts +12 -0
  276. package/dist/src/pets/validator.js +175 -0
  277. package/dist/src/pets/validator.js.map +1 -0
  278. package/dist/src/projects/project-service.d.ts +2 -0
  279. package/dist/src/projects/project-service.js +6 -0
  280. package/dist/src/projects/project-service.js.map +1 -1
  281. package/dist/src/projects/project-store.d.ts +1 -0
  282. package/dist/src/projects/project-store.js +14 -7
  283. package/dist/src/projects/project-store.js.map +1 -1
  284. package/dist/src/projects/types.d.ts +2 -0
  285. package/dist/src/session/session-title.js +22 -2
  286. package/dist/src/session/session-title.js.map +1 -1
  287. package/dist/src/storage/sqlite/migrations/025_project_pinned_at.sql +5 -0
  288. package/dist/src/storage/sqlite/migrations/026_goal_contracts.sql +10 -0
  289. package/dist/src/storage/sqlite/migrations/027_mobile_notifications.sql +43 -0
  290. package/dist/src/storage/sqlite/migrations/028_goal_evidence_requirements.sql +47 -0
  291. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  292. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  293. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  294. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  295. package/dist/src/storage/sqlite/schema.js +1 -1
  296. package/dist/src/storage/sqlite/schema.sql +44 -0
  297. package/dist/src/tui/tui-startup-resources.js +1 -1
  298. package/package.json +1 -1
  299. package/skills/THIRD_PARTY_NOTICES.md +16 -0
  300. package/skills/creative/algorithmic-art/SKILL.md +37 -0
  301. package/skills/creative/algorithmic-art/templates/generator-template.js +27 -0
  302. package/skills/creative/algorithmic-art/templates/viewer.html +27 -0
  303. package/skills/creative/hatch-pet/SKILL.md +63 -0
  304. package/skills/documents/doc-coauthoring/SKILL.md +40 -0
  305. package/skills/documents/doc-coauthoring/references/reader-review.md +9 -0
  306. package/skills/documents/docx/SKILL.md +40 -0
  307. package/skills/documents/docx/references/editing-checklist.md +8 -0
  308. package/skills/documents/docx/scripts/inspect_ooxml.py +36 -0
  309. package/skills/documents/docx/scripts/render_docx.py +33 -0
  310. package/skills/documents/pdf/SKILL.md +47 -0
  311. package/skills/documents/pdf/references/operations.md +16 -0
  312. package/skills/documents/pdf/scripts/inspect_pdf.py +41 -0
  313. package/skills/documents/pdf/scripts/render_pdf.py +32 -0
  314. package/skills/documents/pptx/SKILL.md +41 -0
  315. package/skills/documents/pptx/references/qa-checklist.md +6 -0
  316. package/skills/documents/pptx/scripts/inspect_ooxml.py +34 -0
  317. package/skills/documents/pptx/scripts/render_pptx.py +33 -0
  318. package/skills/engineering/define-goal/SKILL.md +41 -0
  319. package/skills/engineering/define-goal/references/objective-rubric.md +12 -0
  320. package/dist/gateway/static/root/assets/agents-DRYVahI-.js +0 -2
  321. package/dist/gateway/static/root/assets/app-management-settings-panel-D9-HW6cy.js +0 -1
  322. package/dist/gateway/static/root/assets/apps-page-BdJ1eQg3.js +0 -1
  323. package/dist/gateway/static/root/assets/automations-page-D8hYQbkl.js +0 -4
  324. package/dist/gateway/static/root/assets/browser-settings-page-CiWEO-Iy.js +0 -8
  325. package/dist/gateway/static/root/assets/capability-presets-api-Bgc8ag55.js +0 -1
  326. package/dist/gateway/static/root/assets/capability-presets-settings-panel-B1nIi0TC.js +0 -1
  327. package/dist/gateway/static/root/assets/channel-recipient-api-0sauApoC.js +0 -1
  328. package/dist/gateway/static/root/assets/channels-settings-BddPdqVo.js +0 -1
  329. package/dist/gateway/static/root/assets/connectors-page-Ba2GDhSE.js +0 -2
  330. package/dist/gateway/static/root/assets/directory-picker-path-field-CiEc4KmY.js +0 -1
  331. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +0 -1
  332. package/dist/gateway/static/root/assets/dreaming-settings-4bvpk5wr.js +0 -3
  333. package/dist/gateway/static/root/assets/extension-settings-page-D9VGHmYJ.js +0 -1
  334. package/dist/gateway/static/root/assets/fetch-5V96dUz3.js +0 -1
  335. package/dist/gateway/static/root/assets/gateway-config-api-BtIzObwp.js +0 -1
  336. package/dist/gateway/static/root/assets/gateway-settings-KFsGGDhg.js +0 -1
  337. package/dist/gateway/static/root/assets/goal-create-dialog-4PcF6Sh6.js +0 -1
  338. package/dist/gateway/static/root/assets/goal-detail-page-B482PSaG.js +0 -1
  339. package/dist/gateway/static/root/assets/goals-config-api-CVN7-pdM.js +0 -1
  340. package/dist/gateway/static/root/assets/goals-page-CUdgJuDn.js +0 -2
  341. package/dist/gateway/static/root/assets/goals-settings-IYCH3-Pi.js +0 -1
  342. package/dist/gateway/static/root/assets/heartbeat-settings-Cf_a2Bmz.js +0 -1
  343. package/dist/gateway/static/root/assets/index-CA2tR2vm.js +0 -256
  344. package/dist/gateway/static/root/assets/index-Ds3u0LOk.css +0 -1
  345. package/dist/gateway/static/root/assets/logs-page-BCporcNH.js +0 -2
  346. package/dist/gateway/static/root/assets/messages-C22hxE1N.js +0 -3
  347. package/dist/gateway/static/root/assets/models-hub-panel-D68Pyow7.js +0 -2
  348. package/dist/gateway/static/root/assets/notes-page-CuUMOiyv.js +0 -1
  349. package/dist/gateway/static/root/assets/notes-workbench-Dx2N5zTk.js +0 -2
  350. package/dist/gateway/static/root/assets/project-detail-page-sB8AzZi3.js +0 -1
  351. package/dist/gateway/static/root/assets/projects-page-LBnJqWK2.js +0 -1
  352. package/dist/gateway/static/root/assets/remote-access-hub-Dbj0o6SC.js +0 -1
  353. package/dist/gateway/static/root/assets/sessions-page-DhDZKspB.js +0 -1
  354. package/dist/gateway/static/root/assets/settings-advanced-gate-BvXLMNL6.js +0 -1
  355. package/dist/gateway/static/root/assets/settings-page-Cfm9UxAr.js +0 -1
  356. package/dist/gateway/static/root/assets/setup-status-panel-kQEsTGAs.js +0 -1
  357. package/dist/gateway/static/root/assets/share-preview-page-DbYZNAPb.js +0 -2
  358. package/dist/gateway/static/root/assets/shares-settings-BtR4B0kn.js +0 -1
  359. package/dist/gateway/static/root/assets/skill-reload-api-CJNVOWoK.js +0 -1
  360. package/dist/gateway/static/root/assets/skills-page-DcWDHrt3.js +0 -2
  361. package/dist/gateway/static/root/assets/use-channel-catalog-NBqg3iFY.js +0 -1
  362. package/dist/gateway/static/root/assets/user-profile-settings-panel-suQ2x-LB.js +0 -1
  363. package/dist/gateway/static/root/assets/vendor-codemirror-BvNgyE1Q.js +0 -45
  364. package/dist/gateway/static/root/assets/voice-api-key-field-DaJASKFP.js +0 -1
  365. package/dist/gateway/static/root/assets/work-item-detail-page-BrCZpAWh.js +0 -1
  366. package/dist/gateway/static/root/assets/workflows-page-vyJ8wSXm.js +0 -18
@@ -1 +1 @@
1
- {"version":3,"file":"skill-manage-tool.js","names":[],"sources":["../../../../src/agent/tools/skill-manage-tool.ts"],"sourcesContent":["import { Type, type Static } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport { existsSync, rmSync } from 'fs';\nimport { join } from 'path';\nimport { readFile, rm } from 'fs/promises';\n\nimport { resolveStateDir } from '../../config/paths.js';\nimport { createSkillConfigManager } from '../skills/config.js';\nimport type { SkillManager } from '../skills/skill-manager.js';\nimport {\n applyPatchToContent,\n atomicWriteUtf8,\n effectiveAgentWritePolicy,\n ensureCategorySegment,\n maxSkillMdChars,\n maxSupportFileBytes,\n mutatableSkillOrNull,\n isPathInsideDir,\n resolveCreateSkillDir,\n scanSkillDirOrError,\n validateSkillMdContent,\n validateSkillNameSegment,\n validateSupportingRelativePath,\n} from '../skills/skill-manage-ops.js';\n\nconst SkillManageSchema = Type.Object({\n action: Type.Union([\n Type.Literal('create'),\n Type.Literal('edit'),\n Type.Literal('patch'),\n Type.Literal('delete'),\n Type.Literal('write_file'),\n Type.Literal('remove_file'),\n ]),\n name: Type.Optional(Type.String({ description: 'Skill name (directory id / frontmatter name)' })),\n content: Type.Optional(Type.String({ description: 'Full SKILL.md for create or edit' })),\n category: Type.Optional(Type.String({ description: 'Optional single-segment category folder under skills root' })),\n write_target: Type.Optional(\n Type.Union([Type.Literal('global'), Type.Literal('workspace')], {\n description: 'Where to create the skill (default global). Respects skills.agentWritePolicy.',\n }),\n ),\n old_string: Type.Optional(Type.String()),\n new_string: Type.Optional(Type.String()),\n replace_all: Type.Optional(Type.Boolean({ default: false })),\n file_path: Type.Optional(\n Type.String({\n description: 'Relative path under skill dir (references/, templates/, scripts/, assets/)',\n }),\n ),\n file_content: Type.Optional(Type.String({ description: 'For write_file' })),\n});\n\nexport interface SkillManageToolDeps {\n getSkillManager: () => SkillManager | undefined;\n getWorkspace: () => string;\n onSkillsFilesystemMutate?: () => void;\n}\n\nfunction jsonResult(obj: Record<string, unknown>): AgentToolResult<{}> {\n return { content: [{ type: 'text', text: JSON.stringify(obj, null, 2) }], details: {} };\n}\n\nexport function createSkillManageTool(deps: SkillManageToolDeps): AgentTool {\n return {\n name: 'skill_manage',\n label: '🛠️ Skill',\n description:\n 'Create, edit, patch, or delete user skills under ~/.xopc/skills and/or workspace .xopc/skills/ (see skills.agentWritePolicy). ' +\n 'Also write_file / remove_file under references/, templates/, scripts/, assets/. ' +\n 'Bundled and extra-dir skills cannot be modified. Runs a security scan after writes.',\n parameters: SkillManageSchema,\n async execute(\n _toolCallId: string,\n params: Static<typeof SkillManageSchema>,\n ): Promise<AgentToolResult<{}>> {\n const mgr = deps.getSkillManager();\n if (!mgr) {\n return jsonResult({ success: false, error: 'Skill manager not available in this context.' });\n }\n\n const workspace = deps.getWorkspace();\n const skillsCfg = createSkillConfigManager(resolveStateDir()).load();\n const policy = effectiveAgentWritePolicy(skillsCfg);\n const mdMax = maxSkillMdChars(skillsCfg);\n const supMax = maxSupportFileBytes(skillsCfg);\n\n const notify = () => deps.onSkillsFilesystemMutate?.();\n\n try {\n switch (params.action) {\n case 'create': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const catErr = ensureCategorySegment(params.category);\n if (catErr) return jsonResult({ success: false, error: catErr });\n\n const md = validateSkillMdContent(params.content ?? '', name, mdMax);\n if (md.ok === false) return jsonResult({ success: false, error: md.error });\n\n if (mgr.hasSkill(name)) {\n return jsonResult({\n success: false,\n error: `A skill named \"${name}\" already exists. Use edit or choose another name.`,\n });\n }\n\n const target = params.write_target ?? 'global';\n const dirRes = resolveCreateSkillDir(name, params.category?.trim(), target, workspace, policy);\n if (dirRes.ok === false) return jsonResult({ success: false, error: dirRes.error });\n\n if (existsSync(dirRes.dir)) {\n return jsonResult({ success: false, error: `Directory already exists: ${dirRes.dir}` });\n }\n\n const skillMdPath = join(dirRes.dir, 'SKILL.md');\n try {\n await atomicWriteUtf8(skillMdPath, params.content!);\n const scanErr = await scanSkillDirOrError(dirRes.dir, name);\n if (scanErr) {\n rmSync(dirRes.dir, { recursive: true, force: true });\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n rmSync(dirRes.dir, { recursive: true, force: true });\n throw e;\n }\n\n notify();\n return jsonResult({\n success: true,\n message: `Skill \"${name}\" created.`,\n path: dirRes.dir,\n });\n }\n\n case 'edit': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable (bundled/extra or policy).`,\n });\n }\n\n const md = validateSkillMdContent(params.content ?? '', name, mdMax);\n if (md.ok === false) return jsonResult({ success: false, error: md.error });\n\n const skillMdPath = join(sk.baseDir, 'SKILL.md');\n let previous: string;\n try {\n previous = await readFile(skillMdPath, 'utf-8');\n } catch {\n return jsonResult({ success: false, error: 'SKILL.md could not be read.' });\n }\n\n try {\n await atomicWriteUtf8(skillMdPath, params.content!);\n const scanErr = await scanSkillDirOrError(sk.baseDir, name);\n if (scanErr) {\n await atomicWriteUtf8(skillMdPath, previous);\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n await atomicWriteUtf8(skillMdPath, previous).catch(() => {});\n throw e;\n }\n\n notify();\n return jsonResult({ success: true, message: `Skill \"${name}\" updated.`, path: sk.baseDir });\n }\n\n case 'patch': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n let relPath: string | undefined;\n if (params.file_path?.trim()) {\n const pErr = validateSupportingRelativePath(params.file_path.trim());\n if (pErr) return jsonResult({ success: false, error: pErr });\n relPath = params.file_path.trim().replace(/\\\\/g, '/');\n }\n\n const targetPath = relPath ? join(sk.baseDir, relPath) : join(sk.baseDir, 'SKILL.md');\n if (!isPathInsideDir(sk.baseDir, targetPath)) {\n return jsonResult({ success: false, error: 'Resolved path escapes skill directory.' });\n }\n\n let previous: string;\n try {\n previous = await readFile(targetPath, 'utf-8');\n } catch {\n return jsonResult({ success: false, error: `File not found: ${relPath ?? 'SKILL.md'}` });\n }\n\n const patched = applyPatchToContent(\n previous,\n params.old_string ?? '',\n params.new_string ?? '',\n params.replace_all === true,\n );\n if (patched.ok === false) return jsonResult({ success: false, error: patched.error });\n\n if (!relPath) {\n const md = validateSkillMdContent(patched.next, name, mdMax);\n if (md.ok === false) return jsonResult({ success: false, error: `Patch rejected: ${md.error}` });\n } else if (Buffer.byteLength(patched.next, 'utf-8') > supMax) {\n return jsonResult({ success: false, error: `File exceeds size limit (${supMax} bytes).` });\n }\n\n try {\n await atomicWriteUtf8(targetPath, patched.next);\n const scanErr = await scanSkillDirOrError(sk.baseDir, name);\n if (scanErr) {\n await atomicWriteUtf8(targetPath, previous);\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n await atomicWriteUtf8(targetPath, previous).catch(() => {});\n throw e;\n }\n\n notify();\n return jsonResult({\n success: true,\n message: `Patched ${relPath ?? 'SKILL.md'} (${patched.replacements} replacement(s)).`,\n });\n }\n\n case 'delete': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n rmSync(sk.baseDir, { recursive: true, force: true });\n notify();\n return jsonResult({ success: true, message: `Skill \"${name}\" removed.`, path: sk.baseDir });\n }\n\n case 'write_file': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n const pErr = validateSupportingRelativePath(params.file_path ?? '');\n if (pErr) return jsonResult({ success: false, error: pErr });\n const rel = params.file_path!.trim().replace(/\\\\/g, '/');\n const targetPath = join(sk.baseDir, rel);\n if (!isPathInsideDir(sk.baseDir, targetPath)) {\n return jsonResult({ success: false, error: 'Resolved path escapes skill directory.' });\n }\n\n const body = params.file_content ?? '';\n if (Buffer.byteLength(body, 'utf-8') > supMax) {\n return jsonResult({ success: false, error: `File exceeds size limit (${supMax} bytes).` });\n }\n\n const existed = existsSync(targetPath);\n let previous: string | null = null;\n if (existed) {\n try {\n previous = await readFile(targetPath, 'utf-8');\n } catch {\n previous = null;\n }\n }\n\n try {\n await atomicWriteUtf8(targetPath, body);\n const scanErr = await scanSkillDirOrError(sk.baseDir, name);\n if (scanErr) {\n if (previous !== null) await atomicWriteUtf8(targetPath, previous);\n else await rm(targetPath, { force: true });\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n if (previous !== null) await atomicWriteUtf8(targetPath, previous).catch(() => {});\n else await rm(targetPath, { force: true }).catch(() => {});\n throw e;\n }\n\n notify();\n return jsonResult({\n success: true,\n message: `Wrote ${rel}.`,\n });\n }\n\n case 'remove_file': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n const pErr = validateSupportingRelativePath(params.file_path ?? '');\n if (pErr) return jsonResult({ success: false, error: pErr });\n const rel = params.file_path!.trim().replace(/\\\\/g, '/');\n const targetPath = join(sk.baseDir, rel);\n if (!isPathInsideDir(sk.baseDir, targetPath)) {\n return jsonResult({ success: false, error: 'Resolved path escapes skill directory.' });\n }\n\n if (!existsSync(targetPath)) {\n return jsonResult({ success: false, error: `File not found: ${rel}` });\n }\n\n await rm(targetPath, { force: true });\n await scanSkillDirOrError(sk.baseDir, name);\n notify();\n return jsonResult({ success: true, message: `Removed ${rel}.` });\n }\n\n default:\n return jsonResult({ success: false, error: 'Unknown action.' });\n }\n } catch (e) {\n return jsonResult({\n success: false,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n },\n } as any;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"skill-manage-tool.js","names":[],"sources":["../../../../src/agent/tools/skill-manage-tool.ts"],"sourcesContent":["import { Type, type Static } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport { existsSync, rmSync } from 'fs';\nimport { join } from 'path';\nimport { readFile, rm } from 'fs/promises';\n\nimport { resolveStateDir } from '../../config/paths.js';\nimport { createSkillConfigManager } from '../skills/config.js';\nimport type { SkillManager } from '../skills/skill-manager.js';\nimport {\n applyPatchToContent,\n atomicWriteUtf8,\n effectiveAgentWritePolicy,\n ensureCategorySegment,\n maxSkillMdChars,\n maxSupportFileBytes,\n mutatableSkillOrNull,\n isPathInsideDir,\n resolveCreateSkillDir,\n scanSkillDirOrError,\n validateSkillMdContent,\n validateSkillNameSegment,\n validateSupportingRelativePath,\n} from '../skills/skill-manage-ops.js';\n\nconst SkillManageSchema = Type.Object({\n action: Type.Union([\n Type.Literal('create'),\n Type.Literal('edit'),\n Type.Literal('patch'),\n Type.Literal('delete'),\n Type.Literal('write_file'),\n Type.Literal('remove_file'),\n ]),\n name: Type.Optional(Type.String({ description: 'Skill name (directory id / frontmatter name)' })),\n content: Type.Optional(Type.String({ description: 'Full SKILL.md for create or edit' })),\n category: Type.Optional(Type.String({ description: 'Optional single-segment category folder under skills root' })),\n write_target: Type.Optional(\n Type.Union([Type.Literal('global'), Type.Literal('workspace')], {\n description:\n 'Where to create the skill. Defaults to workspace. Use global only when the user explicitly asks for a global/personal skill. Respects skills.agentWritePolicy.',\n }),\n ),\n old_string: Type.Optional(Type.String()),\n new_string: Type.Optional(Type.String()),\n replace_all: Type.Optional(Type.Boolean({ default: false })),\n file_path: Type.Optional(\n Type.String({\n description: 'Relative path under skill dir (references/, templates/, scripts/, assets/)',\n }),\n ),\n file_content: Type.Optional(Type.String({ description: 'For write_file' })),\n});\n\nexport interface SkillManageToolDeps {\n getSkillManager: () => SkillManager | undefined;\n getWorkspace: () => string;\n onSkillsFilesystemMutate?: () => void;\n}\n\nfunction jsonResult(obj: Record<string, unknown>): AgentToolResult<{}> {\n return { content: [{ type: 'text', text: JSON.stringify(obj, null, 2) }], details: {} };\n}\n\nexport function createSkillManageTool(deps: SkillManageToolDeps): AgentTool {\n return {\n name: 'skill_manage',\n label: '🛠️ Skill',\n description:\n 'Create, edit, patch, or delete user skills under ~/.xopc/skills and/or workspace .xopc/skills/ (see skills.agentWritePolicy). ' +\n 'Also write_file / remove_file under references/, templates/, scripts/, assets/. ' +\n 'Bundled and extra-dir skills cannot be modified. Runs a security scan after writes.',\n parameters: SkillManageSchema,\n async execute(\n _toolCallId: string,\n params: Static<typeof SkillManageSchema>,\n ): Promise<AgentToolResult<{}>> {\n const mgr = deps.getSkillManager();\n if (!mgr) {\n return jsonResult({ success: false, error: 'Skill manager not available in this context.' });\n }\n\n const workspace = deps.getWorkspace();\n const skillsCfg = createSkillConfigManager(resolveStateDir()).load();\n const policy = effectiveAgentWritePolicy(skillsCfg);\n const mdMax = maxSkillMdChars(skillsCfg);\n const supMax = maxSupportFileBytes(skillsCfg);\n\n const notify = () => deps.onSkillsFilesystemMutate?.();\n\n try {\n switch (params.action) {\n case 'create': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const catErr = ensureCategorySegment(params.category);\n if (catErr) return jsonResult({ success: false, error: catErr });\n\n const md = validateSkillMdContent(params.content ?? '', name, mdMax);\n if (md.ok === false) return jsonResult({ success: false, error: md.error });\n\n const target = params.write_target ?? 'workspace';\n const dirRes = resolveCreateSkillDir(name, params.category?.trim(), target, workspace, policy);\n if (dirRes.ok === false) return jsonResult({ success: false, error: dirRes.error });\n\n if (existsSync(dirRes.dir)) {\n return jsonResult({ success: false, error: `Directory already exists: ${dirRes.dir}` });\n }\n\n const skillMdPath = join(dirRes.dir, 'SKILL.md');\n try {\n await atomicWriteUtf8(skillMdPath, params.content!);\n const scanErr = await scanSkillDirOrError(dirRes.dir, name);\n if (scanErr) {\n rmSync(dirRes.dir, { recursive: true, force: true });\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n rmSync(dirRes.dir, { recursive: true, force: true });\n throw e;\n }\n\n notify();\n return jsonResult({\n success: true,\n message: `Skill \"${name}\" created.`,\n target,\n path: dirRes.dir,\n });\n }\n\n case 'edit': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable (bundled/extra or policy).`,\n });\n }\n\n const md = validateSkillMdContent(params.content ?? '', name, mdMax);\n if (md.ok === false) return jsonResult({ success: false, error: md.error });\n\n const skillMdPath = join(sk.baseDir, 'SKILL.md');\n let previous: string;\n try {\n previous = await readFile(skillMdPath, 'utf-8');\n } catch {\n return jsonResult({ success: false, error: 'SKILL.md could not be read.' });\n }\n\n try {\n await atomicWriteUtf8(skillMdPath, params.content!);\n const scanErr = await scanSkillDirOrError(sk.baseDir, name);\n if (scanErr) {\n await atomicWriteUtf8(skillMdPath, previous);\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n await atomicWriteUtf8(skillMdPath, previous).catch(() => {});\n throw e;\n }\n\n notify();\n return jsonResult({ success: true, message: `Skill \"${name}\" updated.`, path: sk.baseDir });\n }\n\n case 'patch': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n let relPath: string | undefined;\n if (params.file_path?.trim()) {\n const pErr = validateSupportingRelativePath(params.file_path.trim());\n if (pErr) return jsonResult({ success: false, error: pErr });\n relPath = params.file_path.trim().replace(/\\\\/g, '/');\n }\n\n const targetPath = relPath ? join(sk.baseDir, relPath) : join(sk.baseDir, 'SKILL.md');\n if (!isPathInsideDir(sk.baseDir, targetPath)) {\n return jsonResult({ success: false, error: 'Resolved path escapes skill directory.' });\n }\n\n let previous: string;\n try {\n previous = await readFile(targetPath, 'utf-8');\n } catch {\n return jsonResult({ success: false, error: `File not found: ${relPath ?? 'SKILL.md'}` });\n }\n\n const patched = applyPatchToContent(\n previous,\n params.old_string ?? '',\n params.new_string ?? '',\n params.replace_all === true,\n );\n if (patched.ok === false) return jsonResult({ success: false, error: patched.error });\n\n if (!relPath) {\n const md = validateSkillMdContent(patched.next, name, mdMax);\n if (md.ok === false) return jsonResult({ success: false, error: `Patch rejected: ${md.error}` });\n } else if (Buffer.byteLength(patched.next, 'utf-8') > supMax) {\n return jsonResult({ success: false, error: `File exceeds size limit (${supMax} bytes).` });\n }\n\n try {\n await atomicWriteUtf8(targetPath, patched.next);\n const scanErr = await scanSkillDirOrError(sk.baseDir, name);\n if (scanErr) {\n await atomicWriteUtf8(targetPath, previous);\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n await atomicWriteUtf8(targetPath, previous).catch(() => {});\n throw e;\n }\n\n notify();\n return jsonResult({\n success: true,\n message: `Patched ${relPath ?? 'SKILL.md'} (${patched.replacements} replacement(s)).`,\n });\n }\n\n case 'delete': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n rmSync(sk.baseDir, { recursive: true, force: true });\n notify();\n return jsonResult({ success: true, message: `Skill \"${name}\" removed.`, path: sk.baseDir });\n }\n\n case 'write_file': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n const pErr = validateSupportingRelativePath(params.file_path ?? '');\n if (pErr) return jsonResult({ success: false, error: pErr });\n const rel = params.file_path!.trim().replace(/\\\\/g, '/');\n const targetPath = join(sk.baseDir, rel);\n if (!isPathInsideDir(sk.baseDir, targetPath)) {\n return jsonResult({ success: false, error: 'Resolved path escapes skill directory.' });\n }\n\n const body = params.file_content ?? '';\n if (Buffer.byteLength(body, 'utf-8') > supMax) {\n return jsonResult({ success: false, error: `File exceeds size limit (${supMax} bytes).` });\n }\n\n const existed = existsSync(targetPath);\n let previous: string | null = null;\n if (existed) {\n try {\n previous = await readFile(targetPath, 'utf-8');\n } catch {\n previous = null;\n }\n }\n\n try {\n await atomicWriteUtf8(targetPath, body);\n const scanErr = await scanSkillDirOrError(sk.baseDir, name);\n if (scanErr) {\n if (previous !== null) await atomicWriteUtf8(targetPath, previous);\n else await rm(targetPath, { force: true });\n return jsonResult({ success: false, error: scanErr });\n }\n } catch (e) {\n if (previous !== null) await atomicWriteUtf8(targetPath, previous).catch(() => {});\n else await rm(targetPath, { force: true }).catch(() => {});\n throw e;\n }\n\n notify();\n return jsonResult({\n success: true,\n message: `Wrote ${rel}.`,\n });\n }\n\n case 'remove_file': {\n const nameErr = validateSkillNameSegment(params.name ?? '', 'name');\n if (nameErr) return jsonResult({ success: false, error: nameErr });\n const name = params.name!.trim();\n\n const sk = mutatableSkillOrNull(mgr.findSkill(name), workspace, policy);\n if (!sk) {\n return jsonResult({\n success: false,\n error: `Skill \"${name}\" not found or not writable.`,\n });\n }\n\n const pErr = validateSupportingRelativePath(params.file_path ?? '');\n if (pErr) return jsonResult({ success: false, error: pErr });\n const rel = params.file_path!.trim().replace(/\\\\/g, '/');\n const targetPath = join(sk.baseDir, rel);\n if (!isPathInsideDir(sk.baseDir, targetPath)) {\n return jsonResult({ success: false, error: 'Resolved path escapes skill directory.' });\n }\n\n if (!existsSync(targetPath)) {\n return jsonResult({ success: false, error: `File not found: ${rel}` });\n }\n\n await rm(targetPath, { force: true });\n await scanSkillDirOrError(sk.baseDir, name);\n notify();\n return jsonResult({ success: true, message: `Removed ${rel}.` });\n }\n\n default:\n return jsonResult({ success: false, error: 'Unknown action.' });\n }\n } catch (e) {\n return jsonResult({\n success: false,\n error: e instanceof Error ? e.message : String(e),\n });\n }\n },\n } as any;\n}\n"],"mappings":";;;;;;;;;YAMwD;AAmBxD,MAAM,oBAAoB,KAAK,OAAO;CACpC,QAAQ,KAAK,MAAM;EACjB,KAAK,QAAQ,SAAS;EACtB,KAAK,QAAQ,OAAO;EACpB,KAAK,QAAQ,QAAQ;EACrB,KAAK,QAAQ,SAAS;EACtB,KAAK,QAAQ,aAAa;EAC1B,KAAK,QAAQ,cAAc;EAC5B,CAAC;CACF,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,gDAAgD,CAAC,CAAC;CACjG,SAAS,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,oCAAoC,CAAC,CAAC;CACxF,UAAU,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,6DAA6D,CAAC,CAAC;CAClH,cAAc,KAAK,SACjB,KAAK,MAAM,CAAC,KAAK,QAAQ,SAAS,EAAE,KAAK,QAAQ,YAAY,CAAC,EAAE,EAC9D,aACE,kKACH,CAAC,CACH;CACD,YAAY,KAAK,SAAS,KAAK,QAAQ,CAAC;CACxC,YAAY,KAAK,SAAS,KAAK,QAAQ,CAAC;CACxC,aAAa,KAAK,SAAS,KAAK,QAAQ,EAAE,SAAS,OAAO,CAAC,CAAC;CAC5D,WAAW,KAAK,SACd,KAAK,OAAO,EACV,aAAa,8EACd,CAAC,CACH;CACD,cAAc,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,kBAAkB,CAAC,CAAC;CAC5E,CAAC;AAQF,SAAS,WAAW,KAAmD;AACrE,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,KAAK,MAAM,EAAE;GAAE,CAAC;EAAE,SAAS,EAAE;EAAE;;AAGzF,SAAgB,sBAAsB,MAAsC;AAC1E,QAAO;EACL,MAAM;EACN,OAAO;EACP,aACE;EAGF,YAAY;EACZ,MAAM,QACJ,aACA,QAC8B;GAC9B,MAAM,MAAM,KAAK,iBAAiB;AAClC,OAAI,CAAC,IACH,QAAO,WAAW;IAAE,SAAS;IAAO,OAAO;IAAgD,CAAC;GAG9F,MAAM,YAAY,KAAK,cAAc;GACrC,MAAM,YAAY,yBAAyB,iBAAiB,CAAC,CAAC,MAAM;GACpE,MAAM,SAAS,0BAA0B,UAAU;GACnD,MAAM,QAAQ,gBAAgB,UAAU;GACxC,MAAM,SAAS,oBAAoB,UAAU;GAE7C,MAAM,eAAe,KAAK,4BAA4B;AAEtD,OAAI;AACF,YAAQ,OAAO,QAAf;KACE,KAAK,UAAU;MACb,MAAM,UAAU,yBAAyB,OAAO,QAAQ,IAAI,OAAO;AACnE,UAAI,QAAS,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAS,CAAC;MAClE,MAAM,OAAO,OAAO,KAAM,MAAM;MAEhC,MAAM,SAAS,sBAAsB,OAAO,SAAS;AACrD,UAAI,OAAQ,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAQ,CAAC;MAEhE,MAAM,KAAK,uBAAuB,OAAO,WAAW,IAAI,MAAM,MAAM;AACpE,UAAI,GAAG,OAAO,MAAO,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,GAAG;OAAO,CAAC;MAE3E,MAAM,SAAS,OAAO,gBAAgB;MACtC,MAAM,SAAS,sBAAsB,MAAM,OAAO,UAAU,MAAM,EAAE,QAAQ,WAAW,OAAO;AAC9F,UAAI,OAAO,OAAO,MAAO,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,OAAO;OAAO,CAAC;AAEnF,UAAI,WAAW,OAAO,IAAI,CACxB,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,6BAA6B,OAAO;OAAO,CAAC;MAGzF,MAAM,cAAc,KAAK,OAAO,KAAK,WAAW;AAChD,UAAI;AACF,aAAM,gBAAgB,aAAa,OAAO,QAAS;OACnD,MAAM,UAAU,MAAM,oBAAoB,OAAO,KAAK,KAAK;AAC3D,WAAI,SAAS;AACX,eAAO,OAAO,KAAK;SAAE,WAAW;SAAM,OAAO;SAAM,CAAC;AACpD,eAAO,WAAW;SAAE,SAAS;SAAO,OAAO;SAAS,CAAC;;eAEhD,GAAG;AACV,cAAO,OAAO,KAAK;QAAE,WAAW;QAAM,OAAO;QAAM,CAAC;AACpD,aAAM;;AAGR,cAAQ;AACR,aAAO,WAAW;OAChB,SAAS;OACT,SAAS,UAAU,KAAK;OACxB;OACA,MAAM,OAAO;OACd,CAAC;;KAGJ,KAAK,QAAQ;MACX,MAAM,UAAU,yBAAyB,OAAO,QAAQ,IAAI,OAAO;AACnE,UAAI,QAAS,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAS,CAAC;MAClE,MAAM,OAAO,OAAO,KAAM,MAAM;MAEhC,MAAM,KAAK,qBAAqB,IAAI,UAAU,KAAK,EAAE,WAAW,OAAO;AACvE,UAAI,CAAC,GACH,QAAO,WAAW;OAChB,SAAS;OACT,OAAO,UAAU,KAAK;OACvB,CAAC;MAGJ,MAAM,KAAK,uBAAuB,OAAO,WAAW,IAAI,MAAM,MAAM;AACpE,UAAI,GAAG,OAAO,MAAO,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,GAAG;OAAO,CAAC;MAE3E,MAAM,cAAc,KAAK,GAAG,SAAS,WAAW;MAChD,IAAI;AACJ,UAAI;AACF,kBAAW,MAAM,SAAS,aAAa,QAAQ;cACzC;AACN,cAAO,WAAW;QAAE,SAAS;QAAO,OAAO;QAA+B,CAAC;;AAG7E,UAAI;AACF,aAAM,gBAAgB,aAAa,OAAO,QAAS;OACnD,MAAM,UAAU,MAAM,oBAAoB,GAAG,SAAS,KAAK;AAC3D,WAAI,SAAS;AACX,cAAM,gBAAgB,aAAa,SAAS;AAC5C,eAAO,WAAW;SAAE,SAAS;SAAO,OAAO;SAAS,CAAC;;eAEhD,GAAG;AACV,aAAM,gBAAgB,aAAa,SAAS,CAAC,YAAY,GAAG;AAC5D,aAAM;;AAGR,cAAQ;AACR,aAAO,WAAW;OAAE,SAAS;OAAM,SAAS,UAAU,KAAK;OAAa,MAAM,GAAG;OAAS,CAAC;;KAG7F,KAAK,SAAS;MACZ,MAAM,UAAU,yBAAyB,OAAO,QAAQ,IAAI,OAAO;AACnE,UAAI,QAAS,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAS,CAAC;MAClE,MAAM,OAAO,OAAO,KAAM,MAAM;MAEhC,MAAM,KAAK,qBAAqB,IAAI,UAAU,KAAK,EAAE,WAAW,OAAO;AACvE,UAAI,CAAC,GACH,QAAO,WAAW;OAChB,SAAS;OACT,OAAO,UAAU,KAAK;OACvB,CAAC;MAGJ,IAAI;AACJ,UAAI,OAAO,WAAW,MAAM,EAAE;OAC5B,MAAM,OAAO,+BAA+B,OAAO,UAAU,MAAM,CAAC;AACpE,WAAI,KAAM,QAAO,WAAW;QAAE,SAAS;QAAO,OAAO;QAAM,CAAC;AAC5D,iBAAU,OAAO,UAAU,MAAM,CAAC,QAAQ,OAAO,IAAI;;MAGvD,MAAM,aAAa,UAAU,KAAK,GAAG,SAAS,QAAQ,GAAG,KAAK,GAAG,SAAS,WAAW;AACrF,UAAI,CAAC,gBAAgB,GAAG,SAAS,WAAW,CAC1C,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAA0C,CAAC;MAGxF,IAAI;AACJ,UAAI;AACF,kBAAW,MAAM,SAAS,YAAY,QAAQ;cACxC;AACN,cAAO,WAAW;QAAE,SAAS;QAAO,OAAO,mBAAmB,WAAW;QAAc,CAAC;;MAG1F,MAAM,UAAU,oBACd,UACA,OAAO,cAAc,IACrB,OAAO,cAAc,IACrB,OAAO,gBAAgB,KACxB;AACD,UAAI,QAAQ,OAAO,MAAO,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,QAAQ;OAAO,CAAC;AAErF,UAAI,CAAC,SAAS;OACZ,MAAM,KAAK,uBAAuB,QAAQ,MAAM,MAAM,MAAM;AAC5D,WAAI,GAAG,OAAO,MAAO,QAAO,WAAW;QAAE,SAAS;QAAO,OAAO,mBAAmB,GAAG;QAAS,CAAC;iBACvF,OAAO,WAAW,QAAQ,MAAM,QAAQ,GAAG,OACpD,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,4BAA4B,OAAO;OAAW,CAAC;AAG5F,UAAI;AACF,aAAM,gBAAgB,YAAY,QAAQ,KAAK;OAC/C,MAAM,UAAU,MAAM,oBAAoB,GAAG,SAAS,KAAK;AAC3D,WAAI,SAAS;AACX,cAAM,gBAAgB,YAAY,SAAS;AAC3C,eAAO,WAAW;SAAE,SAAS;SAAO,OAAO;SAAS,CAAC;;eAEhD,GAAG;AACV,aAAM,gBAAgB,YAAY,SAAS,CAAC,YAAY,GAAG;AAC3D,aAAM;;AAGR,cAAQ;AACR,aAAO,WAAW;OAChB,SAAS;OACT,SAAS,WAAW,WAAW,WAAW,IAAI,QAAQ,aAAa;OACpE,CAAC;;KAGJ,KAAK,UAAU;MACb,MAAM,UAAU,yBAAyB,OAAO,QAAQ,IAAI,OAAO;AACnE,UAAI,QAAS,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAS,CAAC;MAClE,MAAM,OAAO,OAAO,KAAM,MAAM;MAEhC,MAAM,KAAK,qBAAqB,IAAI,UAAU,KAAK,EAAE,WAAW,OAAO;AACvE,UAAI,CAAC,GACH,QAAO,WAAW;OAChB,SAAS;OACT,OAAO,UAAU,KAAK;OACvB,CAAC;AAGJ,aAAO,GAAG,SAAS;OAAE,WAAW;OAAM,OAAO;OAAM,CAAC;AACpD,cAAQ;AACR,aAAO,WAAW;OAAE,SAAS;OAAM,SAAS,UAAU,KAAK;OAAa,MAAM,GAAG;OAAS,CAAC;;KAG7F,KAAK,cAAc;MACjB,MAAM,UAAU,yBAAyB,OAAO,QAAQ,IAAI,OAAO;AACnE,UAAI,QAAS,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAS,CAAC;MAClE,MAAM,OAAO,OAAO,KAAM,MAAM;MAEhC,MAAM,KAAK,qBAAqB,IAAI,UAAU,KAAK,EAAE,WAAW,OAAO;AACvE,UAAI,CAAC,GACH,QAAO,WAAW;OAChB,SAAS;OACT,OAAO,UAAU,KAAK;OACvB,CAAC;MAGJ,MAAM,OAAO,+BAA+B,OAAO,aAAa,GAAG;AACnE,UAAI,KAAM,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAM,CAAC;MAC5D,MAAM,MAAM,OAAO,UAAW,MAAM,CAAC,QAAQ,OAAO,IAAI;MACxD,MAAM,aAAa,KAAK,GAAG,SAAS,IAAI;AACxC,UAAI,CAAC,gBAAgB,GAAG,SAAS,WAAW,CAC1C,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAA0C,CAAC;MAGxF,MAAM,OAAO,OAAO,gBAAgB;AACpC,UAAI,OAAO,WAAW,MAAM,QAAQ,GAAG,OACrC,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,4BAA4B,OAAO;OAAW,CAAC;MAG5F,MAAM,UAAU,WAAW,WAAW;MACtC,IAAI,WAA0B;AAC9B,UAAI,QACF,KAAI;AACF,kBAAW,MAAM,SAAS,YAAY,QAAQ;cACxC;AACN,kBAAW;;AAIf,UAAI;AACF,aAAM,gBAAgB,YAAY,KAAK;OACvC,MAAM,UAAU,MAAM,oBAAoB,GAAG,SAAS,KAAK;AAC3D,WAAI,SAAS;AACX,YAAI,aAAa,KAAM,OAAM,gBAAgB,YAAY,SAAS;YAC7D,OAAM,GAAG,YAAY,EAAE,OAAO,MAAM,CAAC;AAC1C,eAAO,WAAW;SAAE,SAAS;SAAO,OAAO;SAAS,CAAC;;eAEhD,GAAG;AACV,WAAI,aAAa,KAAM,OAAM,gBAAgB,YAAY,SAAS,CAAC,YAAY,GAAG;WAC7E,OAAM,GAAG,YAAY,EAAE,OAAO,MAAM,CAAC,CAAC,YAAY,GAAG;AAC1D,aAAM;;AAGR,cAAQ;AACR,aAAO,WAAW;OAChB,SAAS;OACT,SAAS,SAAS,IAAI;OACvB,CAAC;;KAGJ,KAAK,eAAe;MAClB,MAAM,UAAU,yBAAyB,OAAO,QAAQ,IAAI,OAAO;AACnE,UAAI,QAAS,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAS,CAAC;MAClE,MAAM,OAAO,OAAO,KAAM,MAAM;MAEhC,MAAM,KAAK,qBAAqB,IAAI,UAAU,KAAK,EAAE,WAAW,OAAO;AACvE,UAAI,CAAC,GACH,QAAO,WAAW;OAChB,SAAS;OACT,OAAO,UAAU,KAAK;OACvB,CAAC;MAGJ,MAAM,OAAO,+BAA+B,OAAO,aAAa,GAAG;AACnE,UAAI,KAAM,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAAM,CAAC;MAC5D,MAAM,MAAM,OAAO,UAAW,MAAM,CAAC,QAAQ,OAAO,IAAI;MACxD,MAAM,aAAa,KAAK,GAAG,SAAS,IAAI;AACxC,UAAI,CAAC,gBAAgB,GAAG,SAAS,WAAW,CAC1C,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO;OAA0C,CAAC;AAGxF,UAAI,CAAC,WAAW,WAAW,CACzB,QAAO,WAAW;OAAE,SAAS;OAAO,OAAO,mBAAmB;OAAO,CAAC;AAGxE,YAAM,GAAG,YAAY,EAAE,OAAO,MAAM,CAAC;AACrC,YAAM,oBAAoB,GAAG,SAAS,KAAK;AAC3C,cAAQ;AACR,aAAO,WAAW;OAAE,SAAS;OAAM,SAAS,WAAW,IAAI;OAAI,CAAC;;KAGlE,QACE,QAAO,WAAW;MAAE,SAAS;MAAO,OAAO;MAAmB,CAAC;;YAE5D,GAAG;AACV,WAAO,WAAW;KAChB,SAAS;KACT,OAAO,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;KAClD,CAAC;;;EAGP"}
@@ -1,6 +1,6 @@
1
1
  import type { AgentTool } from '@earendil-works/pi-agent-core';
2
- declare const ToolManualSchema: import("@sinclair/typebox/build/cjs/index.js").TObject<{
3
- tool: import("@sinclair/typebox/build/cjs/index.js").TString;
2
+ declare const ToolManualSchema: import("@sinclair/typebox").TObject<{
3
+ tool: import("@sinclair/typebox").TString;
4
4
  }>;
5
5
  export declare function createToolManualTool(): AgentTool<typeof ToolManualSchema, {}>;
6
6
  export {};
@@ -3,11 +3,11 @@ import type { Config } from '../../config/schema.js';
3
3
  import type { NotesService } from '../../notes/index.js';
4
4
  import { type ProjectService } from '../../projects/index.js';
5
5
  import type { WorkItemService } from '../../work-items/index.js';
6
- declare const XopcUseToolSchema: import("@sinclair/typebox/build/cjs/index.js").TObject<{
7
- mode: import("@sinclair/typebox/build/cjs/index.js").TUnion<[import("@sinclair/typebox/build/cjs/index.js").TLiteral<"project">, import("@sinclair/typebox/build/cjs/index.js").TLiteral<"note">, import("@sinclair/typebox/build/cjs/index.js").TLiteral<"work_item">]>;
8
- command: import("@sinclair/typebox/build/cjs/index.js").TString;
9
- args: import("@sinclair/typebox/build/cjs/index.js").TOptional<import("@sinclair/typebox/build/cjs/index.js").TRecord<import("@sinclair/typebox/build/cjs/index.js").TString, import("@sinclair/typebox/build/cjs/index.js").TAny>>;
10
- dryRun: import("@sinclair/typebox/build/cjs/index.js").TOptional<import("@sinclair/typebox/build/cjs/index.js").TBoolean>;
6
+ declare const XopcUseToolSchema: import("@sinclair/typebox").TObject<{
7
+ mode: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"project">, import("@sinclair/typebox").TLiteral<"note">, import("@sinclair/typebox").TLiteral<"work_item">]>;
8
+ command: import("@sinclair/typebox").TString;
9
+ args: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TAny>>;
10
+ dryRun: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
11
11
  }>;
12
12
  export type XopcUseMode = 'project' | 'note' | 'work_item';
13
13
  export interface XopcUseToolInput {
@@ -151,6 +151,7 @@ export interface AutomationDeps {
151
151
  workflowRunService?: {
152
152
  startWorkflowRun(params: StartWorkflowRunServiceParams): Promise<WorkflowRunServiceResult>;
153
153
  };
154
+ onRunCompleted?: (run: AutomationRun) => void;
154
155
  }
155
156
  export interface AutomationActionOutcome {
156
157
  status: 'succeeded' | 'failed' | 'timeout' | 'cancelled';
@@ -329,6 +329,15 @@ var AutomationService = class {
329
329
  });
330
330
  this.activeRuns.delete(initialRun.id);
331
331
  this.finishAutomationRun(automation.id, status, error, endedAtMs);
332
+ try {
333
+ this.deps.onRunCompleted?.(run);
334
+ } catch (err) {
335
+ log.warn({
336
+ err,
337
+ automationId: automation.id,
338
+ runId: run.id
339
+ }, "Automation completion hook failed");
340
+ }
332
341
  }
333
342
  }
334
343
  appendRunEvent(run, type, message, data) {
@@ -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
+ }>;