plugin-agent-orchestrator 1.0.6 → 1.0.14

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 (257) hide show
  1. package/README.md +16 -291
  2. package/dist/client/AIEmployeesContext.d.ts +7 -0
  3. package/dist/client/OrchestratorSettings.d.ts +2 -1
  4. package/dist/client/index.js +1 -1
  5. package/dist/client/plugin.d.ts +1 -0
  6. package/dist/client/skill-hub/components/ExecutionHistory.d.ts +2 -0
  7. package/dist/client/skill-hub/components/ExecutionProgress.d.ts +20 -0
  8. package/dist/client/skill-hub/components/GitSkillImport.d.ts +7 -0
  9. package/dist/client/skill-hub/components/SkillEditor.d.ts +7 -0
  10. package/dist/client/skill-hub/components/SkillManager.d.ts +2 -0
  11. package/dist/client/skill-hub/components/SkillMetrics.d.ts +2 -0
  12. package/dist/client/skill-hub/components/SkillTestPanel.d.ts +7 -0
  13. package/dist/client/skill-hub/index.d.ts +10 -0
  14. package/dist/client/skill-hub/locale.d.ts +3 -0
  15. package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +19 -0
  16. package/dist/client/skill-hub/tools/SkillHubCard.d.ts +3 -0
  17. package/dist/client/skill-hub/utils/jsonFields.d.ts +3 -0
  18. package/dist/externalVersion.js +6 -6
  19. package/dist/node_modules/adm-zip/LICENSE +21 -0
  20. package/dist/node_modules/adm-zip/adm-zip.js +1 -0
  21. package/dist/node_modules/adm-zip/headers/entryHeader.js +377 -0
  22. package/dist/node_modules/adm-zip/headers/index.js +2 -0
  23. package/dist/node_modules/adm-zip/headers/mainHeader.js +130 -0
  24. package/dist/node_modules/adm-zip/methods/deflater.js +33 -0
  25. package/dist/node_modules/adm-zip/methods/index.js +3 -0
  26. package/dist/node_modules/adm-zip/methods/inflater.js +34 -0
  27. package/dist/node_modules/adm-zip/methods/zipcrypto.js +175 -0
  28. package/dist/node_modules/adm-zip/package.json +1 -0
  29. package/dist/node_modules/adm-zip/util/constants.js +142 -0
  30. package/dist/node_modules/adm-zip/util/decoder.js +5 -0
  31. package/dist/node_modules/adm-zip/util/errors.js +63 -0
  32. package/dist/node_modules/adm-zip/util/fattr.js +76 -0
  33. package/dist/node_modules/adm-zip/util/index.js +5 -0
  34. package/dist/node_modules/adm-zip/util/utils.js +339 -0
  35. package/dist/node_modules/adm-zip/zipEntry.js +405 -0
  36. package/dist/node_modules/adm-zip/zipFile.js +446 -0
  37. package/dist/node_modules/simple-git/dist/cjs/index.js +7399 -0
  38. package/dist/node_modules/simple-git/dist/esm/index.js +4745 -0
  39. package/dist/node_modules/simple-git/dist/esm/package.json +3 -0
  40. package/dist/node_modules/simple-git/dist/src/lib/api.d.ts +13 -0
  41. package/dist/node_modules/simple-git/dist/src/lib/args/log-format.d.ts +9 -0
  42. package/dist/node_modules/simple-git/dist/src/lib/errors/git-construct-error.d.ts +15 -0
  43. package/dist/node_modules/simple-git/dist/src/lib/errors/git-error.d.ts +30 -0
  44. package/dist/node_modules/simple-git/dist/src/lib/errors/git-plugin-error.d.ts +7 -0
  45. package/dist/node_modules/simple-git/dist/src/lib/errors/git-response-error.d.ts +32 -0
  46. package/dist/node_modules/simple-git/dist/src/lib/errors/task-configuration-error.d.ts +12 -0
  47. package/dist/node_modules/simple-git/dist/src/lib/git-factory.d.ts +15 -0
  48. package/dist/node_modules/simple-git/dist/src/lib/git-logger.d.ts +21 -0
  49. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-branch-delete.d.ts +5 -0
  50. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-branch.d.ts +2 -0
  51. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-commit.d.ts +2 -0
  52. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-diff-summary.d.ts +3 -0
  53. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-fetch.d.ts +2 -0
  54. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-list-log-summary.d.ts +6 -0
  55. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-merge.d.ts +11 -0
  56. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-move.d.ts +2 -0
  57. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-pull.d.ts +6 -0
  58. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-push.d.ts +4 -0
  59. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-remote-messages.d.ts +5 -0
  60. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-remote-objects.d.ts +3 -0
  61. package/dist/node_modules/simple-git/dist/src/lib/plugins/abort-plugin.d.ts +3 -0
  62. package/dist/node_modules/simple-git/dist/src/lib/plugins/block-unsafe-operations-plugin.d.ts +3 -0
  63. package/dist/node_modules/simple-git/dist/src/lib/plugins/command-config-prefixing-plugin.d.ts +2 -0
  64. package/dist/node_modules/simple-git/dist/src/lib/plugins/completion-detection.plugin.d.ts +3 -0
  65. package/dist/node_modules/simple-git/dist/src/lib/plugins/custom-binary.plugin.d.ts +3 -0
  66. package/dist/node_modules/simple-git/dist/src/lib/plugins/error-detection.plugin.d.ts +7 -0
  67. package/dist/node_modules/simple-git/dist/src/lib/plugins/index.d.ts +11 -0
  68. package/dist/node_modules/simple-git/dist/src/lib/plugins/plugin-store.d.ts +11 -0
  69. package/dist/node_modules/simple-git/dist/src/lib/plugins/progress-monitor-plugin.d.ts +3 -0
  70. package/dist/node_modules/simple-git/dist/src/lib/plugins/simple-git-plugin.d.ts +48 -0
  71. package/dist/node_modules/simple-git/dist/src/lib/plugins/spawn-options-plugin.d.ts +3 -0
  72. package/dist/node_modules/simple-git/dist/src/lib/plugins/suffix-paths.plugin.d.ts +2 -0
  73. package/dist/node_modules/simple-git/dist/src/lib/plugins/timout-plugin.d.ts +3 -0
  74. package/dist/node_modules/simple-git/dist/src/lib/responses/BranchDeleteSummary.d.ts +12 -0
  75. package/dist/node_modules/simple-git/dist/src/lib/responses/BranchSummary.d.ts +14 -0
  76. package/dist/node_modules/simple-git/dist/src/lib/responses/CheckIgnore.d.ts +4 -0
  77. package/dist/node_modules/simple-git/dist/src/lib/responses/CleanSummary.d.ts +9 -0
  78. package/dist/node_modules/simple-git/dist/src/lib/responses/ConfigList.d.ts +13 -0
  79. package/dist/node_modules/simple-git/dist/src/lib/responses/DiffSummary.d.ts +10 -0
  80. package/dist/node_modules/simple-git/dist/src/lib/responses/FileStatusSummary.d.ts +9 -0
  81. package/dist/node_modules/simple-git/dist/src/lib/responses/GetRemoteSummary.d.ts +11 -0
  82. package/dist/node_modules/simple-git/dist/src/lib/responses/InitSummary.d.ts +9 -0
  83. package/dist/node_modules/simple-git/dist/src/lib/responses/MergeSummary.d.ts +16 -0
  84. package/dist/node_modules/simple-git/dist/src/lib/responses/PullSummary.d.ts +25 -0
  85. package/dist/node_modules/simple-git/dist/src/lib/responses/StatusSummary.d.ts +19 -0
  86. package/dist/node_modules/simple-git/dist/src/lib/responses/TagList.d.ts +7 -0
  87. package/dist/node_modules/simple-git/dist/src/lib/runners/git-executor-chain.d.ts +25 -0
  88. package/dist/node_modules/simple-git/dist/src/lib/runners/git-executor.d.ts +14 -0
  89. package/dist/node_modules/simple-git/dist/src/lib/runners/promise-wrapped.d.ts +2 -0
  90. package/dist/node_modules/simple-git/dist/src/lib/runners/scheduler.d.ts +11 -0
  91. package/dist/node_modules/simple-git/dist/src/lib/runners/tasks-pending-queue.d.ts +23 -0
  92. package/dist/node_modules/simple-git/dist/src/lib/simple-git-api.d.ts +20 -0
  93. package/dist/node_modules/simple-git/dist/src/lib/task-callback.d.ts +2 -0
  94. package/dist/node_modules/simple-git/dist/src/lib/tasks/apply-patch.d.ts +3 -0
  95. package/dist/node_modules/simple-git/dist/src/lib/tasks/branch.d.ts +7 -0
  96. package/dist/node_modules/simple-git/dist/src/lib/tasks/change-working-directory.d.ts +2 -0
  97. package/dist/node_modules/simple-git/dist/src/lib/tasks/check-ignore.d.ts +2 -0
  98. package/dist/node_modules/simple-git/dist/src/lib/tasks/check-is-repo.d.ts +9 -0
  99. package/dist/node_modules/simple-git/dist/src/lib/tasks/checkout.d.ts +2 -0
  100. package/dist/node_modules/simple-git/dist/src/lib/tasks/clean.d.ts +25 -0
  101. package/dist/node_modules/simple-git/dist/src/lib/tasks/clone.d.ts +9 -0
  102. package/dist/node_modules/simple-git/dist/src/lib/tasks/commit.d.ts +4 -0
  103. package/dist/node_modules/simple-git/dist/src/lib/tasks/config.d.ts +8 -0
  104. package/dist/node_modules/simple-git/dist/src/lib/tasks/count-objects.d.ts +12 -0
  105. package/dist/node_modules/simple-git/dist/src/lib/tasks/diff-name-status.d.ts +12 -0
  106. package/dist/node_modules/simple-git/dist/src/lib/tasks/diff.d.ts +5 -0
  107. package/dist/node_modules/simple-git/dist/src/lib/tasks/fetch.d.ts +4 -0
  108. package/dist/node_modules/simple-git/dist/src/lib/tasks/first-commit.d.ts +2 -0
  109. package/dist/node_modules/simple-git/dist/src/lib/tasks/grep.d.ts +12 -0
  110. package/dist/node_modules/simple-git/dist/src/lib/tasks/hash-object.d.ts +5 -0
  111. package/dist/node_modules/simple-git/dist/src/lib/tasks/init.d.ts +3 -0
  112. package/dist/node_modules/simple-git/dist/src/lib/tasks/log.d.ts +32 -0
  113. package/dist/node_modules/simple-git/dist/src/lib/tasks/merge.d.ts +4 -0
  114. package/dist/node_modules/simple-git/dist/src/lib/tasks/move.d.ts +3 -0
  115. package/dist/node_modules/simple-git/dist/src/lib/tasks/pull.d.ts +3 -0
  116. package/dist/node_modules/simple-git/dist/src/lib/tasks/push.d.ts +9 -0
  117. package/dist/node_modules/simple-git/dist/src/lib/tasks/remote.d.ts +8 -0
  118. package/dist/node_modules/simple-git/dist/src/lib/tasks/reset.d.ts +11 -0
  119. package/dist/node_modules/simple-git/dist/src/lib/tasks/show.d.ts +2 -0
  120. package/dist/node_modules/simple-git/dist/src/lib/tasks/stash-list.d.ts +4 -0
  121. package/dist/node_modules/simple-git/dist/src/lib/tasks/status.d.ts +3 -0
  122. package/dist/node_modules/simple-git/dist/src/lib/tasks/sub-module.d.ts +5 -0
  123. package/dist/node_modules/simple-git/dist/src/lib/tasks/tag.d.ts +18 -0
  124. package/dist/node_modules/simple-git/dist/src/lib/tasks/task.d.ts +14 -0
  125. package/dist/node_modules/simple-git/dist/src/lib/tasks/version.d.ts +9 -0
  126. package/dist/node_modules/simple-git/dist/src/lib/types/handlers.d.ts +21 -0
  127. package/dist/node_modules/simple-git/dist/src/lib/types/index.d.ts +136 -0
  128. package/dist/node_modules/simple-git/dist/src/lib/types/tasks.d.ts +19 -0
  129. package/dist/node_modules/simple-git/dist/src/lib/utils/argument-filters.d.ts +14 -0
  130. package/dist/node_modules/simple-git/dist/src/lib/utils/exit-codes.d.ts +10 -0
  131. package/dist/node_modules/simple-git/dist/src/lib/utils/git-output-streams.d.ts +7 -0
  132. package/dist/node_modules/simple-git/dist/src/lib/utils/index.d.ts +8 -0
  133. package/dist/node_modules/simple-git/dist/src/lib/utils/line-parser.d.ts +15 -0
  134. package/dist/node_modules/simple-git/dist/src/lib/utils/simple-git-options.d.ts +2 -0
  135. package/dist/node_modules/simple-git/dist/src/lib/utils/task-options.d.ts +13 -0
  136. package/dist/node_modules/simple-git/dist/src/lib/utils/task-parser.d.ts +5 -0
  137. package/dist/node_modules/simple-git/dist/src/lib/utils/util.d.ts +47 -0
  138. package/dist/node_modules/simple-git/dist/typings/errors.d.ts +5 -0
  139. package/dist/node_modules/simple-git/dist/typings/index.d.ts +14 -0
  140. package/dist/node_modules/simple-git/dist/typings/response.d.ts +556 -0
  141. package/dist/node_modules/simple-git/dist/typings/simple-git.d.ts +1033 -0
  142. package/dist/node_modules/simple-git/dist/typings/types.d.ts +22 -0
  143. package/dist/node_modules/simple-git/node_modules/debug/package.json +64 -0
  144. package/dist/node_modules/simple-git/node_modules/debug/src/browser.js +272 -0
  145. package/dist/node_modules/simple-git/node_modules/debug/src/common.js +292 -0
  146. package/dist/node_modules/simple-git/node_modules/debug/src/index.js +10 -0
  147. package/dist/node_modules/simple-git/node_modules/debug/src/node.js +263 -0
  148. package/dist/node_modules/simple-git/package.json +1 -0
  149. package/dist/node_modules/simple-git/promise.js +17 -0
  150. package/dist/server/collections/agent-execution-spans.d.ts +9 -0
  151. package/dist/server/collections/agent-execution-spans.js +152 -0
  152. package/dist/server/collections/orchestrator-config.js +16 -0
  153. package/dist/server/collections/orchestrator-logs.js +19 -2
  154. package/dist/server/collections/skill-definitions.d.ts +3 -0
  155. package/dist/server/collections/skill-definitions.js +158 -0
  156. package/dist/server/collections/skill-executions.d.ts +3 -0
  157. package/dist/server/collections/skill-executions.js +123 -0
  158. package/dist/server/collections/skill-worker-configs.d.ts +3 -0
  159. package/dist/server/collections/skill-worker-configs.js +115 -0
  160. package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +4 -0
  161. package/dist/server/migrations/20260423000000-add-progress-fields.js +69 -0
  162. package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +4 -0
  163. package/dist/server/migrations/20260425000000-add-interaction-schema.js +61 -0
  164. package/dist/server/migrations/20260427000000-add-tracing-detail-fields.d.ts +7 -0
  165. package/dist/server/migrations/20260427000000-add-tracing-detail-fields.js +62 -0
  166. package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +4 -0
  167. package/dist/server/migrations/20260427000000-change-packages-to-text.js +70 -0
  168. package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +4 -0
  169. package/dist/server/migrations/20260427000001-change-other-json-to-text.js +80 -0
  170. package/dist/server/migrations/20260429000000-add-llm-fields.d.ts +7 -0
  171. package/dist/server/migrations/20260429000000-add-llm-fields.js +68 -0
  172. package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +16 -0
  173. package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.js +51 -0
  174. package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +7 -0
  175. package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.js +57 -0
  176. package/dist/server/plugin.d.ts +3 -0
  177. package/dist/server/plugin.js +37 -1
  178. package/dist/server/resources/tracing.js +160 -12
  179. package/dist/server/services/CodeValidator.d.ts +32 -0
  180. package/dist/server/services/CodeValidator.js +205 -0
  181. package/dist/server/services/ExecutionSpanService.d.ts +44 -0
  182. package/dist/server/services/ExecutionSpanService.js +104 -0
  183. package/dist/server/services/FileManager.d.ts +28 -0
  184. package/dist/server/services/FileManager.js +151 -0
  185. package/dist/server/services/SandboxRunner.d.ts +41 -0
  186. package/dist/server/services/SandboxRunner.js +167 -0
  187. package/dist/server/services/SkillManager.d.ts +6 -0
  188. package/dist/server/services/SkillManager.js +640 -0
  189. package/dist/server/services/SkillRepositoryService.d.ts +22 -0
  190. package/dist/server/services/SkillRepositoryService.js +157 -0
  191. package/dist/server/services/WorkerEnvManager.d.ts +26 -0
  192. package/dist/server/services/WorkerEnvManager.js +120 -0
  193. package/dist/server/skill-hub/actions/git-import.d.ts +21 -0
  194. package/dist/server/skill-hub/actions/git-import.js +413 -0
  195. package/dist/server/skill-hub/mcp/McpController.d.ts +15 -0
  196. package/dist/server/skill-hub/mcp/McpController.js +111 -0
  197. package/dist/server/skill-hub/plugin.d.ts +58 -0
  198. package/dist/server/skill-hub/plugin.js +694 -0
  199. package/dist/server/skill-hub/sandbox-config.json +6 -0
  200. package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +14 -0
  201. package/dist/server/skill-hub/tasks/SkillExecutionTask.js +267 -0
  202. package/dist/server/skill-hub/utils/json-fields.d.ts +7 -0
  203. package/dist/server/skill-hub/utils/json-fields.js +88 -0
  204. package/dist/server/tools/delegate-task.d.ts +4 -0
  205. package/dist/server/tools/delegate-task.js +832 -119
  206. package/dist/server/tools/skill-execute.d.ts +36 -0
  207. package/dist/server/tools/skill-execute.js +167 -0
  208. package/package.json +3 -1
  209. package/src/client/AIEmployeeSelect.tsx +1 -3
  210. package/src/client/AIEmployeesContext.tsx +28 -13
  211. package/src/client/OrchestratorSettings.tsx +43 -5
  212. package/src/client/RulesTab.tsx +368 -21
  213. package/src/client/TracingTab.tsx +316 -102
  214. package/src/client/plugin.tsx +39 -0
  215. package/src/client/skill-hub/components/ExecutionHistory.tsx +201 -0
  216. package/src/client/skill-hub/components/ExecutionProgress.tsx +55 -0
  217. package/src/client/skill-hub/components/GitSkillImport.tsx +555 -0
  218. package/src/client/skill-hub/components/SkillEditor.tsx +456 -0
  219. package/src/client/skill-hub/components/SkillManager.tsx +181 -0
  220. package/src/client/skill-hub/components/SkillMetrics.tsx +124 -0
  221. package/src/client/skill-hub/components/SkillTestPanel.tsx +144 -0
  222. package/src/client/skill-hub/index.tsx +75 -0
  223. package/src/client/skill-hub/locale.ts +16 -0
  224. package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +59 -0
  225. package/src/client/skill-hub/tools/SkillHubCard.tsx +78 -0
  226. package/src/client/skill-hub/utils/jsonFields.ts +37 -0
  227. package/src/server/collections/agent-execution-spans.ts +129 -0
  228. package/src/server/collections/orchestrator-config.ts +17 -0
  229. package/src/server/collections/orchestrator-logs.ts +19 -2
  230. package/src/server/collections/skill-definitions.ts +128 -0
  231. package/src/server/collections/skill-executions.ts +94 -0
  232. package/src/server/collections/skill-worker-configs.ts +86 -0
  233. package/src/server/migrations/20260423000000-add-progress-fields.ts +50 -0
  234. package/src/server/migrations/20260425000000-add-interaction-schema.ts +35 -0
  235. package/src/server/migrations/20260427000000-add-tracing-detail-fields.ts +41 -0
  236. package/src/server/migrations/20260427000000-change-packages-to-text.ts +47 -0
  237. package/src/server/migrations/20260427000001-change-other-json-to-text.ts +57 -0
  238. package/src/server/migrations/20260429000000-add-llm-fields.ts +46 -0
  239. package/src/server/migrations/20260429000000-fix-inputargs-json-to-text.ts +38 -0
  240. package/src/server/migrations/20260503000000-add-orchestrator-trace-fields.ts +32 -0
  241. package/src/server/plugin.ts +51 -3
  242. package/src/server/resources/tracing.ts +187 -16
  243. package/src/server/services/CodeValidator.ts +159 -0
  244. package/src/server/services/ExecutionSpanService.ts +106 -0
  245. package/src/server/services/FileManager.ts +144 -0
  246. package/src/server/services/SandboxRunner.ts +205 -0
  247. package/src/server/services/SkillManager.ts +623 -0
  248. package/src/server/services/SkillRepositoryService.ts +142 -0
  249. package/src/server/services/WorkerEnvManager.ts +113 -0
  250. package/src/server/skill-hub/actions/git-import.ts +486 -0
  251. package/src/server/skill-hub/mcp/McpController.ts +86 -0
  252. package/src/server/skill-hub/plugin.ts +771 -0
  253. package/src/server/skill-hub/sandbox-config.json +6 -0
  254. package/src/server/skill-hub/tasks/SkillExecutionTask.ts +297 -0
  255. package/src/server/skill-hub/utils/json-fields.ts +57 -0
  256. package/src/server/tools/delegate-task.ts +1085 -147
  257. package/src/server/tools/skill-execute.ts +157 -0
