@xopcai/xopc 0.0.171 → 0.0.173

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 (228) 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/{activity-store-BLz30jWq.js → activity-store-ByVA0N5n.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BKZO0EFn.js → agent-avatar-dicebear-CJ5HvqE7.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents--TQ9jM_1.js +2 -0
  6. package/dist/gateway/static/root/assets/{api-N2qKY-WI.js → api-BZtCKzg4.js} +1 -1
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-CNZkpXCD.js → app-management-settings-panel-B0oNNcFn.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-Drf5a563.js → appearance-settings-DbIj4NQ1.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-BDsoZDEn.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-ChVwOXE5.js → archive-plugin-BICLQFWJ.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-BVK3Y2d9.js → attachment-load-DV3PteSU.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automation-suggestion-card-DH4N0SYR.js → automation-suggestion-card-CZUImis0.js} +1 -1
  13. package/dist/gateway/static/root/assets/automations-page-CHrNcppN.js +6 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-CeHY6VVP.js → binary-plugins-D6zkab6N.js} +1 -1
  15. package/dist/gateway/static/root/assets/block-editor-zCzoQI-g.js +184 -0
  16. package/dist/gateway/static/root/assets/browser-settings-page-BQoRuQzH.js +8 -0
  17. package/dist/gateway/static/root/assets/{browser-workflow-inputs-femCtfpo.js → browser-workflow-inputs-CY3X83xQ.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-workflows-page-o0GVE_aF.js → browser-workflows-page-DDRtZLuM.js} +2 -2
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-BOcU0qeM.js +7 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-Bx-JJC0R.js → capability-presets-api-pYLW6P7g.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CJ1F_hlX.js +1 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-CTw3ibx4.js → channel-recipient-api-DxyOH3BO.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-C4vDwRil.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-B0Pgq5x2.js +1 -0
  25. package/dist/gateway/static/root/assets/connector-logo-BgANwjt-.js +1 -0
  26. package/dist/gateway/static/root/assets/connectors-page-D6JEqDEj.js +2 -0
  27. package/dist/gateway/static/root/assets/desktop-pet-BPjQbPeA.js +1 -0
  28. package/dist/gateway/static/root/assets/{desktop-pet-settings-CIeH4VyP.js → desktop-pet-settings-8CaU1Mhm.js} +1 -1
  29. package/dist/gateway/static/root/assets/{directory-picker-path-field-Ddgt6c3K.js → directory-picker-path-field-BtNRUvzM.js} +1 -1
  30. package/dist/gateway/static/root/assets/dreaming-settings-Byv-h8XZ.js +3 -0
  31. package/dist/gateway/static/root/assets/{extension-debug-page-CJGwUaQX.js → extension-debug-page-DFjTfx6f.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-page-B3zHKJAB.js → extension-page-NyEYtWWg.js} +1 -1
  33. package/dist/gateway/static/root/assets/{extension-settings-page-Cj9rrSr1.js → extension-settings-page-BynTCfgf.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-BdmtlJRP.js → gateway-config-api-BzOWImvU.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-settings-C2RwKIsl.js → gateway-settings-DXepE_Jw.js} +1 -1
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-mcMq_uu_.js → gateway-startup-retry-C2JXXtwg.js} +1 -1
  37. package/dist/gateway/static/root/assets/{goal-create-dialog-5Ryd_rx4.js → goal-create-dialog-ClOZyG52.js} +1 -1
  38. package/dist/gateway/static/root/assets/goal-detail-page-UbZB77De.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-CAO1J4jn.js → goals-config-api-CU3JR9MI.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-GMqV8Fwv.js +2 -0
  41. package/dist/gateway/static/root/assets/{goals-settings-Boj2izKZ.js → goals-settings-DSZguLEx.js} +1 -1
  42. package/dist/gateway/static/root/assets/{heartbeat-settings-DbPC9a_y.js → heartbeat-settings-KRkYziEF.js} +1 -1
  43. package/dist/gateway/static/root/assets/{image-generation-api-DrLCLTXn.js → image-generation-api-Y-n6TaZ_.js} +1 -1
  44. package/dist/gateway/static/root/assets/index-BCkNJ5cR.css +1 -0
  45. package/dist/gateway/static/root/assets/{index-vHb2z7VS.js → index-CAZ9343h.js} +67 -67
  46. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BrxfptgY.js → keyboard-shortcuts-settings-CwrQv952.js} +1 -1
  47. package/dist/gateway/static/root/assets/{local-app-workbench-page-BP0_Ih0e.js → local-app-workbench-page-m5HEyrHT.js} +2 -2
  48. package/dist/gateway/static/root/assets/{local-apps-page-DNCRlfFs.js → local-apps-page-DtITcS4K.js} +1 -1
  49. package/dist/gateway/static/root/assets/{locale-store-CzIfXqm8.js → locale-store-Ccv7tH8B.js} +1 -1
  50. package/dist/gateway/static/root/assets/logs-page-Bf_nk75f.js +7 -0
  51. package/dist/gateway/static/root/assets/{markdown-split-CIUH9Lor.js → markdown-split-D1oZlq1m.js} +1 -1
  52. package/dist/gateway/static/root/assets/{media-plugins-DX4AgkCs.js → media-plugins-BKz5V32t.js} +1 -1
  53. package/dist/gateway/static/root/assets/{messages-CKZuaOeG.js → messages-DWrg3c4K.js} +2 -2
  54. package/dist/gateway/static/root/assets/{notes-page-D1KprtxL.js → notes-page-DLekBQPa.js} +1 -1
  55. package/dist/gateway/static/root/assets/notes-workbench-BTDmprHM.js +4 -0
  56. package/dist/gateway/static/root/assets/{page-tabs-DjZPJGf6.js → page-tabs-pT4nLfqS.js} +1 -1
  57. package/dist/gateway/static/root/assets/{preview-open-alternatives-DNiJTpwZ.js → preview-open-alternatives-OtAiaJm2.js} +1 -1
  58. package/dist/gateway/static/root/assets/{product-open-page-CNfR17-g.js → product-open-page-CfryBKD9.js} +1 -1
  59. package/dist/gateway/static/root/assets/project-detail-page-C7kntu4H.js +1 -0
  60. package/dist/gateway/static/root/assets/projects-page-3ubcbqHr.js +1 -0
  61. package/dist/gateway/static/root/assets/remote-access-hub-DoUkN3ik.js +1 -0
  62. package/dist/gateway/static/root/assets/{save-bar-controls-BGZFVO9S.js → save-bar-controls-nP1SB3Lf.js} +1 -1
  63. package/dist/gateway/static/root/assets/{schedule-field-BAZiHtds.js → schedule-field-OEQTsUNz.js} +1 -1
  64. package/dist/gateway/static/root/assets/{schema-form-CesBcwJH.js → schema-form-DIcAa7CJ.js} +1 -1
  65. package/dist/gateway/static/root/assets/sessions-page-ElAAlZ-R.js +1 -0
  66. package/dist/gateway/static/root/assets/settings-advanced-gate-CQn_KBqr.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-form-section-Bxc54BLj.js → settings-form-section-BxNcTbYO.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-loading-skeleton-CYrho7Db.js → settings-loading-skeleton-Dpdxu4sf.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-page-C03X5fkh.js → settings-page-DwPeOm1c.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-page-layout-CZAJbv4E.js → settings-page-layout-CqirFmMn.js} +1 -1
  71. package/dist/gateway/static/root/assets/{setup-status-panel-Jv8_bcOD.js → setup-status-panel-DX_LdcTN.js} +1 -1
  72. package/dist/gateway/static/root/assets/{share-preview-page-DSC7tKKG.js → share-preview-page-D72gYeux.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-nSfe-5xK.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-1tYpZrJf.js +1 -0
  75. package/dist/gateway/static/root/assets/skills-page-BUJl8LJG.js +2 -0
  76. package/dist/gateway/static/root/assets/{system-settings-panel-BO89zw5H.js → system-settings-panel-U0tBgW46.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-1OkdVC8l.js → theme-store-DCKDVPFF.js} +1 -1
  78. package/dist/gateway/static/root/assets/time-picker-BpiBF5-d.js +1 -0
  79. package/dist/gateway/static/root/assets/{typed-models-lib-D-_vct_y.js → typed-models-lib-D0XCOCAM.js} +1 -1
  80. package/dist/gateway/static/root/assets/{use-channel-catalog-VlFtjlET.js → use-channel-catalog-mq_Inao2.js} +1 -1
  81. package/dist/gateway/static/root/assets/user-context-page-BOC6Hn19.js +1 -0
  82. package/dist/gateway/static/root/assets/{voice-api-key-field-BhDk-UV_.js → voice-api-key-field-CKaDitO6.js} +1 -1
  83. package/dist/gateway/static/root/assets/work-discovery-page-DWGYp5yV.js +1 -0
  84. package/dist/gateway/static/root/assets/work-item-detail-page-CpeWcpSp.js +1 -0
  85. package/dist/gateway/static/root/assets/work-page-MsEKzmSt.js +1 -0
  86. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-uVw4Yoej.js → workflow-run-setup-panel-s_kS_FYA.js} +2 -2
  87. package/dist/gateway/static/root/assets/workflows-page-ByhHaUHB.js +11 -0
  88. package/dist/gateway/static/root/index.html +7 -7
  89. package/dist/package.js +1 -1
  90. package/dist/src/agent/agent-manager.d.ts +3 -1
  91. package/dist/src/agent/agent-manager.js +4 -3
  92. package/dist/src/agent/capabilities/definitions.d.ts +2 -1
  93. package/dist/src/agent/capabilities/definitions.js +3 -1
  94. package/dist/src/agent/memory/builtin-provider.js +4 -4
  95. package/dist/src/agent/memory/manager.d.ts +4 -1
  96. package/dist/src/agent/memory/manager.js +8 -3
  97. package/dist/src/agent/memory/understanding/service.d.ts +2 -0
  98. package/dist/src/agent/memory/understanding/service.js +11 -9
  99. package/dist/src/agent/prompt/sections/tooling.js +4 -0
  100. package/dist/src/agent/service.d.ts +3 -1
  101. package/dist/src/agent/service.js +29 -0
  102. package/dist/src/agent/skills/hub-pull.js +1 -1
  103. package/dist/src/agent/skills/index.js +1 -1
  104. package/dist/src/agent/skills/install-target.js +1 -1
  105. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.d.ts +64 -0
  106. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +27 -18
  107. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +1 -1
  108. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +1 -1
  109. package/dist/src/agent/skills/marketplace/search.d.ts +46 -0
  110. package/dist/src/agent/skills/marketplace/search.js +193 -0
  111. package/dist/src/agent/skills/skill-tool-gating.js +2 -1
  112. package/dist/src/agent/tools/delegate-tool.js +2 -0
  113. package/dist/src/agent/tools/factory.d.ts +4 -2
  114. package/dist/src/agent/tools/factory.js +11 -5
  115. package/dist/src/agent/tools/index.d.ts +2 -1
  116. package/dist/src/agent/tools/index.js +2 -1
  117. package/dist/src/agent/tools/skill-install-tool.d.ts +17 -0
  118. package/dist/src/agent/tools/skill-install-tool.js +76 -8
  119. package/dist/src/agent/tools/skills-marketplace-search-tool.d.ts +17 -0
  120. package/dist/src/agent/tools/skills-marketplace-search-tool.js +77 -0
  121. package/dist/src/automations/domain/validation.d.ts +8 -8
  122. package/dist/src/automations/draft/automation-draft-validator.d.ts +1 -1
  123. package/dist/src/browser/providers/cloakbrowser.js +1 -1
  124. package/dist/src/capabilities/store-connector.js +1 -1
  125. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  126. package/dist/src/config/agent-profile.js +1 -1
  127. package/dist/src/connectors/composio-sessions.d.ts +1 -0
  128. package/dist/src/connectors/composio-sessions.js +14 -5
  129. package/dist/src/connectors/composio-triggers.d.ts +1 -1
  130. package/dist/src/connectors/composio-triggers.js +4 -3
  131. package/dist/src/connectors/composio.js +1 -0
  132. package/dist/src/connectors/{connector-memory-sync.d.ts → connected-source-ingestion.d.ts} +11 -4
  133. package/dist/src/connectors/{connector-memory-sync.js → connected-source-ingestion.js} +49 -101
  134. package/dist/src/connectors/connected-source-normalizers.d.ts +15 -0
  135. package/dist/src/connectors/connected-source-normalizers.js +186 -0
  136. package/dist/src/connectors/connector-identity.d.ts +2 -0
  137. package/dist/src/connectors/connector-identity.js +29 -0
  138. package/dist/src/connectors/learning-coordinator.d.ts +25 -0
  139. package/dist/src/connectors/learning-coordinator.js +214 -0
  140. package/dist/src/connectors/learning-recipes.d.ts +22 -0
  141. package/dist/src/connectors/learning-recipes.js +121 -0
  142. package/dist/src/connectors/runtime-status.d.ts +1 -8
  143. package/dist/src/connectors/runtime-status.js +4 -29
  144. package/dist/src/extensions/api.js +1 -1
  145. package/dist/src/extensions/install.js +1 -1
  146. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  147. package/dist/src/gateway/agent-builtin-tools.js +2 -0
  148. package/dist/src/gateway/agents-admin.js +1 -1
  149. package/dist/src/gateway/heartbeat/service.js +1 -1
  150. package/dist/src/gateway/hono/routes/commands-skills.js +2 -2
  151. package/dist/src/gateway/hono/routes/connectors.js +76 -118
  152. package/dist/src/gateway/hono/routes/local-apps.js +1 -1
  153. package/dist/src/gateway/hono/routes/models.js +24 -0
  154. package/dist/src/gateway/hono/routes/public-gateway.js +3 -2
  155. package/dist/src/gateway/hono/routes/you.js +86 -5
  156. package/dist/src/gateway/service/marketplace-service.js +1 -1
  157. package/dist/src/gateway/service.d.ts +5 -2
  158. package/dist/src/gateway/service.js +18 -13
  159. package/dist/src/heartbeat/index.js +1 -1
  160. package/dist/src/knowledge/connected-understanding-pipeline.d.ts +19 -0
  161. package/dist/src/knowledge/connected-understanding-pipeline.js +268 -0
  162. package/dist/src/knowledge/index.d.ts +1 -0
  163. package/dist/src/knowledge/index.js +2 -1
  164. package/dist/src/knowledge/ingestion-service.d.ts +6 -4
  165. package/dist/src/knowledge/ingestion-service.js +13 -10
  166. package/dist/src/knowledge/local-folder-adapter.js +1 -0
  167. package/dist/src/knowledge/people-graph.js +43 -110
  168. package/dist/src/knowledge/types.d.ts +3 -0
  169. package/dist/src/mcp/channel-bridge.js +1 -1
  170. package/dist/src/providers/xopc-cloud-account-service.d.ts +40 -0
  171. package/dist/src/providers/xopc-cloud-account-service.js +65 -0
  172. package/dist/src/storage/sqlite/connector-learning-repository.d.ts +47 -0
  173. package/dist/src/storage/sqlite/connector-learning-repository.js +110 -0
  174. package/dist/src/storage/sqlite/index.d.ts +3 -1
  175. package/dist/src/storage/sqlite/index.js +4 -2
  176. package/dist/src/storage/sqlite/knowledge-repository.d.ts +4 -2
  177. package/dist/src/storage/sqlite/knowledge-repository.js +24 -13
  178. package/dist/src/storage/sqlite/migrations/062_connector_learning_jobs.sql +27 -0
  179. package/dist/src/storage/sqlite/migrations/063_knowledge_collection_scopes.sql +14 -0
  180. package/dist/src/storage/sqlite/migrations/064_user_claims.sql +60 -0
  181. package/dist/src/storage/sqlite/migrations/065_knowledge_item_scope_identity.sql +116 -0
  182. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  183. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  184. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  185. package/dist/src/storage/sqlite/schema.js +1 -1
  186. package/dist/src/storage/sqlite/user-claims-repository.d.ts +101 -0
  187. package/dist/src/storage/sqlite/user-claims-repository.js +241 -0
  188. package/dist/src/user-context/projection.d.ts +36 -1
  189. package/dist/src/user-context/projection.js +84 -6
  190. package/dist/src/work-discovery/service.js +1 -0
  191. package/package.json +1 -1
  192. package/skills/tools/find-skills/SKILL.md +18 -428
  193. package/dist/gateway/static/root/assets/agents-ZCIC8mhO.js +0 -2
  194. package/dist/gateway/static/root/assets/apps-page-DJmgBaAm.js +0 -1
  195. package/dist/gateway/static/root/assets/automations-page-Ddot8-Md.js +0 -6
  196. package/dist/gateway/static/root/assets/block-editor-D3GIllO3.js +0 -184
  197. package/dist/gateway/static/root/assets/browser-settings-page-DvETvRcg.js +0 -8
  198. package/dist/gateway/static/root/assets/capabilities-settings-panel-ChXIYbys.js +0 -7
  199. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CUekXsJy.js +0 -1
  200. package/dist/gateway/static/root/assets/channels-settings-CkhveNsQ.js +0 -1
  201. package/dist/gateway/static/root/assets/channels-status-swr-DRTb8DBk.js +0 -1
  202. package/dist/gateway/static/root/assets/connector-logo-CQznQcd4.js +0 -1
  203. package/dist/gateway/static/root/assets/connectors-page-DkSGIxWP.js +0 -2
  204. package/dist/gateway/static/root/assets/desktop-pet-BtP-xUQ9.js +0 -1
  205. package/dist/gateway/static/root/assets/dreaming-settings-gd9W6SLj.js +0 -3
  206. package/dist/gateway/static/root/assets/goal-detail-page-DizZ6Cpl.js +0 -4
  207. package/dist/gateway/static/root/assets/goals-page-Dqry_hi2.js +0 -2
  208. package/dist/gateway/static/root/assets/index-DEdyUjxM.css +0 -1
  209. package/dist/gateway/static/root/assets/logs-page-mT48mcF4.js +0 -7
  210. package/dist/gateway/static/root/assets/notes-workbench-wgt2Osyk.js +0 -4
  211. package/dist/gateway/static/root/assets/project-detail-page-CDjHvxJm.js +0 -1
  212. package/dist/gateway/static/root/assets/projects-page-kJZwQXfC.js +0 -1
  213. package/dist/gateway/static/root/assets/remote-access-hub-MJdI9ek_.js +0 -1
  214. package/dist/gateway/static/root/assets/sessions-page-BqC7GDC_.js +0 -1
  215. package/dist/gateway/static/root/assets/settings-advanced-gate-CYwz8MfF.js +0 -1
  216. package/dist/gateway/static/root/assets/shares-settings-h8tGDkA3.js +0 -1
  217. package/dist/gateway/static/root/assets/skill-reload-api-D2DGvRUn.js +0 -1
  218. package/dist/gateway/static/root/assets/skills-page-vqhjSMhZ.js +0 -2
  219. package/dist/gateway/static/root/assets/time-picker-mtD64kFB.js +0 -1
  220. package/dist/gateway/static/root/assets/user-context-page-BgF0WxjM.js +0 -1
  221. package/dist/gateway/static/root/assets/work-discovery-page-CP0Daig-.js +0 -1
  222. package/dist/gateway/static/root/assets/work-item-detail-page-NEWZPKB_.js +0 -1
  223. package/dist/gateway/static/root/assets/work-page-BkWntcQh.js +0 -1
  224. package/dist/gateway/static/root/assets/workflows-page-DRvhNQGe.js +0 -11
  225. package/dist/src/connectors/memory-sync-coordinator.d.ts +0 -28
  226. package/dist/src/connectors/memory-sync-coordinator.js +0 -162
  227. package/dist/src/connectors/memory-sync-profile.d.ts +0 -13
  228. package/dist/src/connectors/memory-sync-profile.js +0 -73
@@ -0,0 +1,193 @@
1
+ import { searchClawHubFederatedSkills } from "./adapters/clawhub/adapter.js";
2
+ import { listMarketplacePackages } from "../skills-marketplace.js";
3
+ //#region src/agent/skills/marketplace/search.ts
4
+ const SKILL_MARKETPLACE_SEARCH_SOURCES = [
5
+ "store",
6
+ "clawhub",
7
+ "skills-sh"
8
+ ];
9
+ function boundedNumber(value) {
10
+ const parsed = Number(value);
11
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
12
+ }
13
+ function normalizeDate(value) {
14
+ if (value === void 0 || value === null || value === "") return null;
15
+ const numeric = typeof value === "number" ? value : typeof value === "string" && /^\d+(?:\.\d+)?$/.test(value.trim()) ? Number(value) : null;
16
+ const timestamp = numeric !== null && Number.isFinite(numeric) ? Math.abs(numeric) < 0xe8d4a51000 ? numeric * 1e3 : numeric : value;
17
+ const date = new Date(timestamp);
18
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
19
+ }
20
+ function scannerStatus(value) {
21
+ const normalized = String(value ?? "").trim().toLowerCase();
22
+ if (normalized === "pass") return "pass";
23
+ if (normalized === "warn" || normalized === "warning" || normalized === "review") return "warn";
24
+ if (normalized === "fail" || normalized === "failed" || normalized === "block") return "fail";
25
+ return "unknown";
26
+ }
27
+ function securityFromClawHub(item) {
28
+ const scanners = Object.entries(item.trust?.upstreamScanners ?? {}).map(([name, evidence]) => ({
29
+ name,
30
+ status: scannerStatus(evidence.status),
31
+ checkedAt: normalizeDate(evidence.sourceCheckedAt),
32
+ url: evidence.sourceUrl ?? null
33
+ }));
34
+ const statuses = scanners.map((scanner) => scanner.status);
35
+ return {
36
+ status: statuses.includes("fail") ? "fail" : statuses.includes("warn") ? "warn" : statuses.length > 0 && statuses.every((value) => value === "pass") ? "pass" : scannerStatus(item.trust?.clawHubVerdict),
37
+ scanners
38
+ };
39
+ }
40
+ function absoluteClawHubUrl(value) {
41
+ if (!value) return null;
42
+ try {
43
+ const base = process.env.CLAWHUB_REGISTRY?.trim() || "https://clawhub.ai";
44
+ return new URL(value, base).toString();
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+ function relevanceScore(query, result) {
50
+ const terms = query.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 1);
51
+ if (terms.length === 0) return 0;
52
+ const name = result.name.toLowerCase();
53
+ const description = result.description.toLowerCase();
54
+ const matched = terms.reduce((score, term) => {
55
+ if (name === term) return score + 3;
56
+ if (name.includes(term)) return score + 2;
57
+ if (description.includes(term)) return score + 1;
58
+ return score;
59
+ }, 0);
60
+ return Math.min(35, Math.round(matched / (terms.length * 3) * 35));
61
+ }
62
+ function valueScore(query, result) {
63
+ const relevance = relevanceScore(query, result);
64
+ const adoption = Math.min(30, Math.log10(result.downloads + 1) * 7);
65
+ const endorsement = Math.min(15, Math.log10(result.stars + 1) * 6);
66
+ const updatedMs = result.updatedAt ? Date.parse(result.updatedAt) : 0;
67
+ const ageDays = updatedMs > 0 ? (Date.now() - updatedMs) / 864e5 : Number.POSITIVE_INFINITY;
68
+ const freshness = ageDays <= 90 ? 15 : ageDays <= 365 ? 10 : ageDays <= 730 ? 5 : 0;
69
+ const provenance = result.canonicalUrl && result.install.reference ? 5 : 0;
70
+ const security = result.security.status === "pass" ? 5 : result.security.status === "warn" ? -20 : result.security.status === "fail" ? -100 : 0;
71
+ return Math.round((relevance + adoption + endorsement + freshness + provenance + security) * 10) / 10;
72
+ }
73
+ function fromClawHub(item) {
74
+ const source = item.source === "skills-sh" ? "skills-sh" : "clawhub";
75
+ const owner = item.publisher?.handle ?? item.sourceIdentity?.owner ?? item.owner?.handle ?? item.ownerHandle ?? source;
76
+ const reference = item.install?.reference ?? (source === "clawhub" && owner !== "clawhub" ? `${owner}/${item.slug}` : item.slug);
77
+ return {
78
+ id: item.id ?? `${source}:${reference}`,
79
+ provider: "clawhub",
80
+ source,
81
+ name: item.displayName || item.slug,
82
+ description: item.summary || "",
83
+ author: owner,
84
+ downloads: boundedNumber(item.downloads ?? item.native?.skill?.stats?.downloads),
85
+ stars: boundedNumber(item.native?.skill?.stats?.stars ?? item.metrics?.bookmarks),
86
+ updatedAt: normalizeDate(item.metrics?.updatedAt ?? item.updatedAt),
87
+ canonicalUrl: absoluteClawHubUrl(item.canonicalUrl ?? item.links?.canonical),
88
+ install: {
89
+ kind: item.install?.kind ?? source,
90
+ reference,
91
+ sourceUrl: item.install?.sourceUrl ?? item.links?.source ?? null
92
+ },
93
+ security: securityFromClawHub(item),
94
+ valueScore: 0
95
+ };
96
+ }
97
+ function dedupeAndRank(query, rows) {
98
+ const unique = /* @__PURE__ */ new Map();
99
+ for (const row of rows) {
100
+ const key = `${row.source}:${row.install.reference || row.id}`.toLowerCase();
101
+ const scored = {
102
+ ...row,
103
+ valueScore: valueScore(query, row)
104
+ };
105
+ const current = unique.get(key);
106
+ if (!current || scored.valueScore > current.valueScore) unique.set(key, scored);
107
+ }
108
+ return [...unique.values()].sort((a, b) => b.valueScore - a.valueScore || b.downloads - a.downloads || a.name.localeCompare(b.name));
109
+ }
110
+ async function searchSkillMarketplaces(params) {
111
+ const requested = new Set(params.sources?.length ? params.sources : SKILL_MARKETPLACE_SEARCH_SOURCES);
112
+ const fetchLimit = Math.min(100, Math.max(params.limit ?? 10, 20));
113
+ const rows = [];
114
+ const statuses = [];
115
+ const jobs = [];
116
+ if (requested.has("store")) jobs.push((async () => {
117
+ try {
118
+ const response = await listMarketplacePackages(params.config, {
119
+ q: params.query,
120
+ page: 1,
121
+ pageSize: fetchLimit,
122
+ sort: "downloads"
123
+ }, "store");
124
+ for (const item of response.items) rows.push({
125
+ id: item.id,
126
+ provider: "store",
127
+ source: "store",
128
+ name: item.name,
129
+ description: item.description,
130
+ author: item.author.username,
131
+ downloads: boundedNumber(item.downloads),
132
+ stars: boundedNumber(item.stars),
133
+ updatedAt: normalizeDate(item.updatedAt),
134
+ canonicalUrl: null,
135
+ install: {
136
+ kind: "store",
137
+ reference: item.name,
138
+ sourceUrl: null
139
+ },
140
+ security: {
141
+ status: "unknown",
142
+ scanners: []
143
+ },
144
+ valueScore: 0
145
+ });
146
+ statuses.push({
147
+ source: "store",
148
+ ok: true,
149
+ count: response.items.length
150
+ });
151
+ } catch (error) {
152
+ statuses.push({
153
+ source: "store",
154
+ ok: false,
155
+ count: 0,
156
+ error: String(error)
157
+ });
158
+ }
159
+ })());
160
+ if (requested.has("clawhub") || requested.has("skills-sh")) jobs.push((async () => {
161
+ try {
162
+ const converted = (await searchClawHubFederatedSkills(params.query, fetchLimit)).results.map(fromClawHub);
163
+ for (const source of ["clawhub", "skills-sh"]) {
164
+ if (!requested.has(source)) continue;
165
+ const matches = converted.filter((row) => row.source === source);
166
+ rows.push(...matches);
167
+ statuses.push({
168
+ source,
169
+ ok: true,
170
+ count: matches.length,
171
+ ...source === "skills-sh" ? { via: "clawhub" } : {}
172
+ });
173
+ }
174
+ } catch (error) {
175
+ for (const source of ["clawhub", "skills-sh"]) if (requested.has(source)) statuses.push({
176
+ source,
177
+ ok: false,
178
+ count: 0,
179
+ error: String(error),
180
+ ...source === "skills-sh" ? { via: "clawhub" } : {}
181
+ });
182
+ }
183
+ })());
184
+ await Promise.all(jobs);
185
+ const limit = Math.min(20, Math.max(1, params.limit ?? 10));
186
+ const orderedStatuses = SKILL_MARKETPLACE_SEARCH_SOURCES.filter((source) => requested.has(source)).map((source) => statuses.find((status) => status.source === source)).filter(Boolean);
187
+ return {
188
+ results: dedupeAndRank(params.query, rows).slice(0, limit),
189
+ sources: orderedStatuses
190
+ };
191
+ }
192
+ //#endregion
193
+ export { SKILL_MARKETPLACE_SEARCH_SOURCES, searchSkillMarketplaces };
@@ -14,7 +14,8 @@ const SKILL_TOOLSET_TOOLS = {
14
14
  "skills_list",
15
15
  "skill_view",
16
16
  "skill_manage"
17
- ]
17
+ ],
18
+ skill_marketplaces: ["skills_marketplace_search"]
18
19
  };