@@ -0,0 +1,694 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __create = Object.create;
11
+ var __defProp = Object.defineProperty;
12
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
+ var __getOwnPropNames = Object.getOwnPropertyNames;
14
+ var __getProtoOf = Object.getPrototypeOf;
15
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
+ var plugin_exports = {};
38
+ __export(plugin_exports, {
39
+ SkillHubSubFeature: () => SkillHubSubFeature,
40
+ default: () => plugin_default
41
+ });
42
+ module.exports = __toCommonJS(plugin_exports);
43
+ var import_path = require("path");
44
+ var import_fs = require("fs");
45
+ var os = __toESM(require("os"));
46
+ var import_SandboxRunner = require("../services/SandboxRunner");
47
+ var import_FileManager = require("../services/FileManager");
48
+ var import_SkillManager = require("../services/SkillManager");
49
+ var import_WorkerEnvManager = require("../services/WorkerEnvManager");
50
+ var import_SkillExecutionTask = require("./tasks/SkillExecutionTask");
51
+ var import_skill_execute = require("../tools/skill-execute");
52
+ var import_McpController = require("./mcp/McpController");
53
+ var import_SkillRepositoryService = require("../services/SkillRepositoryService");
54
+ var import_git_import = require("./actions/git-import");
55
+ var import_json_fields = require("./utils/json-fields");
56
+ class RateLimiter {
57
+ constructor(maxExecutions = 10, windowMs = 60 * 1e3) {
58
+ this.maxExecutions = maxExecutions;
59
+ this.windowMs = windowMs;
60
+ }
61
+ userExecutions = /* @__PURE__ */ new Map();
62
+ /**
63
+ * Check if the user is allowed to execute.
64
+ * @returns true if allowed, false if rate limited.
65
+ */
66
+ check(userId) {
67
+ const now = Date.now();
68
+ const executions = this.userExecutions.get(userId) || [];
69
+ const valid = executions.filter((t) => now - t < this.windowMs);
70
+ this.userExecutions.set(userId, valid);
71
+ if (valid.length >= this.maxExecutions) {
72
+ return false;
73
+ }
74
+ valid.push(now);
75
+ return true;
76
+ }
77
+ /** Get remaining executions for a user */
78
+ remaining(userId) {
79
+ const now = Date.now();
80
+ const executions = (this.userExecutions.get(userId) || []).filter(
81
+ (t) => now - t < this.windowMs
82
+ );
83
+ return Math.max(0, this.maxExecutions - executions.length);
84
+ }
85
+ /** Periodically clean up expired entries (call from interval) */
86
+ cleanup() {
87
+ const now = Date.now();
88
+ for (const [userId, executions] of this.userExecutions) {
89
+ const valid = executions.filter((t) => now - t < this.windowMs);
90
+ if (valid.length === 0) {
91
+ this.userExecutions.delete(userId);
92
+ } else {
93
+ this.userExecutions.set(userId, valid);
94
+ }
95
+ }
96
+ }
97
+ }
98
+ class SkillHubSubFeature {
99
+ constructor(plugin) {
100
+ this.plugin = plugin;
101
+ }
102
+ sandboxRunner;
103
+ fileManager;
104
+ skillManager;
105
+ workerEnvManager;
106
+ cleanupInterval = null;
107
+ initEnvDoneCallback = null;
108
+ initEnvProgressCallback = null;
109
+ mcpController;
110
+ skillRepoService;
111
+ rateLimiter = new RateLimiter(
112
+ parseInt(process.env.SKILL_HUB_RATE_LIMIT_MAX || "10", 10),
113
+ parseInt(process.env.SKILL_HUB_RATE_LIMIT_WINDOW_MS || "60000", 10)
114
+ );
115
+ skillTemplates = /* @__PURE__ */ new Map();
116
+ get app() {
117
+ return this.plugin.app;
118
+ }
119
+ get db() {
120
+ return this.plugin.db;
121
+ }
122
+ get name() {
123
+ return this.plugin.name;
124
+ }
125
+ async load() {
126
+ const storagePath = (0, import_path.resolve)(process.cwd(), "storage", "plugin-skill-hub");
127
+ this.fileManager = new import_FileManager.FileManager(storagePath);
128
+ this.sandboxRunner = new import_SandboxRunner.SandboxRunner(this.fileManager, this.app.logger, storagePath);
129
+ this.skillManager = new import_SkillManager.SkillManager(this.db);
130
+ this.workerEnvManager = new import_WorkerEnvManager.WorkerEnvManager(this.app, this.db, storagePath);
131
+ this.skillRepoService = new import_SkillRepositoryService.SkillRepositoryService(storagePath);
132
+ this.mcpController = new import_McpController.McpController(this);
133
+ this.app.resourceManager.define({
134
+ name: "skillHub",
135
+ actions: {
136
+ download: this.handleDownload.bind(this),
137
+ test: this.handleTest.bind(this),
138
+ initEnv: this.handleInitEnv.bind(this),
139
+ clearStorage: this.handleClearStorage.bind(this),
140
+ mcpListTools: this.mcpController.listTools.bind(this.mcpController),
141
+ mcpCallTool: this.mcpController.callTool.bind(this.mcpController),
142
+ listTemplates: this.handleListTemplates.bind(this),
143
+ gitListSkills: import_git_import.gitListSkills,
144
+ gitSyncSkills: import_git_import.gitSyncSkills
145
+ }
146
+ });
147
+ this.db.on("skillExecutions.afterDestroy", async (model, options) => {
148
+ const execId = model.get("id");
149
+ try {
150
+ const dir = this.fileManager.getExecDir(String(execId));
151
+ if (require("fs").existsSync(dir)) {
152
+ require("fs").rmSync(dir, { recursive: true, force: true });
153
+ }
154
+ } catch (err) {
155
+ this.app.logger.error(`[skill-hub] Failed to cleanup physical storage for execId ${execId}`, { error: err });
156
+ }
157
+ });
158
+ this.db.on("skillDefinitions.afterSave", async (model, options) => {
159
+ if (model.changed("fileId") && model.get("fileId")) {
160
+ try {
161
+ const attachment = await this.db.getRepository("attachments").findOne({
162
+ filter: { id: model.get("fileId") },
163
+ transaction: options.transaction
164
+ });
165
+ if (attachment) {
166
+ const fileManager = this.app.pm.get("@nocobase/plugin-file-manager");
167
+ if (!fileManager) {
168
+ this.app.logger.warn("[skill-hub] plugin-file-manager not found, cannot extract skill package");
169
+ return;
170
+ }
171
+ const streamData = await fileManager.getFileStream(attachment);
172
+ if (!streamData || !streamData.stream) {
173
+ this.app.logger.warn(`[skill-hub] Could not get file stream for attachment ${attachment.get("id")}`);
174
+ return;
175
+ }
176
+ const tempZipPath = (0, import_path.resolve)(os.tmpdir(), `skill_${Date.now()}_${model.get("id")}.zip`);
177
+ await new Promise((resolvePipe, rejectPipe) => {
178
+ const writeStream = (0, import_fs.createWriteStream)(tempZipPath);
179
+ streamData.stream.pipe(writeStream);
180
+ writeStream.on("finish", resolvePipe);
181
+ writeStream.on("error", rejectPipe);
182
+ streamData.stream.on("error", rejectPipe);
183
+ });
184
+ if (require("fs").existsSync(tempZipPath)) {
185
+ const skillName = model.get("name");
186
+ const { metadata, instructions } = await this.skillRepoService.extractSkillPackage(skillName, tempZipPath);
187
+ const code = this.skillRepoService.getSkillCode(skillName);
188
+ const updateValues = { storageType: attachment.get("storageId") ? `storage-${attachment.get("storageId")}` : "local" };
189
+ if (code) updateValues.codeTemplate = code;
190
+ if (metadata.description) updateValues.description = metadata.description;
191
+ if (metadata.title) updateValues.title = metadata.title;
192
+ if (metadata.language) updateValues.language = metadata.language;
193
+ if (metadata.inputSchema) updateValues.inputSchema = (0, import_json_fields.stringifyJsonText)((0, import_json_fields.parseJsonLike)(metadata.inputSchema, null));
194
+ if (metadata.interactionSchema) updateValues.interactionSchema = (0, import_json_fields.stringifyJsonText)((0, import_json_fields.parseJsonLike)(metadata.interactionSchema, null));
195
+ if (metadata.packages) updateValues.packages = (0, import_json_fields.stringifyJsonText)((0, import_json_fields.parseJsonLike)(metadata.packages, []), []);
196
+ if (metadata.timeoutSeconds) updateValues.timeoutSeconds = metadata.timeoutSeconds;
197
+ if (instructions) updateValues.instructions = instructions;
198
+ await this.db.getRepository("skillDefinitions").update({
199
+ filter: { id: model.get("id") },
200
+ values: updateValues,
201
+ transaction: options.transaction
202
+ });
203
+ (0, import_fs.unlinkSync)(tempZipPath);
204
+ this.app.logger.info(`[skill-hub] Successfully extracted zip and updated skill: ${skillName}`);
205
+ }
206
+ }
207
+ } catch (err) {
208
+ this.app.logger.error(`[skill-hub] Failed to unpack skill zip`, { error: err });
209
+ }
210
+ }
211
+ });
212
+ this.app.pubSubManager.subscribe("skill-hub.task", async (payload) => {
213
+ if (process.env.SKILL_HUB_SANDBOX === "false") return;
214
+ await this.onQueueTask(payload);
215
+ });
216
+ this.app.pubSubManager.subscribe("skill-hub.init-env", async (payload) => {
217
+ if (process.env.SKILL_HUB_SANDBOX === "false") return;
218
+ await this.workerEnvManager.executeInit(payload);
219
+ });
220
+ this.app.on("afterStart", async () => {
221
+ this.registerAITools();
222
+ this.startCleanupInterval();
223
+ await this.subscribeInitEnvDone();
224
+ await this.skillManager.seedDefaults().catch((e) => {
225
+ this.app.logger.error(`[skill-hub] Failed to seed default skills: ${e.message}`);
226
+ });
227
+ });
228
+ }
229
+ async onQueueTask(message) {
230
+ this.app.logger.info(`[skill-hub] Worker received queue task: ${message.id}`);
231
+ const execution = await this.db.getRepository("skillExecutions").findOne({
232
+ filter: { id: message.id },
233
+ appends: ["skill"]
234
+ });
235
+ if (!execution) {
236
+ this.app.logger.warn(`[skill-hub] Task ${message.id} ignored: execution record not found.`);
237
+ return;
238
+ }
239
+ const task = new import_SkillExecutionTask.SkillExecutionTask(
240
+ execution,
241
+ this.sandboxRunner,
242
+ this.fileManager,
243
+ this.skillRepoService,
244
+ this.app
245
+ );
246
+ await task.run();
247
+ }
248
+ /**
249
+ * Execute skill — called by both AI tool and REST test endpoint.
250
+ * Dispatches to worker via EventQueue, waits for result via PubSub.
251
+ * Pushes progress to SSE via runtime.writer (if within AI tool context).
252
+ * Includes rate limiting and graceful abort propagation.
253
+ */
254
+ async executeSkill(skill, inputArgs, ctx) {
255
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
256
+ const userId = (_b = (_a = ctx == null ? void 0 : ctx.state) == null ? void 0 : _a.currentUser) == null ? void 0 : _b.id;
257
+ if (userId) {
258
+ if (!this.rateLimiter.check(String(userId))) {
259
+ const remaining = this.rateLimiter.remaining(String(userId));
260
+ throw new Error(
261
+ `Rate limit exceeded. You can execute up to ${this.rateLimiter["maxExecutions"]} skills per minute. Remaining: ${remaining}. Please wait and try again.`
262
+ );
263
+ }
264
+ }
265
+ const execution = await this.db.getRepository("skillExecutions").create({
266
+ values: {
267
+ skillId: skill.id,
268
+ status: "pending",
269
+ inputArgs: (0, import_json_fields.stringifyJsonText)(inputArgs, {}),
270
+ sessionId: (_c = ctx == null ? void 0 : ctx.state) == null ? void 0 : _c.sessionId,
271
+ triggeredById: (_e = (_d = ctx == null ? void 0 : ctx.state) == null ? void 0 : _d.currentUser) == null ? void 0 : _e.id
272
+ }
273
+ });
274
+ const execId = String(execution.id);
275
+ this.app.logger.info(
276
+ `[skill-hub] Queued execution ${execId}: skill=${skill.get ? skill.get("name") : skill.name}, user=${userId || "system"}`
277
+ );
278
+ const cleanups = [];
279
+ const progressChannel = `skill-hub.progress.${execId}`;
280
+ const doneChannel = `skill-hub.done.${execId}`;
281
+ const abortChannel = `skill-hub.abort.${execId}`;
282
+ const progressCallback = async (progress) => {
283
+ var _a2, _b2, _c2;
284
+ try {
285
+ (_c2 = (_a2 = ctx == null ? void 0 : ctx.runtime) == null ? void 0 : _a2.writer) == null ? void 0 : _c2.call(_a2, {
286
+ action: "skillProgress",
287
+ body: { execId, skillName: skill.name || ((_b2 = skill.get) == null ? void 0 : _b2.call(skill, "name")), ...progress }
288
+ });
289
+ } catch {
290
+ }
291
+ };
292
+ let result;
293
+ try {
294
+ let resolvePromise;
295
+ let rejectPromise;
296
+ const resultPromise = new Promise((resolve2, reject) => {
297
+ resolvePromise = resolve2;
298
+ rejectPromise = reject;
299
+ });
300
+ const timeoutMs = ((skill.timeoutSeconds || ((_f = skill.get) == null ? void 0 : _f.call(skill, "timeoutSeconds")) || 60) + 15) * 1e3;
301
+ const timeout = setTimeout(() => {
302
+ rejectPromise(new Error(`Skill execution timeout after ${skill.timeoutSeconds || 60}s`));
303
+ }, timeoutMs);
304
+ const doneCallback = async (data) => {
305
+ clearTimeout(timeout);
306
+ resolvePromise(data);
307
+ };
308
+ await this.app.pubSubManager.subscribe(progressChannel, progressCallback);
309
+ cleanups.push({ channel: progressChannel, callback: progressCallback });
310
+ await this.app.pubSubManager.subscribe(doneChannel, doneCallback);
311
+ cleanups.push({ channel: doneChannel, callback: doneCallback });
312
+ if (((_g = ctx == null ? void 0 : ctx.req) == null ? void 0 : _g.signal) || (ctx == null ? void 0 : ctx.signal)) {
313
+ const signal = ((_h = ctx.req) == null ? void 0 : _h.signal) || ctx.signal;
314
+ (_i = signal.addEventListener) == null ? void 0 : _i.call(signal, "abort", () => {
315
+ clearTimeout(timeout);
316
+ this.app.pubSubManager.publish(abortChannel, { reason: "user_cancel" }).catch(() => {
317
+ });
318
+ this.db.getRepository("skillExecutions").update({
319
+ filter: { id: execId },
320
+ values: { status: "canceled" }
321
+ }).catch(() => {
322
+ });
323
+ rejectPromise(new Error("Canceled by user"));
324
+ });
325
+ }
326
+ await this.app.pubSubManager.publish("skill-hub.task", { id: execId });
327
+ result = await resultPromise;
328
+ } finally {
329
+ for (const { channel, callback } of cleanups) {
330
+ try {
331
+ await this.app.pubSubManager.unsubscribe(channel, callback);
332
+ } catch {
333
+ }
334
+ }
335
+ }
336
+ const filesWithUrls = (result.files || []).map((f) => {
337
+ const b64name = Buffer.from(f.name).toString("base64url");
338
+ return {
339
+ ...f,
340
+ downloadUrl: `/api/skillHub:download?execId=${execId}&f=${b64name}`
341
+ };
342
+ });
343
+ return { ...result, files: filesWithUrls, execId };
344
+ }
345
+ async handleDownload(ctx, next) {
346
+ var _a, _b;
347
+ const { execId, filename, f } = ctx.action.params;
348
+ let targetFile = filename;
349
+ if (f) {
350
+ targetFile = Buffer.from(f, "base64url").toString("utf8");
351
+ }
352
+ if (!execId || !targetFile) {
353
+ ctx.throw(400, "Missing execId or filename");
354
+ }
355
+ const currentUser = (_a = ctx == null ? void 0 : ctx.state) == null ? void 0 : _a.currentUser;
356
+ if (!currentUser) {
357
+ ctx.throw(401, "Unauthorized");
358
+ }
359
+ const execution = await this.db.getRepository("skillExecutions").findOne({
360
+ filter: { id: execId }
361
+ });
362
+ if (!execution) {
363
+ ctx.throw(404, "Execution not found");
364
+ }
365
+ const isOwner = execution.triggeredById === currentUser.id;
366
+ const isAdmin = (_b = currentUser.roles) == null ? void 0 : _b.some((r) => r.name === "root" || r === "root" || r.name === "admin");
367
+ if (!isOwner && !isAdmin) {
368
+ ctx.throw(403, "Permission denied: you cannot view files from this execution");
369
+ }
370
+ const filePath = this.fileManager.getOutputFilePath(execId, targetFile);
371
+ if (!filePath) {
372
+ ctx.throw(404, "File not found");
373
+ }
374
+ ctx.attachment(targetFile);
375
+ ctx.body = (0, import_fs.createReadStream)(filePath);
376
+ await next();
377
+ }
378
+ async handleTest(ctx, next) {
379
+ const { skillId, input } = ctx.action.params.values || {};
380
+ if (!skillId) {
381
+ ctx.throw(400, "Missing skillId");
382
+ }
383
+ const skill = await this.db.getRepository("skillDefinitions").findOne({
384
+ filter: { id: skillId }
385
+ });
386
+ if (!skill) {
387
+ ctx.throw(404, "Skill not found");
388
+ }
389
+ const result = await this.executeSkill(skill, input || {}, ctx);
390
+ ctx.body = result;
391
+ await next();
392
+ }
393
+ /**
394
+ * Handle Init Environment request from admin UI.
395
+ * Dispatches init task to all workers via EventQueue.
396
+ */
397
+ async handleInitEnv(ctx, next) {
398
+ var _a;
399
+ const config = await this.workerEnvManager.getOrCreateConfig();
400
+ const customPackages = (0, import_json_fields.parseJsonText)(((_a = config.get) == null ? void 0 : _a.call(config, "customPackages")) ?? config.customPackages, {
401
+ python: [],
402
+ node: []
403
+ });
404
+ const message = await this.workerEnvManager.initEnvironment(
405
+ config.get ? {
406
+ npmRegistryUrl: config.get("npmRegistryUrl"),
407
+ npmAuthToken: config.get("npmAuthToken"),
408
+ pypiIndexUrl: config.get("pypiIndexUrl"),
409
+ pypiTrustedHost: config.get("pypiTrustedHost"),
410
+ aptMirrorUrl: config.get("aptMirrorUrl"),
411
+ aptGpgKeyUrl: config.get("aptGpgKeyUrl"),
412
+ customPackages
413
+ } : config
414
+ );
415
+ ctx.body = { message };
416
+ await next();
417
+ }
418
+ /**
419
+ * Subscribe to init-env done AND progress PubSub channels.
420
+ * When a worker finishes init, auto-update the DB with status.
421
+ */
422
+ async subscribeInitEnvDone() {
423
+ this.initEnvDoneCallback = async (data) => {
424
+ try {
425
+ const values = {
426
+ initStatus: data.status,
427
+ lastInitLog: data.log
428
+ };
429
+ if (data.status === "succeeded" && data.whitelist) {
430
+ values.packageWhitelist = (0, import_json_fields.stringifyJsonText)(data.whitelist, { python: [], node: [], apt: [] });
431
+ }
432
+ await this.db.getRepository("skillWorkerConfigs").update({
433
+ filter: {},
434
+ values,
435
+ forceUpdate: true
436
+ });
437
+ this.app.logger.info(`[skill-hub] Init env ${data.status}`);
438
+ } catch (err) {
439
+ this.app.logger.warn("[skill-hub] Failed to update init env status:", err);
440
+ }
441
+ };
442
+ this.initEnvProgressCallback = async (data) => {
443
+ try {
444
+ await this.db.getRepository("skillWorkerConfigs").update({
445
+ filter: {},
446
+ values: {
447
+ initProgressPercent: data.percent,
448
+ initProgressLog: data.log
449
+ },
450
+ forceUpdate: true
451
+ });
452
+ } catch (err) {
453
+ }
454
+ };
455
+ await this.app.pubSubManager.subscribe("skill-hub.init-env.done", this.initEnvDoneCallback);
456
+ await this.app.pubSubManager.subscribe("skill-hub.init-env.progress", this.initEnvProgressCallback);
457
+ }
458
+ registerAITools() {
459
+ var _a;
460
+ try {
461
+ const aiPlugin = this.app.pm.get("@nocobase/plugin-ai");
462
+ if (!((_a = aiPlugin == null ? void 0 : aiPlugin.ai) == null ? void 0 : _a.toolsManager)) {
463
+ this.app.logger.warn("[skill-hub] plugin-ai not available, skip AI tool registration.");
464
+ return;
465
+ }
466
+ aiPlugin.ai.toolsManager.registerTools((0, import_skill_execute.createSkillExecuteTool)(this));
467
+ aiPlugin.ai.toolsManager.registerDynamicTools(async (register) => {
468
+ try {
469
+ const skills = await this.db.getRepository("skillDefinitions").find({
470
+ filter: { enabled: true }
471
+ });
472
+ if (!skills || skills.length === 0) return;
473
+ const tools = await Promise.all(skills.map(async (skill) => {
474
+ const sanitizedToolName = skill.get("name").toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
475
+ const autoCall = !!skill.get("autoCall");
476
+ const interactionSchema = (0, import_json_fields.parseJsonText)(skill.get("interactionSchema"), null);
477
+ const fullDescription = await this.getSkillDescriptionForAI(skill);
478
+ const baseDescription = `${fullDescription || skill.get("description")}
479
+ Language: ${skill.get("language")}`;
480
+ const description = !autoCall && interactionSchema ? `${baseDescription}
481
+
482
+ IMPORTANT: This skill requires human confirmation. Pass best-effort args; the user will adjust them in UI before execution.` : baseDescription;
483
+ return {
484
+ scope: "CUSTOM",
485
+ execution: "backend",
486
+ defaultPermission: autoCall ? "ALLOW" : "ASK",
487
+ introduction: {
488
+ title: `Skill Hub: ${skill.get("title")}`,
489
+ about: skill.get("description") || `Th\u1EF1c thi k\u1EF9 n\u0103ng ${skill.get("title")}`
490
+ },
491
+ definition: {
492
+ name: `skill_hub_${sanitizedToolName}`,
493
+ description,
494
+ schema: (0, import_json_fields.parseJsonText)(skill.get("inputSchema"), { type: "object", properties: {} })
495
+ },
496
+ invoke: async (toolCtx, args) => {
497
+ const latestSkill = await this.db.getRepository("skillDefinitions").findOne({
498
+ filter: { id: skill.get("id"), enabled: true }
499
+ });
500
+ if (!latestSkill) {
501
+ return { error: `Skill "${skill.get("name")}" is no longer available` };
502
+ }
503
+ const result = await this.executeSkill(latestSkill, args, toolCtx);
504
+ return {
505
+ status: result.status === "succeeded" ? "success" : "error",
506
+ result
507
+ // Attach raw result
508
+ };
509
+ }
510
+ };
511
+ }));
512
+ register.registerTools(tools);
513
+ } catch (err) {
514
+ this.app.logger.warn("[skill-hub] Failed to provide dynamic tools", err);
515
+ }
516
+ });
517
+ this.app.logger.info("[skill-hub] AI tools registered (dynamic provider + general tool).");
518
+ } catch (error) {
519
+ this.app.logger.warn("[skill-hub] Failed to register AI tools:", error);
520
+ }
521
+ }
522
+ startCleanupInterval() {
523
+ const CLEANUP_INTERVAL = 60 * 60 * 1e3;
524
+ this.cleanupInterval = setInterval(async () => {
525
+ try {
526
+ const config = await this.db.getRepository("skillWorkerConfigs").findOne();
527
+ const hours = config ? config.get("retentionHours") : 24;
528
+ if (hours && hours > 0) {
529
+ const MAX_AGE_MS = hours * 60 * 60 * 1e3;
530
+ const cutoff = new Date(Date.now() - MAX_AGE_MS);
531
+ const repo = this.db.getRepository("skillExecutions");
532
+ const outdated = await repo.find({
533
+ where: { createdAt: { $lt: cutoff } }
534
+ });
535
+ if (outdated.length > 0) {
536
+ for (const record of outdated) {
537
+ await record.destroy();
538
+ }
539
+ this.app.logger.info(`[skill-hub] Auto-cleaned up ${outdated.length} expired execution records`);
540
+ }
541
+ }
542
+ } catch (err) {
543
+ this.app.logger.warn("[skill-hub] Auto Cleanup error:", err);
544
+ }
545
+ this.rateLimiter.cleanup();
546
+ }, CLEANUP_INTERVAL);
547
+ }
548
+ async beforeStop() {
549
+ if (this.initEnvDoneCallback) {
550
+ try {
551
+ await this.app.pubSubManager.unsubscribe("skill-hub.init-env.done", this.initEnvDoneCallback);
552
+ } catch {
553
+ }
554
+ }
555
+ if (this.initEnvProgressCallback) {
556
+ try {
557
+ await this.app.pubSubManager.unsubscribe("skill-hub.init-env.progress", this.initEnvProgressCallback);
558
+ } catch {
559
+ }
560
+ }
561
+ if (this.cleanupInterval) {
562
+ clearInterval(this.cleanupInterval);
563
+ this.cleanupInterval = null;
564
+ }
565
+ }
566
+ // --- Handlers ---
567
+ async handleClearStorage(ctx, next) {
568
+ const { type } = ctx.request.body || ctx.action.params.values;
569
+ const repo = this.db.getRepository("skillExecutions");
570
+ let count = 0;
571
+ if (type === "all") {
572
+ const results = await repo.find({ fields: ["id"] });
573
+ for (const rec of results) {
574
+ await rec.destroy();
575
+ }
576
+ count = results.length;
577
+ } else if (type === "expired") {
578
+ const config = await this.db.getRepository("skillWorkerConfigs").findOne();
579
+ const hours = config ? config.get("retentionHours") : 24;
580
+ if (hours > 0) {
581
+ const cutoff = new Date(Date.now() - hours * 60 * 60 * 1e3);
582
+ const results = await repo.find({ where: { createdAt: { $lt: cutoff } }, fields: ["id"] });
583
+ for (const rec of results) {
584
+ await rec.destroy();
585
+ }
586
+ count = results.length;
587
+ }
588
+ }
589
+ ctx.body = { count };
590
+ await next();
591
+ }
592
+ async handleListTemplates(ctx, next) {
593
+ try {
594
+ const allPlugins = this.app.pm.getPlugins();
595
+ for (const [, pluginInstance] of allPlugins) {
596
+ if (typeof pluginInstance.getSkillTemplates === "function") {
597
+ const pluginSkills = pluginInstance.getSkillTemplates();
598
+ if (Array.isArray(pluginSkills)) {
599
+ for (const s of pluginSkills) {
600
+ if (!this.skillTemplates.has(s.name)) {
601
+ this.skillTemplates.set(s.name, this.hydrateSkillTemplate(pluginInstance.name, s));
602
+ }
603
+ }
604
+ }
605
+ }
606
+ }
607
+ } catch (e) {
608
+ this.app.logger.warn(`[skill-hub] Failed to discover some plugin skills: ${e.message}`);
609
+ }
610
+ ctx.body = { data: Array.from(this.skillTemplates.values()) };
611
+ await next();
612
+ }
613
+ // ─── Extension API: other plugins register/unregister skills ───
614
+ /**
615
+ * Register a skill template into memory for UI importing.
616
+ */
617
+ registerSkillTemplate(pluginName, skillDef) {
618
+ this.skillTemplates.set(skillDef.name, this.hydrateSkillTemplate(pluginName, skillDef));
619
+ this.app.logger.info(`[skill-hub] Registered skill template "${skillDef.name}" from plugin "${pluginName}"`);
620
+ }
621
+ resolveSkillTemplate(templateName) {
622
+ if (!templateName) return null;
623
+ const cached = this.skillTemplates.get(templateName);
624
+ if (cached) return cached;
625
+ try {
626
+ const allPlugins = this.app.pm.getPlugins();
627
+ for (const [, pluginInstance] of allPlugins) {
628
+ if (typeof pluginInstance.getSkillTemplates !== "function") continue;
629
+ const pluginSkills = pluginInstance.getSkillTemplates();
630
+ if (!Array.isArray(pluginSkills)) continue;
631
+ const found = pluginSkills.find((s) => (s == null ? void 0 : s.name) === templateName);
632
+ if (found) {
633
+ const hydrated = this.hydrateSkillTemplate(pluginInstance.name, found);
634
+ this.skillTemplates.set(templateName, hydrated);
635
+ return hydrated;
636
+ }
637
+ }
638
+ } catch (e) {
639
+ this.app.logger.warn(`[skill-hub] Failed to resolve plugin skill "${templateName}": ${e.message}`);
640
+ }
641
+ return null;
642
+ }
643
+ async getSkillDescriptionForAI(skill) {
644
+ const description = skill.get ? skill.get("description") : skill.description;
645
+ const instructions = await this.getSkillInstructions(skill);
646
+ const maxInlineInstructionChars = 24e3;
647
+ const inlineInstructions = instructions && instructions.length > maxInlineInstructionChars ? `${instructions.slice(0, maxInlineInstructionChars)}
648
+
649
+ [Instructions truncated in tool description. Call skill_hub_execute with action="describe" and this skillName to load the complete workflow.]` : instructions;
650
+ return [description, inlineInstructions ? `Instructions:
651
+ ${inlineInstructions}` : ""].filter(Boolean).join("\n\n");
652
+ }
653
+ async getSkillInstructions(skill) {
654
+ const storedInstructions = skill.get ? skill.get("instructions") : skill.instructions;
655
+ if (storedInstructions) return storedInstructions;
656
+ const storageType = skill.get ? skill.get("storageType") : skill.storageType;
657
+ if (storageType !== "plugin") return "";
658
+ const templateName = (skill.get ? skill.get("pluginSource") : skill.pluginSource) || (skill.get ? skill.get("name") : skill.name);
659
+ const template = this.resolveSkillTemplate(templateName);
660
+ return (template == null ? void 0 : template.instructions) || "";
661
+ }
662
+ hydrateSkillTemplate(pluginName, skillDef) {
663
+ var _a;
664
+ const skillName = skillDef.name;
665
+ const packageRoot = (_a = skillDef.skillPackage) == null ? void 0 : _a.rootDir;
666
+ let packageInfo = null;
667
+ if (packageRoot && this.skillRepoService) {
668
+ packageInfo = this.skillRepoService.readSkillPackage(packageRoot);
669
+ }
670
+ const metadata = (packageInfo == null ? void 0 : packageInfo.metadata) || {};
671
+ const packageInstructions = packageInfo == null ? void 0 : packageInfo.instructions;
672
+ return {
673
+ ...skillDef,
674
+ title: skillDef.title || metadata.title || skillName,
675
+ description: skillDef.description || metadata.description || "",
676
+ instructions: [skillDef.instructions, packageInstructions].filter(Boolean).join("\n\n").trim(),
677
+ language: skillDef.language || metadata.language || "python",
678
+ codeTemplate: skillDef.codeTemplate || (packageInfo == null ? void 0 : packageInfo.code) || "",
679
+ storageType: "plugin",
680
+ storageUrl: skillDef.storageUrl || `plugin://${pluginName}/${skillName}`,
681
+ // Keep pluginSource as the skill template name because existing DB records use it for lookup.
682
+ pluginSource: skillName,
683
+ pluginName
684
+ };
685
+ }
686
+ async install() {
687
+ await this.skillManager.seedDefaults();
688
+ }
689
+ }
690
+ var plugin_default = SkillHubSubFeature;
691
+ // Annotate the CommonJS export names for ESM import in node:
692
+ 0 && (module.exports = {
693
+ SkillHubSubFeature
694
+ });