19
20
  function emptyConditions(c) {
20
21
  if (!c) return true;
@@ -28,6 +28,8 @@ const DELEGATE_BLOCKED_TOOLS = new Set([
28
28
  "skills_list",
29
29
  "skill_view",
30
30
  "skill_manage",
31
+ "skills_marketplace_search",
32
+ "skill_install",
31
33
  "bundle-mcp"
32
34
  ]);
33
35
  const DelegateTaskSchema = Type.Object({
@@ -10,7 +10,7 @@ import type { AgentTool } from '@earendil-works/pi-agent-core';
10
10
  import type { Model, Api } from '@earendil-works/pi-ai';
11
11
  import type { Config } from '../../config/schema.js';
12
12
  import type { MessageBus } from '../../infra/bus/index.js';
13
- import { type SkillInstallToolOptions, type SkillInstallToolResult } from './index.js';
13
+ import { type SkillInstallToolOptions, type SkillInstallToolResult, type MarketplaceSkillInstallToolOptions, type MarketplaceSkillInstallToolResult } from './index.js';
14
14
  import type { MemoryManager } from '../memory/manager.js';
15
15
  import type { SessionStore } from '../../session/store.js';
16
16
  import type { GatewayClarifyRequestFn } from './clarify-tool.js';
@@ -70,6 +70,8 @@ export interface ToolFactoryDeps {
70
70
  registerSkillEnvPassthrough?: (names: string[]) => void;
71
71
  /** Install managed skills from explicit sources when a capability/tool enables it. */
72
72
  installSkillFromSource?: (opts: SkillInstallToolOptions) => Promise<SkillInstallToolResult>;
73
+ /** Install a managed skill from a built-in marketplace provider. */
74
+ installSkillFromMarketplace?: (opts: MarketplaceSkillInstallToolOptions) => Promise<MarketplaceSkillInstallToolResult>;
73
75
  /** Workspace-scoped structural code intelligence runtime. */
74
76
  getCodeIntelligenceRuntime?: (workspace: string) => CodeIntelligenceRuntimeLike;
75
77
  }
@@ -86,7 +88,7 @@ export interface CreateCoreToolsOptions {
86
88
  /** Shared user memories directory used for dreaming state (`user/memories`). */
87
89
  dreamingRoot?: string;
88
90
  agentId?: string;
89
- /** When set, registers `skills_list` and `skill_view` bound to this workspace\'s skills. */
91
+ /** When set, registers local skill tools plus marketplace discovery for this workspace. */
90
92
  getSkillManager?: () => SkillManager;
91
93
  }
92
94
  export declare class AgentToolsFactory {
@@ -38,6 +38,7 @@ import { createGoalTool } from "./goal-tool.js";
38
38
  import { createXopcUseTool } from "./xopc-use-tool.js";
39
39
  import { createSkillViewTool, createSkillsListTool } from "./skills-tools.js";
40
40
  import { createSkillManageTool } from "./skill-manage-tool.js";
41
+ import { createSkillsMarketplaceSearchTool } from "./skills-marketplace-search-tool.js";
41
42
  import { createSkillInstallTool } from "./skill-install-tool.js";
42
43
  import { createToolManualTool } from "./tool-manual-tool.js";
43
44
  import { createDesktopPetTool } from "./desktop-pet-tool.js";
@@ -234,6 +235,15 @@ var AgentToolsFactory = class {
234
235
  onSkillsFilesystemMutate: this.deps.onSkillsFilesystemMutate
235
236
  })
236
237
  ] : [],
238
+ createSkillsMarketplaceSearchTool({
239
+ getConfig: () => this.deps.getConfig?.(),
240
+ getSkillManager: getSkillMgr
241
+ }),
242
+ ...this.deps.installSkillFromSource || this.deps.installSkillFromMarketplace ? [createSkillInstallTool({
243
+ installSkillFromSource: this.deps.installSkillFromSource,
244
+ installSkillFromMarketplace: this.deps.installSkillFromMarketplace,
245
+ getSessionKey: () => this.deps.getCurrentContext()?.sessionKey
246
+ })] : [],
237
247
  readTool,
238
248
  ...codeIntelligenceTools,
239
249
  writeTool,
@@ -328,15 +338,11 @@ var AgentToolsFactory = class {
328
338
  if (disabled?.has(toolName) || toolNames.has(toolName)) continue;
329
339
  toolNames.add(toolName);
330
340
  if (toolName === "create_desktop_pet") raw.push(createDesktopPetTool());
331
- if (toolName === "skill_install") raw.push(createSkillInstallTool({
332
- installSkillFromSource: this.deps.installSkillFromSource,
333
- getSessionKey: () => this.deps.getCurrentContext()?.sessionKey
334
- }));
335
341
  }
336
342
  return wrapToolsWithProtection(raw, this.deps.toolExecutorConfig);
337
343
  }
338
344
  getLazyCapabilityToolNames() {
339
- return ["create_desktop_pet", ...this.deps.installSkillFromSource ? ["skill_install"] : []];
345
+ return ["create_desktop_pet"];
340
346
  }
341
347
  createAllTools(coreOptions) {
342
348
  const coreTools = this.createCoreTools(coreOptions);
@@ -32,7 +32,8 @@ export { createGoalTool, type GoalToolOptions } from './goal-tool.js';
32
32
  export { createXopcUseTool, type XopcUseToolDeps, type XopcUseToolInput } from './xopc-use-tool.js';
33
33
  export { createSkillsListTool, createSkillViewTool, type SkillsToolsDeps } from './skills-tools.js';
34
34
  export { createSkillManageTool, type SkillManageToolDeps } from './skill-manage-tool.js';
35
- export { createSkillInstallTool, type SkillInstallToolDeps, type SkillInstallToolOptions, type SkillInstallToolResult, } from './skill-install-tool.js';
35
+ export { createSkillsMarketplaceSearchTool, type SkillsMarketplaceSearchToolDeps, } from './skills-marketplace-search-tool.js';
36
+ export { createSkillInstallTool, type SkillInstallToolDeps, type SkillInstallToolOptions, type SkillInstallToolResult, type MarketplaceSkillInstallToolOptions, type MarketplaceSkillInstallToolResult, } from './skill-install-tool.js';
36
37
  export { createToolManualTool } from './tool-manual-tool.js';
37
38
  export { createDesktopPetTool, type DesktopPetCreateDetails } from './desktop-pet-tool.js';
38
39
  export { createCodeIntelligenceTools } from '../code-intelligence/tools.js';
@@ -36,6 +36,7 @@ import { createGoalTool } from "./goal-tool.js";
36
36
  import { createXopcUseTool } from "./xopc-use-tool.js";
37
37
  import { createSkillViewTool, createSkillsListTool } from "./skills-tools.js";
38
38
  import { createSkillManageTool } from "./skill-manage-tool.js";
39
+ import { createSkillsMarketplaceSearchTool } from "./skills-marketplace-search-tool.js";
39
40
  import { createSkillInstallTool } from "./skill-install-tool.js";
40
41
  import { createToolManualTool } from "./tool-manual-tool.js";
41
42
  import { createDesktopPetTool } from "./desktop-pet-tool.js";
@@ -43,4 +44,4 @@ import { createCodeIntelligenceTools } from "../code-intelligence/tools.js";
43
44
  import { resolveImageModelConfigForTool } from "../image/tool-model-config.js";
44
45
  import { createImageTool } from "./image-tool.js";
45
46
  import { createImageGenerateTool, resolveImageGenerationModelConfigForTool } from "./image-generate-tool.js";
46
- export { BrowserManager, DEFAULT_DELEGATE_TOOLS, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, DEFAULT_TOOL_METADATA, DEFAULT_WEB_EXTRACT_MAX_LENGTH, DELEGATE_BLOCKED_TOOLS, GREP_MAX_LINE_LENGTH, MAX_RAW_HTML_CHARS_FOR_WEB_EXTRACT, SANDBOX_ALLOWED_TOOLS, TodoStore, ToolConcurrencyController, assertBrowserUrlAllowed, buildSandboxToolMap, createApplyPatchTool, createAutomationTool, createBrowserRecipeTool, createClarifyTool, createCodeIntelligenceTools, createComposioTools, createCreateShareTool, createCuratedMemoryTool, createDelegateTool, createDesktopPetTool, createDreamingTool, createExecCommandTool, createExecuteCodeTool, createFindTool, createGoalTool, createGrepTool, createImageGenerateTool, createImageTool, createListDirTool, createMemoryGetTool, createMemorySearchTool, createMessageTool, createReadFileTool, createReadMediaTool, createSendMediaTool, createSessionSearchTool, createSessionStatusTool, createSkillInstallTool, createSkillManageTool, createSkillViewTool, createSkillsListTool, createTodoTool, createToolManualTool, createUpdatePlanTool, createWebExtractTool, createWebFetchTool, createWebSearchTool, createWorkflowTool, createWriteFileTool, createXopcUseTool, findTool, formatSize, fuzzyFindText, generateDiffString, getToolMetadata, grepTool, isShareToolAvailable, listDirTool, normalizeForFuzzyMatch, normalizeToLF, resolveImageGenerationModelConfigForTool, resolveImageModelConfigForTool, resolveToolLockMode, restoreLineEndings, stripBom, stripHtmlBoilerplate, truncateHead, truncateLine, truncateTail, writeFileTool };
47
+ export { BrowserManager, DEFAULT_DELEGATE_TOOLS, DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, DEFAULT_TOOL_METADATA, DEFAULT_WEB_EXTRACT_MAX_LENGTH, DELEGATE_BLOCKED_TOOLS, GREP_MAX_LINE_LENGTH, MAX_RAW_HTML_CHARS_FOR_WEB_EXTRACT, SANDBOX_ALLOWED_TOOLS, TodoStore, ToolConcurrencyController, assertBrowserUrlAllowed, buildSandboxToolMap, createApplyPatchTool, createAutomationTool, createBrowserRecipeTool, createClarifyTool, createCodeIntelligenceTools, createComposioTools, createCreateShareTool, createCuratedMemoryTool, createDelegateTool, createDesktopPetTool, createDreamingTool, createExecCommandTool, createExecuteCodeTool, createFindTool, createGoalTool, createGrepTool, createImageGenerateTool, createImageTool, createListDirTool, createMemoryGetTool, createMemorySearchTool, createMessageTool, createReadFileTool, createReadMediaTool, createSendMediaTool, createSessionSearchTool, createSessionStatusTool, createSkillInstallTool, createSkillManageTool, createSkillViewTool, createSkillsListTool, createSkillsMarketplaceSearchTool, createTodoTool, createToolManualTool, createUpdatePlanTool, createWebExtractTool, createWebFetchTool, createWebSearchTool, createWorkflowTool, createWriteFileTool, createXopcUseTool, findTool, formatSize, fuzzyFindText, generateDiffString, getToolMetadata, grepTool, isShareToolAvailable, listDirTool, normalizeForFuzzyMatch, normalizeToLF, resolveImageGenerationModelConfigForTool, resolveImageModelConfigForTool, resolveToolLockMode, restoreLineEndings, stripBom, stripHtmlBoilerplate, truncateHead, truncateLine, truncateTail, writeFileTool };
@@ -21,8 +21,25 @@ export interface SkillInstallToolResult {
21
21
  contentHash: string;
22
22
  target?: SkillInstallTarget;
23
23
  }
24
+ export interface MarketplaceSkillInstallToolOptions {
25
+ provider: 'store' | 'clawhub';
26
+ name: string;
27
+ version?: string;
28
+ target?: SkillInstallTarget;
29
+ sessionKey?: string;
30
+ force?: boolean;
31
+ }
32
+ export interface MarketplaceSkillInstallToolResult {
33
+ skillId: string;
34
+ path: string;
35
+ provider: 'store' | 'clawhub';
36
+ name: string;
37
+ version?: string;
38
+ target?: SkillInstallTarget;
39
+ }
24
40
  export interface SkillInstallToolDeps {
25
41
  installSkillFromSource?: (opts: SkillInstallToolOptions) => Promise<SkillInstallToolResult>;
42
+ installSkillFromMarketplace?: (opts: MarketplaceSkillInstallToolOptions) => Promise<MarketplaceSkillInstallToolResult>;
26
43
  getSessionKey?: () => string | undefined;
27
44
  }
28
45
  export declare function createSkillInstallTool(deps: SkillInstallToolDeps): AgentTool;
@@ -2,11 +2,14 @@ import { isSkillInstallTarget } from "../skills/install-target.js";
2
2
  import { Type } from "@sinclair/typebox";
3
3
  //#region src/agent/tools/skill-install-tool.ts
4
4
  const SkillInstallSchema = Type.Object({
5
- source: Type.String({ description: "Explicit skill source: Git URL, GitHub repository URL, https .zip/.tar.gz URL, file:// URL, or local archive/path." }),
5
+ source: Type.Optional(Type.String({ description: "Explicit source install: Git URL, GitHub repository URL, https .zip/.tar.gz URL, file:// URL, or local archive/path." })),
6
+ provider: Type.Optional(Type.Union([Type.Literal("store"), Type.Literal("clawhub")], { description: "Marketplace provider. Use with name; copy it from skills_marketplace_search." })),
7
+ name: Type.Optional(Type.String({ description: "Marketplace package name or install.reference. For ClawHub prefer owner/slug to disambiguate publishers." })),
8
+ version: Type.Optional(Type.String({ description: "Optional marketplace package version." })),
6
9
  ref: Type.Optional(Type.String({ description: "Optional Git branch/tag/ref." })),
7
10
  path: Type.Optional(Type.String({ description: "Optional subdirectory inside the source that contains SKILL.md." })),
8
- skillId: Type.Optional(Type.String({ description: "Optional target managed skill id under the current workspace .xopc/skills." })),
9
- target: Type.Optional(Type.Union([Type.Literal("workspace"), Type.Literal("global")], { description: "Install target. Defaults to workspace. Use global only when the user explicitly asks for a global/personal install." })),
11
+ skillId: Type.Optional(Type.String({ description: "Optional target managed skill id under the selected global or workspace skills root." })),
12
+ target: Type.Optional(Type.Union([Type.Literal("workspace"), Type.Literal("global")], { description: "Install target. Defaults to global (~/.xopc/skills). Use workspace only when the user explicitly asks to scope the skill to the current agent workspace." })),
10
13
  force: Type.Optional(Type.Boolean({ description: "Replace an existing managed skill with the same id." })),
11
14
  strictScan: Type.Optional(Type.Boolean({ description: "Fail when the current scanner reports critical findings." }))
12
15
  });
@@ -17,9 +20,70 @@ function createSkillInstallTool(deps) {
17
20
  return {
18
21
  name: "skill_install",
19
22
  label: "Install skill",
20
- description: "Install an xopc skill from an explicit user-provided source. Use only when the user clearly asks to install or update a skill; do not install from a URL the user merely pasted without installation intent.",
23
+ description: "Install an xopc skill from a Store/ClawHub marketplace result or an explicit source. Use only when the user clearly asks to install or update a skill; never treat search or a pasted URL as installation consent.",
21
24
  parameters: SkillInstallSchema,
22
25
  async execute(_toolCallId, params) {
26
+ const provider = clean(params.provider);
27
+ const name = clean(params.name);
28
+ const target = isSkillInstallTarget(params.target) ? params.target : "global";
29
+ const sessionKey = deps.getSessionKey?.();
30
+ if (provider || name) {
31
+ if (provider !== "store" && provider !== "clawhub") return {
32
+ content: [{
33
+ type: "text",
34
+ text: "Marketplace installs require provider: store or clawhub."
35
+ }],
36
+ details: { errorCode: "missing_provider" }
37
+ };
38
+ if (!name) return {
39
+ content: [{
40
+ type: "text",
41
+ text: "Marketplace installs require name from the search result."
42
+ }],
43
+ details: { errorCode: "missing_name" }
44
+ };
45
+ if (!deps.installSkillFromMarketplace) return {
46
+ content: [{
47
+ type: "text",
48
+ text: "Marketplace skill installation is not available in this runtime context."
49
+ }],
50
+ details: { errorCode: "marketplace_install_unavailable" }
51
+ };
52
+ try {
53
+ const result = await deps.installSkillFromMarketplace({
54
+ provider,
55
+ name,
56
+ version: clean(params.version),
57
+ target,
58
+ sessionKey,
59
+ force: params.force === true
60
+ });
61
+ return {
62
+ content: [{
63
+ type: "text",
64
+ text: [
65
+ `Installed skill "${result.skillId}" from ${result.provider}.`,
66
+ `Package: ${result.name}${result.version ? `@${result.version}` : ""}`,
67
+ `Target: ${result.target ?? target}`,
68
+ `Path: ${result.path}`
69
+ ].join("\n")
70
+ }],
71
+ details: { result }
72
+ };
73
+ } catch (err) {
74
+ const message = err instanceof Error ? err.message : String(err);
75
+ return {
76
+ content: [{
77
+ type: "text",
78
+ text: `Marketplace skill install failed: ${message}`
79
+ }],
80
+ details: {
81
+ errorCode: "install_failed",
82
+ errorMessage: message
83
+ }
84
+ };
85
+ }
86
+ }
23
87
  if (!deps.installSkillFromSource) return {
24
88
  content: [{
25
89
  type: "text",
@@ -41,8 +105,8 @@ function createSkillInstallTool(deps) {
41
105
  ref: clean(params.ref),
42
106
  path: clean(params.path),
43
107
  skillId: clean(params.skillId),
44
- target: isSkillInstallTarget(params.target) ? params.target : void 0,
45
- sessionKey: deps.getSessionKey?.(),
108
+ target,
109
+ sessionKey,
46
110
  force: params.force === true,
47
111
  strictScan: params.strictScan === true
48
112
  });
@@ -51,7 +115,7 @@ function createSkillInstallTool(deps) {
51
115
  type: "text",
52
116
  text: [
53
117
  `Installed skill "${result.skillId}".`,
54
- `Target: ${result.target ?? "workspace"}`,
118
+ `Target: ${result.target ?? target}`,
55
119
  `Source: ${result.source} (${result.kind})`,
56
120
  `Path: ${result.path}`,
57
121
  `Tree hash: ${result.contentHash.slice(0, 16)}`
@@ -72,7 +136,11 @@ function createSkillInstallTool(deps) {
72
136
  }
73
137
  };
74
138
  }
75
- }
139
+ },
140
+ mutatesWorkspace: true,
141
+ mutationScope: "unknown",
142
+ idempotent: false,
143
+ finalGuardRelevant: true
76
144
  };
77
145
  }
78
146
  //#endregion
@@ -0,0 +1,17 @@
1
+ import type { AgentTool } from '@earendil-works/pi-agent-core';
2
+ import type { Config } from '../../config/schema.js';
3
+ import type { SkillManager } from '../skills/skill-manager.js';
4
+ import { searchSkillMarketplaces, type SkillsMarketplaceSearchSource } from '../skills/marketplace/search.js';
5
+ type SearchResponse = Awaited<ReturnType<typeof searchSkillMarketplaces>>;
6
+ export interface SkillsMarketplaceSearchToolDeps {
7
+ getConfig: () => Config | undefined;
8
+ getSkillManager?: () => SkillManager | undefined;
9
+ search?: (params: {
10
+ config: Config;
11
+ query: string;
12
+ sources?: SkillsMarketplaceSearchSource[];
13
+ limit?: number;
14
+ }) => Promise<SearchResponse>;
15
+ }
16
+ export declare function createSkillsMarketplaceSearchTool(deps: SkillsMarketplaceSearchToolDeps): AgentTool;
17
+ export {};
@@ -0,0 +1,77 @@
1
+ import { searchSkillMarketplaces } from "../skills/marketplace/search.js";
2
+ import { Type } from "@sinclair/typebox";
3
+ //#region src/agent/tools/skills-marketplace-search-tool.ts
4
+ const SkillsMarketplaceSearchSchema = Type.Object({
5
+ query: Type.String({
6
+ minLength: 2,
7
+ description: "Capability or task to search for, using concise English keywords when possible"
8
+ }),
9
+ sources: Type.Optional(Type.Array(Type.Union([
10
+ Type.Literal("store"),
11
+ Type.Literal("clawhub"),
12
+ Type.Literal("skills-sh")
13
+ ]), {
14
+ minItems: 1,
15
+ maxItems: 3,
16
+ uniqueItems: true
17
+ })),
18
+ limit: Type.Optional(Type.Integer({
19
+ minimum: 1,
20
+ maximum: 20,
21
+ default: 10
22
+ }))
23
+ });
24
+ function jsonResult(payload) {
25
+ return {
26
+ content: [{
27
+ type: "text",
28
+ text: JSON.stringify(payload, null, 2)
29
+ }],
30
+ details: {}
31
+ };
32
+ }
33
+ function createSkillsMarketplaceSearchTool(deps) {
34
+ return {
35
+ name: "skills_marketplace_search",
36
+ label: "🔎 Find skills",
37
+ description: "Search the XOPC Store, native ClawHub catalog, and skills.sh results federated by ClawHub. Returns normalized provenance, install references, adoption metrics, partial-source errors, and a heuristic value score. Read-only; never installs a skill.",
38
+ parameters: SkillsMarketplaceSearchSchema,
39
+ mutatesWorkspace: false,
40
+ mutationScope: "none",
41
+ supportsParallel: true,
42
+ idempotent: true,
43
+ async execute(_toolCallId, params) {
44
+ const config = deps.getConfig();
45
+ if (!config) return jsonResult({
46
+ success: false,
47
+ error: "XOPC config is not available in this runtime context."
48
+ });
49
+ const query = params.query.trim();
50
+ if (query.length < 2) return jsonResult({
51
+ success: false,
52
+ error: "query must contain at least 2 characters."
53
+ });
54
+ const response = await (deps.search ?? searchSkillMarketplaces)({
55
+ config,
56
+ query,
57
+ sources: params.sources,
58
+ limit: params.limit
59
+ });
60
+ const manager = deps.getSkillManager?.();
61
+ const results = response.results.map((result) => ({
62
+ ...result,
63
+ installed: Boolean(manager?.findSkill(result.name))
64
+ }));
65
+ return jsonResult({
66
+ success: true,
67
+ query,
68
+ scoreIsHeuristic: true,
69
+ sources: response.sources,
70
+ results,
71
+ installationRequiresConfirmation: true
72
+ });
73
+ }
74
+ };
75
+ }
76
+ //#endregion
77
+ export { createSkillsMarketplaceSearchTool };
@@ -90,12 +90,12 @@ export declare const AutomationStateSchema: z.ZodObject<{
90
90
  runningRunId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
91
91
  lastRunAtMs: z.ZodOptional<z.ZodNumber>;
92
92
  lastRunStatus: z.ZodOptional<z.ZodEnum<{
93
+ queued: "queued";
94
+ running: "running";
93
95
  failed: "failed";
94
96
  cancelled: "cancelled";
95
97
  timeout: "timeout";
96
98
  succeeded: "succeeded";
97
- running: "running";
98
- queued: "queued";
99
99
  }>>;
100
100
  lastError: z.ZodOptional<z.ZodString>;
101
101
  consecutiveFailures: z.ZodOptional<z.ZodNumber>;
@@ -185,12 +185,12 @@ export declare const AutomationSchema: z.ZodObject<{
185
185
  runningRunId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
186
186
  lastRunAtMs: z.ZodOptional<z.ZodNumber>;
187
187
  lastRunStatus: z.ZodOptional<z.ZodEnum<{
188
+ queued: "queued";
189
+ running: "running";
188
190
  failed: "failed";
189
191
  cancelled: "cancelled";
190
192
  timeout: "timeout";
191
193
  succeeded: "succeeded";
192
- running: "running";
193
- queued: "queued";
194
194
  }>>;
195
195
  lastError: z.ZodOptional<z.ZodString>;
196
196
  consecutiveFailures: z.ZodOptional<z.ZodNumber>;
@@ -283,12 +283,12 @@ export declare const CreateAutomationSchema: z.ZodObject<{
283
283
  runningRunId: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
284
284
  lastRunAtMs: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
285
285
  lastRunStatus: z.ZodOptional<z.ZodOptional<z.ZodEnum<{
286
+ queued: "queued";
287
+ running: "running";
286
288
  failed: "failed";
287
289
  cancelled: "cancelled";
288
290
  timeout: "timeout";
289
291
  succeeded: "succeeded";
290
- running: "running";
291
- queued: "queued";
292
292
  }>>>;
293
293
  lastError: z.ZodOptional<z.ZodOptional<z.ZodString>>;
294
294
  consecutiveFailures: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
@@ -331,12 +331,12 @@ export declare const UpdateAutomationSchema: z.ZodObject<{
331
331
  runningRunId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
332
332
  lastRunAtMs: z.ZodOptional<z.ZodNumber>;
333
333
  lastRunStatus: z.ZodOptional<z.ZodEnum<{
334
+ queued: "queued";
335
+ running: "running";
334
336
  failed: "failed";
335
337
  cancelled: "cancelled";
336
338
  timeout: "timeout";
337
339
  succeeded: "succeeded";
338
- running: "running";
339
- queued: "queued";
340
340
  }>>;
341
341
  lastError: z.ZodOptional<z.ZodString>;
342
342
  consecutiveFailures: z.ZodOptional<z.ZodNumber>;
@@ -89,7 +89,7 @@ export declare function buildAutomationDraftResponse(draft: GeneratedAutomationD
89
89
  nextRunAtMs?: number;
90
90
  runningRunId?: string;
91
91
  lastRunAtMs?: number;
92
- lastRunStatus?: "failed" | "cancelled" | "timeout" | "succeeded" | "running" | "queued";
92
+ lastRunStatus?: "queued" | "running" | "failed" | "cancelled" | "timeout" | "succeeded";
93
93
  lastError?: string;
94
94
  consecutiveFailures?: number;
95
95
  };
@@ -11,8 +11,8 @@ import { createReadStream, createWriteStream } from "node:fs";
11
11
  import { spawn } from "node:child_process";
12
12
  import { createHash } from "node:crypto";
13
13
  import { mkdir, mkdtemp, rm, stat } from "node:fs/promises";
14
- import { Readable, Transform } from "node:stream";
15
14
  import AdmZip from "adm-zip";
15
+ import { Readable, Transform } from "node:stream";
16
16
  import { pipeline } from "node:stream/promises";
17
17
  //#region src/browser/providers/cloakbrowser.ts
18
18
  /**
@@ -1,5 +1,5 @@
1
- import { installConnectorDefinition } from "../connectors/install.js";
2
1
  import { downloadConnectorStoreZipBuffer, fetchStoreConnectorPackageDetail, listConnectorPackages, resolveSkillsStoreBaseUrl } from "../agent/skills/marketplace/adapters/store/store-api-client.js";
2
+ import { installConnectorDefinition } from "../connectors/install.js";
3
3
  import { createHash } from "node:crypto";
4
4
  import { isIP } from "node:net";
5
5
  import AdmZip from "adm-zip";
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
52
52
  id: "database-schema",
53
53
  label: "Database schema",
54
54
  status: "pass",
55
- message: `SQLite schema v${status.dbVersion} (current release v61).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v65).`,
56
56
  hints: []
57
57
  };
58
58
  }